梯度下降優化算法

原文:An overview of gradient descent optimization algorithms

梯度下降算法

梯度下降算法(Gradient Descent Optimization)是神經網絡模型訓練最常用的優化算法。詳見:梯度下降

梯度下降算法的原理:

  • 目標函數 J(θ)J(\theta) 關於參數 θ\theta 的梯度將是損失函數(loss function)上升最快的方向。

  • 要最小化 loss,只需要將參數沿着梯度相反的方向前進一個步長,就可以實現目標函數(loss function)的下降。這個步長 η\eta 又稱爲學習速率。

  • 參數更新公式如下:

    θθηJ(θ)\theta\leftarrow \theta-\eta \cdot \nabla J(\theta)

  • 其中 J(θ)\nabla J(\theta) 是參數的梯度。

根據計算目標函數採用數據量的不同,梯度下降算法又可以分爲:

  • 批量梯度下降算法(Batch Gradient Descent,BGD)

    J(θ)J(\theta) 是在整個訓練集上計算的,如果數據集比較大,可能會面臨內存不足問題,而且收斂速度一般比較慢。

  • 隨機梯度下降算法(Stochastic Gradient Descent,SGD)

    又稱爲在線學習,即得到了一個樣本,就可以執行一次參數更新。所以其收斂速度會快一些,但是有可能出現目標函數值震盪現象,因爲高頻率的參數更新導致了高方差。

  • 小批量梯度下降算法(Mini-batch Gradient Descent,MBGD)。

    是折中方案,選取訓練集中一個小批量樣本(一般是2的倍數,如32,64,128等)計算,這樣可以保證訓練過程更穩定,而且採用批量訓練方法也可以利用矩陣計算的優勢,是目前最常用的梯度下降算法。

問題與挑戰:

  • 選擇一個合適的學習率可能是困難的。學習率太小會導致收斂的速度很慢,學習率太大會妨礙收斂,導致損失函數在最小值附近震盪甚至發散。

  • 雖然可以通過退火等方法調整學習率,但策略和閾值需要預先設定好,因此無法適應數據集的特點。

  • 另一方面,SGD 不易處理鞍點處的梯度。由於鞍點周圍的誤差相同,梯度在所有方向都接近於0,導致 SGD 很難脫離鞍點。

Momentum

  • SGD(指上面的三種方法)的參數更新完全依賴於當前的 batch,容易出現震盪現象

  • 動量(Momentum optimization) 通過將當前時刻的梯度 ηθJ(θ)\eta \nabla_\theta J( \theta),與前一時刻的梯度 vt1v_{t-1} 按照動量的係數 γγ 進行加權,使得當前的更新方向包括當前梯度的方向與之前時刻梯度的方向,來增加更新的穩定性,同時抑制 SGD 的震盪現象。

vt=γvt1+ηθJ(θ)v_t = \gamma v_{t-1} + \eta \nabla_\theta J( \theta)

θ=θvt\theta = \theta - v_t

  • 動量的係數 γγ 表示保留原來方向的程度,通常設置爲 0.9 左右。

  • 當梯度指向收斂方向時,動量加快更新速度;當梯度改變方向時,動量降低更新速度。從而在保證收斂更快的同時,減弱震盪現象。

NAG

  • NAG 即 Nesterov accelerated gradient 涅斯捷羅夫梯度加速。相比於momentum,NAG 增加了一個將要去哪裏的指示,因而在曲面上升時,能夠降低更新速度。

  • NAG 在計算參數的梯度時,在損失函數中減去了動量項,即計算 θJ(θγνt1)\nabla_{\theta}J(\theta-\gamma \nu_{t-1}),這種方式預估了下一次參數所在的近似位置。即:

νt=γνt1+ηθJ(θγνt1)\nu_t=\gamma\nu_{t-1}+\eta \cdot \nabla_{\theta}J(\theta-\gamma \nu_{t-1})

θ=θνt\theta=\theta-\nu_t

  • 動量係數 γγ 通常設置爲 0.9 左右。

  • 在 Momentum 中,首先計算當前梯度項(小藍色向量),然後加上動量項,這樣便得到了大的跳躍(大藍色的向量)。

  • NAG 首先進行一個大的跳躍(動量項)(棕色向量),然後加上一個小的使用了動量計算的當前梯度(紅色向量)進行修正得到綠色的向量,避免更新過猛。

