簡單認識Adam優化器

簡單認識Adam優化器

基於隨機梯度下降(SGD)的優化演算法在科研和工程的很多領域裡都是極其核心的。很多理論或工程問題都可以轉化為對目標函數進行最小化的數學問題。

按吳恩達老師所說的,梯度下降(Gradient Descent)就好比一個人想從高山上奔跑到山谷最低點,用最快的方式(steepest)奔向最低的位置(minimum)。

SGD基本公式

動量(Momentum)

動量演算法收斂圖

參考鏈接:https://distill.pub/2017/momentum/

基本的mini-batch SGD優化演算法在深度學習取得很多不錯的成績。然而也存在一些問題需解決:

1. 選擇恰當的初始學習率很困難。

2. 學習率調整策略受限於預先指定的調整規則。

3. 相同的學習率被應用於各個參數。

4. 高度非凸的誤差函數的優化過程,如何避免陷入大量的局部次優解或鞍點。

自適應優化

AdaGrad

針對簡單的SGD及Momentum存在的問題,2011年John Duchi等發布了AdaGrad優化演算法(Adaptive Gradient,自適應梯度),它能夠對每個不同的參數調整不同的學習率,對頻繁變化的參數以更小的步長進行更新,而稀疏的參數以更大的步長進行更新。

公式:

g_{t} 表示第t時間步的梯度(向量,包含各個參數對應的偏導數, g_{t,i} 表示第i個參數t時刻偏導數)

g_{t}^{2} 表示第t時間步的梯度平方(向量,由 g_{t} 各元素自己進行平方運算所得,即Element-wise)

與SGD的核心區別在於計算更新步長時,增加了分母:梯度平方累積和的平方根。此項能夠累積各個參數 g_{t,i} 的歷史梯度平方,頻繁更新的梯度,則累積的分母項逐漸偏大,那麼更新的步長(stepsize)相對就會變小,而稀疏的梯度,則導致累積的分母項中對應值比較小,那麼更新的步長則相對比較大。

AdaGrad能夠自動為不同參數適應不同的學習率(平方根的分母項相當於對學習率α進進行了自動調整,然後再乘以本次梯度),大多數的框架實現採用默認學習率α=0.01即可完成比較好的收斂。

優勢:在數據分布稀疏的場景,能更好利用稀疏梯度的信息,比標準的SGD演算法更有效地收斂。

缺點:主要缺陷來自分母項的對梯度平方不斷累積,隨之時間步地增加,分母項越來越大,最終導致學習率收縮到太小無法進行有效更新。

RMSProp

RMSProp是Geoffrey Hinton教授在教案中提到的演算法,結合梯度平方的指數移動平均數來調節學習率的變化。能夠在不穩定(Non-Stationary)的目標函數情況下進行很好地收斂。

Hinton教授講述RMSProp演算法的材料:

cs.toronto.edu/~tijmen/

計算t時間步的梯度:

計算梯度平方的指數移動平均數(Exponential Moving Average),γ是遺忘因子(或稱為指數衰減率),依據經驗,默認設置為0.9。

梯度更新時候,與AdaGrad類似,只是更新的梯度平方的期望(指數移動均值),其中ε=10^-8,避免除數為0。默認學習率α=0.001。

優勢:能夠克服AdaGrad梯度急劇減小的問題,在很多應用中都展示出優秀的學習率自適應能力。尤其在不穩定(Non-Stationary)的目標函數下,比基本的SGD、Momentum、AdaGrad表現更良好。

Adam優化器

2014年12月, Kingma和Lei Ba兩位學者提出了Adam優化器,結合AdaGrad和RMSProp兩種優化演算法的優點。對梯度的一階矩估計(First Moment Estimation,即梯度的均值)和二階矩估計(Second Moment Estimation,即梯度的未中心化的方差)進行綜合考慮,計算出更新步長。

主要包含以下幾個顯著的優點:

  1. 實現簡單,計算高效,對內存需求少
  2. 參數的更新不受梯度的伸縮變換影響
  3. 超參數具有很好的解釋性,且通常無需調整或僅需很少的微調
  4. 更新的步長能夠被限制在大致的範圍內(初始學習率)
  5. 能自然地實現步長退火過程(自動調整學習率)
  6. 很適合應用於大規模的數據及參數的場景
  7. 適用於不穩定目標函數
  8. 適用於梯度稀疏或梯度存在很大雜訊的問題

綜合Adam在很多情況下算作默認工作性能比較優秀的優化器。

Adam實現原理

演算法偽代碼:

Adam更新規則

計算t時間步的梯度:

首先,計算梯度的指數移動平均數,m0 初始化為0。

類似於Momentum演算法,綜合考慮之前時間步的梯度動量。

β1 係數為指數衰減率,控制權重分配(動量與當前梯度),通常取接近於1的值。

