神經網絡中的優化器 (tensorflow2.0)


在定義了損失函數之后,需要通過優化器來尋找最小損失,下面介紹一些常見的優化方法。

(BGD,SGD,MBGD,Momentum,NAG,Adagrad,Adadelta,RMSprop,Adam,Adamax,Nadam)

1 梯度下降法 (Gradient Descent,GD)

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

  BGD 是梯度下降法最基礎的形式,每次迭代更新中使用所有的訓練樣本,數學表達如下:

  其中L為損失函數,m為訓練樣本個數,α為學習率。每次迭代,先對損失函數中的參數求導,再按照負梯度方向更新參數θ。

  這樣容易得到最優解。但每迭代一次,需要用到訓練集中的所有數據,如果數據量很大,那么迭代速度就會非常慢。

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

   SGD 每次迭代中使用的是單個訓練樣本,數學表達如下:

   SGD 每次迭代只使用一個樣本,如果訓練集很大,可能只使用其中一部分就能把參數θ迭代到最優解了。但是,SGD容易受噪聲影響,並不是每次迭代都向整體最優化方向進行。

  訓練速度快,迭代次數多,在解空間的搜索過程中看起來很盲目。

1.3 小批量梯度下降法 (Mini-Batch Gradient Descent,MBGD)

   MBGD 中和了 BGD 和 SGD 方法,每次迭代使用 batch_size 個訓練樣本,數學表達如下:

   其中 n 表示第 n+1 次迭代,b 表示 batch_size (b=1,就是SGD;b=m,就是BGD),batch_size 一般設置為2的次方數,如16、32、64、128等,可以根據自己的 GPU 或 CPU 大小來設置。

   因為每次迭代使用多個樣本,所以 MBGD 比 SGD 收斂更穩定,也能避免 BGD 在數據集過大時迭代速度慢的問題。如果訓練集本來就不大,直接使用 BGD 就可以了。

1.4 梯度下降法存在的問題

  (1)對於非凸函數可能會陷入局部極小值。此外,還可能會被困在鞍點 (所有維度的梯度在這附近都接近於0,損失函數變化慢),如果是 BGD,可能會停止不動,如果是 MBGD 或者 SGD,因為每次找到的梯度不同,可能會發生震盪,來回跳動。

  (2)SGD 很容易被困在溝壑 (ravine) 中,即一個維度上的曲線比另一個維度的曲線陡的多。在這種情況下,SGD 在溝壑的斜坡上震盪。

  (3)學習率的選擇問題。學習率太小,收斂速度慢;學習率太大,可能會在最優點附近震盪無法收斂。

  (4)對所有參數使用了相同的學習率。對於一些稀疏的數據或者特征,我們希望能更新的更快些。

2 動量算法 (Momentum algorithm)

2.1 Momentum

  momentum 改進自 SGD算法,讓每一次參數更新方向不僅僅取決於當前位置的梯度,還受到上一次參數更新方向的影響,數學形式如下:

  其中,di 和 di-1 分別是這一次和上一次的更新方向,β 是對上一次更新方向的衰減權重,一般在0~1之間。

  momentum 想法很簡單,就是通過之前迭代的更新量,來平滑這一次迭代的梯度方向。從物理的角度來看,就像是一個小球滾落時會受到自身歷史動量的影響,因此就能更平穩、快速的沖向局部最小點。

 2.2 Nesterov Accelerated Gradient (NAG)

  NAG 是對傳統 momentum 方法的一項改進,NAG 認為 “既然我已經知道這次要多走 αβdi-1 的量 (注意 momentum 中的數學表達),那我直接先走到 αβdi-1 之后的地方,再根據那里的梯度前進不是更好嗎?”,所以就有了下面的公式:

   直觀上看是這樣的,momentum 首先計算一個梯度 (短的藍色向量),然后在加速更新梯度的方向進行一個大的跳躍 (長的藍色向量),nesterov項首先在之前加速的梯度方向進行一個大的跳躍 (棕色向量),計算梯度然后進行校正 (綠色梯向量)。

  NAG 的收斂速度比 momentum 更快,許多文章解釋為:能夠讓算法提前看到前方的地形梯度,如果前面的梯度比當前位置的梯度大,那我就可以把步子邁得比原來大一些,如果前面的梯度比現在的梯度小,那我就可以把步子邁得小一些。這個大一些、小一些,都是相對於原來不看前方梯度、只看當前位置梯度的情況來說的。有篇文章給出了另一種更具體的解釋:NAG 本質上是多考慮了目標函數的二階導信息,所謂“往前看”的說法,在牛頓法這樣的二階方法中也是經常提到的,比喻起來是說“往前看”,數學本質上則是利用了目標函數的二階導信息。

2.3 動量算法的優點

  (1)明顯改善了梯度下降法中的問題(2),即在溝壑的斜坡上震盪,使收斂更平滑。

  (2)對於學習率也有一定的改善。在學習率較小的情況下,收斂速度慢,但更新方向基本不變,動量算法中的 d就會不斷疊加、增大,從而加快收斂;學習率較大的時候,會在最優點附近震盪,更新方向在不斷變化,d就會疊加減小,在一定程度上減輕了震盪。(當然,要更好地改善學習率的問題,更推薦后面的自適應學習率的優化方法)