Adagrad

  • Adagrad 即 Adaptive Gradient Algorithm 自適應梯度算法。

  • 上面的方法在參數更新過程中,使用了固定的學習率。Adagrad 則是讓學習率適應參數。

  • 對於出現次數較少的特徵,對其採用更大的學習率,對於出現次數較多的特徵,對其採用較小的學習率。因而適用於處理稀疏數據。

  • gt,ig_{t, i} 爲在 tt 時刻目標函數關於參數 θi\theta_i 的梯度:

    gt,i=θJ(θi)g_{t, i} = \nabla_\theta J( \theta_i )

  • 通常,在 tt 時刻,對參數 θi\theta_i 的更新過程爲:

    θt+1,i=θt,iηgt,i\theta_{t+1, i} = \theta_{t, i} - \eta \cdot g_{t, i}

  • 使用 Adagrad 時,在 tt 時刻,基於對 θi\theta_i 計算過的歷史梯度,對每一個參數 θi\theta_i 的學習率進行了修正:

    θt+1,i=θt,iηGt,ii+ϵgt,i\theta_{t+1, i} = \theta_{t, i} - \dfrac{\eta}{\sqrt{G_{t, ii} + \epsilon}} \cdot g_{t, i}

  • 其中,GtRd×dG_{t} \in \mathbb{R}^{d \times d} 是一個對角矩陣。

  • ii 行的對角元素 eiie_{ii} 爲第 ii 個參數 θi\theta_i 的歷史梯度的平方和。

  • ϵ\epsilon 是一個平滑參數,爲了使得分母不爲 0 (通常 ϵ\epsilone8e−8 )。

  • 另外如果分母不開根號,算法性能會很糟糕。

  • 再進一步,將所有 Gt,ii,gt,iG_{t,ii},g_{t,i} 的元素寫成向量 Gt,gtG_t,g_t , Adagrad 算法參數更新的矩陣形式如下:

θt+1=θtηGt+ϵgt\theta_{t+1} = \theta_{t} - \frac{\eta}{\sqrt{G_{t}+\epsilon}} \odot g_{t}

  • 其中 ⊙ 爲點乘,即矩陣對應元素相乘。

  • Adagrad 的優點是無需手動調整學習率。在大多數的應用場景中,通常採用常數0.01。

  • Adagrad的缺點是它在分母中累加梯度的平方,在整個訓練過程中,累加的和會持續增長,導致學習率最終變得無限小,無法學習到新的特徵。

Adadelta

  • Adadelta 是 Adagrad 的一種擴展算法,以處理 Adagrad 學習速率單調遞減的問題。

  • Adadelta 只計算窗口大小爲 ww 的最近歷史梯度,同時,並不存儲歷史平方梯度值,而是將梯度的平方遞歸地表示成所有歷史梯度平方的均值。

  • tt 時刻的均值 E[g2]tE[g^2]_t 只取決於先前的均值和當前的梯度(分量γγ 類似於動量項):

    E[g2]t=γE[g2]t1+(1γ)gt2E[g^2]_t = \gamma E[g^2]_{t-1} + (1 - \gamma) g^2_t

  • 在 Adagrad 中梯度更新值爲:

    Δθt=ηGt+ϵgt\Delta \theta_t = - \dfrac{\eta}{\sqrt{G_{t} + \epsilon}} \odot g_{t}

  • 在 Adadelta 中梯度更新值爲:

    Δθt=ηE[g2]t+ϵgt\Delta \theta_t = - \dfrac{\eta}{\sqrt{E[g^2]_t + \epsilon}} g_{t}

  • 由於分母僅僅是梯度的均方根(root mean squared,RMS)誤差,可以簡寫爲:

    Δθt=ηRMS[g]tgt\Delta \theta_t = - \dfrac{\eta}{RMS[g]_{t}} g_t

  • 將上面公式改成關於 θtθ_t 的:

    E[Δθ2]t=γE[Δθ2]t1+(1γ)Δθt2E{{\left[ \Delta {{\theta }^{2}} \right]}_{t}}=\gamma E{{\left[ \Delta {{\theta }^{2}} \right]}_{t-1}}+(1-\gamma )\Delta \theta _{t}^{2}

  • 參數更新的均方根誤差爲:

    RMS[Δθ]t=E[Δθ2]t+ϵRMS[\Delta \theta]_{t} = \sqrt{E[\Delta \theta^2]_t + \epsilon}

  • 由於 RMS[Δθ]tRMS[\Delta \theta]_{t} 未知,使用之前時刻的 RMS 值 RMS[Δθ]t1RMS[\Delta \theta]_{t-1} 替換先前的更新規則中的學習率 ηη。最終的 Adadelta 更新公式爲:

    Δθt=RMS[Δθ]t1RMS[g]tgt\Delta \theta_t = - \dfrac{RMS[\Delta \theta]_{t-1}}{RMS[g]_{t}} g_{t}

    θt+1=θt+Δθt\theta_{t+1} = \theta_t + \Delta \theta_t

  • 使用 Adadelta 算法,無需設置默認的學習率,因爲更新規則中已經移除了學習率。