默認為0.9

下圖簡單展示出時間步1~20時,各個時間步的梯度隨著時間的累積佔比情況。

其次,計算梯度平方的指數移動平均數,v0初始化為0。

β2 係數為指數衰減率,控制之前的梯度平方的影響情況。

類似於RMSProp演算法,對梯度平方進行加權均值。

默認為0.999

第三,由於m0初始化為0,會導致mt偏向於0,尤其在訓練初期階段。

所以,此處需要對梯度均值mt進行偏差糾正,降低偏差對訓練初期的影響。

第四,與m0 類似,因為v0初始化為0導致訓練初始階段vt 偏向0,對其進行糾正。

第五,更新參數,初始的學習率α乘以梯度均值 與梯度方差 的平方根之比。

其中默認學習率α=0.001

ε=10^-8,避免除數變為0。

由表達式可以看出,對更新的步長計算,能夠從梯度均值及梯度平方兩個角度進行自適應地調節,而不是直接由當前梯度決定。

Adam代碼實現

演算法思路很清晰,實現比較直觀:

class Adam: def __init__(self, loss, weights, lr=0.001, beta1=0.9, beta2=0.999, epislon=1e-8): self.loss = loss self.theta = weights self.lr = lr self.beta1 = beta1 self.beta2 = beta2 self.epislon = epislon self.get_gradient = grad(loss) self.m = 0 self.v = 0 self.t = 0 def minimize_raw(self): self.t += 1 g = self.get_gradient(self.theta) self.m = self.beta1 * self.m + (1 - self.beta1) * g self.v = self.beta2 * self.v + (1 - self.beta2) * (g * g) self.m_hat = self.m / (1 - self.beta1 ** self.t) self.v_hat = self.v / (1 - self.beta2 ** self.t) self.theta -= self.lr * self.m_hat / (self.v_hat ** 0.5 + self.epislon) def minimize(self): self.t += 1 g = self.get_gradient(self.theta) lr = self.lr * (1 - self.beta2 ** self.t) ** 0.5 / (1 - self.beta1 ** self.t) self.m = self.beta1 * self.m + (1 - self.beta1) * g self.v = self.beta2 * self.v + (1 - self.beta2) * (g * g) self.theta -= lr * self.m / (self.v ** 0.5 + self.epislon)

dream-catcher/learning_blogs?

github.com圖標

Adam可視化

下面以Beale function為例,簡單演示Adam優化器的優化路徑。

https://en.wikipedia.org/wiki/Test_functions_for_optimization?

en.wikipedia.org圖標

dream-catcher/learning_blogs?

github.com圖標

Adam缺陷及改進

雖然Adam演算法目前成為主流的優化演算法,不過在很多領域裡(如計算機視覺的對象識別、NLP中的機器翻譯)的最佳成果仍然是使用帶動量(Momentum)的SGD來獲取到的。Wilson 等人的論文結果顯示,在對象識別、字元級別建模、語法成分分析等方面,自適應學習率方法(包括AdaGrad、AdaDelta、RMSProp、Adam等)通常比Momentum演算法效果更差。

針對Adam等自適應學習率方法的問題,主要兩個方面的改進:

1、解耦權重衰減

在每次更新梯度時,同時對其進行衰減(衰減係數w略小於1),避免產生過大的參數。

在Adam優化過程中,增加參數權重衰減項。解耦學習率和權重衰減兩個超參數,能單獨調試優化兩個參數。

2、修正指數移動均值

最近的幾篇論文顯示較低的β_2(如0.99或0.9)能夠獲得比默認值0.999更佳的結果,暗示出指數移動均值本身可能也包含了缺陷。例如在訓練過程中,某個mini-batch出現比較大信息量的梯度信息,但由於這類mini-batch出現頻次很少,而指數移動均值會減弱他們的作用(因為當前梯度權重 及當前梯度的平方的權重 ,權重都比較小),導致在這種場景下收斂比較差。

openreview.net/pdf?

論文作者提出Adam的變形演算法AMSGrad。

AMSGrad 使用最大的 來更新梯度,而不像Adam演算法中採用歷史 的指數移動均值來實現。作者在小批量數據集及CIFAR-10上觀察到比Adam更佳的效果。

參考文章:

An overview of gradient descent optimization algorithms?

ruder.io圖標Optimization for Deep Learning Highlights in 2017?

ruder.io

http://louistiao.me/notes/visualizing-and-animating-optimization-algorithms-with-matplotlib/?

louistiao.me


推薦閱讀:

一些應用領域看到的問題
【優化演算法】一文搞懂RMSProp優化演算法
如何優化WaitForGPU?
如何在工程實踐中簡單地體驗一把AlphaGo般的智慧?
SD-WAN技術分享

TAG:深度學習DeepLearning | 優化 |