參考引用:
Blog: An overview of gradient descent optimization algorithms
review paper: An overview of gradient descent optimization algorithms
在搭積木的時(shí)候往往面臨要選擇 optimizer, 雖然說(shuō)經(jīng)驗(yàn)指導(dǎo)下選來(lái)選去都是那幾個(gè)(玄學(xué)煉丹),但是作為一個(gè)有 wei 點(diǎn) le 志 zhuang 向 bi 的科研菜鳥(niǎo),還是想自己整理學(xué)習(xí)一下各個(gè) optimizer 的特點(diǎn),留下此篇。
Gradient Descent 梯度下降
Gradient descent is one of the most popular algorithms to perform optimization in Neural network. Nearly all of the state-of-the -art Deep Learning Library contains implementations of various algorithms to optimize gradient descent.
在臺(tái)灣大學(xué)李宏毅教授的《機(jī)器學(xué)習(xí)》課程中,李宏毅教授把機(jī)器學(xué)習(xí)總結(jié)為三個(gè) step:
- step 1 : define a set of function as model
- step 2 : find a function evaluate the goodness of function
- step3: pick the best function (optimization)
Gradient descent 是用于 minimize the object function (or say, the loss function) 的一種推廣方法。我們知道在很多機(jī)器學(xué)習(xí)的課程中,介紹 gradient descent 都從多項(xiàng)式函數(shù)的優(yōu)化開(kāi)始講的,也就是類(lèi)似 這樣的函數(shù)求極值問(wèn)題。學(xué)過(guò)一點(diǎn)數(shù)值計(jì)算的話我們就知道可以用最小二乘法來(lái)求解這種問(wèn)題,但是最小二乘一般來(lái)說(shuō)是針對(duì)于線性方程組的求解方法,所以為了推廣到非線性的問(wèn)題,使用 gradient descent 是不錯(cuò)的選擇。
gradient descent 算法詳解:http://cs231n.github.io/optimization-1/
Gradient descent variants
在處理很多很多 samples,或者說(shuō)在訓(xùn)練數(shù)據(jù)集 dataset 的時(shí)候,我們就要對(duì)最原始介紹的 gradient descent 做變動(dòng)(其實(shí)就是把算法搬到數(shù)據(jù)集上應(yīng)用)。
數(shù)據(jù)集的大小會(huì)影響運(yùn)行 gradient descent 的速度,因?yàn)?gradient descent 的求導(dǎo)/求偏導(dǎo) 運(yùn)算是很花時(shí)間的,求一次導(dǎo)數(shù)更新一次參數(shù)值。如果一次性處理太多 sample 的話,那更新一次參數(shù)也未免太慢了;所以就有了設(shè)置 batch 的想法:一次就計(jì)算一批,由 batch 的 loss function 梯度來(lái)決定(近似)整個(gè) dataset 的 loss function 梯度。
根據(jù)數(shù)據(jù)集的大小,我們需要 make a trade-off between the accuracy of the parameter update and the time it takes to perform an update. 這里有三種 variants:
- Batch gradient descent ( vanilla gradient descent )
- Stocastic gradient descent
- Mini-batch gradient descent
下面一個(gè)一個(gè)講:
Batch gradient descent ( vanilla gradient descent )
Traning set 不管有多少 sample,全都拿去計(jì)算 gradient. 訓(xùn)練集在 500 以下都可以直接用。
Batch gradient descent can be very slow and is intractable for datasets that don't fit in memory. Batch gradient descent also doesn't allow us to update our model online .
Batch gradient descent is guaranteed to converge to the global minimum for convex error surfaces and to a local minimum for non-convex surfaces.
偽代碼如下
for i in range( number_epoch ):
parameters_gradient = evaluate_gradient(loss_function, full_data, parameters)
parameters = parameters - learning_rate * parameters_gradient
缺點(diǎn): Batch gradient descent performs redundant computations for large datasets, as it recomputes gradients for similar examples before each parameter update
Stochastic gradient descent (SGD)
Stochastic gradient descent performs a parameter update for each training example and laybel
. 來(lái)一個(gè) sample 算一次 gradient。
SGD does away with redundancy of recomputes gradient by performing one update at a time. It is therefore usually much faster and can also be used to learn online.
不過(guò)每來(lái)一個(gè) example 就 update 一次參數(shù)未免也太頻繁了,而且每次來(lái)的 example 其實(shí)個(gè)體差異性挺大的,這樣導(dǎo)致最后 object function 波動(dòng)很厲害:
SGD's fluctuation enables it to jump to new and potentially better local minima. On the other hand, this ultimately complicates convergence to the exact minimum, as SGD will keep overshooting.
不過(guò),只要我們緩慢的減小 learning rate,SGD 就可以表現(xiàn)出和 Batch GD一樣的性能 —— 陷入全局最優(yōu) or 局部最優(yōu)。
偽代碼如下:
for i in range(number_epochs):
np.random.shuffle(data)
for example in full_data:
parameters_gradient = evaluate_gradient(loss_function, example, parameters)
parameters = parameters - learning_rate * parameters_gradient
Mini-batch gradient descent
結(jié)合上述兩種方法的利弊(其實(shí)上面兩種方法對(duì)應(yīng)兩個(gè)極端情況),我們?nèi)∫粋€(gè) Batch (批次),一批數(shù)據(jù)算一次 loss 然后算偏導(dǎo)進(jìn)行參數(shù)更新。假設(shè)一個(gè) batch 有 n 個(gè) example, 也就是 batch_size = n, 有:
設(shè)置 batch 的好處在于:
- reduces the variance of the parameter updates, which can lead to more stable convergence
- can make use of highly optimized matrix optimizations common to state-of-the-art deep learning libraries that make computing the gradient w.r.t. a mini-batch very efficient
常用的 batch 大?。?50、100、128、256.... 有的觀點(diǎn)認(rèn)為用 2 的冪次會(huì)更快。
偽代碼如下:
for i in range(number_epochs):
np.random.shuffle(data)
for batch in get_batch(full_data, batch_size=128):
parameter_gradient = evaluate_gradient(loss_function, batch, parameter)
parameter = parameter - learning_rate * parameter_gradient
Challenge 困難與挑戰(zhàn)
照這么看,似乎 Gradient Descent 已經(jīng)很好的滿足了我們的使用需求了。然而進(jìn)一步實(shí)踐可以發(fā)現(xiàn)即使是 mini_batch GD 也存在很多問(wèn)題: 我們只解決了由單次運(yùn)算數(shù)據(jù)量引起的梯度下降準(zhǔn)確性 accuracy 問(wèn)題與運(yùn)算時(shí)間(效率)的問(wèn)題,還有其他困難和挑戰(zhàn):
- How to choose a proper learning rate
?
- If we use 'Learning Rate Schedules', i.e. adjusting (or say, reducing) the learning rate according to a pre-defined schedule or when the change in objective between epochs falls below a threshold. These schedules and thresholds have to be defined in advance and are thus unable to adapt to a dataset's characteristics.
- Additionally, the same learning rate applies to all parameter updates. If our data is sparse and our features have very different frequencies, we might not want to update all of them to the same extent, but perform a larger update for rarely occurring features.
- Another key challenge of minimizing highly non-convex error functions common for neural networks is avoiding getting trapped in their numerous suboptimal local minima & saddle points. For saddle points, they are usually surrounded by a plateau of the same error, which makes it notoriously hard for SGD to escape, as the gradient is close to zero in all dimensions.
面對(duì)以上這些問(wèn)題與挑戰(zhàn),有許多改進(jìn)的方法不斷涌現(xiàn):
Momentum 動(dòng)量
討論一個(gè)二維的優(yōu)化問(wèn)題:假設(shè)兩個(gè)維度上的梯度分布是不同步的,比方說(shuō)梯度曲線為橢圓形(這樣的情況經(jīng)常出現(xiàn)在 local minima 附近),如下圖所示。圖中最中間的小橢圓為梯度引導(dǎo)的最低處,可以把這個(gè)圖想象成一個(gè)峽谷,SGD 的優(yōu)化目標(biāo)就是要優(yōu)化到最中間的低處去。
在這種情況下,SGD 會(huì)在峽谷的兩側(cè)表面頻繁的震蕩,使得整個(gè)優(yōu)化過(guò)程十分緩慢。

