更快速的優(yōu)化器
訓(xùn)練一個非常深的神經(jīng)網(wǎng)絡(luò)可能會慢得讓人絕望懂牧。那么之前的文章已經(jīng)介紹了四種加速訓(xùn)練(并得到更好結(jié)果)的方法:使用合適的初始化方法跟匆,合適的激活函數(shù)聋伦,使用批標(biāo)準(zhǔn)化,以及預(yù)訓(xùn)練模型的重用湾碎。本文想要介紹的是另一種能夠極大加速訓(xùn)練的方法:用更快速的優(yōu)化器替代普通的梯度下降優(yōu)化器。那么我們將展示一些最常用的優(yōu)化器奠货。
動量優(yōu)化介褥,Nesterov加速梯度,AdaGrad递惋,RMSProp以及Adam和Nadam優(yōu)化柔滔。這里一下子列出好多專業(yè)詞匯,由于它們大多是幾個單詞的縮略萍虽,或者是人名睛廊,又沒有對應(yīng)的很統(tǒng)一的中文說法,所以只能暫且擱置在這里杉编。下面我們將對它們一一解釋超全。
動量優(yōu)化
讓我們想象一個保齡球從一個斜坡上滾下來咆霜,它初速度并不大,但是它的動量會越來越大卵迂,直到最終達(dá)到最大速度(由于可能有摩擦力等等)裕便。其實這就是Boris Polyak在1964年提出的動量優(yōu)化背后的核心思想。而常規(guī)的梯度下降只會一步一步勻速地下坡见咒,那么模型收斂就會需要消耗大量的時間偿衰。
讓我們回顧一下梯度下降法,梯度下降更新權(quán)值θ的方法是權(quán)值θ直接減去學(xué)習(xí)率η與損失函數(shù)J(θ)對于權(quán)重的梯度的乘積改览。這個方法并不關(guān)心上一次計算的梯度是什么下翎,那么如果局部的梯度很小,那么下降速度會非常緩慢宝当。
那么動量優(yōu)化就非常關(guān)心之前的梯度是什么:在每一輪訓(xùn)練中视事,它從動量向量m中減去局部梯度(乘以學(xué)習(xí)率),然后加權(quán)重庆揩,就完成了權(quán)重更新(見下式)俐东。換句話說,梯度是用來加速的订晌,并不是用來決定速度的虏辫。為了模擬摩擦力的存在,防止動量變得過大锈拨,這個算法引入了一個新的超參數(shù)β砌庄,稱為動量。動量的值設(shè)置在0(代表高摩擦)和1(代表無摩擦)之間奕枢,一般設(shè)置為0.9娄昆。
我們可以驗證,如果梯度保持不變缝彬,那么最終速度(也就是權(quán)重更新的最大速度)等于梯度乘以學(xué)習(xí)率再乘以1/(1-β)萌焰。比如設(shè)β=0.9,那么最終速度就等于梯度乘以學(xué)習(xí)率乘以10谷浅,也就是說動量優(yōu)化最終會比梯度下降的速度快10倍杆怕。這使得動量優(yōu)化能夠比梯度下降更快速地逃離梯度較小的區(qū)域。當(dāng)各特征輸入值的數(shù)值范圍很不同時壳贪,損失函數(shù)就會像是一個細(xì)長的碗陵珍。梯度下降在陡坡上下降的速度很快,但是要走下山谷需要很長的時間违施。相反互纯,動量優(yōu)化就會越來越快地沿著山谷向下滾動,直到達(dá)到底部最優(yōu)磕蒲。在深度神經(jīng)網(wǎng)絡(luò)中留潦,如果沒有使用批標(biāo)準(zhǔn)化方法只盹,那么上層網(wǎng)絡(luò)的輸入數(shù)值范圍可能差異很大,這種情況下使用動量優(yōu)化可能會很有用兔院。并且動量優(yōu)化還可以很輕松地“滾”出局部最優(yōu)點殖卑。
由于動量的存在,優(yōu)化器可能會滾過最優(yōu)點坊萝,然后再回來孵稽,然后在最優(yōu)點附近震蕩許多次。這也是需要在算法中加入一些阻力的原因之一十偶,它可以減少震蕩菩鲜,使之快速收斂。
在Keras中使用動量優(yōu)化是很傻瓜式的惦积,只需要選擇SGD優(yōu)化器接校,然后設(shè)置momentum超參數(shù),就可以了狮崩。就像這樣:
optimizer = keras.optimizers.SGD(lr=0.001, momentum=0.9)
動量優(yōu)化有一個缺點蛛勉,那就是它多了一個超參數(shù)需要調(diào)整。不過睦柴,動量參數(shù)的默認(rèn)值0.9一般都表現(xiàn)不錯诽凌,并且比梯度下降快得多。
Nesterov加速梯度
Yurii Nesterov在1983年提出了動量優(yōu)化的一個小的變體爱只,并且總會比原本的方法要更快。Nesterov動量優(yōu)化招刹,或者叫Nesterov加速梯度(Nesterov Accelerated Gradient恬试,NAG),并不根據(jù)當(dāng)前權(quán)重點來計算損失函數(shù)的梯度疯暑,而是根據(jù)動量方向训柴,在θ+βm點計算梯度,見下式:
這個小調(diào)整是有效的妇拯,因為一般動量矢量指向的是正確的方向(即最優(yōu)點)幻馁,所以使用動量方向上的一點的梯度會比使用原點的梯度稍微更準(zhǔn)確一些。從圖2.6中可以看出越锈,?1是在起始點θ處的損失函數(shù)梯度仗嗦,?2是在θ+βm處計算出的損失函數(shù)梯度。Nesterov動量法會比普通的動量優(yōu)化方法要快一點點甘凭。另外稀拐,當(dāng)動量將權(quán)重推過一個峽谷,?1仍然會將權(quán)重來回推過峽谷丹弱,而?2將權(quán)重直接推向峽谷的底部德撬。這樣會減少最后最終收斂的振動铲咨,因此NAG的收斂速度將更快。
NAG一般比常規(guī)的動量優(yōu)化更快蜓洪,那么在實際操作中纤勒,只需在創(chuàng)建SGD優(yōu)化器時,設(shè)置nesterov=True
即可:
optimizer = keras.optimizers.SGD(lr=0.001, momentum=0.9, nesterov=True)
AdaGrad
我們再次將梯度下降過程比喻成球從一個拉長的碗中滾下:梯度下降一開始會從最陡的斜坡快速滾下來隆檀,但是這個方向并不指向全局最優(yōu)摇天,然后再慢慢向峽谷底部滾去。
如果有一種算法能夠更早修正梯度下降的方向刚操,并朝向全局最優(yōu)值闸翅,那就太好了。
AdaGrad算法通過將最陡峭的梯度方向進(jìn)行縮小菊霜,來實現(xiàn)梯度方向修正的目的坚冀。
第一步將平方梯度積累至向量s。其中每一個si都積累了損失函數(shù)對參數(shù)θi的偏導(dǎo)數(shù)的平方鉴逞。那么當(dāng)損失函數(shù)在第i個維度上特別陡峭记某,則si就會增加地非常快速构捡。
第二步與梯度下降方法幾乎一致液南,但是 有一個區(qū)別:通過s+?參數(shù)將梯度向量縮小(?是為了避免矩陣被0除勾徽,一般設(shè)置為10^-10)滑凉。
簡而言之,這個算法降低了學(xué)習(xí)率喘帚,但是它在陡峭地維度上比平緩地維度上要更快畅姊。這種方法被稱為自適應(yīng)學(xué)習(xí)率。它有助于更直接地將結(jié)果更新指向全局最優(yōu)值(見圖2.7).另外吹由,這個算法對學(xué)習(xí)率參數(shù)的調(diào)優(yōu)需求很低若未,這算是附加的優(yōu)點。
AdaGrad通常在處理簡單的二次型問題時表現(xiàn)良好倾鲫,但在訓(xùn)練神經(jīng)網(wǎng)絡(luò)時粗合,它經(jīng)常過早停止。因為學(xué)習(xí)率被減到太小乌昔,以至于算法在達(dá)到全局最優(yōu)解之前就完全停止了隙疚。所以,雖然Keras提供了Adagrad優(yōu)化器磕道,但是我們不應(yīng)該使用它來訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)甚淡。不過我們?nèi)匀恍枰獙λ兴私猓驗樗鼘τ诶斫馄渌淖赃m應(yīng)學(xué)習(xí)率優(yōu)化器是有幫助的。