3 自適應學習率算法 

3.1 自適應梯度算法 (Adaptive gradient algorithm,Adagrad)

  Adagrad 對低頻的參數做較大更新,對高頻的參數做較小的更新,因此,該算法對於稀疏數據的表現很好,極大的提高了 SGD 的健壯性。數學表達如下:

   其中 ε 是一個避免零除的平滑項,如取值1e-8。

   可以看出,隨着迭代次數增加,Si 逐漸變大,就會對學習率產生一個約束。改善了梯度下降法中的問題(3),使得參數更新前期變化大,后期變化小。也改善了問題(4),因為稀疏數據 Si 積累較少,更新更快。

   主要缺點也在於分母中平方梯度的積累,隨着 Si 不斷增加,學習率收縮,最終變得無窮小,導致模型無法再訓練,接下來的 Adadelta 算法就是解決這個問題的。

 3.2 Adadelta

  Adadelta 是對 Adagrad 的擴展,最初方案依然是對學習率進行自適應約束。Adadelta 不會累積過去所有的平方梯度,而是過去所有的平方梯度的衰減平均值。即:

   這里的 β 和 momentum 中的 β 沒有關系,是另一個超參數。由於分母相當於梯度的均方根 (RMS),所以可以用 RMS 簡寫上式如下:

   論文作者認為,更新應該具有與參數相同的假設單位,所以他們首次定義另一個指數衰減平均值,這次,不是平方梯度,而是平方參數更新,如下式:

   由於 RMS[Δθ]i 是未知的,我們用上一時刻的參數更新的 RMS 近似它,所以我們用 RMS[Δθ]i-1 來替換學習率,最終得到 Adadelta 更新規則如下:

  這里甚至不需要設置默認的學習率。

  訓練初中期,加速效果不錯,很快;訓練后期,反復在局部最小值附近抖動。

3.3 RMSprop

  RMSprop 和 Adadelta 算法一樣,都是為了解決 Adagrad 算法急劇下降的學習率的算法,RMSprop 與 Adadelta 的第一種形式相同,這兩個算法是同一時間獨立開發的,公式如下:

   一般 β 設置為 0.9,學習率 α 設置為 0.001。

   RMSprop 依然依賴於全局學習率;屬於 Adagrad 的一種發展,Adadelta 的變體,效果趨於二者之間;適合處理非平穩目標;對於RNN效果很好。

3.4 自適應矩估計 (Adaptive Moment Estimation,Adam)

  Adam 是另一種參數自適應學習率的方法,相當於 RMSprop + Momentum,利用梯度的一階矩估計和二階矩估計動態調整每個參數的學習率。公式如下:

  ˆdi 和 ˆSi 是對 di 和 Si 的偏置校正(Bias Correction),調整前期的誤差,這樣可以近似為對期望的無偏估計。一般情況下,β1 設置為0.9,β2 設置為0.999,ε 設置為1e-8。

  Adam 適用於大多非凸優化,適用於大數據集和高維空間。

3.5 Adamax

  Adamax 是 Adam 的一種變體,該方法對學習率的上限提供了一個更簡單的范圍。公式如下:

   可以看出,Adamax 學習率的邊界范圍更簡單。

 3.6 Nadam

  Nadam 類似於帶有 Nesterov 動量項的 Adam。公式如下:

  Nadam 對學習率有了更強的約束,同時對梯度的更新也有更直接的影響。一般而言,在想使用帶動量的 RMSprop,或者 Adam 的地方,大多可以使用 Nadam 取得更好的效果。

4 可視化

  更多內容可參考該 鏈接

 

5 tensorflow2.0 提供的優化器

  tensorflow2.0 官方文檔 中提供了下面幾類優化器:

 

tf.keras.optimizers.SGD(
    learning_rate=0.01, momentum=0.0, nesterov=False, name='SGD', **kwargs
)

該函數實現的是 MBGD,在訓練神經網絡時,可以設置 batch_size 的大小,batch_size=1,就是SGD;batch_size=m,就是BGD。

參數 momentum 決定動量項,當 momentum == 0 時,就是簡單的梯度下降法。

參數 nesterov 決定是否使用 nesterov 動量項。

 

tf.keras.optimizers.Adagrad(
    learning_rate=0.001, initial_accumulator_value=0.1, epsilon=1e-07,
    name='Adagrad', **kwargs
)

initial_accumulator_value 是 Si 的初始值,必須是非負的。

 

tf.keras.optimizers.Adadelta(
    learning_rate=0.001, rho=0.95, epsilon=1e-07, name='Adadelta', **kwargs
)

 

tf.keras.optimizers.RMSprop(
    learning_rate=0.001, rho=0.9, momentum=0.0, epsilon=1e-07, centered=False,
    name='RMSprop', **kwargs
)

 

tf.keras.optimizers.Adam(
    learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-07, amsgrad=False,
    name='Adam', **kwargs
)

 

tf.keras.optimizers.Adamax(
    learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-07, name='Adamax',
    **kwargs
)

 

tf.keras.optimizers.Nadam(
    learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-07, name='Nadam',
    **kwargs
)

 

 

 


免責聲明!

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



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