一.優(yōu)化器算法簡(jiǎn)述
首先來看一下梯度下降最常見的三種變形 BGD,SGD,MBGD,這三種形式的區(qū)別就是取決于我們用多少數(shù)據(jù)來計(jì)算目標(biāo)函數(shù)的梯度,這樣的話自然就涉及到一個(gè) trade-off,即參數(shù)更新的準(zhǔn)確率和運(yùn)行時(shí)間。
?1.Batch Gradient Descent (BGD)
梯度更新規(guī)則:
BGD 采用整個(gè)訓(xùn)練集的數(shù)據(jù)來計(jì)算 cost function 對(duì)參數(shù)的梯度:

缺點(diǎn):
由于這種方法是在一次更新中,就對(duì)整個(gè)數(shù)據(jù)集計(jì)算梯度,所以計(jì)算起來非常慢,遇到很大量的數(shù)據(jù)集也會(huì)非常棘手,而且不能投入新數(shù)據(jù)實(shí)時(shí)更新模型。
for i in range(nb_epochs):
? ????params_grad = evaluate_gradient(loss_function, data, params)
? ????params = params - learning_rate * params_grad
我們會(huì)事先定義一個(gè)迭代次數(shù) epoch,首先計(jì)算梯度向量 params_grad,然后沿著梯度的方向更新參數(shù) params,learning rate 決定了我們每一步邁多大。
Batch gradient descent 對(duì)于凸函數(shù)可以收斂到全局極小值,對(duì)于非凸函數(shù)可以收斂到局部極小值。
2.Stochastic Gradient Descent (SGD)
梯度更新規(guī)則:
和 BGD 的一次用所有數(shù)據(jù)計(jì)算梯度相比,SGD 每次更新時(shí)對(duì)每個(gè)樣本進(jìn)行梯度更新,對(duì)于很大的數(shù)據(jù)集來說,可能會(huì)有相似的樣本,這樣 BGD 在計(jì)算梯度時(shí)會(huì)出現(xiàn)冗余,而?SGD 一次只進(jìn)行一次更新,就沒有冗余,而且比較快,并且可以新增樣本。

for i in range(nb_epochs):
? ? ?np.random.shuffle(data)
? ? ?forexamplein data:
? ? ?params_grad = evaluate_gradient(loss_function, example, params)
? ? ?params = params - learning_rate * params_grad
?看代碼,可以看到區(qū)別,就是整體數(shù)據(jù)集是個(gè)循環(huán),其中對(duì)每個(gè)樣本進(jìn)行一次參數(shù)更新。

隨機(jī)梯度下降是通過每個(gè)樣本來迭代更新一次,如果樣本量很大的情況,那么可能只用其中部分的樣本,就已經(jīng)將theta迭代到最優(yōu)解了,對(duì)比上面的批量梯度下降,迭代一次需要用到十幾萬訓(xùn)練樣本,一次迭代不可能最優(yōu),如果迭代10次的話就需要遍歷訓(xùn)練樣本10次。缺點(diǎn)是SGD的噪音較BGD要多,使得SGD并不是每次迭代都向著整體最優(yōu)化方向。所以雖然訓(xùn)練速度快,但是準(zhǔn)確度下降,并不是全局最優(yōu)。雖然包含一定的隨機(jī)性,但是從期望上來看,它是等于正確的導(dǎo)數(shù)的。
缺點(diǎn):
SGD 因?yàn)楦卤容^頻繁,會(huì)造成 cost function 有嚴(yán)重的震蕩。
BGD 可以收斂到局部極小值,當(dāng)然 SGD 的震蕩可能會(huì)跳到更好的局部極小值處。
當(dāng)我們稍微減小 learning rate,SGD 和 BGD 的收斂性是一樣的。
3.Mini-Batch Gradient Descent (MBGD)
梯度更新規(guī)則:
MBGD 每一次利用一小批樣本,即 n 個(gè)樣本進(jìn)行計(jì)算,這樣它可以降低參數(shù)更新時(shí)的方差,收斂更穩(wěn)定,另一方面可以充分地利用深度學(xué)習(xí)庫中高度優(yōu)化的矩陣操作來進(jìn)行更有效的梯度計(jì)算。
和 SGD 的區(qū)別是每一次循環(huán)不是作用于每個(gè)樣本,而是具有 n 個(gè)樣本的批次。
for i in range(nb_epochs):
? ? ?np.random.shuffle(data)
? ? ?forbatchinget_batches(data, batch_size=50):
? ? ?params_grad = evaluate_gradient(loss_function, batch, params)
? ? ?params = params - learning_rate * params_grad
超參數(shù)設(shè)定值:n 一般取值在 50~256
缺點(diǎn):(兩大缺點(diǎn))
不過 Mini-batch gradient descent 不能保證很好的收斂性,learning rate 如果選擇的太小,收斂速度會(huì)很慢,如果太大,loss function 就會(huì)在極小值處不停地震蕩甚至偏離。(有一種措施是先設(shè)定大一點(diǎn)的學(xué)習(xí)率,當(dāng)兩次迭代之間的變化低于某個(gè)閾值后,就減小 learning rate,不過這個(gè)閾值的設(shè)定需要提前寫好,這樣的話就不能夠適應(yīng)數(shù)據(jù)集的特點(diǎn)。)對(duì)于非凸函數(shù),還要避免陷于局部極小值處,或者鞍點(diǎn)處,因?yàn)榘包c(diǎn)周圍的error是一樣的,所有維度的梯度都接近于0,SGD 很容易被困在這里。(會(huì)在鞍點(diǎn)或者局部最小點(diǎn)震蕩跳動(dòng),因?yàn)樵诖它c(diǎn)處,如果是訓(xùn)練集全集帶入即BGD,則優(yōu)化會(huì)停止不動(dòng),如果是mini-batch或者SGD,每次找到的梯度都是不同的,就會(huì)發(fā)生震蕩,來回跳動(dòng)。)
SGD對(duì)所有參數(shù)更新時(shí)應(yīng)用同樣的 learning rate,如果我們的數(shù)據(jù)是稀疏的,我們更希望對(duì)出現(xiàn)頻率低的特征進(jìn)行大一點(diǎn)的更新。LR會(huì)隨著更新的次數(shù)逐漸變小。
鞍點(diǎn)就是:一個(gè)光滑函數(shù)的鞍點(diǎn)鄰域的曲線,曲面,或超曲面,都位于這點(diǎn)的切線的不同邊。例如這個(gè)二維圖形,像個(gè)馬鞍:在x-軸方向往上曲,在y-軸方向往下曲,鞍點(diǎn)就是(0,0)。

為了應(yīng)對(duì)上面的兩點(diǎn)挑戰(zhàn)就有了下面這些算法。
?指數(shù)加權(quán)平均
在深度學(xué)習(xí)優(yōu)化算法中,例如Momentum、RMSprop、Adam,都提到了一個(gè)概念,指數(shù)加權(quán)平均,看了Andrew Ng的深度學(xué)習(xí)課程后,總結(jié)一下什么是指數(shù)加權(quán)平均。

?式中v_t可近似代表1/(1-β)個(gè)θ的平均值。


偏差修正
由以上證明可以看出,每個(gè)最新數(shù)據(jù)值,依賴于以前的數(shù)據(jù)結(jié)果。
一般令第一個(gè)數(shù)值為0,即v0=0;但此時(shí)初期的幾個(gè)計(jì)算結(jié)果就會(huì)與真實(shí)的平均值有較大偏差,具體如下:

有了指數(shù)加權(quán)平均、偏差修正的基礎(chǔ),就可以研究一下深度學(xué)習(xí)中優(yōu)化算法的實(shí)現(xiàn)原理了。
點(diǎn)擊進(jìn)入文章
4.Momentum
SGD 在 ravines 的情況下容易被困住, ravines 就是曲面的一個(gè)方向比另一個(gè)方向更陡,這時(shí) SGD 會(huì)發(fā)生震蕩而遲遲不能接近極小值:

梯度更新規(guī)則:
?Momentum 通過加入 γv_t?1 ,可以加速 SGD, 并且抑制震蕩

