Adam那么棒,为什么还对SGD念念不忘 (1) —— 一个框架看懂优化算法
機(jī)器學(xué)習(xí)界有一群煉丹師,他們每天的日常是:
?
拿來(lái)藥材(數(shù)據(jù)),架起八卦爐(模型),點(diǎn)著六味真火(優(yōu)化算法),就搖著蒲扇等著丹藥出爐了。
?
不過,當(dāng)過廚子的都知道,同樣的食材,同樣的菜譜,但火候不一樣了,這出來(lái)的口味可是千差萬(wàn)別。火小了夾生,火大了易糊,火不勻則半生半糊。
?
機(jī)器學(xué)習(xí)也是一樣,模型優(yōu)化算法的選擇直接關(guān)系到最終模型的性能。有時(shí)候效果不好,未必是特征的問題或者模型設(shè)計(jì)的問題,很可能就是優(yōu)化算法的問題。
?
說(shuō)到優(yōu)化算法,入門級(jí)必從SGD學(xué)起,老司機(jī)則會(huì)告訴你更好的還有AdaGrad/AdaDelta,或者直接無(wú)腦用Adam。可是看看學(xué)術(shù)界的最新paper,卻發(fā)現(xiàn)一眾大神還在用著入門級(jí)的SGD,最多加個(gè)Moment或者Nesterov ,還經(jīng)常會(huì)黑一下Adam。比如 UC Berkeley的一篇論文就在Conclusion中寫道:
?
Despite the fact that our experimental evidence demonstrates that adaptive methods are not advantageous for machine learning, the Adam algorithm remains incredibly popular. We are not sure exactly as to why ……
?
無(wú)奈與酸楚之情溢于言表。
?
這是為什么呢?難道平平淡淡才是真?
一個(gè)框架回顧優(yōu)化算法
?
首先我們來(lái)回顧一下各類優(yōu)化算法。
?
深度學(xué)習(xí)優(yōu)化算法經(jīng)歷了 SGD -> SGDM -> NAG ->AdaGrad -> AdaDelta -> Adam -> Nadam 這樣的發(fā)展歷程。Google一下就可以看到很多的教程文章,詳細(xì)告訴你這些算法是如何一步一步演變而來(lái)的。在這里,我們換一個(gè)思路,用一個(gè)框架來(lái)梳理所有的優(yōu)化算法,做一個(gè)更加高屋建瓴的對(duì)比。
?
首先定義:待優(yōu)化參數(shù):??,目標(biāo)函數(shù):??,初始學(xué)習(xí)率?。
而后,開始進(jìn)行迭代優(yōu)化。在每個(gè)epoch??:
- 計(jì)算目標(biāo)函數(shù)關(guān)于當(dāng)前參數(shù)的梯度:?
- 根據(jù)歷史梯度計(jì)算一階動(dòng)量和二階動(dòng)量:,
- 計(jì)算當(dāng)前時(shí)刻的下降梯度:?
- 根據(jù)下降梯度進(jìn)行更新:?
掌握了這個(gè)框架,你可以輕輕松松設(shè)計(jì)自己的優(yōu)化算法。
?
我們拿著這個(gè)框架,來(lái)照一照各種玄乎其玄的優(yōu)化算法的真身。步驟3、4對(duì)于各個(gè)算法都是一致的,主要的差別就體現(xiàn)在1和2上。
?
SGD
先來(lái)看SGD。SGD沒有動(dòng)量的概念,也就是說(shuō):
代入步驟3,可以看到下降梯度就是最簡(jiǎn)單的
SGD最大的缺點(diǎn)是下降速度慢,而且可能會(huì)在溝壑的兩邊持續(xù)震蕩,停留在一個(gè)局部最優(yōu)點(diǎn)。
?
SGD with Momentum
為了抑制SGD的震蕩,SGDM認(rèn)為梯度下降過程可以加入慣性。下坡的時(shí)候,如果發(fā)現(xiàn)是陡坡,那就利用慣性跑的快一些。SGDM全稱是SGD with momentum,在SGD基礎(chǔ)上引入了一階動(dòng)量:
一階動(dòng)量是各個(gè)時(shí)刻梯度方向的指數(shù)移動(dòng)平均值,約等于最近??個(gè)時(shí)刻的梯度向量和的平均值。
?
也就是說(shuō),t時(shí)刻的下降方向,不僅由當(dāng)前點(diǎn)的梯度方向決定,而且由此前累積的下降方向決定。??的經(jīng)驗(yàn)值為0.9,這就意味著下降方向主要是此前累積的下降方向,并略微偏向當(dāng)前時(shí)刻的下降方向。想象高速公路上汽車轉(zhuǎn)彎,在高速向前的同時(shí)略微偏向,急轉(zhuǎn)彎可是要出事的。
?
SGD with Nesterov Acceleration
SGD 還有一個(gè)問題是困在局部最優(yōu)的溝壑里面震蕩。想象一下你走到一個(gè)盆地,四周都是略高的小山,你覺得沒有下坡的方向,那就只能待在這里了。可是如果你爬上高地,就會(huì)發(fā)現(xiàn)外面的世界還很廣闊。因此,我們不能停留在當(dāng)前位置去觀察未來(lái)的方向,而要向前一步、多看一步、看遠(yuǎn)一些。
?
NAG全稱Nesterov Accelerated Gradient,是在SGD、SGD-M的基礎(chǔ)上的進(jìn)一步改進(jìn),改進(jìn)點(diǎn)在于步驟1。我們知道在時(shí)刻t的主要下降方向是由累積動(dòng)量決定的,自己的梯度方向說(shuō)了也不算,那與其看當(dāng)前梯度方向,不如先看看如果跟著累積動(dòng)量走了一步,那個(gè)時(shí)候再怎么走。因此,NAG在步驟1,不計(jì)算當(dāng)前位置的梯度方向,而是計(jì)算如果按照累積動(dòng)量走了一步,那個(gè)時(shí)候的下降方向:
然后用下一個(gè)點(diǎn)的梯度方向,與歷史累積動(dòng)量相結(jié)合,計(jì)算步驟2中當(dāng)前時(shí)刻的累積動(dòng)量。
?
AdaGrad
此前我們都沒有用到二階動(dòng)量。二階動(dòng)量的出現(xiàn),才意味著“自適應(yīng)學(xué)習(xí)率”優(yōu)化算法時(shí)代的到來(lái)。SGD及其變種以同樣的學(xué)習(xí)率更新每個(gè)參數(shù),但深度神經(jīng)網(wǎng)絡(luò)往往包含大量的參數(shù),這些參數(shù)并不是總會(huì)用得到(想想大規(guī)模的embedding)。對(duì)于經(jīng)常更新的參數(shù),我們已經(jīng)積累了大量關(guān)于它的知識(shí),不希望被單個(gè)樣本影響太大,希望學(xué)習(xí)速率慢一些;對(duì)于偶爾更新的參數(shù),我們了解的信息太少,希望能從每個(gè)偶然出現(xiàn)的樣本身上多學(xué)一些,即學(xué)習(xí)速率大一些。
?
怎么樣去度量歷史更新頻率呢?那就是二階動(dòng)量——該維度上,迄今為止所有梯度值的平方和:
我們?cè)倩仡櫼幌虏襟E3中的下降梯度:
可以看出,此時(shí)實(shí)質(zhì)上的學(xué)習(xí)率由??變成了??。 一般為了避免分母為0,會(huì)在分母上加一個(gè)小的平滑項(xiàng)。因此?是恒大于0的,而且參數(shù)更新越頻繁,二階動(dòng)量越大,學(xué)習(xí)率就越小。
?
這一方法在稀疏數(shù)據(jù)場(chǎng)景下表現(xiàn)非常好。但也存在一些問題:因?yàn)?是單調(diào)遞增的,會(huì)使得學(xué)習(xí)率單調(diào)遞減至0,可能會(huì)使得訓(xùn)練過程提前結(jié)束,即便后續(xù)還有數(shù)據(jù)也無(wú)法學(xué)到必要的知識(shí)。
?
AdaDelta / RMSProp
?
由于AdaGrad單調(diào)遞減的學(xué)習(xí)率變化過于激進(jìn),我們考慮一個(gè)改變二階動(dòng)量計(jì)算方法的策略:不累積全部歷史梯度,而只關(guān)注過去一段時(shí)間窗口的下降梯度。這也就是AdaDelta名稱中Delta的來(lái)歷。
?
修改的思路很簡(jiǎn)單。前面我們講到,指數(shù)移動(dòng)平均值大約就是過去一段時(shí)間的平均值,因此我們用這一方法來(lái)計(jì)算二階累積動(dòng)量:
這就避免了二階動(dòng)量持續(xù)累積、導(dǎo)致訓(xùn)練過程提前結(jié)束的問題了。
?
Adam
?
談到這里,Adam和Nadam的出現(xiàn)就很自然而然了——它們是前述方法的集大成者。我們看到,SGD-M在SGD基礎(chǔ)上增加了一階動(dòng)量,AdaGrad和AdaDelta在SGD基礎(chǔ)上增加了二階動(dòng)量。把一階動(dòng)量和二階動(dòng)量都用起來(lái),就是Adam了——Adaptive + Momentum。
?
SGD的一階動(dòng)量:
加上AdaDelta的二階動(dòng)量:
?
優(yōu)化算法里最常見的兩個(gè)超參數(shù)??就都在這里了,前者控制一階動(dòng)量,后者控制二階動(dòng)量。
?
Nadam
?
最后是Nadam。我們說(shuō)Adam是集大成者,但它居然遺漏了Nesterov,這還能忍?必須給它加上,按照NAG的步驟1:
這就是Nesterov + Adam = Nadam了。
?
說(shuō)到這里,大概可以理解為什么j經(jīng)常有人說(shuō) Adam / Nadam 目前最主流、最好用的優(yōu)化算法了。新手上路,先拿來(lái)一試,收斂速度嗖嗖滴,效果也是杠杠滴。
?
那為什么Adam還老招人黑,被學(xué)術(shù)界一頓鄙夷?難道只是為了發(fā)paper灌水嗎?
?
請(qǐng)繼續(xù)閱讀:
Adam那么棒,為什么還對(duì)SGD念念不忘 (2)—— Adam的兩宗罪
Adam那么棒,為什么還對(duì)SGD念念不忘 (3)—— 優(yōu)化算法的選擇與使用策略
?
————————————————————
補(bǔ)充:指數(shù)移動(dòng)平均值的偏差修正
?
前面我們講到,一階動(dòng)量和二階動(dòng)量都是按照指數(shù)移動(dòng)平均值進(jìn)行計(jì)算的:
實(shí)際使用過程中,參數(shù)的經(jīng)驗(yàn)值是
初始化:
這個(gè)時(shí)候我們看到,在初期,??都會(huì)接近于0,這個(gè)估計(jì)是有問題的。因此我們常常根據(jù)下式進(jìn)行誤差修正:
?
————————————————————
行有所思,學(xué)有所得,陋鄙之言,請(qǐng)多指教。
歡迎關(guān)注我的微信公眾號(hào) Julius-AI
總結(jié)
以上是生活随笔為你收集整理的Adam那么棒,为什么还对SGD念念不忘 (1) —— 一个框架看懂优化算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PyTorch中文文档 说明书
- 下一篇: python开启GPU加速