深度學習各種優化函數詳解

深度學習中有衆多有效的優化函數,比如應用最廣泛的SGD,Adam等等,而它們有什麼區別,各有什麼特徵呢?下面就來詳細解讀一下


一、先來看看有哪些優化函數


BGD 批量梯度下降

所謂的梯度下降方法是無約束條件中最常用的方法。假設f(x)是具有一階連續偏導的函數,現在的目標是要求取最小的f(x) : min f(x)

核心思想:負梯度方向是使函數值下降最快的方向,在迭代的每一步根據負梯度的方向更新x的值,從而求得最小的f(x)。因此我們的目標就轉變爲求取f(x)的梯度。

當f(x)是凸函數的時候,用梯度下降的方法取得的最小值是全局最優解,但是在計算的時候,需要在每一步(xk處)計算梯度,它每更新一個參數都要遍歷完整的訓練集,不僅很慢,還會造成訓練集太大無法加載到內存的問題,此外該方法還不支持在線更新模型。其代碼表示如下:

for i in range(nb_epochs):
  params_grad = evaluate_gradient(loss_function, data, params)
  params = params - learning_rate * params_grad

我們首先需要針對每個參數計算在整個訓練集樣本上的梯度,再根據設置好的學習速率進行更新。

公式表示如下:
假設h(theta)是我們需要擬合的函數,n表示參數的個數,m表示訓練集的大小。J(theta)表示損失函數。
這裏寫圖片描述

這裏寫圖片描述

不難看出,在批量梯度下降法中,因爲每次都遍歷了完整的訓練集,其能保證結果爲全局最優,但是也因爲我們需要對於每個參數求偏導,且在對每個參數求偏導的過程中還需要對訓練集遍歷一次,當訓練集(m)很大時,這個計算量是驚人的!

所以,爲了提高速度,減少計算量,提出了SGD隨機梯度下降的方法,該方法每次隨機選取一個樣本進行梯度計算,大大降低了計算成本。


SGD隨機梯度下降

隨機梯度下降算法和批量梯度下降的不同點在於其梯度是根據隨機選取的訓練集樣本來決定的,其每次對theta的更新,都是針對單個樣本數據,並沒有遍歷完整的參數。當樣本數據很大時,可能到迭代完成,也只不過遍歷了樣本中的一小部分。因此,其速度較快,但是其每次的優化方向不一定是全局最優的,但最終的結果是在全局最優解的附近。

需要:學習速率 ϵ, 初始參數 θ
每步迭代過程:
1. 從訓練集中的隨機抽取一批容量爲m的樣本{x1,…,xm},以及相關的輸出yi
2. 計算梯度和誤差並更新參數

代碼表示如下:(需要注意的是,在每次迭代訓練中,需要重新洗牌訓練集)

for i in range(nb_epochs):
  np.random.shuffle(data)
  for example in data:
    params_grad = evaluate_gradient(loss_function, example, params)
    params = params - learning_rate * params_grad

雖然BGD可以讓參數達到全局最低點並且停止,而SGD可能會讓參數達到局部最優,但是仍然會波動,甚至在訓練過程中讓參數會朝一個更好的更有潛力的方向更新。但是衆多的實驗表明,當我們逐漸減少學習速率時,SGD和BGD會達到一樣的全局最優點。

優點:
訓練速度快,避免了批量梯度更新過程中的計算冗餘問題,對於很大的數據集,也能夠以較快的速度收斂.

缺點:
由於是抽取,因此不可避免的,得到的梯度肯定有誤差.因此學習速率需要逐漸減小,否則模型無法收斂
因爲誤差,所以每一次迭代的梯度受抽樣的影響比較大,也就是說梯度含有比較大的噪聲,不能很好的反映真實梯度.並且SGD有較高的方差,其波動較大,如下圖:
這裏寫圖片描述

學習速率該如何調整:
那麼這樣一來,ϵ如何衰減就成了問題.如果要保證SGD收斂,應該滿足如下兩個要求:

這裏寫圖片描述

而在實際操作中,一般是進行線性衰減:

這裏寫圖片描述

