【深度學習】深刻理解優化器Optimizer算法(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)

在機器學習、深度學習中使用的優化算法除了常見的梯度降低,還有 Adadelta,Adagrad,RMSProp 等幾種優化器,都是什麼呢,又該怎麼選擇呢?html

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

本文將梳理:網絡

  • 每一個算法的梯度更新規則和缺點
  • 爲了應對這個不足而提出的下一個算法
  • 超參數的通常設定值
  • 幾種算法的效果比較
  • 選擇哪一種算法

0.梯度降低法深刻理解

如下爲我的總結,若有錯誤之處,各位前輩請指出。dom

對於優化算法,優化的目標是網絡模型中的參數θ(是一個集合,θ1θ2θ3 ......)目標函數爲損失函數L = 1/N ∑ L(每一個樣本損失函數的疊加求均值)。這個損失函數L變量就是θ,其中L中的參數是整個訓練集,換句話說,目標函數(損失函數)是經過整個訓練集來肯定的,訓練集全集不一樣,則損失函數的圖像也不一樣。那麼爲什麼在mini-batch中若是遇到鞍點/局部最小值點就沒法進行優化了呢?由於在這些點上,L對於θ的梯度爲零,換句話說,對θ每一個份量求偏導數,帶入訓練集全集,導數爲零。對於SGD/MBGD而言,每次使用的損失函數只是經過這一個小批量的數據肯定的,其函數圖像與真實全集損失函數有所不一樣,因此其求解的梯度也含有必定的隨機性,在鞍點或者局部最小值點的時候,震盪跳動,由於在此點處,若是是訓練集全集帶入即BGD,則優化會中止不動,若是是mini-batch或者SGD,每次找到的梯度都是不一樣的,就會發生震盪,來回跳動。機器學習


一.優化器算法簡述

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

 1.Batch Gradient Descent (BGD)

梯度更新規則:學習

BGD 採用整個訓練集的數據來計算 cost function 對參數的梯度:優化

 

缺點:lua

因爲這種方法是在一次更新中,就對整個數據集計算梯度,因此計算起來很是慢,遇到很大量的數據集也會很是棘手,並且不能投入新數據實時更新模型。spa

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

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

Batch gradient descent 對於凸函數能夠收斂到全局極小值,對於非凸函數能夠收斂到局部極小值。

2.Stochastic Gradient Descent (SGD)

梯度更新規則:

和 BGD 的一次用全部數據計算梯度相比,SGD 每次更新時對每一個樣本進行梯度更新,對於很大的數據集來講,可能會有類似的樣本,這樣 BGD 在計算梯度時會出現冗餘,而 SGD 一次只進行一次更新,就沒有冗餘,並且比較快,而且能夠新增樣本。

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 

 看代碼,能夠看到區別,就是總體數據集是個循環,其中對每一個樣本進行一次參數更新。

 

隨機梯度降低是經過每一個樣原本迭代更新一次,若是樣本量很大的狀況,那麼可能只用其中部分的樣本,就已經將theta迭代到最優解了,對比上面的批量梯度降低,迭代一次須要用到十幾萬訓練樣本,一次迭代不可能最優,若是迭代10次的話就須要遍歷訓練樣本10次。缺點是SGD的噪音較BGD要多,使得SGD並非每次迭代都向着總體最優化方向因此雖然訓練速度快,可是準確度降低,並非全局最優雖然包含必定的隨機性,可是從指望上來看,它是等於正確的導數的。

缺點:

SGD 由於更新比較頻繁,會形成 cost function 有嚴重的震盪。

BGD 能夠收斂到局部極小值,固然 SGD 的震盪可能會跳到更好的局部極小值處。

當咱們稍微減少 learning rate,SGD 和 BGD 的收斂性是同樣的。

3.Mini-Batch Gradient Descent (MBGD)

梯度更新規則:

MBGD 每一次利用一小批樣本,即 n 個樣本進行計算,這樣它能夠下降參數更新時的方差,收斂更穩定,另外一方面能夠充分地利用深度學習庫中高度優化的矩陣操做來進行更有效的梯度計算。

和 SGD 的區別是每一次循環不是做用於每一個樣本,而是具備 n 個樣本的批次。

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 

 超參數設定值:  n 通常取值在 50~256

缺點:(兩大缺點)

  1. 不過 Mini-batch gradient descent 不能保證很好的收斂性,learning rate 若是選擇的過小,收斂速度會很慢,若是太大,loss function 就會在極小值處不停地震盪甚至偏離。(有一種措施是先設定大一點的學習率,當兩次迭代之間的變化低於某個閾值後,就減少 learning rate,不過這個閾值的設定須要提早寫好,這樣的話就不可以適應數據集的特色。)對於非凸函數,還要避免陷於局部極小值處,或者鞍點處,由於鞍點周圍的error是同樣的,全部維度的梯度都接近於0,SGD 很容易被困在這裏。會在鞍點或者局部最小點震盪跳動,由於在此點處,若是是訓練集全集帶入即BGD,則優化會中止不動,若是是mini-batch或者SGD,每次找到的梯度都是不一樣的,就會發生震盪,來回跳動。
  2. SGD對全部參數更新時應用一樣的 learning rate,若是咱們的數據是稀疏的,咱們更但願對出現頻率低的特徵進行大一點的更新。LR會隨着更新的次數逐漸變小。

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

 

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


 前期知識:指數加權平均,請參看博文《什麼是指數加權平均、誤差修正?》

