深度學習優化器 optimizer 的原理及選擇

在很多機器學習和深度學習的應用中,我們發現用的最多的優化器是 Adam,為什么呢?

下面是 TensorFlow 中的優化器, 
https://www.tensorflow.org/api_guides/python/train 
深度學習優化器 optimizer 的原理及選擇的圖1

在 keras 中也有 SGD,RMSprop,Adagrad,Adadelta,Adam 等: 
https://keras.io/optimizers/

我們可以發現除了常見的梯度下降,還有 Adadelta,Adagrad,RMSProp 等幾種優化器,都是什么呢,又該怎么選擇呢?

在 Sebastian Ruder 的這篇論文中給出了常用優化器的比較,今天來學習一下: 
https://arxiv.org/pdf/1609.04747.pdf

本文將梳理:

  • 每個算法的梯度更新規則和缺點

  • 為了應對這個不足而提出的下一個算法

  • 超參數的一般設定值

  • 幾種算法的效果比較

  • 選擇哪種算法

深度學習優化器 optimizer 的原理及選擇的圖2深度學習優化器 optimizer 的原理及選擇的圖3優化器算法簡述?

首先來看一下梯度下降最常見的三種變形 BGD,SGD,MBGD, 
這三種形式的區別就是取決于我們用多少數據來計算目標函數的梯度, 
這樣的話自然就涉及到一個 trade-off,即參數更新的準確率和運行時間。

<span style="color:#000000"><code>1. Batch gradient descent
</code></span>
  • 1

  • 2

梯度更新規則: 
BGD 采用整個訓練集的數據來計算 cost function 對參數的梯度: 

θ=θ?α?θJ(θ)θ=θ?α?θJ(θ)

 

缺點: 
由于這種方法是在一次更新中,就對整個數據集計算梯度,所以計算起來非常慢,遇到很大量的數據集也會非常棘手,而且不能投入新數據實時更新模型

我們會事先定義一個迭代次數 epoch,首先計算梯度向量 params_grad,然后沿著梯度的方向更新參數 params,learning rate 決定了我們每一步邁多大。

Batch gradient descent 對于凸函數可以收斂到全局極小值,對于非凸函數可以收斂到局部極小值。

<span style="color:#000000"><code>2. Stochastic gradient descent
</code></span>
  • 1

  • 2

梯度更新規則: 
和 BGD 的一次用所有數據計算梯度相比,SGD 每次更新時對每個樣本進行梯度更新, 對于很大的數據集來說,可能會有相似的樣本,這樣 BGD 在計算梯度時會出現冗余, 而 SGD 一次只進行一次更新,就沒有冗余,而且比較快,并且可以新增樣本。

缺點: 
SGD 因為更新比較頻繁,會造成 cost function 有嚴重的震蕩,此外SGD對噪聲比較敏感。

深度學習優化器 optimizer 的原理及選擇的圖4

BGD 可以收斂到局部極小值,當然 SGD 的震蕩可能會跳到更好的局部極小值處。

當我們稍微減小 learning rate,SGD 和 BGD 的收斂性是一樣的。

<span style="color:#000000"><code>3. Mini-batch gradient descent
</code></span>
  • 1

  • 2

梯度更新規則: 
MBGD 每一次利用一小批樣本,即 n 個樣本進行計算, 這樣它可以降低參數更新時的方差,收斂更穩定, 另一方面可以充分地利用深度學習庫中高度優化的矩陣操作來進行更有效的梯度計算。 
和 SGD 的區別是每一次循環不是作用于每個樣本,而是具有 n 個樣本的Batch。

超參數設定值: 
n 一般取值在 50~200

缺點: 
Mini-batch gradient descent 不能保證很好的收斂性,

①learning rate 如果選擇的太小,收斂速度會很慢,如果太大,loss function 就會在極小值處不停地震蕩甚至偏離。

②有一種措施是先設定大一點的學習率,當兩次迭代之間的變化低于某個閾值后,就減小 learning rate,不過這個閾值的設定需要提前寫好,這樣的話就不能夠適應數據集的特點。此外,這種方法是對所有參數更新時應用同樣的 learning rate,如果我們的數據是稀疏的,我們更希望對出現頻率低的特征進行大一點的更新。

③另外,對于非凸函數,還要避免陷于局部極小值處,或者鞍點處,因為鞍點周圍的error 是一樣的,所有維度的梯度都接近于0,SGD 很容易被困在這里。

鞍點:一個光滑函數的鞍點鄰域的曲線,曲面,或超曲面,都位于這點的切線的不同邊。 
例如這個二維圖形,像個馬鞍:在x-軸方向往上曲,在y-軸方向往下曲,鞍點就是(0,0)

深度學習優化器 optimizer 的原理及選擇的圖5

為了應對上面的三點挑戰就有了下面這些算法。

[應對挑戰 1]

<span style="color:#000000"><code>4. Momentum(動量法)
</code></span>
  • 1

  • 2

SGD 在 ravinesravines 的情況下容易被困住, ravinesravines就是曲面的一個方向比另一個方向更陡,這時 SGD 會發生震蕩而遲遲不能接近極小值:

深度學習優化器 optimizer 的原理及選擇的圖6

梯度更新規則: 
Momentum 通過加入 γvt?1γvt?1 ,可以加速 SGD, 并且抑制震蕩 

vt=γvt?1+α?θJ(θ)vt=γvt?1+α?θJ(θ)

 

θ=θ?vtθ=θ?vt


當我們將一個小球從山上滾下來時,沒有阻力的話,它的動量會越來越大,但是如果遇到了阻力,速度就會變小。 
加入的這一項,可以使得梯度方向不變的維度上速度變快,梯度方向有所改變的維度上的更新速度變慢,這樣就可以加快收斂并減小震蕩。

 

超參數設定值: 
一般 γγ取值 0.9 左右。

缺點: 
這種情況相當于小球從山上滾下來時是在盲目地沿著坡滾,如果它能具備一些先知,例如快要上坡時,就知道需要減速了的話,適應性會更好。

<span style="color:#000000"><code>5. Nesterov accelerated gradient(NAG)
</code></span>
  • 1

  • 2

梯度更新規則: 
用 θ?γvt?1θ?γvt?1來近似當做參數下一步會變成的值,則在計算梯度時,不是在當前位置,而是未來的位置上 

vt=γvt?1+α?θJ(θ?γvt?1)vt=γvt?1+α?θJ(θ?γvt?1)

 

θ=θ?vtθ=θ?vt


超參數設定值: 
γγ仍然取值 0.9 左右。

 

效果比較: 
深度學習優化器 optimizer 的原理及選擇的圖7

藍色是 Momentum 的過程,會先計算當前的梯度,然后在更新后的累積梯度后會有一個大的跳躍。 
而 NAG 會先在前一步的累積梯度上(brown vector)有一個大的跳躍,然后衡量一下梯度做一下修正(red vector),這種預期的更新可以避免我們走的太快。

NAG 可以使 RNN 在很多任務上有更好的表現。

目前為止,我們可以做到,在更新梯度時順應 loss function 的梯度來調整速度,并且對 SGD 進行加速。

我們還希望可以根據參數的重要性而對不同的參數進行不同程度的更新。

[應對挑戰 2]

<span style="color:#000000"><code>6. Adagrad
</code></span>
  • 1

  • 2

這個算法就可以對低頻的參數做較大的更新,對高頻的做較小的更新,也因此,對于稀疏的數據它的表現很好,很好地提高了 SGD 的魯棒性,例如識別 Youtube 視頻里面的貓,訓練 GloVe word embeddings,因為它們都是需要在低頻的特征上有更大的更新。

梯度更新規則: 

θt+1,i=θt,i?αGt,ii+????????√gt,iθt+1,i=θt,i?αGt,ii+?gt,i

 

其中gt,igt,i為:t 時刻參數 θiθi的梯度;GtGt是個對角矩陣, (i,i) 元素就是 t 時刻參數 θiθi 的梯度gt,igt,i的平方和。

Adagrad 的優點是減少了學習率的手動調節

超參數設定值: 
一般 η 就取 0.01。

缺點: 
它的缺點是分母會不斷積累,這樣學習率就會收縮并最終會變得非常小。

<span style="color:#000000"><code>7. Adadelta
</code></span>
  • 1

  • 2

這個算法是對 Adagrad 的改進, 

Δθt=?αE[g2]t+?????????√gtΔθt=?αE[g2]t+?gt


和 Adagrad 相比,就是分母的GG換成了過去的梯度平方E[g2]tE[g2]t的衰減平均值。

 

這個分母相當于梯度的均方根 root mean squared (RMS) ,所以可以用 RMS 簡寫: 