當(dāng)我們將一個(gè)小球從山上滾下來時(shí),沒有阻力的話,它的動(dòng)量會(huì)越來越大,但是如果遇到了阻力,速度就會(huì)變小。
加入的這一項(xiàng),可以使得梯度方向不變的維度上速度變快,梯度方向有所改變的維度上的更新速度變慢,這樣就可以加快收斂并減小震蕩。
超參數(shù)設(shè)定值: ?一般 γ 取值 0.9 左右。
缺點(diǎn):
這種情況相當(dāng)于小球從山上滾下來時(shí)是在盲目地沿著坡滾,如果它能具備一些先知,例如快要上坡時(shí),就知道需要減速了的話,適應(yīng)性會(huì)更好。
5.Nesterov Accelerated Gradient
梯度更新規(guī)則:
用 θ?γv_t?1 來近似當(dāng)做參數(shù)下一步會(huì)變成的值,則在計(jì)算梯度時(shí),不是在當(dāng)前位置,而是未來的位置上

超參數(shù)設(shè)定值: ?一般 γ 仍取值 0.9 左右。
效果比較:

藍(lán)色是 Momentum 的過程,會(huì)先計(jì)算當(dāng)前的梯度,然后在更新后的累積梯度后會(huì)有一個(gè)大的跳躍。
而 NAG 會(huì)先在前一步的累積梯度上(brown vector)有一個(gè)大的跳躍,然后衡量一下梯度做一下修正(red vector),這種預(yù)期的更新可以避免我們走的太快。
NAG 可以使 RNN 在很多任務(wù)上有更好的表現(xiàn)。
目前為止,我們可以做到,在更新梯度時(shí)順應(yīng) loss function 的梯度來調(diào)整速度,并且對(duì) SGD 進(jìn)行加速。
我們還希望可以根據(jù)參數(shù)的重要性而對(duì)不同的參數(shù)進(jìn)行不同程度的更新。
[應(yīng)對(duì)挑戰(zhàn) 2]
?6.Adagrad (Adaptive gradient algorithm)
這個(gè)算法就可以對(duì)低頻的參數(shù)做較大的更新,對(duì)高頻的做較小的更新,也因此,對(duì)于稀疏的數(shù)據(jù)它的表現(xiàn)很好,很好地提高了 SGD 的魯棒性,例如識(shí)別 Youtube 視頻里面的貓,訓(xùn)練 GloVe word embeddings,因?yàn)樗鼈兌际切枰诘皖l的特征上有更大的更新。
Adagrad其實(shí)是對(duì)學(xué)習(xí)率進(jìn)行了一個(gè)約束。即:

特點(diǎn):
前期gt較小的時(shí)候, regularizer較大,能夠放大梯度
后期gt較大的時(shí)候,regularizer較小,能夠約束梯度
適合處理稀疏梯度
缺點(diǎn):
由公式可以看出,仍依賴于人工設(shè)置一個(gè)全局學(xué)習(xí)率
學(xué)習(xí)率設(shè)置過大的話,會(huì)使regularizer過于敏感,對(duì)梯度的調(diào)節(jié)太大
中后期,分母上梯度平方的累加將會(huì)越來越大,使gradient趨近于0,使得訓(xùn)練提前結(jié)束
7.Adadelta
改進(jìn)方法一:Accumulate Over Window
在一個(gè)窗口w中對(duì)梯度進(jìn)行求和,而不是對(duì)梯度一直累加
因?yàn)榇娣?w 之前的梯度是低效的,所以可以用對(duì)先前所有梯度均值(使用RMS即均方根值實(shí)現(xiàn))的一個(gè)指數(shù)衰減作為代替的實(shí)現(xiàn)方法。
更新公式如下:
① 將累計(jì)梯度信息從全部歷史梯度變?yōu)楫?dāng)前時(shí)間向前的一個(gè)窗口期內(nèi)的累積:

相當(dāng)于歷史梯度信息的累計(jì)乘上一個(gè)衰減系數(shù)ρ,然后用(1?ρ)作為當(dāng)前梯度的平方加權(quán)系數(shù)相加。
②然后將上述E[gt2?] 開方后,作為每次迭代更新后的學(xué)習(xí)率衰減系數(shù):

,其中?是為了防止分母為0而加上的一個(gè)極小值。
這種更新方法解決了對(duì)歷史梯度一直累加而導(dǎo)致學(xué)習(xí)率一直下降的問題,但是還是需要自己選擇初始的學(xué)習(xí)率。
改進(jìn)方法二:Correct Units with Hessian Approximation
通過牛頓法可以知道,牛頓法迭代步長(zhǎng)是f''(x),一階牛頓迭代公式為;

