Caffe 現在提供了六種優化算法:
- 隨機梯度下降 (type: SGD)
- AdaDelta (type: AdaDelta)
- 自適應梯度 (type: AdaGrad)
- Adam (type: Adam)
- Nesterov 加速梯度 (type: Nesterov)
- RMSprop (type: RMSPorp)
Solver 求解器是 Caffe 的核心。它的作用就是交替進行前向計算求得 loss 和後向計算更新參數,從而最小化 loss。是一種迭代優化算法。
假設一個數據集,其數據總量為 D,那麼這整個數據集的 loss 的平均值是:
其中,前面第一部分就是求所有數據損失值的平均值,第二部分是正則項,lamda 是正則項系數,用於防止過擬合。
如果數據量很小的話,用上面的公式還可以計算。但是如果數據量 D 非常大,那麼計算一次 Loss 將耗費很長的時間。
所以這時候提出了 batch(批)這個概念,將所有數據集 D 分割成很多個小的 batch,記為 N。
在一次前向計算和後向計算中,我們只提取一個 batch 數量的數據,然後只更新這一 batch 數據的 loss,
然後我們可以重複的,多次的提取一個 batch 數據來進行計算。
** 在 caffe 中,默認的優化算法是 SGD,也就是隨機梯度下降算法。 **
一。隨機梯度下降 (SGD)#
隨機梯度下降算法是在梯度下降算法的基礎上發展起來的,梯度下降算法也叫最速下降算法。
簡要一句話說明 SGD 的原理就是當前參數 W (t+1) 等於上一次更新後的參數 Wt 和當前權重更新值的線性組合。
而我們實際在 caffe 中使用的時候都是加上衝量法的。
其中,α 是學習率 (base_lr),μ 是上一次梯度值的權重,就是衝量 (momentum)。
學習率是要不斷下降才能讓模型不斷優化的。學習率可以理解為步長,優化模型就是翻山越嶺的從最陡方向出發找最低谷。如果步子太大了,容易跨過最低谷,
如果步子太小,找的太慢,而且容易陷入其他非最低谷出不來。在 solver 文件中,學習率下降策略 lr_policy 有很多,以後我會詳細講的,
知道有這麼回事就好。
上面說的最陡方向,其實就是負的梯度方向。
衝量就是在保證 loss 穩定的情況下,儘量加速其下降。** 對於 SGD,這個一般默認設置為 0.9,在某些特殊情況,當學習率下降到很小的時候,
可以將衝量設置為 0.99,提高訓練效果。 **
二. AdaDelta#
Paper 地址: https://arxiv.org/pdf/1212.5701.pdf
AdaDelta 是一種具有適應性的學習率方法,也是基於梯度下降發展出來的。這個算法不需要手動調優學習率,並且對噪音有很好的魯棒性。
下面是幾點這個方法的優點:
-
不用手動設置學習率。
-
對超參數初始化不敏感。
-
對於每一維度,分別有一個動態的學習率。
-
對大梯度、噪音和結構選擇有很好的魯棒性。
-
對本地和分佈式環境的適應性都很好。
原作者一開始想對梯度下降法做很多改動,最大的想法就是應用牛頓法,使用二階導的代價函數,即 Hessian 海森矩陣:
其中 Δxt 是參數變化量,Ht 是 Hessian 海森矩陣,相當於學習率,即步長。gt 就是梯度,決定下降方向。這時候學習率是由海森矩陣決定的,
所以我們就不用手動的設置學習率了。
但是,海森矩陣在計算上是非常複雜和麻煩的,所以作者借著海森矩陣這個思路,想到加強對一階導數使用或者用估算海森矩陣結果的方法。
最終是選擇了加強一階導數使用的方法,近似模擬二階牛頓法
基本思路還是跟 SGD 一樣,實際的變化量是衝量和上一次變化量的乘積減去基礎學習率乘以當前梯度值(這裡基礎學習率是 1.0,而且保持不變。)
AdaDelta 衝量一般設置成 0.95
solver 中 delta 一般設置成 1e-6
** base_lr 必須設置為 1.0 **
** lr_policy 必須設置為 fixed.
**
------------------------- 下面是具體算法實現步驟 --------------------------------------------------------------------------------------------------------------
paper 中作者跟 AdaGrad 方法做了大量的對比,作者提出 AdaDelta 方法主要解決了 AdaGrad 的兩個缺點。一是解決了隨著訓練的進行,
學習率會持續衰減的問題。我認為作者想表達的意思就是隨著訓練的進行,如果學習率持續降低,到後期對優化的影響會降到很低導致優化不完全。
二就是解決的需要手動設置初始學習率的問題。
2012 年 Schaul&S. Zhang&LeCun 提出了 AdaGrad-like 算法,我這裡提到這個算法是因為和 AdaDelta 算法有相似的地方。
其中,diag (Ht) 是海森矩陣的對角矩陣,E [gt-w] 是從當前 t 算起前 w 次迭代梯度的期望值,分母就是從當前 t 算起前 w 次迭代梯度平方的期望值
這樣取前 w 次梯度的好處是,不會讓梯度消失。
好了回到 AdaDelta,這個方法沒有只是取前 w 次迭代梯度,而是取所有迭代的梯度。
其中,** ρ 是衰減常量,在 caffe 中通過設置 momentum 來設置這個參數 **。通過這個公式,我們算出當前 iteration
所有梯度平方的期望值。
我們需要上面結果的平方跟用於參數更新,這裡用 RMS(root mean square 均方根)表示:
其中,RMS [g] t 表示當前 iteration 下,梯度 g 的均方根值,** ε 是一個常數(就是 solver 中參數 delta) **,平滑項,
為了保證輸出結果不為零,因為後面這個結果是要做分母的。
最後參數的變化量公式:
上面的方法就是 Tieleman&Hinton 的 RMSProp。
後來的 Zeiler 考慮到 units 的問題,Δx 是用來更新參數 x 的,所以他們的 units 必須要一致。
說說我的理解,上面的公式中,gt 的 units 應該是跟 x 正相關的。RMS [g] t 的 units 也是跟 x 正相關的。
但是一相除,就變成了 unitless 這種情況了。
所以在看下面公式,在分子上加上了上一次迭代的參數變化量的 RMS,將 units 又找了回來。
** 這個 units 到底怎麼理解我還有困惑,我覺得應該可以理解為 "單位" **
並且加入上一次迭代,會增加最終結果的魯棒性,不會發生突變。
分子分母 RMS 中的 ε 取相同的值
實際步長,也可以認為是學習率,跟當前梯度和上一次參數變化量相關。
所以不同層、不同維度的參數的學習率也是不同的。可以用 "因人而異" 來形容。
而不是 SGD 那樣所有參數的學習率是相同的。
AdaDelta 在訓練初期和中期,速度很快。但是到後期容易陷入局部最優。這一點沒有 SGD 效果好。
三. AdaGrad#
Adaptive Gradient 自適應梯度算法,借鑒了 L2 Regularizer
其中,分母是從 1 開始到 t 的所有梯度和的平方根,η 是基礎學習率。
權值初始化對 AdaGrad 影響敏感,如果權值初始化過大,梯度很大,調節幅度會很小。
訓練中後期,梯度很容易逼近 0,提前結束訓練。
適合處理稀疏梯度。
實際使用公式是:
** solver 中 base_lr 一般設置不大,可參考使用 0.01 **
** lr_policy 必須設置為 "fixed" **
momentum 對應公式 ** 中 ε **
四. Adam#
Adaptive Moment Estimation
同樣也是基於梯度的優化方法。
只需要一階梯度信息,並且占用很少的內存。
通過估計梯度的一階矩和二階矩去動態的調整每個參數的學習率。
其中,mt 是對梯度的一階矩估計,nt 是對梯度的二階矩估計。上面帶拐的是對其自身的校正。
u 一般取 0.9
v 一般取 0.999
ε 一般取 1e-8。
五. NAG#
Nesterov 的加速梯度
Nesterov 的改進是讓之前的動量直接影響到當前的動量。
其中,η 是基礎學習率,μ 是動量(衝量)。
momentum 首先計算一個梯度,短的藍色向量。然後在加速更新梯度的方向進行一個大的跳躍,長的藍色向量。
nesterov 項先在以前的加速梯度方向進行一個大的跳躍,棕色向量。
最後計算梯度,進行校正,綠色向量。
** solver 中 base_lr 一般為 0.01,gamma 為 0.1 **
** lr_policy 一般為 "step",stepsize 視情況而定。 **
** momentum 一般為 0.95 **
**
**
六. RMSprop#
這個算法公式在上面 AdaDelta 中已經寫出來了,RMSprop 是 AdaDelta 的中間形式。
** solver 中 base_lr 看情況為 1.0 或者 0.001 **
** ** lr_policy 一般為 "fixed" ** **
** ** rms_decay 一般為 0.98 ** **
** ** momentum 一般為 0.95 ** **
七。選擇優化方法和優化策略#
-
RMSprop 解決了 AdaGrad 訓練中後期梯度消失的問題。
-
AdaDelta 中參數的學習率與初始學習率無關。而 RMSprop 中參數學習率與初始學習率有關。
-
Adam 比 RMSprop 增加了偏差校正和動量(注意 RMSprop 中參數 momentum 的數值是作用在求期望的過程中,不算動量。)
-
如果輸入數據是稀疏的,最好使用自適應學習速率的優化方法(AdaGrad、AdaDelta、RMSprop 和 Adam)。因為在優化過程中它們會自動調整學習率。
-
如果關心優化速度,那麼自適應學習速率方法會比較快。** Adam 可能是當前最好的優化方法。但很多大牛還是使用原始的 SGD 並且不用動量項。 **
-
Shuffle: 每次迭代時隨機打亂數據樣本順序。
-
Curriculum Learn: 把訓練樣本按某種有意義的方式排序,對逐步解決困難問題有幫助。
-
归一化參數初始值。
-
Early Stopping,這個結合可視化技術來看。取過擬合前的模型來用。
-
在損失函數中添加正則化項。
-
Dropout,測試階段不要用 Dropout。
-
並行與分佈式優化方法: Hogwild, Downpour SGD, Delay-tolerant Algorithms for SGD, Elastic Averaging SGD, 工具使用 Tensor Flow。