其中ϵ0是初始學習率, ϵτ是最後一次迭代的學習率. τ自然代表迭代次數.一般來說,ϵτ 設爲ϵ0的1%比較合適.而τ一般設爲讓訓練集中的每個數據都輸入模型上百次比較合適.那麼初始學習率ϵ0怎麼設置呢?書上說,你先用固定的學習速率迭代100次,找出效果最好的學習速率,然後ϵ0設爲比它大一點就可以了.

  • 另外,需要注意的是因爲存在樣本選擇的隨機性,所以在梯度下降過程中會存在較大的噪聲,因此學習速率應該要逐漸減小,來尋找一個相對全局最優的方向。

  • 同時也考慮到每次只選擇一個樣本進行梯度更新存在較大的噪聲,學者們開始嘗試每次選擇一小批樣本進行梯度更新,在降低噪聲的同時提高速度,因此就有了下面的MBGD小批量梯度下降法。


MBGD小批量梯度下降

爲了綜合上述兩種方法,提出了小批量梯度下降。它:(1)降低在SGD中高方差的問題,能使得收斂更加穩定;(2)可以利用深度學習中最先進的庫進行矩陣優化的操作,加速操作;(3)一般的小批量介於50~256,但是當適用很小的批量時,有時也統稱爲SGD。

核心思想:在每次迭代時考慮一小部分樣本,比如考慮10個樣本,同時計算在這10個樣本點上的每個參數的偏導數,對於每個優化參數,將該參數在這10個樣本點的偏導數求和。

代碼表示:

for i in range(nb_epochs):
  np.random.shuffle(data)
  for batch in get_batches(data, batch_size=50):
    params_grad = evaluate_gradient(loss_function, batch, params)
    params = params - learning_rate * params_grad

但是,需要注意的是因爲這裏也存在樣本選擇的隨機性,學習速率應該要逐漸減小,同時上述方法並不能保證好的收斂性。主要存在的挑戰有:

  1. 選擇適當的學習率可能很困難。 太小的學習率會導致收斂性緩慢,而學習速度太大可能會妨礙收斂,並導致損失函數在最小點波動。
  2. 使用學習率計劃:嘗試在訓練期間調整學習率。 比如根據預先制定的規則緩慢的降低學習速率,或者當每次迭代之間的偏導差異已經低於某個閾值時,就降低學習速率。但是這裏面的學習速率更新規則,以及閾值都是需要預先設定的,因此不適應於所有的數據集。
  3. 此外,使用梯度更新的方法會導致所有參數都用學習速率更新。但是當訓練集數據是稀疏的,或者特徵的頻率是不同的,我們可能不希望它們更新到同樣的程度,因此使用相同的學習速率會導致那些很少出現的特徵有較大的變化。
  4. 在求取那些高度非凸的誤差函數的最小值時,我們應該避免陷入局部最優解,實驗表明,最困難的不是從局部最優而是鞍點,鞍點就是沿着某一個方向他是穩定的,沿着另一個方向不穩定,既不是最小點也不是最大點。這會使得該點在所有維度上梯度爲0,讓SGD難以逃脫。

基於上述問題,又有了如下更多的優化策略!


momentum

上述SGD和MBGD算法都存在樣本選擇的隨機性,因此含有較多的噪聲,而momentum能解決上述噪聲問題,尤其在面對小而較多噪聲的梯度時,它往往能加速學習速率。

這裏寫圖片描述

核心思想:Momentum借用了物理中的動量概念,即前幾次的梯度也會參與運算。爲了表示動量,引入了一個新的變量v(velocity)。v是之前的梯度的累加,但是每回合都有一定的衰減。

每步迭代過程:
1. 從訓練集中的隨機抽取一批容量爲m的樣本{x1,…,xm},以及相關的輸出yi
2. 計算梯度和誤差,並更新速度v和參數θ:

ĝ ←+1m∇θ∑iL(f(xi;θ),yi)
v←αv−ϵĝ
θ←θ+v

其中參數α表示每回合速率v的衰減程度.同時也可以推斷得到,如果每次迭代得到的梯度都是g,那麼最後得到的v的穩定值爲 ϵ∥g∥/1−α

