1. 程式人生 > 其它 >機器學習調優實戰

機器學習調優實戰

導語

機器學習演算法效能很差怎麼辦?過擬合和欠擬合是什麼?調優方法有哪些?如何高效運用trick?

大家知道最近 A.I 非常火,經常看到各種相關技術介紹,像什麼論壇啊、牛人講座啊,當然網上也有很多非常好的大牛的教程,像最近公司剛跟優達學城合作,提供了很多免費的課程。相信大家或多或少都瞭解到一些機器學習的相關技術和演算法了,有些同學可能也用過一些演算法,然後就感覺自己可以稱之為"懂機器學習"了。我曾經也是這麼認為的,但是後來發現真正懂機器學習的人是確實知道如何高效運用的,而另一些人,像我這種,其實並沒有完全理解,所以總是把時間浪費在一些毫無意義的嘗試上面。最近我在學習吳恩達的 Machine Learning 課程中看到他講的關於如何高效對機器學習效果進行調優的內容,感覺非常有用,想給大家分享下。

大概會從三個方面進行介紹,首先會給大家講一個簡單的例子,瞭解為什麼要做調優這件事情。然後會介紹一些具體的調優方法。最後會對這些調優方法進行一個總結概括。

一、引子

我們都知道機器學習的應用範圍很廣,演算法也有很多種,耳熟能詳像邏輯迴歸,SVM,神經網路等演算法。在用這些演算法的過程中可能會遇到效果不能達到預期的情況,這個時候就需要對演算法和模型進行調優。我們先來看一個例子。

1. 過擬合

這裡我們來看一個識別天鵝的例子:

(1)打個形象的比方,有一些天鵝的圖片,讓機器通過這些圖片來學習天鵝的特徵,經過訓練後,知道了天鵝是有翅膀的,天鵝的嘴巴是長長的彎曲的,天鵝的脖子是長長的有點曲度,天鵝的整個體型像一個"2"且略大於鴨子。這時候機器已經基本能區別天鵝和其他動物了。

(2)然後,很不巧已有的天鵝圖片全是白天鵝的,於是機器經過學習後,會認為天鵝的羽毛都是白的,以後看到羽毛是黑的天鵝就會認為那不是天鵝。

好,來分析一下上面這個例子:(1) 中的規律都是對的,所有的天鵝都有的特徵,是全域性特徵;然而,(2) 中的規律:天鵝的羽毛是白的。這實際上並不是所有天鵝都有的特徵,只是區域性樣本的特徵。機器在學習全域性特徵的同時,又學習了局部特徵,這才導致了不能識別黑天鵝的情況。

機器在學習過程中是無法區別區域性特徵和全域性特徵的,學習的區域性特徵比重越多,那麼新樣本中不具有這些區域性特徵但具有所有全域性特徵的樣本也越多,於是機器能識別到的正確樣本的概率就會下降,也就是所謂的"泛化性"變差,這是過擬合會造成的最大問題。

所謂過擬合,就是指把學習進行的太徹底,把樣本資料的幾乎所有特徵都學習到了,於是機器學到了過多的區域性特徵,過多的由於噪聲帶來的假特徵,造成模型的"泛化性"和識別正確率幾乎達到谷點,於是用這個機器識別新的樣本的時候會發現就沒幾個是正確識別的。

解決過擬合的方法,其基本原理就是限制機器的學習,使機器學習特徵時學得不那麼徹底,因此這樣就可以降低機器學到區域性特徵和錯誤特徵的機率,使得識別正確率得到優化。

從上面的分析可以看出,要防止過擬合,訓練資料的選取也是很關鍵的,良好的訓練資料本身的區域性特徵應儘可能少,噪聲也儘可能小。

2.欠擬合