可以看出牛頓算法的迭代步長(zhǎng)是二階近似的解析解,不需要我們手動(dòng)指定學(xué)習(xí)率。
??而高階的牛頓法迭代的步長(zhǎng)為Hessian矩陣。
AdaDelta算法正是采用了這種思想,采用Hessian矩陣的對(duì)角線近似Hessian矩陣。

同理對(duì)分子分母按照上一個(gè)方法進(jìn)行處理,可以得到以下公式:

7.RMSprop
RMSprop 是 Geoff Hinton 提出的一種自適應(yīng)學(xué)習(xí)率方法。
RMSprop 和 Adadelta 都是為了解決 Adagrad 學(xué)習(xí)率急劇下降問題的,
梯度更新規(guī)則:
RMSprop 與 Adadelta 的第一種形式相同:(使用的是指數(shù)加權(quán)平均,旨在消除梯度下降中的擺動(dòng),與Momentum的效果一樣,某一維度的導(dǎo)數(shù)比較大,則指數(shù)加權(quán)平均就大,某一維度的導(dǎo)數(shù)比較小,則其指數(shù)加權(quán)平均就小,這樣就保證了各維度導(dǎo)數(shù)都在一個(gè)量級(jí),進(jìn)而減少了擺動(dòng)。允許使用一個(gè)更大的學(xué)習(xí)率η)

超參數(shù)設(shè)定值:
Hinton 建議設(shè)定 γ 為 0.9, 學(xué)習(xí)率 η 為 0.001。
8.Adam:Adaptive Moment Estimation
這個(gè)算法是另一種計(jì)算每個(gè)參數(shù)的自適應(yīng)學(xué)習(xí)率的方法。相當(dāng)于 RMSprop + Momentum
除了像 Adadelta 和 RMSprop 一樣存儲(chǔ)了過去梯度的平方 vt 的指數(shù)衰減平均值 ,也像 momentum 一樣保持了過去梯度 mt 的指數(shù)衰減平均值:

如果 mt 和 vt 被初始化為 0 向量,那它們就會(huì)向 0 偏置,所以做了偏差校正,通過計(jì)算偏差校正后的 mt 和 vt 來抵消這些偏差:

梯度更新規(guī)則:

超參數(shù)設(shè)定值:
建議 β1 = 0.9,β2 = 0.999,? = 10e?8
實(shí)踐表明,Adam 比其他適應(yīng)性學(xué)習(xí)方法效果要好。
?二.效果比較
下面看一下幾種算法在鞍點(diǎn)和等高線上的表現(xiàn):

SGD optimization on saddle point

?SGD optimization on loss surface contours
上面兩種情況都可以看出,Adagrad, Adadelta, RMSprop 幾乎很快就找到了正確的方向并前進(jìn),收斂速度也相當(dāng)快,而其它方法要么很慢,要么走了很多彎路才找到。
由圖可知自適應(yīng)學(xué)習(xí)率方法即 Adagrad, Adadelta, RMSprop, Adam 在這種情景下會(huì)更合適而且收斂性更好。
三.如何選擇優(yōu)化算法
如果數(shù)據(jù)是稀疏的,就用自適用方法,即 Adagrad, Adadelta, RMSprop, Adam。
RMSprop, Adadelta, Adam 在很多情況下的效果是相似的。
Adam 就是在 RMSprop 的基礎(chǔ)上加了 bias-correction 和 momentum,
隨著梯度變的稀疏,Adam 比 RMSprop 效果會(huì)好。
整體來講,Adam 是最好的選擇。
很多論文里都會(huì)用 SGD,沒有 momentum 等。SGD 雖然能達(dá)到極小值,但是比其它算法用的時(shí)間長(zhǎng),而且可能會(huì)被困在鞍點(diǎn)。
如果需要更快的收斂,或者是訓(xùn)練更深更復(fù)雜的神經(jīng)網(wǎng)絡(luò),需要用一種自適應(yīng)的算法。
備用知識(shí):
駐點(diǎn),極值點(diǎn),拐點(diǎn) ,鞍點(diǎn)
導(dǎo)數(shù)、微分、偏導(dǎo)數(shù)、全微分、方向?qū)?shù)、梯度的定義與關(guān)系