【模型训练】SGD的那些变种,真的比SGD强吗
文章首發于微信公眾號《有三AI》
【模型訓練】SGD的那些變種,真的比SGD強嗎
深度學習框架目前基本上都是使用梯度下降算法及其變種進行優化,通常意義上大家會認為原始的梯度下降算法是最弱的,但事實上并非如此。
很多的論文依然采用了原始的梯度下降算法而不采用更高級的算法,今天就以一個實踐例子來給大家展示一下各類算法的比較,所有內容參考文章【An overview of gradient descent optimization algorithms】。
?
01?梯度下降算法
本文目標不是為了從零開始講清楚優化算法,所以有些細節和基礎就略過。
梯度下降算法,即通過梯度的反方向來進行優化,批量梯度下降(Batch gradient descent)用公式表述如下:
寫成偽代碼如下:
for i in range(nb_epochs):
????params_grad = evaluate_gradient(loss_function, data, params)?
????params = params - learning_rate * params_grad
上面的梯度下降算法用到了數據集所有的數據,這在解決實際問題時通常是不可能,想想imagenet1000有100G以上的圖像,內存裝不下,速度也很慢。
我們需要在線能夠實時計算,于是一次取一個樣本,就有了隨機梯度下降(Stochastic gradient descent),簡稱sgd。
公式如下:
寫成偽代碼如下:
for i in range(nb_epochs):?
? ? np.random.shuffle(data)
? ? for example in data:
????????params_grad = evaluate_gradient(loss_function , example , params)?
????????params = params - learning_rate * params_grad
sgd方法缺點很明顯,梯度震蕩,所以就有了后來大家常用的小批量梯度下降算法(Mini-batch gradient descent)。
偽代碼如下:
for i in range(nb_epochs):?
????np.random.shuffle(data)
????for batch in get_batches(data, batch_size=50):
????????params_grad = evaluate_gradient(loss_function, batch, params)?
????????params = params - learning_rate * params_grad
下面我們要形成共識,說sgd算法,實際上指的就是mini-batch gradient descent算法,沒有人會去一次拿整個數據集或者一個樣本進行優化。
當然還是要總結一下SGD算法的毛病。
(1)學習率大小和策略選擇困難,想必動手經驗豐富的自然懂。
(2)學習率不夠智能,對所有參數一視同仁。
(3)同時面臨局部極值和鞍點的問題。
可能有同學不知道鞍點怎么回事,簡單來說,它就是在某一些方向梯度下降,另一些方向梯度上升,形狀似馬鞍,抄來一張圖如下,紅點就是鞍點。
?
02?梯度下降方法改進
1.1 動量法? ? ? ? ? ? ? ? ??
改進方法那么多,我覺得真正最有用的就是它。
前面說了梯度下降算法是按照梯度的反方向進行參數更新,但是剛開始的時候梯度不穩定呀,方向改變是很正常的,梯度就是抽瘋了似的一下正一下反,導致做了很多無用的迭代。
而動量法做的很簡單,相信之前的梯度。如果梯度方向不變,就越發更新的快,反之減弱當前梯度。
畫成圖就是這樣。
效果對比就這意思。
?
1.2 nesterov動量法? ? ? ? ? ? ? ? ??
仍然是動量法,只是它要求這個下降更加智能。
既然動量法已經把前一次的梯度和當前梯度融合,那何不更進一步,直接先按照前一次梯度方向更新一步將它作為當前的梯度,看下面的式子就明白了。
?
?
如上圖,自己領會。
nesterov的好處就是,當梯度方向快要改變的時候,它提前獲得了該信息,從而減弱了這個過程,再次減少了無用的迭代。
?
1.3?Adagrad法??? ? ? ? ? ? ? ??
思路很簡單,不同的參數是需要不同的學習率的,有的要慢慢學,有的要快快學,所以就給了一個權重咯,而且是用了歷史上所有的梯度幅值。
?
1.4 Adadelta與Rmsprop? ? ? ? ? ? ? ? ?
adagrad用了所有的梯度,問題也就來了,累加的梯度幅值是越來越大的。導致學習率前面的乘因子越來越小,后來就學不動了呀。
Adadelta就只是動了一丟丟小心思,用移動平均的方法計算累加梯度,只累加了一個窗口的梯度,而且計算方法也更有效。
并且,將學習率用前一時刻參數的平方根來代替,最終更新算法變成了這樣。
RMSprop方法的不同就在于分子上還是使用學習率η而不是Adadelta中的
這個方法在Hinton的課程中使用,沒有發表成論文,畢竟有Adadelta了沒有發表必要。
1.5 adam法? ? ? ? ? ? ? ? ??
最后就是這個adam算法,作為最晚出現的,當然是集大成者。
adam對梯度的一階和二階都進行了估計與偏差修正,使用梯度的一階矩估計和二階矩估計來動態調整每個參數的學習率。
看出來了吧,與adadelta和rmsprop如出一轍,與momentum sgd也頗為相似。上面的式子根據梯度對參數更新的幅度進行了動態調整,所以adam對學習率沒有那么敏感。
1.6 adamax?
將adam使用的二階矩變成更高階,就成了adamax算法。
1.7 nadam法? ? ? ? ? ? ? ? ??
nag加上adam,就成了nadam方法,即帶有動量項的adam,所以形式也很簡單,如下,可以將其分別與adam算法和nag算法的式子比較看看。
說了這么多,對上面各種方法從一個鞍點開始優化,表現如何的預期效果圖如下。
理論上,就是上面這樣的。文章作者會告訴你對于數據稀疏的問題,用自適應學習率算法就好了,而且使用人家推薦的參數就好。其中,adam會最佳。
?
03?各種方法表現究竟如何
上面說了這么多理論,分析起來頭頭是道,各種改進版本似乎各個碾壓SGD算法,然而根據筆者經驗,很多時候仔細調優后的SGD算法絕對吊打其他算法。
實驗結果看下圖,基礎任務模型和數據集上次已經說過,此處不再贅述。
所有方法都采用作者們的默認配置,并且進行了比較,不好的結果就不拿出來了。
-
nesterov方法,與sgd算法同樣的配置。
-
adam算法,m1=0.9,m2=0.999,lr=0.001。
-
rms算法,rms_decay=0.9,lr=0.001。
-
adagrad,adadelta學習率不敏感。
怎么著,好像都不如SGD算法呀。為什么呢?留言討論吧。
感謝各位看官的耐心閱讀,不足之處希望多多指教。后續內容將會不定期奉上,歡迎大家關注有三公眾號 有三AI!
?
總結
以上是生活随笔為你收集整理的【模型训练】SGD的那些变种,真的比SGD强吗的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样学会科学的调研并启动一个项目
- 下一篇: 【模型训练】如何选择最适合你的学习率变更