我們再來看一下對應欠擬合的情況。同樣讓機器學習一堆天鵝圖片的特徵,然後經過訓練後,知道了天鵝是有翅膀的,天鵝的嘴巴是長長的。因為具備這兩個特徵的動物很多,像鴨子、鸚鵡都具有這些特徵,所以這時候讓機器去區別天鵝和其他動物,效果是很差的。因為機器學習到的天鵝特徵太少了,導致區分標準太粗糙,不能準確識別出天鵝。這個時候就需要去擴充天鵝的特徵,讓特徵更為具體些。

二、調優方法選取

為了避免過擬合和欠擬合的情況,我們可以進行哪些優化呢?一提到模型優化,可能我們最容易想到的就是增大或者減小訓練集,這算是一個方向;獲取更多或者更少特性,這也是一個方向;除此以外,還有一些增加多項式特徵、增加或者減少正則化引數λ等都是行之有效的方法。如下所示:

• 獲取更多訓練樣本

• 嘗試少些特徵

• 嘗試增大λ

• 嘗試更多特徵 • 嘗試增加多項式特徵(

• 嘗試減小λ

這上面列的很多方法都可以擴充套件成一個六個月或者更長時間的專案。其實大部分人都是隨隨便便試一試,可能花費了六個月後發現這是一條不歸路。其實是可以通過診斷,排除掉單子上至少一半的方法,留下真正有效的方法的,這樣的話,可以節省大量不必要的時間開銷。那到底如何做到這一點呢?接下來讓我們看看如何判斷什麼時候該選取什麼方法。

1.假設函式(hypothesis function)

為了介紹判斷方法,我們首先來了解下假設函式。我們來看個預測房價的例子,如下圖所示,這裡僅考慮房屋面積對房價的影響。紅叉叉是實際房價,藍線是預測的房價。

如果我們用一條直線來擬合實際房價,如下圖中左圖所示,可以看到這些紅叉叉基本上都不在藍線上,並且有一定偏差。

為了更好的擬合這些紅叉叉,我們改用一個 2 次函式來擬合,如中間這幅圖所示,可以看到這些紅叉叉基本上都在藍線上或者臨近的地方,偏差不算太大。

我們想繼續減小偏差,於是用一個 4 次函式來擬合,如右圖所示,可以看到幾乎所有紅叉叉都在線上,偏差趨於 0。

以上所用的這些函式就是假設函式。可以看到隨著假設函式的次數越來越高,越來越複雜,對樣本的擬合程度會越來越好。但是大家有沒有想過,如果用右邊這個函式來預測房價會有什麼問題嗎?因為這個函式對訓練樣本,也就是上面這些紅叉叉擬合得太精確了,導致了過擬合,所以如果要預測一個訓練集中從未出現過的樣本的時候,它會缺乏預測能力,效果會很差。當然效果的好壞並不能全憑我們肉眼觀察,特別對於更多樣本、更多維度等更復雜的情況,我們應該如何選取最佳的假設函式呢。

2.評估假設函式 1.0

讓我們來看看評估假設函式效果的方法。這裡我們仍然以預測房價為例子,我們有一個 10 個數據樣本的資料集,從中隨機選擇 7 個樣本作為訓練集,剩下 3 個作為測試集,為什麼這麼選,是因為 70%,30%這種配比是最常見的一種,當然也可以有其他選擇。

這裡我們要評估 10 種線性迴歸的假設函式,如上圖所示,通過分別針對每個假設函式進行訓練,最小化訓練集的偏差,我們可以得到每個假設函式的引數 θ;然後把引數代入假設函式中,去計算測試集的總偏差,對比每個假設函式的測試集總偏差,選出最小的那個,就是我們認為最好的假設函數了。

這裡提出一個問題。如上所示,可能大家會說簡直是送分題,不就是 h5 嗎?其實並不一定。因為 h5 是在特定測試集上的效果最好,所以它對於這個測試集中的那些樣本是適配得最好的,但是如果換一個測試集就不一定了。所以如果以此作為判斷來選取假設函式,其實並不公平。這樣選取出來的假設函式對於從未出現過的新樣本來說,並不一定支援得很好。所以為了解決這個問題,下面介紹改良版的評估假設函式的方法。

3.評估假設函式 2.0

同樣我們有 10 個樣本,然後從中隨機選取 60%作為訓練集,20%作為交叉驗證集(cross validation),剩下 20%作為測試集。60%,20%,20%,這種配比,也是一種常規選擇方法,當然也可以有所變化。

同樣我們分別將 10 個假設函式用於訓練集的訓練,通過最小化訓練集上的總偏差得到引數θ,然後分別將θ用於交叉驗證集,計算出各自在交叉驗證集上的總偏差,以此作為標準,對比選出最小的那個,例如是 h5,然後將 h5 對應的引數θ在測試集上進行驗證,計算出測試集上的總偏差,這才能評估 h5 這個假設函式真正的效能。

4.高偏差 vs 高度不一致診斷

實際情況中我們不可能窮舉所有假設函式,對比選出他們中效果最好的那個。我們只會選取少數幾個假設函式進行評估,那麼當我們針對一個假設函式,算出訓練集和交叉驗證集的偏差後,如何選擇方法進行下一步優化呢?這裡畫一張關於假設函式的維度大小跟資料集總偏差的關係圖:

橫座標是假設函式的維度,也就是前面所說的 1 次、2 次這種。縱座標是資料集的總偏差。這裡包括訓練集和交叉驗證集的總偏差兩種。

我們知道當維度很低時,如一次函式,非常簡單,所以在擬合訓練集時,偏差會很大,同樣把它用在交叉驗證集上時,偏差也是很大的。但是因為有針對訓練集做引數優化,所以交叉驗證集的偏差還是會比訓練集更大一些。所以就畫出圖上左邊這部分,此時就是所謂的欠擬合狀態,習慣上也叫高偏差狀態,即訓練集和交叉驗證集的偏差都很高。

然後增加維度,如我們前面所說的 2 次函式,它的複雜性會適當提高,於是能更好的擬合訓練集上的樣本,於是訓練集上的偏差會降低。對於交叉驗證集來說,也會擬合得更好,所以交叉驗證集的偏差也會降低。

繼續增大維度,當維度過大時,如前面所說的 4 次函式,它的複雜性很高,所以對於訓練集來說可以非常好的擬合,於是訓練集偏差會繼續下降,甚至趨於 0。但是因為複雜度過高,對於新樣本泛化能力會變弱,所以對於交叉驗證集來說,偏差會大大提高。即圖中右邊部分。此時就是過擬合狀態,習慣上也叫高度不一致狀態,即訓練集的偏差和交叉驗證集的偏差高度不一致。

通過這幅圖可以看出:

  • 在高偏差的時候,訓練集和交叉驗證集的偏差都很大,且相近;
  • 而在高度不一致的時候,訓練集的偏差很小,但是交叉驗證集的偏差非常大,遠遠大於訓練集偏差。

所以通過這種性質就能判斷模型當前是高偏差還是高不一致,就可以對此採用行之有效的方法去解決。如果發現是高偏差可以提高假設函式的維度,如果是高不一致可以降低假設函式的維度。這就是一種解決方法。下面我們來認識另一種解決方法——正則化。

5.正則化

在實際應用中欠擬合的狀態是比較容易發現的,因為在訓練時就可知道,但是過擬合是比較難發現的。為了防止過擬合,我們在訓練時,對訓練集總偏差引入一個正則化項,也就是下圖中黃色框框所示這部分,它的目的是讓引數儘可能小,避免參數過多過大。

例如:對於這個 4 次假設函式來說,在它的總偏差後面加上這樣一個正則化項,也就是將引數

的平方累加起來,前面乘上一個λ/2m,其中 m 是訓練集樣本數。

因為在訓練模型時,我們的目的是讓訓練集的總偏差最小,所以在引入正則化項後,會更多的考慮讓引數變小一些。特別是如果當 λ 非常大如 10000 時,引數

會趨近 0,這時候,我們的假設函式會約等於

,於是就變成一條直線,轉變為欠擬合問題。相反,當 λ 很小,趨近於 0 時,就會讓引數變大,於是就更傾向於沒有正則化項的時候,也就是回到了過擬合問題。

既然 λ 這麼有用,那麼我們如何找到一個最佳的 λ 呢?

這裡我們列出一系列 λ 的取值(通常會按照 0.01*2 的指數次方這種模式進行選取),針對每個 λ 進行訓練,最小化訓練集上的總偏差,得到各自對應的一組引數 θ,然後將各自的引數 θ 應用到交叉驗證集上,算出交叉驗證集上的總偏差 Jcv,然後對比選出最小的那個,這裡假如是第 5 個,然後就用

這一組引數對測試集進行驗證,就得到了測試集上的總偏差。

這裡提出一個思考,也是容易誤解的地方,我之前也是不小心掉進了這個坑:

不是說在計算總偏差時要加上正則化項嗎?為何計算測試集偏差時不加上呢?

其實不管是計算訓練集、還是交叉測試集、還是測試集的總偏差時,都不用也不能加上正則化式,因為它只是在訓練時為了提高訓練效果採用的一個技巧而已,跟偏差本身並沒有半毛錢關係。這點需要理解清楚,不然就沒理解為啥要用 λ 。

為了進一步理解正則化引數 λ 對資料集偏差的影響,我們也來畫一張它們之間的關係圖:

當 λ 很大的時候,引數會變小,更傾向於一條直線,所以模擬函式會變簡單,傾向於欠擬合,所以訓練集偏差很大,交叉驗證集的偏差也很大,且兩者近似。

這時候減小 λ,引數會變大,模擬函式會稍微複雜一些,擬合程度會提高,所以訓練集和交叉驗證集的偏差都會降低。

繼續減小 λ,到λ很小的時候,引數會繼續變大,模擬函式會更復雜,擬合程度會更好,更容易出現過擬合,所以訓練集偏差很小,但是交叉驗證集偏差很大。

於是就得到圖中這樣兩條曲線。中間會有一個點讓交叉驗證集上的偏差最小。對應的λ就是我們要求的最優 λ 。

所以可以根據這個圖確定當前所處的狀態,並可以據此調節 λ 來提高模型效果。

6.學習曲線(learning curves)

下面介紹另一種很有用的工具,學習曲線。通過畫出學習曲線,也可以判斷當前模型是否處於高偏差或者高不一致狀態。學習曲線反應的是訓練集大小跟資料集總偏差之間的關係,下面我們看下怎麼畫出一條學習曲線。

我們首先來畫訓練集的:

這裡我們選取假設函式為一個二次函式,當樣本數為 1 時,用二次函式很容易擬合一個點,誤差絕對也很小,當樣本數為 2 時也可以完全擬合,然後繼續增加樣本數到 3、4,也還是可以基本擬合,只是誤差會逐漸變大一點。事實上隨著訓練集越來越大,會發現擬合所有點越來越困難了,也就是說誤差會越來越大。於是我們得到一條學習曲線,如淺藍色曲線所示。

那對交叉驗證集來說誤差又會如何變化呢?當訓練集樣本很少時,泛化程度很差,對新樣本的適應能力很差,所以誤差會非常大。隨著訓練樣本的增加,泛化程度會越來越好,對新樣本的適應能力會越來越強,所以誤差會越來越小。就得到了關於交叉驗證集的紅色的這條學習曲線。

下面我們來看下過擬合和欠擬合,也可以是高偏差狀態下的學習曲線是什麼樣子。

假設我們用一條直線來擬合我們的訓練集,當只有一個樣本的時候,可以完全擬合,所以誤差為 0,然後隨著樣本的增加,它很快就不能很好的擬合這些樣本了。所以誤差會越來越大,當找到一個最佳擬合的直線後,再增大訓練集,發現誤差也不會有太大變化了,所以趨於平直。大致也就是淡藍色曲線所示的樣子。

而交叉驗證集的誤差如何變化呢?一開始同樣因為泛化能力差,所以誤差很大,然後隨著樣本增加,泛化能力變強所以誤差會降低,然後等到找到最佳擬合直線後,誤差就基本上不會怎麼變化了,趨於平直,並且誤差跟訓練集相近。

所以在高偏差的情況下呢,無論如何增大訓練集樣本,訓練集和交叉驗證集的誤差都會處於一個比較高的水平,而且兩者比較接近。

所以當我們發現畫出的學習曲線中,交叉驗證集誤差不會隨著橫座標的增大而有明顯下降,而是變為水平了,就說明演算法處於高偏差的情況,這個時候增大訓練集,對於改善演算法並沒有太大用處,所以也不要在這上面做太多無用功了。

接下來再讓我們看下高不一致的情況吧。

我們選用一個超級複雜的假設函式,一個 100 次的函式,即使用了正則化,λ 也非常小。這時候如果要用這個函式去擬合幾個點,會發現擬合得非常非常好,繼續增大訓練集,雖然誤差有所上升,但仍然擬合得非常好。誤差始終處於一個相對較低的水平。

但是對於交叉驗證集誤差來說又如何呢?同樣當樣本非常少時,由於缺乏泛化能力,所以誤差很高,隨著樣本的增加,誤差有所下降,但是因為存在過擬合的情況,所以交叉驗證集的誤差始終很高。所以在訓練集和交叉驗證集之間存在著一個很大的差距。

同時從圖中可以看出如果繼續增大訓練集,也就是把圖中的線往右邊延伸,兩條曲線是在逐漸逼近的,雖然訓練集誤差在增大,但我們更關注的交叉驗證集的誤差在減小,所以增大訓練樣本在過擬合的情況下是有意義的。

當然我們上面畫的這些學習曲線都是理想情況下的,實際中可能會出現一點噪聲或者干擾,但大體上還是差不多的。所以可以通過畫出學習曲線,幫助我們去判斷當前演算法模型是處於高偏差還是高不一致,還是兩者都有的情形。這樣可以節省不少時間。

三、總結

通過前面介紹的這些判斷方法,就可以判斷當前演算法模型所處狀態,一旦我們確定當前演算法是過擬合還是欠擬合後,就可以採取對應的方法進行調優了。

總結起來就是這些方法。

  • 針對過擬合
    • 獲取更多訓練樣本
    • 嘗試少些特徵
    • 嘗試增大 λ
  • 針對欠擬合
    • 嘗試更多特徵
    • 嘗試增加多項式特徵(

    • 嘗試減小 λ

針對過擬合的場景:我們可以獲取更多訓練樣本,這樣可以覆蓋更多場景。第二個呢,可以嘗試少一些特徵,這樣模擬函式會簡單一些。也可以嘗試增大正則化引數 λ,這樣函式引數會變小一些,模擬函式會更傾向於簡單。

相反,針對欠擬合的情況呢:可以嘗試更多特徵,讓模擬函式複雜一些;也可以嘗試增加多項式特徵,也是為了讓模擬函式複雜一些。還可以嘗試減小 λ,這樣函式引數會變大一些,模擬函式會更傾向於複雜。

最後我們來看看在神經網路中,如何判斷和解決過擬合欠擬合問題。

當設計神經網路演算法時,首先要選擇層次。最常用的神經網路是三層,也就是一個隱藏層,當神經網路層次很少,然後每一層的節點很少的時候,對應的引數就很少,模型就更簡單,計算就更簡單,但是也更容易出現欠擬合;

當神經網路層次很多,或者每一層的節點很多的時候,對應的引數就很多,模型就會很複雜,計算開銷也會很大,也就更容易出現過擬合。一個很有效的避免過擬合的方法就是使用正則化項。前面我們也提到了增大正則化引數 λ 對避免過擬合的好處。

實際應用中可以把資料集拆分成訓練集、交叉訓練集和測試集,然後用交叉驗證的方法來嘗試多種層次和節點個數,對比他們的效果,最終選定一個最佳的神經網路結構。

感謝作者分享。