目錄
- 1 vanilla gradient descent
- 2 Newton’s method
- 3 damped Newton’s method
- 4 conjugate gradient descent
- 5 momentum
- 6 Nesterov accelerated gradient
- 7 Adagrad
- 8 Adadelta/RMSprop
- 9 Adam
0介紹——目標(biāo)函數(shù)函數(shù)
選取的二元函數(shù)為 . 該函數(shù)在原點(diǎn)附近有全局最小值膘魄、局部極小值和鞍點(diǎn)。作目標(biāo)函數(shù)等高線圖如下:
source('gradientDescent.R')
showTrace(NULL, 'Contour')
優(yōu)化方法比較
所有優(yōu)化算法的R代碼都在 gradientDescent.R 中。
1Vanilla Gradient Descent
基本思路:
多元函數(shù)在
處下降最快的方向?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=-%5Cnabla%20f(%5Cboldsymbol%7Bx%7D)" alt="-\nabla f(\boldsymbol{x})" mathimg="1">,取正數(shù)
作為學(xué)習(xí)率,其梯度下降的迭代公式為:
[\boldsymbol{x} \leftarrow \boldsymbol{x} - \eta \nabla f(\boldsymbol{x})]
從以上等高線圖中選取初始點(diǎn)讶坯,以0.1的學(xué)習(xí)率進(jìn)行梯度下降:
result1 = train_2d(vanilla_gd, c(0.8, -1, 0.1)); showTrace(result1, 'vanilla')
result2 = train_2d(vanilla_gd, c(0.5, 1, 0.1)); addTrace(result2, 'red')
result3 = train_2d(vanilla_gd, c(-1, -1, 0.1)); addTrace(result3, 'yellow')
result4 = train_2d(vanilla_gd, c(0.5, -0.2, 0.1)); addTrace(result4, 'green')
result5 = train_2d(vanilla_gd, c(-1, 2, 0.1)); addTrace(result5, 'purple')
上圖中一共進(jìn)行了20次迭代,除了黑色軌跡,其他軌跡基本都收斂到了全局最小值焰扳。綠色軌跡起始點(diǎn)在鞍點(diǎn)附近,最終也迭代到了全局最小误续。
目標(biāo)函數(shù)下降過(guò)程(顏色和上圖對(duì)應(yīng)吨悍,不包括迭代到鞍點(diǎn)的曲線):
source('gradientDescent.R')
objLineChart(result5, 1, 'purple')
objLineChart(result2, 0, 'red')
objLineChart(result3, 0, 'yellow')
objLineChart(result4, 0, 'green')
2Newton's Method
迭代公式:
[\boldsymbol{x} \leftarrow \boldsymbol{x} - H^{-1}(x) \nabla f(\boldsymbol{x})]
等高線圖上的下降過(guò)程:
fiter = Newton;
result1 = train_2d(fiter, c(0.8, -1)); showTrace(result1, 'Newton\'s Method')
result2 = train_2d(fiter, c(-0.5, 0.5)); addTrace(result2, 'red')
result3 = train_2d(fiter, c(-1, 0.5)); addTrace(result3, 'blue')
result4 = train_2d(fiter, c(1.5, -1)); addTrace(result4, 'green')
result5 = train_2d(fiter, c(-0.2, -0.4)); addTrace(result5, 'purple')
上圖中一共進(jìn)行了20次迭代,首先可見雖然下降速度非程G叮快育瓜,符合前面的討論,但牛頓法也很容易落入saddle point/local minima 中栽烂。
目標(biāo)函數(shù)值下降過(guò)程(顏色和上圖對(duì)應(yīng)躏仇,不包括迭代到鞍點(diǎn)的曲線):
objLineChart(result5, 1, 'purple')
objLineChart(result2, 0, 'red')
objLineChart(result3, 0, 'yellow')
objLineChart(result4, 0, 'green')
從本質(zhì)上看恋脚,牛頓法是二階收斂(用二次曲面擬合當(dāng)前曲面),梯度下降是一階收斂钙态,因此牛頓法收斂更快慧起。缺點(diǎn)是迭代過(guò)程每一步都需要計(jì)算 Hessian 矩陣,當(dāng)多元函數(shù)復(fù)雜或者不可知時(shí)運(yùn)算量巨大册倒。
3Damped Newton's Method
阻尼牛頓法相比牛頓法在迭代過(guò)程中增加了線搜索蚓挤,可以修改迭代的步長(zhǎng),在原步長(zhǎng)的基礎(chǔ)上進(jìn)行線性拉伸使目標(biāo)函數(shù)最小驻子。
等高線圖上的下降過(guò)程:
fiter = dampedNewton;
result1 = train_2d(fiter, c(0.8, -1)); showTrace(result1, 'Newton\'s Method')
result2 = train_2d(fiter, c(-0.5, 1.5)); addTrace(result2, 'red')
result3 = train_2d(fiter, c(-1, 0.5)); addTrace(result3, 'blue')
result4 = train_2d(fiter, c(1.5, -1)); addTrace(result4, 'green')
result5 = train_2d(fiter, c(-1, -1.5)); addTrace(result5, 'purple')
上圖中一共進(jìn)行了20次迭代灿意,可以明顯看出線搜索的效果(尤其是紫色軌跡)。但如果改變參數(shù)崇呵,仍然很容易出現(xiàn)收斂到鞍點(diǎn)和局部極小值的情形缤剧。
目標(biāo)函數(shù)值下降過(guò)程:
objLineChart(result5, 1, 'purple')
objLineChart(result2, 0, 'red')
objLineChart(result3, 0, 'blue')
4Conjugate Gradient
共軛梯度法是介于最速下降法與牛頓法之間的一個(gè)方法,它僅需利用一階導(dǎo)數(shù)信息域慷,但克服了最速下降法收斂慢的缺點(diǎn)荒辕,又避免了牛頓法需要存儲(chǔ)和計(jì)算Hesse矩陣并求逆的缺點(diǎn)。其優(yōu)點(diǎn)是所需存儲(chǔ)量小犹褒,具有步收斂性抵窒,穩(wěn)定性高,而且不需要任何外來(lái)參數(shù)叠骑。^[https://en.wikipedia.org/wiki/Conjugate_gradient_method] 算法如下:
conjugateGradient = function(x, eps){
results = x
r = 10;
for(k in 0:r){
if(k == 0){
p = - dfun(x)
g = dfun(x)
}
lambda = softline(x, p, fun, dfun)
x = x + lambda*p
g0 = g
g = dfun(x)
if(sqrt(g*g) < eps) break
if(k==r-1){
k = 0
}else{
alpha = g*g/(g0*g0)
p = -g + alpha*p
}
if(p %*% g){
k = 0
}
results = rbind(results, x)
}
print(dfun(x))
return(results)
}
等高線圖上的下降過(guò)程:
result1 = conjugateGradient(c(1, -1), 1e-6); showTrace(result1, 'Conjugate Gradient')
result2 = conjugateGradient(c(0.5, 1), 1e-6); addTrace(result2, 'red')
result3 = conjugateGradient(c(-1, -1), 1e-6); addTrace(result3, 'blue')
result4 = conjugateGradient(c(0.5, -0.2), 1e-6); addTrace(result4, 'green')
result5 = conjugateGradient(c(-1, 2), 1e-6); addTrace(result5, 'purple')
圖中沒(méi)有體現(xiàn)出的是李皇,共軛梯度法并不是迭代次數(shù)越多精度越高,在實(shí)際應(yīng)用中對(duì)終止條件有比較高的要求宙枷。
目標(biāo)函數(shù)值下降過(guò)程:
objLineChart(result2, 1, 'red')
objLineChart(result3, 0, 'blue')
objLineChart(result4, 0, 'green')
objLineChart(result5, 0, 'purple')
5Momentum
在使用梯度下降迭代時(shí)掉房,常出現(xiàn)目標(biāo)函數(shù)不同方向下降速度差異很大的情況,這時(shí)就容易導(dǎo)致自變量在某些方向上振蕩甚至發(fā)散(學(xué)習(xí)率過(guò)大時(shí))慰丛。動(dòng)量法的引入解決了上述問(wèn)題卓囚,其原理是使用指數(shù)加權(quán)平均的步長(zhǎng),在每個(gè)時(shí)間步的自變量更新量近似于將前者對(duì)應(yīng)的最近 個(gè)時(shí)間步的更新量做了指數(shù)加權(quán)移動(dòng)平均后再除以
诅病。所以動(dòng)量法中哪亿,自變量在各個(gè)方向上的移動(dòng)幅度不僅取決當(dāng)前梯度,還取決于過(guò)去的各個(gè)梯度在各個(gè)方向上是否一致睬隶。
迭代公式:
其中,動(dòng)量 hyperparameter 滿足
页徐。當(dāng)
時(shí)苏潜,動(dòng)量法等價(jià)于梯度下降。
等高線圖上的下降過(guò)程:
fiter = momentum;
hyperparams = c(0.1, 0.5)
result1 = train_2d(fiter, c(0.67, -1.8, hyperparams, 0, 0)); showTrace(result1, 'Momentum')
result2 = train_2d(fiter, c(-1.9, 1.5, hyperparams, 0, 0)); addTrace(result2, 'red')
result3 = train_2d(fiter, c(0.5, 1, hyperparams, 0, 0)); addTrace(result3, 'blue')
result4 = train_2d(fiter, c(1.5, 1.5, hyperparams, 0, 0)); addTrace(result4, 'green')
result5 = train_2d(fiter, c(0.2, -1.8, hyperparams, 0, 0)); addTrace(result5, 'purple')
局部極小值是難以避免的变勇,但相比牛頓法等二階方法恤左,不容易落到鞍點(diǎn)贴唇。
目標(biāo)函數(shù)值下降過(guò)程(綠色為局部極小值):
objLineChart(result2, 1, 'red')
objLineChart(result1, 0, 'black')
objLineChart(result5, 0, 'purple')
objLineChart(result3, 0, 'blue')
objLineChart(result4, 0, 'green')
6Nesterov Accelerated Gradient
NAG 是在動(dòng)量法基礎(chǔ)上改進(jìn)得到的。NAG在 Momentum 計(jì)算步長(zhǎng)的步驟中飞袋,不計(jì)算當(dāng)前位置的梯度方向戳气,而是計(jì)算“按照累積動(dòng)量方向迭代一步后的下降方向”。迭代公式:
等高線圖上的下降過(guò)程:
fiter = NAG;
hyperparams = c(0.1, 0.5)
result1 = train_2d(fiter, c(0.66, -1.8, hyperparams, 0, 0)); showTrace(result1, 'NAG')
result2 = train_2d(fiter, c(-1.9, 1.5, hyperparams, 0, 0)); addTrace(result2, 'red')
result3 = train_2d(fiter, c(0.5, 1, hyperparams, 0, 0)); addTrace(result3, 'blue')
result4 = train_2d(fiter, c(1.5, 1.5, hyperparams, 0, 0)); addTrace(result4, 'green')
result5 = train_2d(fiter, c(0.2, -1.8, hyperparams, 0, 0)); addTrace(result5, 'purple')
目標(biāo)函數(shù)值下降過(guò)程(綠色為局部極小值):
objLineChart(result2, 1, 'red')
objLineChart(result1, 0, 'black')
objLineChart(result5, 0, 'purple')
objLineChart(result3, 0, 'blue')
objLineChart(result4, 0, 'green')
從等高線圖可以看出巧鸭,和 Momentum 下降軌跡相比瓶您,NAG 的梯度計(jì)算方式使得整體下降過(guò)程更加平滑連貫,下降速度也有一定的提升(黑色纲仍、紅色曲線)呀袱。
7Adagrad
在之前的GD、Momentum及其變種中郑叠,目標(biāo)函數(shù)自變量的每一個(gè)元素在相同時(shí)間步都使用同一個(gè)學(xué)習(xí)率來(lái)自我迭代夜赵。通常為了使函數(shù)在梯度較大的維度上不發(fā)散,需要選擇比較小的學(xué)習(xí)率乡革。這又會(huì)使得自變量在梯度較小的維度上迭代過(guò)慢寇僧。對(duì)此,動(dòng)量法的解決方式是讓自變量的更新方向更加連貫沸版。而 Adagrad 及以下幾種算法的解決方式是為目標(biāo)函數(shù)的每個(gè)維度調(diào)整不同的學(xué)習(xí)率嘁傀。
算法^[《動(dòng)手學(xué)習(xí)深度學(xué)習(xí)》, 李沐]:
Adagrad 的算法會(huì)使用一個(gè)小批量隨機(jī)梯度 按元素平方的累加變量
推穷。在時(shí)間步 0心包,adagrad 將
中每個(gè)元素初始化為 0。在時(shí)間步
馒铃,首先將梯度
按元素平方后累加到變量
:
其中 是按元素相乘蟹腾。接著,我們將目標(biāo)函數(shù)自變量中每個(gè)元素的學(xué)習(xí)率通過(guò)按元素運(yùn)算重新調(diào)整一下:
其中 是學(xué)習(xí)率区宇,
是為了維持?jǐn)?shù)值穩(wěn)定性而添加的常數(shù)娃殖,例如
。這里開方议谷、除法和乘法的運(yùn)算都是按元素進(jìn)行的炉爆。這些按元素運(yùn)算使得目標(biāo)函數(shù)自變量中每個(gè)元素都分別擁有自己的學(xué)習(xí)率。
等高線圖上的下降過(guò)程:
fiter = adagrad;
lr = 0.25 # learning rate
epoch = 30
result1 = train_2d(fiter, c(0.66, -1.8, 0, 0, lr), epoch); showTrace(result1, 'Adagrad')
result2 = train_2d(fiter, c(-1.9, 1.5, 0, 0, lr), epoch); addTrace(result2, 'red')
result3 = train_2d(fiter, c(0.5, 1, 0, 0, lr), epoch); addTrace(result3, 'blue')
result4 = train_2d(fiter, c(1.5, 1.5, 0, 0, lr), epoch); addTrace(result4, 'green')
result5 = train_2d(fiter, c(0.2, -1.8, 0, 0, lr), epoch); addTrace(result5, 'purple')
目標(biāo)函數(shù)值下降過(guò)程(綠色為局部極小值):
objLineChart(result2, 1, 'red')
objLineChart(result1, 0, 'black')
objLineChart(result5, 0, 'purple')
objLineChart(result3, 0, 'blue')
objLineChart(result4, 0, 'green')
等高線圖中可以明顯看出越往后下降速度越慢卧晓,表現(xiàn)在自變量越來(lái)越密集芬首。這里使用了 0.25 的學(xué)習(xí)率,和之前的方法相比逼裆,某些出發(fā)點(diǎn)的最終迭代結(jié)果仍然沒(méi)有完全下降到最小值郁稍。由此可見 Adagrad 的缺陷是,在步長(zhǎng)計(jì)算中分母根號(hào)內(nèi)的參數(shù) 是之前梯度平方的累加胜宇,導(dǎo)致整個(gè)學(xué)習(xí)率分式單調(diào)遞減耀怜。如果學(xué)習(xí)率在早期下降過(guò)快恢着,而目標(biāo)函數(shù)仍然沒(méi)有到達(dá)極小值附近,Adagrad 可能因后期移動(dòng)幅度太小而無(wú)法到達(dá)期望的解财破。
8Adadelta/rmsprop
為了解決上述分母單調(diào)遞增導(dǎo)致后期移動(dòng)幅度過(guò)小的問(wèn)題掰派,rmsprop將自適應(yīng)學(xué)習(xí)率的計(jì)算公式改為指數(shù)加權(quán)移動(dòng)平均:
其中表示按元素平方。如此一來(lái)左痢,每個(gè)變量的學(xué)習(xí)率不再單調(diào)下降或停滯不前靡羡。
fiter = rmsprop;
lr = 0.1 # learning rate
gamma = 0.9
epoch = 20
result1 = train_2d(fiter, c(0.66, -1.8, 0, 0, lr, gamma), epoch); showTrace(result1, 'rmsprop')
result2 = train_2d(fiter, c(-1.9, 1.5, 0, 0, lr, gamma), epoch); addTrace(result2, 'red')
result3 = train_2d(fiter, c(0.5, 1, 0, 0, lr, gamma), epoch); addTrace(result3, 'blue')
result4 = train_2d(fiter, c(1.5, 1.5, 0, 0, lr, gamma), epoch); addTrace(result4, 'green')
result5 = train_2d(fiter, c(0.2, -1.8, 0, 0, lr, gamma), epoch); addTrace(result5, 'purple')
目標(biāo)函數(shù)值下降過(guò)程(綠色為局部極小值):
objLineChart(result2, 1, 'red')
objLineChart(result1, 0, 'black')
objLineChart(result5, 0, 'purple')
objLineChart(result3, 0, 'blue')
objLineChart(result4, 0, 'green')
這里采用0.1的學(xué)習(xí)率, 按照原文獻(xiàn)采用0.9抖锥,從等高線圖可以看出移動(dòng)步長(zhǎng)不會(huì)像 Adagrad 那樣衰減亿眠,在較少的 epoch 內(nèi)即可收斂。
9Adam
Adam 加入了 Momentum磅废,并保留了自適應(yīng)梯度(每個(gè)元素學(xué)習(xí)率不同)纳像。迭代算法如下,其中超參數(shù) 的區(qū)間均為
拯勉,原文獻(xiàn)的建議值為
竟趾。
其中 是學(xué)習(xí)率,
是為了維持?jǐn)?shù)值穩(wěn)定性而添加的常數(shù)宫峦,例如
岔帽。
按照原文獻(xiàn)中推薦的超參數(shù) ,每一步學(xué)習(xí)率的分子有90%受前面的v決定导绷,效果不佳犀勒。參數(shù)調(diào)整為0.8后:
fiter = Adam;
lr = 0.8 # learning rate
beta = c(0.8, 0.98)
epoch = 3500
t = 1
result1 = train_2d(fiter, c(0.6, -1, 0, 0, lr, 0,0, beta, t), epoch); showTrace(result1, 'Adam, beta1 = 0.8')
result2 = train_2d(fiter, c(1, -1, 0, 0, lr, 0,0, beta, t), epoch); addTrace(result2, 'red')
result3 = train_2d(fiter, c(-1, -1, 0, 0, lr, 0,0, beta, t), epoch); addTrace(result3, 'blue')
result4 = train_2d(fiter, c(-1, 1, 0, 0, lr, 0,0, beta, t), epoch); addTrace(result4, 'green')
result5 = train_2d(fiter, c(1.8, -1.8, 0, 0, lr, 0,0, beta, t), epoch); addTrace(result5, 'purple')
目標(biāo)函數(shù)值下降過(guò)程:
#objLineChart(result2, 1, 'red')
objLineChart(result1, 1, 'black')
objLineChart(result5, 0, 'purple')
objLineChart(result3, 0, 'blue')
objLineChart(result4, 0, 'green')
最終可以收斂,但需要較大的迭代次數(shù)妥曲。出現(xiàn)這樣結(jié)果的一個(gè)原因是迭代過(guò)程中遇到了目標(biāo)函數(shù)的大片平坦區(qū)域贾费,因?yàn)榫植刻荻忍 ⒔?jīng)過(guò)指數(shù)校正后移動(dòng)較慢檐盟。另外褂萧,在代碼中使用的梯度是 batch=1 的當(dāng)前自變量梯度,實(shí)際運(yùn)用中使用小批量隨機(jī)梯度時(shí)應(yīng)該可以提升收斂速度葵萎。
參考文獻(xiàn)
- https://www.cnblogs.com/ljy2013/p/5129294.html
- https://blog.csdn.net/garfielder007/article/details/50292447
- https://zhuanlan.zhihu.com/p/22810533
- 《動(dòng)手學(xué)習(xí)深度學(xué)習(xí)》李沐