Momentum 就是幫助 SGD 在這種條件下進(jìn)行加速的一種方法: 在每次對(duì) parameter vector 進(jìn)行更新時(shí),加上一個(gè)動(dòng)量項(xiàng),即上一次梯度更新的步長(zhǎng)
很小的常量
:
Vanilla_SGD:
SGD_with_ Momentum :
常常取 0.9、0.8 等等,而初速度
其實(shí)自己定義就行,初速度為0就可以,初始梯度會(huì)賦予它更新的速度值
在使用 Momentum 的時(shí)候,由于動(dòng)量的不斷累積,在 參數(shù) update 過(guò)程中相同方向的 update 會(huì)越來(lái)越快,可以沖過(guò)一些 saddle point, 使得算法更快收斂、震蕩次數(shù)更少。
Nesterov accelerated gradient
重新想回 Momentum,我們?cè)O(shè)想假如一個(gè) minima 位于兩座“山”之間,由于 Momentum 的存在,小球總是要往兩邊滾來(lái)滾去往復(fù)很久才能最終停在中間位置。有沒(méi)有一種方法能夠讓小球能夠在小球準(zhǔn)備沖上下一座“山”之前就減速呢?
Nesterov accelerated gradient (NAG) 就是這樣一種方法。
回想一下我們?cè)?Momentum 方法中用到的動(dòng)量項(xiàng) 代表了上一次梯度更新的影響,
表示參數(shù)
減去動(dòng)量項(xiàng)的影響后,下一次參數(shù)應(yīng)該更新的 “大概位置”。這里說(shuō)大概位置是因?yàn)檎鎸?shí)的下一次參數(shù)應(yīng)該更新的位置其實(shí)是
. 如果我們知道了下一次位置的近似值,根據(jù)下一次的位置求偏導(dǎo)求更新的步長(zhǎng)來(lái)指導(dǎo)當(dāng)下的運(yùn)動(dòng),那么算法就有了 “預(yù)見(jiàn)性 prescience”, 這樣就可以讓
在參數(shù)準(zhǔn)備到達(dá) minima 的時(shí)候提前減速,而不用過(guò)多受 Momentum term 的影響 push 到更遠(yuǎn)的地方。
SGD with Momentum :
Nesterov accelerated gradient :
更多更具體的數(shù)學(xué)解釋?zhuān)梢詤⒄眨?a target="_blank" rel="nofollow">http://cs231n.github.io/neural-networks-3/
上面的方法已經(jīng)可以讓 optimizer 根據(jù) Loss function surface 自適應(yīng)的進(jìn)行加速/減速了,但科學(xué)家還不滿足,之前計(jì)算 gradient 都是計(jì)算 ,
各個(gè)分量(維度)在統(tǒng)一的 learning rate 下進(jìn)行更新。我們還希望根據(jù)每個(gè)單獨(dú)的參數(shù)進(jìn)行調(diào)整更新,以便根據(jù)它們的重要性執(zhí)行較大或較小的 update。
Adagrad
Adagrad 的好處在于:It adapts the learning rate to the parameters.
所謂的 “Adapts 自適應(yīng)” 就是說(shuō),在 frequently occurring features 時(shí)能夠減小 learning rate;在 infrequently occurring features 時(shí)能夠增大 learning rate
.什么意思呢?就是當(dāng)優(yōu)化過(guò)程中一些 feature 頻繁出現(xiàn)的時(shí)候(例如說(shuō) loss function 的 error 不太怎么改變的時(shí)候),表示算法接近收斂了,這個(gè)時(shí)候就要減小 learning rate
,也就是說(shuō)減少步長(zhǎng)去逐步接近那個(gè) minima.
For this reason, Adagrad is well-suited for dealing with sparse data.