也就是說,Momentum最好情況下能夠將學習速率加速1/1−α倍.一般α的取值爲0.9或者更小。當然,也可以讓α的值隨着時間而變化,一開始小點,後來再加大.不過這樣一來,又會引進新的參數.

特點:
本質上來說,就和我們把球從山上退下來一樣,球的速度會越來越快。和我們的參數更新一樣,當方向一致時,動量項會增加;當方向不一致時,動量項會降低。
即:
前後梯度方向一致時,能夠加速學習
前後梯度方向不一致時,能夠抑制震盪


Nesterov Momentum

僅僅有一個追求速度的球往山下滾是不能令人滿意的,我們需要一個球,它能知道往前一步的信息,並且當山坡再次變陡時他能夠減速。因此,帶有nesterov的出現了!

在momentum裏,先計算當前的梯度(短藍色線),然後結合以前的梯度執行更新(長藍色線)。而在nesterov momentum裏,先根據事先計算好的梯度更新(棕色),然後在預計的點處計算梯度(紅色),結合兩者形成真正的更新方向(綠色)。
這裏寫圖片描述
這是對之前的Momentum的一種改進,大概思路就是,先對參數進行估計(先往前看一步,探路),然後使用估計後的參數來計算誤差
具體實現:
需要:學習速率 ϵ, 初始參數 θ, 初始速率v, 動量衰減參數α
每步迭代過程:
1. 從訓練集中的隨機抽取一批容量爲m的樣本{x1,…,xm},以及相關的輸出yi
2. 計算梯度和誤差,並更新速度v和參數θ:

ĝ ←+1m∇θ∑iL(f(xi;θ+αv),yi)
v←αv−ϵĝ
θ←θ+v

注意在估算ĝ 的時候,參數變成了θ+αv而不是之前的θ

推薦好文——揭開nesters momentum的面紗


AdaGrad

AdaGrad可以自動變更學習速率,只是需要設定一個全局的學習速率ϵ,但是這並非是實際學習速率,實際的速率是與以往參數的模之和的開方成反比的.也許說起來有點繞口,不過用公式來表示就直白的多:

這裏寫圖片描述

其中δ是一個很小的常亮,大概在10−7,防止出現除以0的情況.

核心思想:對於頻繁出現的參數使用更小的更新速率,對於不頻繁出現的參數使用更大的更新速率。
正因爲如此,該優化函數腳適用於稀疏的數據,比如在Google從YouTube視頻上識別貓時,該優化函數大大提升了SGD的魯棒性。在訓練GloVe詞向量時該優化函數更加適用。

具體實現:
需要:全局學習速率 ϵ, 初始參數 θ, 數值穩定量δ
中間變量: 梯度累計量r(初始化爲0)
每步迭代過程:
1. 從訓練集中的隨機抽取一批容量爲m的樣本{x1,…,xm},以及相關的輸出yi
2. 計算梯度和誤差,更新r,再根據r和梯度計算參數更新量

在SGD中,我們對所有參數進行同時更新,這些參數都使用同樣的學習速率。
比圖用gt,i表示在t時間點,對i參數求得的偏導。
這裏寫圖片描述
那麼在SGD中就會用同一個學習速率對i參數進行更新:
這裏寫圖片描述
但是在adagrad裏,會綜合考慮i之前的所有梯度值來更新學習速率,其中Gt,ii是一個對角矩陣,i行i列存儲了目前時間點爲止的所有i參數的偏導的平方和。後面的項是一個很小的值(1e−8),爲了防止除0錯誤。
這裏寫圖片描述
優點:
能夠實現學習率的自動更改。如果這次梯度大,那麼學習速率衰減的就快一些;如果這次梯度小,那麼學習速率衰減的就慢一些。

缺點:
最大的缺點在於分母中那個G是偏導的累積,隨着時間的推移,分母會不斷的變大,最後會使得學習速率變的非常小,而此時會使得模型不再具備學習其他知識的能力。
經驗表明,在普通算法中也許效果不錯,但在深度學習中,深度過深時會造成訓練提前結束。因爲它到後面的衰減可能越來越慢,然後就提前結束了。爲了解決提前結束的問題,引入瞭如下的算法:Adadelta!RMSprop!