[應對挑戰 1]

4.Momentum

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

 

梯度更新規則:

 Momentum 經過加入 γ*vt−1 ,能夠加速 SGD, 而且抑制震盪

 

當咱們將一個小球從山上滾下來時,沒有阻力的話,它的動量會愈來愈大,可是若是遇到了阻力,速度就會變小。
加入的這一項,可使得梯度方向不變的維度上速度變快,梯度方向有所改變的維度上的更新速度變慢,這樣就能夠加快收斂並減少震盪。

超參數設定值:  通常 γ 取值 0.9 左右。

缺點:

這種狀況至關於小球從山上滾下來時是在盲目地沿着坡滾,若是它能具有一些先知,例如快要上坡時,就知道須要減速了的話,適應性會更好。

5.Nesterov Accelerated Gradient

梯度更新規則:

用 θ−γv_t−1 來近似當作參數下一步會變成的值,則在計算梯度時,不是在當前位置,而是將來的位置上

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

效果比較:

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

NAG 可使 RNN 在不少任務上有更好的表現。

目前爲止,咱們能夠作到,在更新梯度時順應 loss function 的梯度來調整速度,而且對 SGD 進行加速

咱們還但願能夠根據參數的重要性而對不一樣的參數進行不一樣程度的更新。


[應對挑戰 2]

 6.Adagrad (Adaptive gradient algorithm)

 這個算法就能夠對低頻的參數作較大的更新對高頻的作較小的更新,也所以,對於稀疏的數據它的表現很好,很好地提升了 SGD 的魯棒性,例如識別 Youtube 視頻裏面的貓,訓練 GloVe word embeddings,由於它們都是須要在低頻的特徵上有更大的更新。

 梯度更新規則:

 

其中 g 爲:t 時刻參數 θ_i 的梯度

若是是普通的 SGD, 那麼 θ_i 在每一時刻的梯度更新公式爲:

但這裏的 learning rate η 也隨 t 和 i 而變:

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

Adagrad 的優勢是減小了學習率的手動調節

超參數設定值:通常η選取0.01

缺點:

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

7.Adadelta

這個算法是對 Adagrad 的改進,

和 Adagrad 相比,就是分母的 G 換成了過去的梯度平方的衰減平均值,指數衰減平均值

這個分母至關於梯度的均方根 root mean squared (RMS),在數據統計分析中,將全部值平方求和,求其均值,再開平方,就獲得均方根值 ,因此能夠用 RMS 簡寫:

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

梯度更新規則:

此外,還將學習率 η 換成了 RMS[Δθ],這樣的話,咱們甚至都不須要提早設定學習率了:

超參數設定值:  γ 通常設定爲 0.9

7.RMSprop

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

RMSprop 和 Adadelta 都是爲了解決 Adagrad 學習率急劇降低問題的

梯度更新規則:

RMSprop 與 Adadelta 的第一種形式相同:(使用的是指數加權平均,旨在消除梯度降低中的擺動,與Momentum的效果同樣,某一維度的導數比較大,則指數加權平均就大,某一維度的導數比較小,則其指數加權平均就小,這樣就保證了各維度導數都在一個量級,進而減小了擺動。容許使用一個更大的學習率η)

 

超參數設定值:

Hinton 建議設定 γ 爲 0.9, 學習率 η 爲 0.001。

8.Adam:Adaptive Moment Estimation

這個算法是另外一種計算每一個參數的自適應學習率的方法。至關於 RMSprop + Momentum

除了像 Adadelta 和 RMSprop 同樣存儲了過去梯度的平方 vt 的指數衰減平均值 ,也像 momentum 同樣保持了過去梯度 mt指數衰減平均值

若是 mt 和 vt 被初始化爲 0 向量,那它們就會向 0 偏置,因此作了誤差校訂,經過計算誤差校訂後的 mt 和 vt 來抵消這些誤差:

梯度更新規則:

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

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


 二.效果比較

下面看一下幾種算法在鞍點和等高線上的表現:

SGD optimization on saddle point

SGD optimization on saddle point

 SGD optimization on loss surface contours

上面兩種狀況均可以看出,Adagrad, Adadelta, RMSprop 幾乎很快就找到了正確的方向並前進,收斂速度也至關快,而其它方法要麼很慢,要麼走了不少彎路才找到。

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


三.如何選擇優化算法

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

RMSprop, Adadelta, Adam 在不少狀況下的效果是類似的。

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

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

總體來說,Adam 是最好的選擇

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

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

 

 


 

資料:
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

相關文章
相關標籤/搜索