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