RMSprop

  • RMSprop 未發表,但是也是自適應學習率的算法,由Geoff Hinton提出。

  • RMSprop 和 Adadelta 在相同的時間裏被獨立的提出,都起源於對Adagrad 的極速遞減的學習率問題的求解。

  • 實際上,RMSprop 是 Adadelta 的第一個更新向量的特例:

    E[g2]t=0.9E[g2]t1+0.1gt2E[g^2]_t = 0.9 E[g^2]_{t-1} + 0.1 g^2_t

    θt+1=θtηE[g2]t+ϵgt\theta_{t+1} = \theta_{t} - \dfrac{\eta}{\sqrt{E[g^2]_t + \epsilon}} g_{t}

  • 同樣,RMSprop 將學習率分解成一個平方梯度的指數衰減的平均。Hinton 建議將 γγ 設置爲 0.9,對於學習率 ηη,一個好的固定值爲0.001。

Adam

  • Adam 即 Adaptive Moment Estimation 自適應矩估計,是另一種自適應學習率的算法,Adam對每一個參數都計算自適應的學習率。

  • 除了像 Adadelta 和 RMSprop一樣存儲一個指數衰減的歷史平方梯度的平均 vtv_t,Adam 同時還保存一個歷史梯度的指數衰減均值 mtm_t,類似於動量:

    mt=β1mt1+(1β1)gtm_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t

    vt=β2vt1+(1β2)gt2v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2

  • mtm_tvtv_t 分別是對梯度的一階矩(均值)和二階矩(非確定的方差)的估計,正如該算法的名稱。

  • Adam 的作者發現當衰減率(decay rate)很小時(β1β_1β2β_2 接近於 1),mtm_tvtv_t 最終都趨於0,因而Adam算法最終對一階矩和二階矩進行校正(β1β_1β2β_2 的上標 tt 代表 tt 次方):

    m^t=mt1β1t\hat{m}_t = \dfrac{m_t}{1 - \beta^t_1}

    v^t=vt1β2t\hat{v}_t = \dfrac{v_t}{1 - \beta^t_2}

  • 最終 Adam 的更新規則爲:

    θt+1=θtηv^t+ϵm^t\theta_{t+1} = \theta_{t} - \dfrac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t

  • 作者建議 $β_1 取默認值爲 0.9, β2β_2 爲0.999,ϵϵ10810^{−8}

算法的選擇

  • 如果輸入數據是稀疏的,選擇任一自適應學習率算法可能會得到最好的結果。選用這類算法的另一個好處是無需調整學習率,選用默認值就可能達到最好的結果。

  • RMSprop 是 Adagrad 的擴展形式,用於處理在 Adagrad 中急速遞減的學習率。

  • RMSprop 與 Adadelta 相同,所不同的是 Adadelta 在更新規則中使用參數的均方根進行更新。

  • Adam 是將偏差校正和動量加入到 RMSprop 中。

  • 在這樣的情況下,RMSprop、Adadelta 和 Adam 是很相似的算法並且在相似的環境中性能都不錯。在優化後期由於梯度變得越來越稀疏,偏差校正能夠幫助Adam微弱地勝過 RMSprop。

  • 綜合看來,Adam可能是最佳的選擇。

  • 有趣的是,最近許多論文中採用不帶動量的 SGD 和一種簡單的學習率的退火策略。通常 SGD 能夠找到最小值點,但是比其他優化的 SGD 花費更多的時間,與其他算法相比,SGD 更加依賴魯棒的初始化和退火策略,同時,SGD 可能會陷入鞍點,而不是局部極小值點。

  • 因此,如果想要快速收斂和訓練一個深層的或者複雜的神經網絡,可以選擇一個自適應學習率的方法。

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