Δθt=?αRMS[g]tgtΔθt=?αRMS[g]tgt

 

其中 E 的計算公式如下,t 時刻的依賴于前一時刻的平均和當前的梯度:

 

E[g2]t=γE[g2]t?1+(1?γ)g2tE[g2]t=γE[g2]t?1+(1?γ)gt2

 

梯度更新規則:

此外,還將學習率 αα換成了 RMS[Δθ]RMS[Δθ],這樣的話,我們甚至都不需要提前設定學習率了: 
深度學習優化器 optimizer 的原理及選擇的圖8

超參數設定值: 
γ 一般設定為 0.9,

<span style="color:#000000"><code>7. RMSprop
</code></span>
  • 1

  • 2

RMSprop 是 Geoff Hinton 提出的一種自適應學習率方法。

RMSprop 和 Adadelta 都是為了解決 Adagrad 學習率急劇下降問題的。

梯度更新規則: 
RMSprop 與 Adadelta 的第一種形式相同: 

E[g2]t=0.9E[g2]t?1+0.1g2tE[g2]t=0.9E[g2]t?1+0.1gt2

 

θt+1=θt?αE[g2]t+?????????√gtθt+1=θt?αE[g2]t+?gt

 

超參數設定值: 
Hinton 建議設定 γγ為 0.9, 學習率 αα為 0.001。

<span style="color:#000000"><code>8. Adam
</code></span>
  • 1

  • 2

這個算法是另一種計算每個參數的自適應學習率的方法。目前在DL領域,是最常見的優化器。

除了像 Adadelta 和 RMSprop 一樣存儲了過去梯度的平方 vtvt 的指數衰減平均值 ,也像 momentum 一樣保持了過去梯度 mtmt的指數衰減平均值: 
深度學習優化器 optimizer 的原理及選擇的圖9

如果 mtmt和 vtvt 被初始化為 0 向量,那它們就會向 0 偏置,所以做了偏差校正, 
通過計算偏差校正后的 mt 和 vt 來抵消這些偏差: 
深度學習優化器 optimizer 的原理及選擇的圖10

梯度更新規則: 

θt+1=θt?αvt+??????√mtθt+1=θt?αvt+?mt

 

超參數設定值: 
建議 β1 = 0.9,β2 = 0.999,? = 10e?8

實踐表明,Adam 比其他適應性學習方法效果要好。

深度學習優化器 optimizer 的原理及選擇的圖11深度學習優化器 optimizer 的原理及選擇的圖12效果比較?

下面看一下幾種算法在鞍點和等高線上的表現: 
深度學習優化器 optimizer 的原理及選擇的圖13 
深度學習優化器 optimizer 的原理及選擇的圖14 
上面兩種情況都可以看出,Adagrad, Adadelta, RMSprop 幾乎很快就找到了正確的方向并前進,收斂速度也相當快,而其它方法要么很慢,要么走了很多彎路才找到。

由圖可知自適應學習率方法即 Adagrad, Adadelta, RMSprop, Adam 在這種情景下會更合適而且收斂性更好。

深度學習優化器 optimizer 的原理及選擇的圖15深度學習優化器 optimizer 的原理及選擇的圖16如何選擇?

如果數據是稀疏的,就用自適應方法,即 Adagrad, Adadelta, RMSprop, Adam。

RMSprop, Adadelta, Adam 在很多情況下的效果是相似的。

Adam 就是在 RMSprop 的基礎上加了 bias-correction 和 momentum。

隨著梯度變的稀疏,Adam 比 RMSprop 效果會好。

整體來講,Adam 是最好的選擇。

很多論文里都會用 SGD,沒有 momentum 等。SGD 雖然能達到極小值,但是比其它算法用的時間長,而且可能會被困在鞍點。

如果需要更快的收斂,或者是訓練更深更復雜的神經網絡,需要用一種自適應的算法。

深度學習優化器 optimizer 的原理及選擇的圖17深度學習優化器 optimizer 的原理及選擇的圖18參考:

http://sebastianruder.com/optimizing-gradient-descent/index.html#fn:24 
http://www.redcedartech.com/pdfs/Select_Optimization_Method.pdf 
https://stats.stackexchange.com/questions/55247/how-to-choose-the-right-optimization-algorithm

登錄后免費查看全文
立即登錄
App下載
技術鄰APP
工程師必備
  • 項目客服
  • 培訓客服
  • 平臺客服

TOP