Adadelta
adadelta是adagrad的延伸,不同於adadelta將以前所有的偏導都累加起來,adadelta控制了累加的範圍到一定的窗口中。
但是,並非簡單的將窗口大小設置並且存儲,我們是通過下式動態改變的上述的G:
這裏寫圖片描述
這裏面的gamma類似於momentum裏面的項(通常取值0.9),用來控制更新的權重。
因此以前的:
這裏寫圖片描述
將被改變爲:
這裏寫圖片描述


RMSprop

RMSProp通過引入一個衰減係數,讓r每回合都衰減一定比例,類似於Momentum中的做法。(我覺得和Adadelta沒啥區別)

具體實現:
需要:全局學習速率 ϵ, 初始參數 θ, 數值穩定量δ,衰減速率ρ
中間變量: 梯度累計量r(初始化爲0)
每步迭代過程:
1. 從訓練集中的隨機抽取一批容量爲m的樣本{x1,…,xm},以及相關的輸出yi
2. 計算梯度和誤差,更新r,再根據r和梯度計算參數更新量

這裏寫圖片描述

算法的提出者建議如上式所示,gamma取0.9,學習速率爲0.001

優點:
相比於AdaGrad,這種方法很好的解決了深度學習中過早結束的問題
適合處理非平穩目標,對於RNN效果很好

缺點:
又引入了新的超參,衰減係數ρ
依然依賴於全局學習速率


Adam

Adam(Adaptive Moment Estimation)是另外一種給每個參數計算不同更新速率的方法,其本質上是帶有動量項的RMSprop,它利用梯度的一階矩估計和二階矩估計動態調整每個參數的學習率。Adam的優點主要在於經過偏置校正後,每一次迭代學習率都有個確定範圍,使得參數比較平穩。它和上述的adadelta和RMSprop一樣,都存儲了以前的偏導平方衰減平均值,此外,它還存儲以前的偏導衰減平均值。

具體實現:
需要:步進值 ϵ, 初始參數 θ, 數值穩定量δ,一階動量衰減係數ρ1, 二階動量衰減係數ρ2
其中幾個取值一般爲:δ=10−8,ρ1=0.9,ρ2=0.999
中間變量:一階動量s,二階動量r,都初始化爲0
每步迭代過程:
1. 從訓練集中的隨機抽取一批容量爲m的樣本{x1,…,xm},以及相關的輸出yi
2. 計算梯度和誤差,更新r和s,再根據r和s以及梯度計算參數更新量

這裏寫圖片描述

其中的Mt和Vt分別表示平均值角度和非中心方差角度的偏導。
這裏寫圖片描述
這裏寫圖片描述

才方法的作者建議 β1取0.9, β2取0.999 ,ϵ取10-8。並且聲稱Adam在實踐中比其他的自適應算法有更好的表現。


二、可視化

讓我們來可視化的看看它們的表現:

比較一下速度:
這裏寫圖片描述

比較一下在鞍點的性能:
這裏寫圖片描述


三、如何選擇


  • 如果你的數據很稀疏,那應該選擇有自適應性的優化函數。並且你還可以減少調參的時間,用默認參數取得好的結果。
  • RMSprop是adagrad的一個拓展,旨在解決它提前結束的問題。
  • 而RMSprop和Adadelta類似,只是adadelta採用了RMS的方法更新參數。
  • 在RMSprop基礎上增加了偏差校正和momentum,形成了Adam。
  • 綜上,RMSprop、Adadelta、Adam都是類似的。
  • Kingma【Kingma, D. P., & Ba, J. L. (2015). Adam: a Method for Stochastic Optimization. International Conference on Learning Representations, 1–13.】的實驗表示,偏差校正使得Adam在優化到後面梯度變的稀疏的時候使得其優化性能最好。
  • 所以,可能Adam是最好的優化函數。
  • 所以,如果你希望你的訓練能變的更快,或者你要訓練的是一個複雜的深度的網絡,儘量選擇自適應的優化函數。

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章