深度學習優化算法總結——從SGD到Adam


本文參考自:SGD、Momentum、RMSprop、Adam區別與聯系

上一篇博客總結了一下隨機梯度下降、mini-batch梯度下降和batch梯度下降之間的區別,這三種都屬於在Loss這個level的區分,並且實際應用中也是mini-batch梯度下降應用的比較多。為了在實際應用中彌補這種朴素的梯度下降的一些缺陷,有許多另外的變種算法被提出,其中一些由於在許多情況下表現優秀而得到廣泛使用,包括Momentum、Nesterov Accelerated Gradient、Adagrad和Adam等。

梯度下降

利用梯度下降求解的時候遵循這樣一個模式,對於當前模型的參數 \(\boldsymbol{\theta}\),計算在訓練樣本上的損失 \(\boldsymbol{\theta}\),接下來計算損失函數 \(\boldsymbol{\theta}\) 關於參數 \(\boldsymbol{\theta}\) 的梯度 \(\nabla_{\boldsymbol{\theta}} J(\boldsymbol{\theta})\),接下來沿着 \(\nabla_{\boldsymbol{\theta}} J(\boldsymbol{\theta})\) 的反方向更新。再考慮到計算參數更新量的方式,可以將其一般化為下面這幾個步驟:
(1)計算損失函數關於參數 \(\boldsymbol{\theta}\) 的梯度:

\[\boldsymbol{g}_{t}=\nabla_{\boldsymbol{\theta}} J(\boldsymbol{\theta}) \]

(2)根據歷史梯度計算一階動量和二階動量:

\[\boldsymbol{m}_{t}=\phi\left(\boldsymbol{g}_{1}, \boldsymbol{g}_{2}, \cdots, \boldsymbol{g}_{t}\right) \]

\[\boldsymbol{V}_{t}=\psi\left(\boldsymbol{g}_{1}, \boldsymbol{g}_{2}, \cdots, \boldsymbol{g}_{t}\right) \]

(3)計算參數更新量,其中 \(\eta\) 為學習率,\(\varepsilon\)防止分母為0,通常取1e-8:

\[\Delta \boldsymbol{\theta}_{t}=\eta \cdot \frac{\boldsymbol{m}_{t}}{\sqrt{\boldsymbol{V}_{t}+\varepsilon}} \]

(4)進行參數更新:

\[\boldsymbol{\theta}_{t+1}=\boldsymbol{\theta}_{t}-\Delta \boldsymbol{\theta}_{t} \]

隨機梯度下降SGD

朴素的SGD中沒有動量的概念,即 \(\boldsymbol{m}_{t}=\boldsymbol{g}_{t}\)\(\boldsymbol{V}_{t}=\boldsymbol{I}\)\(\varepsilon=0\)。此時參數更新量就是\(\Delta \boldsymbol{\theta}_{t}=\eta \cdot \boldsymbol{g}_{t}\),即

\[\boldsymbol{\theta}_{t+1}=\boldsymbol{\theta}_{t}-\eta \cdot \boldsymbol{g}_{t} \]

SGD在下降過程中會出現震盪(即使通過mini-batch梯度下降能夠緩解),特別是容易陷入局部最優點或者是鞍點。

Momentum

Momentum借鑒了物理中動量的概念,能夠有效的加速學習速度。原因在於Momentum使用了歷史梯度的指數加權平均來調整參數更新方向,使得震盪方向的更新減慢,向最優解方向的更新加快,最終更快的收斂。Momentum使用了一階動量來實現這個目的:

\[\boldsymbol{m}_{t}=\beta_1\boldsymbol{m}_{t-1}+(1-\beta_1)\boldsymbol{g}_{t} \]

沒有使用二階動量\(\boldsymbol{V}_{t}=\boldsymbol{I}\)\(\varepsilon=0\)\(\beta_1\) 的經驗值是0.9,即當前時刻的下降方向主要有前一時刻的方向加上一點當前時刻的梯度方向得到。

Nesterov Accelerated Gradient

Nesterov Accelerated Gradient算法在損失函數有增大趨勢的時候減緩學習速率。下圖非常有助於理解

具體來說,NAG先沿着上一步的梯度更新一次參數(相當於估計下一次的近似位置),在更新后的位置重新計算梯度,然后用這個梯度值進行修正得到更新方向:

\[\boldsymbol{g}_{t}=\nabla_{\boldsymbol{\theta}} J(\boldsymbol{\theta}_{t}-\eta \cdot \frac{\boldsymbol{m}_{t-1}}{\sqrt{\boldsymbol{V}_{t-1}+\varepsilon}}) \]

接下來計算一階動量並計算參數的更新方向,更新參數(這一步同Momentum)。

Adagrad

前面的集中方法對於所有的參數都使用了相同的更新速率進行更新,但事實上在更新過程中可能有的參數已經進行了很大的更新,只需要微調即可。Adagrad算法就實現了這個功能,通過用某個參數的所有歷史梯度平方和來縮放其更新量,達到自適應的改變所有參數的學習率的目的。

\[\boldsymbol{V}_{t}=\sum_{\tau=1}^{t} \boldsymbol{g}_{\tau}^{2} \]

這樣歷史梯度平方和小的參數得到更大的學習率。其中一階動量使用梯度。
雖然Adagrad有一些較好的性質,但是在訓練深度神經網絡的時候往往會導致學習率衰減過量甚至在訓練后期衰減到0。

RMSprop

RMSprop算法由Hinton大師在Coursera課程上提出,解決了Adagrad學習率下降過快的問題,主要是改變了Adagrad中二階動量的計算方式,才用了類似於Momentum的指數移動平均的方式來計算二階動量:

\[\boldsymbol{V}_{t}=\beta_{2}\boldsymbol{V}_{t}+\left(1-\beta_{2}\right) \boldsymbol{g}_{t}^{2} \]

這樣不會出現由於歷史梯度平方和累計造成的學習率急劇下降的問題。Hinton建議 \(\beta_{2}=0.9\)

Adam

Adam = Adaptive + Momentum,顧名思義Adam集成了SGD的一階動量和RMSProp的二階動量。即:

\[\boldsymbol{m}_{t}=\beta_{1}\boldsymbol{m}_{t}+\left(1-\beta_{1}\right) \boldsymbol{g}_{t} \]

\[\boldsymbol{V}_{t}=\beta_{2}\boldsymbol{V}_{t}+\left(1-\beta_{2}\right) \boldsymbol{g}_{t}^{2} \]

感覺是除了SGD之外我這個菜鳥在程序中見到的最多的優化方式了。\(\beta_{1}\)\(\beta_{2}\) 也不用多說了,一個用來修正一階動量,一個用來修正二階動量。

參考資料:

https://zhuanlan.zhihu.com/p/32488889
https://zhuanlan.zhihu.com/p/32626442


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM