之前一直想總結(jié)一下深度學習中常用的梯度下降算法的,后來發(fā)現(xiàn)有人做了,那好吧,直接翻譯吧。
一、變量的更新方法
1.1 Batch gradient descent
這種變量的更新方法是利用整個數(shù)據(jù)集的數(shù)據(jù),也就是一個batch來計算出損失函數(shù)的梯度,進而來更新網(wǎng)絡(luò)中的參數(shù),公式如下:
因為這種更新方法,我們更新一次參數(shù)需要對整個數(shù)據(jù)集進行計算,所以更新一次參數(shù)的速度很慢。而且這種方式也不允許我們進行線上更新,比如隨時有新的圖片輸入的情況。
這種batch的梯度下降更新方式的偽代碼如下所示:
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
上面表示的過程是對于預先定義的迭代次數(shù)nb_epochs,先通過損失函數(shù)和整個數(shù)據(jù)集計算出各個參數(shù)的梯度值,然后利用所得的梯度和預定義學習率更新參數(shù)。batch gradient descent能保證在凸損失函數(shù)曲面取得全局最優(yōu)解,對于非凸曲面能取得局部最優(yōu)解。
1.2 Stochastic gradient descent
這個方法叫做隨機梯度下降,簡稱SGD。該方法是為一個樣例(樣例包含訓練樣本和標注
)來更新一次參數(shù),如下式所示:
因為該更新方法是對每一個樣例而言的,所以參數(shù)更新比Batch的方式快。但這種方式可能會導致參數(shù)更新波動較大,如下圖所示。

相對于Batch方式,SGD的更新方式,波動大可能能使得梯度下降到更好的另一個局部最優(yōu)解,但另一方面來講,SGD的更新可能導致梯度一直在局部最優(yōu)解附近波動。然而,訓練時不斷的緩慢減小學習率,SGD能和Batch方法一樣,在凸損失函數(shù)曲面取得全局最優(yōu)解,對于非凸曲面能取得局部最優(yōu)解。
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
1.3 Mini-batch gradient descent
這種更新方式是目前用的最多的一種更新方式,如下式所示:
這種方式有兩個優(yōu)點:
a) 相對于SGD來說可以減小參數(shù)更新的波動
b) 能夠利用矩陣操作,來提高參數(shù)的更新效率
一般minibatch的值在50~256之間選擇,不同的應(yīng)用選擇不同,這個也是一個超參數(shù)。
Mini-batch gradient descent的偽代碼如下所示:
for i in range(nb_epochs):
np.random.shuffle(data)
for batch in get_batches(data, batch_size):
params_grad = evaluate_gradient(loss_function, batch, params)
params = params - learning_rate * params_grad
二、挑戰(zhàn)
上述的方法不一定能保證好的收斂性,而且還有下面一些挑戰(zhàn):
- learning rate這個超參數(shù)不好選擇。太小收斂速度慢,太大容易在局部最優(yōu)附近波動。
- learning rate的變化規(guī)則不好定。預先定好的規(guī)則不能很好的適應(yīng)數(shù)據(jù)集的特征。
- 同一個learning rate對所有的參數(shù)進行更新。不同的參數(shù)可能需要更新的步長不一致,但是上述方法都是按照相同的步長更新。
- 對于非凸損失函數(shù),參數(shù)的更新不能很好的使得梯度更新跳出高緯函數(shù)的多個局部最優(yōu),甚至是遇到某些鞍點(可以想象一個馬鞍的形狀,一個緯度坡度是上升的,其他的坡度是下降的)的區(qū)域,不能很快的跳出鞍點。
三、梯度下降優(yōu)化算法
為了解決上述一些問題,下面介紹一些常用的優(yōu)化算法。
3.1 Momentum
SGD容易在一些類似于溝壑的曲面上震蕩,可以想象一個小球在一個溝上滑動,這個溝壑一個緯度比其他緯度更陡,SGD更新方法在更陡的坡上震蕩較大,導致算法更新到達局部最優(yōu)的時間較長。為了解決這種問題,Momentum梯度優(yōu)化算法提出來了,可以想象在坡度更不陡的方向上給小球加上一個動量,使得小球更快的跑到局部最優(yōu)點。如下圖所示

Momentum是SGD的一種改進方法,該算法新增一個的超參數(shù),根據(jù)以前的動量和新的梯度來計算新的動量,公式如下所示:
通常設(shè)置為0.9左右的數(shù)值。
類似與一個球從u形山谷形狀的坡度滾下,它向最低點方向的速度是越來越快的,上述中的參數(shù)就會使得同一個方向的梯度疊加,不斷變化方向的梯度會相互抵消,所以可以使得梯度可以更快的收斂。
3.2 Nesterov accelerated gradient
假象一個球讓它沒有指導的自由的沿著山坡滾到山谷,這樣做法非常的不安全。我們希望有一個更為聰明的小球,當它快要滾到山谷的時候,它速度減慢。
Nesterov accelerated gradient下面簡稱NAG就是這樣一種梯度更新算法。在上述的momentum算法中,我們會使用來更新參數(shù),這樣就可以得到新的參數(shù)位置
。下面我們可以通過即將得到的新參數(shù)位置先一步的得到我們要更新的參數(shù)大小,如下式所示:
如下圖所示,假設(shè)我們設(shè)為0.9。對于momentum來說,優(yōu)化器先計算出參數(shù)的梯度,如圖中的短藍線所示,然后momentum要更新的動量為圖中的長藍線。對于NAG來說,先計算出梯度,然后指導帶更新的動量大小如下圖的長灰線所示,根據(jù)所得的灰線再計算要修改真正要更新動量的大小和方向,最后得到長的綠色線。通過這種更新方式可以防止參數(shù)更新過快的問題,這種算法對RNNs來說有較好的效果。

3.3 Adagrad
Adagrad是這樣的一種更新算法,它對于不同的參數(shù)有不同的更新參數(shù),對于頻繁更新參數(shù)采用小的更新值,不頻繁的更新參數(shù)采用較大的更新值進行更新。
之前所提到的算法,對于所有參數(shù)中的每個參數(shù)
來說,使用的都是相同的學習率
來更新的。而Adagrad優(yōu)化算法,對于t時刻,每個參數(shù)
使用的學習率是不同的。為了方便理解,對于每個參數(shù)
來解釋一下它的原理。下面規(guī)定使用符號
來表示目標函數(shù)對于在t時刻,參數(shù)
的梯度值。
對于SGD來說,在在t時刻,參數(shù)的更新方式如下:
而Adagrad在t時刻對參數(shù)的更新值是更新
過去的梯度來求得的:
上式中,是一個對角矩陣,該矩陣中每個對角線上的元素(i,i)為過去0-t時刻參數(shù)
梯度的平方和。
是為了防止除零設(shè)置的一個參數(shù),一般設(shè)置為1e-8。這個算法還有個有趣的事情,公式中不加入平方根,會導致算法效果不好。
因為包含了過去的梯度值的平方,對于所有參數(shù)來說,上述公式可以寫成矩陣的形式:
表示矩陣元素間相乘。
使用Adagrad算法的一個好處就是可以不用手動調(diào)節(jié)訓練率,一般默認設(shè)置為0.01。
而它也有不太好的地方,因為該算法不斷的在分母加過去的梯度平方值,導致隨著訓練次數(shù)的增加,訓練的步長越來越小,可能最后模型還沒收斂,參數(shù)確不怎么更新了。
3.4 Adadelta
Adadelta是Adagrad的升級版,它的提出是為了解決Adagrad梯度不停減小的問題。
Adadelta采用的不是將過去所有的梯度平方相加,而是引入了指數(shù)平均來做的。
這里和momentum里設(shè)置的一樣,為0.9。
下面為了更好理解,先把SGD公式抄過來
對于Adagrad來說是過去所有梯度平方和
現(xiàn)在將分母替換為指數(shù)平均數(shù)得到下式
上式中因為分母為梯度的均方根形式,所以可以簡寫為
Adadelta作者發(fā)現(xiàn)上式的更新(也包括SGD,momentum,Adagrad)中,值和待更新的參數(shù)假設(shè)的單位(hypothetical units)不同(這里的單位是假設(shè)的,如果有單位的話,adagrad的更新參數(shù)的單位分子和分母抵消了),為了解決這個問題,文章又引入下面一個指數(shù)平均:
上式的均方根誤差的形式如下
因為在求時,
還沒求出來,所以使用
作為代替,參數(shù)的更新規(guī)則如下:
從上面公式可以看出,使用Adadelta不需要設(shè)置學習率。
3.5 RMSProp
RMSProp通過文章而公布的一個算法,它是在Geoff Hinton課堂上提出的算法。
和Adadelta一樣,RMSProp也是Adagrad一個改進版本,只是它和Adadelta是獨立提出來的。它的公式其實上面已經(jīng)介紹過了,下面再抄一遍:
一般的設(shè)置為0.9,
設(shè)置為0.001。
3.6 Adam
Adam全稱Adaptive Moment Estimation,Adam不僅像Adadelta和RMSprop一樣計算過去梯度平方的指數(shù)平均值,還會計算過去梯度的指數(shù)平均值
。
從上式可以看出,當和
初始化為0,且在
和
值接近1的情況下,這兩個指數(shù)平均值一直在0附近。
Adam為了消除這種影響,使用下面兩式來代替上述兩個momentum:
然后類似與Adadelta和RMSprop,Adam參數(shù)更新算法如下所示:
通常,上式中設(shè)為0.9,
設(shè)為0.999,
設(shè)為
3.7 AdaMax
不同于Adam,在計算時使用的是過去的梯度平方也就是
norm,更為廣義的可以計算過去梯度的
norm。
AdaMax就是將之前的1范數(shù)和2范數(shù)替換成了無窮范數(shù),下面為了防止符號與之前的符號混淆,使用代替
:
于是,AdaMax的參數(shù)更新規(guī)則為
通常,設(shè)為0.002,
設(shè)為0.9,
設(shè)為0.999。
4.8 Nadam
因為Adam優(yōu)化器可以看作RMSprop與momentum的結(jié)合,而NAG又是來源于原始的momentum,那Nadam可以看作是將NAG和Adam結(jié)合的一個算法。
為了使公式能和Adam統(tǒng)一,下面momentum項用表示。下面先來用新的符號重寫一下momentum算法:
將上面三個式子合并得
而NAG算法可以表示如下:
下面Dozat提出將NAG做一些修改,不同于原來的NAG算法,先更新梯度,然后更新參數(shù)。這里直接通過look-ahead momentum直接更新參數(shù):
從上式可以看出,不同于以往是通過來更新參數(shù),這里是使用
來更新參數(shù)。
為了將NAG應(yīng)用到Adam中,先抄寫Adam公式:
將展開得到下式:
上式又可寫為:
這個式子與上面寫的momentum式子很像,類似于將momentum做一個NAG的優(yōu)化,得到Nadam。
參考