編譯:AI100,本文經(jīng)授權(quán)發(fā)布肛走,轉(zhuǎn)載請(qǐng)聯(lián)系A(chǔ)I100.
英文:https://www.analyticsvidhya.com/blog/2017/03/introduction-to-gradient-descent-algorithm-along-its-variants/
前 言
無論是要解決現(xiàn)實(shí)生活中的難題恶复,還是要?jiǎng)?chuàng)建一款新的軟件產(chǎn)品详羡,我們最終的目標(biāo)都是使其達(dá)到最優(yōu)狀態(tài)。作為一名計(jì)算機(jī)科學(xué)專業(yè)的學(xué)生钧栖,我經(jīng)常需要優(yōu)化各種代碼低零,以便提高其整體的運(yùn)行速度。
一般情況下拯杠,最優(yōu)狀態(tài)會(huì)伴隨問題的最佳解決方案掏婶。如果閱讀近期發(fā)表的關(guān)于優(yōu)化問題的文章的話,你會(huì)發(fā)現(xiàn)潭陪,優(yōu)化問題在現(xiàn)實(shí)生活中扮演著非常重要的作用雄妥。
機(jī)器學(xué)習(xí)中的優(yōu)化問題與我們剛剛提到的內(nèi)容有些許不同。通常情況下依溯,在優(yōu)化的過程中老厌,我們非常清楚數(shù)據(jù)的狀態(tài),也知道我們想要優(yōu)化哪些區(qū)域黎炉。但是枝秤,在機(jī)器學(xué)習(xí)中,我們本就對(duì)“新數(shù)據(jù)”一無所知慷嗜,更不要提優(yōu)化問題了淀弹!
因此在機(jī)器學(xué)習(xí)中,我們對(duì)訓(xùn)練數(shù)據(jù)進(jìn)行優(yōu)化庆械,隨后再在全新的驗(yàn)證數(shù)據(jù)中檢驗(yàn)其運(yùn)行情況薇溃。
目前,優(yōu)化技術(shù)正被廣泛應(yīng)用于各種不同的領(lǐng)域中缭乘,例如:
結(jié)構(gòu)——比如說:決定航天設(shè)計(jì)的外型痊焊。
經(jīng)濟(jì)——比如說:成本最低化。
物理——比如說:優(yōu)化量子計(jì)算時(shí)間忿峻。
優(yōu)化還有許多更為高級(jí)的應(yīng)用薄啥,例如:提供最優(yōu)運(yùn)輸路徑,使貨架空間最合理化等等逛尚。
許多受歡迎的機(jī)器算法都源于優(yōu)化技術(shù)垄惧,例如:線性回歸算法、K-最近鄰算法绰寞、神經(jīng)網(wǎng)絡(luò)算法等等到逊。在學(xué)術(shù)界以及各行各業(yè)中,優(yōu)化研究比比皆是滤钱,優(yōu)化應(yīng)用隨處可見觉壶。
在本篇文章中,我會(huì)向大家介紹梯度下降(GradientDescent)這一特殊的優(yōu)化技術(shù)件缸,在機(jī)器學(xué)習(xí)中我們會(huì)頻繁用到铜靶。
什么是梯度下降?
運(yùn)用梯度下降算法所面臨的挑戰(zhàn)
梯度下降算法的變式
梯度下降的實(shí)現(xiàn)過程
使用梯度下降算法的實(shí)用小貼士
附錄
我會(huì)以經(jīng)典的登山案例來解釋梯度下降的含義争剿。
假設(shè)你現(xiàn)在在山頂處,必須抵達(dá)山腳下(也就是山谷最低處)的湖泊痊末。但讓人頭疼的是蚕苇,你的雙眼被蒙上了無法辨別前進(jìn)方向。那么凿叠,你會(huì)采取什么辦法抵達(dá)湖泊處呢涩笤?
最好的辦法就是查看一下周圍的地勢(shì),觀察有下降趨勢(shì)的地面盒件,這會(huì)幫助你邁出第一步蹬碧。如果沿著下降的路線前進(jìn),那么你非常有可能到達(dá)湖泊履恩。
以圖形的形式呈現(xiàn)該處地勢(shì)锰茉。注意下面的曲線圖:
現(xiàn)在讓我們用數(shù)學(xué)術(shù)語(yǔ)把這個(gè)情景繪制成地圖吧。
為了學(xué)習(xí)梯度下降算法切心,假設(shè)我們需要找出最佳的參數(shù)(θ1)和(θ2)飒筑。與上述做法相似,在測(cè)繪“成本空間”時(shí)绽昏,我們需要找到相似的山脈和山谷协屡。成本空間是指為參數(shù)選定了一個(gè)特殊值后,算法的運(yùn)行情況全谤。
所以肤晓,在Y軸上,我們讓J(θ1)與X軸上的參數(shù)(θ1)以及Z軸上的參數(shù)(θ2)分別相交。在這里补憾,數(shù)值高的紅色區(qū)域代表山峰漫萄,數(shù)值低的藍(lán)色區(qū)域代表山谷。
梯度下降算法的類型有很多種盈匾,主要分為兩種:
基于數(shù)據(jù)的獲取
1.全批梯度下降算法
2.隨機(jī)梯度下降算法
在全批梯度下降算法中腾务,需要利用全部數(shù)據(jù)同時(shí)計(jì)算梯度;然而在隨機(jī)梯度下降算法中削饵,通常只需選取其中一個(gè)樣例來計(jì)算梯度岩瘦。
基于微分技術(shù)
1.一階微分
2.二階微分
梯度下降需要通過成本函數(shù)微分來計(jì)算梯度。我們可以用一階微分技術(shù)或者二階微分技術(shù)來計(jì)算窿撬。
在大多數(shù)情況下启昧,梯度下降是一種聲音技術(shù)。但在很多情況下劈伴,梯度下降無法正常工作密末,甚至不工作。原因有三點(diǎn):
數(shù)據(jù)挑戰(zhàn)
梯度挑戰(zhàn)
執(zhí)行挑戰(zhàn)
如果數(shù)據(jù)按照某種方式進(jìn)行組合形成了一個(gè)非凸的優(yōu)化問題宰啦,那么就很難利用梯度下降算法對(duì)其進(jìn)行優(yōu)化了苏遥。梯度下降算法只能解決那些意義非常明確的凸優(yōu)化問題。
在優(yōu)化凸問題時(shí)赡模,可能會(huì)出現(xiàn)無數(shù)的極小點(diǎn)田炭。最低點(diǎn)被稱為全局最小值,其它的點(diǎn)被稱為局部極小值漓柑。我們的目的是要達(dá)到全局極小值教硫,而非局部極小值。
還有一個(gè)問題就是鞍點(diǎn)辆布。梯度為零時(shí)瞬矩,它是數(shù)據(jù)中的一個(gè)點(diǎn),但是不是最優(yōu)點(diǎn)锋玲。目前景用,我們還沒有特定的方法來規(guī)避鞍點(diǎn)的出現(xiàn),是一個(gè)新的研究領(lǐng)域惭蹂。
如果執(zhí)行梯度下降算法時(shí)出現(xiàn)了錯(cuò)誤伞插,那么可能會(huì)導(dǎo)致諸如梯度消失或者梯度崩潰等的問題。當(dāng)梯度太小或者太大時(shí)盾碗,就會(huì)出現(xiàn)這樣的問題媚污。也正因?yàn)檫@些問題,算法無法收斂廷雅。
通常情況下耗美,大多數(shù)神經(jīng)網(wǎng)絡(luò)的開發(fā)者不會(huì)留意執(zhí)行情況京髓,但是觀察網(wǎng)絡(luò)資源利用率是非常重要的。比如商架,在執(zhí)行梯度下降算法時(shí)堰怨,了解需要多少資源是非常重要的。如果應(yīng)用程序的儲(chǔ)存器太小甸私,那么網(wǎng)絡(luò)就會(huì)失敗诚些。
跟蹤諸如浮點(diǎn)數(shù)的注意事項(xiàng)以及軟/硬件的先決條件,也非常重要皇型。
讓我們來看一下最常用的梯度下降算法及其執(zhí)行情況。
這是梯度下降技術(shù)中最簡(jiǎn)單的形式砸烦。此處的 vanilla 是純凈/不摻雜任何雜質(zhì)的意思弃鸦。它的主要特性就是,使我們向著成本函數(shù)梯度的最小值又邁進(jìn)了一小步幢痘。
我們來看一下它的偽代碼唬格。
update=learning_rate*gradient_of_parameters
parameters=parameters-update
在這里,我們通過參數(shù)梯度來更新參數(shù)颜说。而后通過學(xué)習(xí)率使其多樣化购岗,實(shí)質(zhì)上,常數(shù)代表著我們期望的達(dá)到最小值的速率门粪。學(xué)習(xí)率是一種超參數(shù)喊积,其數(shù)值一旦確定,就需要我們認(rèn)真對(duì)待玄妈。
在進(jìn)行下一步之前乾吻,我們先對(duì)之前的算法稍作調(diào)整,以便回顧前面的步驟拟蜻。
這是一組偽代碼绎签。
update=learning_rate*gradient
velocity=previous_update*momentum
parameter=parameter+velocity–update
此處,更新后的代碼與普通的梯度下降算法一樣酝锅。但是考慮到之前的更新和常量(動(dòng)量)诡必,我們引進(jìn)了一個(gè)名為速率(velocity)的術(shù)語(yǔ)。
ADAGRAD 算法使用了自適應(yīng)技術(shù)來更新學(xué)習(xí)率搔扁。在這種算法中爸舒,我們會(huì)根據(jù)前期所有更迭的梯度變化情況,改變學(xué)習(xí)率阁谆。
這是一組偽代碼碳抄。
grad_component=previous_grad_component+(gradient*gradient)
rate_change=square_root(grad_component)+epsilon
adapted_learning_rate=learning_rate*rate_change
update=adapted_learning_rate*gradient
parameter=parameter–update
在上述代碼中,epsilon 是一個(gè)用于抑制學(xué)習(xí)率產(chǎn)生變動(dòng)率的常量场绿。
ADAM 算法是一種以 adagrad 算法為基礎(chǔ)并且能進(jìn)一步減少其缺點(diǎn)的更加自適應(yīng)的技術(shù)剖效。也就是說,你可以認(rèn)為 ADAM 算法是動(dòng)量和 ADAGRAD 算法的綜合體。
這是一組偽代碼璧尸。
adapted_gradient=previous_gradient+((gradient–previous_gradient)*(1–beta1))
gradient_component=(gradient_change–previous_learning_rate)
adapted_learning_rate=previous_learning_rate+(gradient_component*(1–beta2))
update=adapted_learning_rate*adapted_gradient
parameter=parameter–update
上述代碼中的 beta1 和 beta2 是用來保持梯度和學(xué)習(xí)率不變的常量咒林。
與此同時(shí),還存在如 l-BFGS 等這樣的二階微分算法爷光。你可以在 scipy 數(shù)據(jù)庫(kù)中看到這種算法的執(zhí)行情況垫竞。
現(xiàn)在我們來看一下利用 python 實(shí)現(xiàn)梯度下降的基礎(chǔ)小案例。
在這里蛀序,我們將會(huì)利用梯度下降優(yōu)化算法找出深度學(xué)習(xí)模型中圖像識(shí)別應(yīng)用問題的最佳參數(shù)欢瞪。我們的問題是圖像識(shí)別,從已給的28 x 28圖像中分辨出其中的數(shù)字徐裸。我們有一個(gè)關(guān)于圖像的子集遣鼓,一部分圖像用于訓(xùn)練模型,另一部分圖像用于測(cè)試模型重贺。在本篇文章中骑祟,我們會(huì)向大家介紹定義梯度下降算法的過程以及算法的運(yùn)行過程。請(qǐng)參考這篇文章中有關(guān)利用 python 實(shí)現(xiàn)端到端運(yùn)行的內(nèi)容气笙。
這是定義普通梯度下降算法的主代碼:
params=[weights_hidden,weights_output,bias_hidden,bias_output]
defsgd(cost,params,lr=0.05):
grads=T.grad(cost=cost,wrt=params)
updates=[]
forp,ginzip(params,grads):
updates.append([p,p-g*lr])
returnupdates
updates=sgd(cost,params)
為了能更好的理解上述代碼次企,接下來我們會(huì)分成不同的步驟詳細(xì)講解。
我們把 sgd 這個(gè)含有參數(shù)的函數(shù)分別定義為 cost潜圃、params 和 lr缸棵,分別代表上述例子中的 J(θ),θ是深度學(xué)習(xí)算法和學(xué)習(xí)率的參數(shù)秉犹。我們將默認(rèn)的學(xué)習(xí)率設(shè)為0.05蛉谜,但是學(xué)習(xí)率可以隨著我們的喜好輕易地發(fā)生改變。
defsgd(cost,params,lr=0.05):
然后崇堵,我們定義關(guān)于這個(gè)成本函數(shù)的梯度參數(shù)型诚。在這里,我們利用 theano 數(shù)據(jù)庫(kù)來尋找梯度鸳劳,T是我們將導(dǎo)入的 theano 數(shù)據(jù):
grads=T.grad(cost=cost,wrt=params)
最后狰贯,通過所有參數(shù)的迭代找出所有可能需要更新的參數(shù)。大家可以看到赏廓,在這里我們使用的是普通梯度下降算法涵紊。
forp,ginzip(params,grads):
updates.append([p,p-g*lr]
接下來,我們可以利用這個(gè)函數(shù)找出神經(jīng)網(wǎng)絡(luò)中的最優(yōu)參數(shù)幔摸。通過這個(gè)函數(shù)摸柄,我們發(fā)現(xiàn)神經(jīng)網(wǎng)絡(luò)非常擅長(zhǎng)在圖片中查找數(shù)據(jù),如下圖所示:
Predictionis:8
在這個(gè)實(shí)例中既忆,我們了解到利用梯度下降算法能夠得到深度學(xué)習(xí)算法中的最優(yōu)參數(shù)驱负。
對(duì)于上述提到的各種梯度下降算法嗦玖,各有利弊。接下來跃脊,我會(huì)介紹一些能夠幫助大家找到正確算法的實(shí)用方法宇挫。
如果是為了快速地獲得原型,那就選取諸如Adam/Adagrad這樣的自適應(yīng)技術(shù)酪术,這會(huì)讓我們事半功倍器瘪,并且無須大量調(diào)優(yōu)超參數(shù)。
如果是為了得到最好的結(jié)果绘雁,那就選取普通的梯度下降算法或者動(dòng)量梯度下降算法橡疼。雖然利用梯度下降算法達(dá)到預(yù)期效果的過程很緩慢,但是大部分的結(jié)果比自適應(yīng)技術(shù)要好得多咧七。
如果你的數(shù)據(jù)偏小而且能夠適應(yīng)一次迭代衰齐,那么就可以選擇諸如 l-BFGS這樣的二階技術(shù)。這是因?yàn)榧套瑁A技術(shù)雖然速度非常快并且非常準(zhǔn)確废酷,但是只適用于數(shù)據(jù)偏小的情況瘟檩。
還有一種是利用學(xué)習(xí)特性來預(yù)測(cè)梯度下降學(xué)習(xí)率的新興方法(雖然我還沒有嘗試過這種新興方法,但是看起來前途無量)澈蟆∧粒可以仔細(xì)地閱讀一下這篇文章。
目前趴俘,無法學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)算法的原因由很多睹簇。但是如果你能檢查出算法出現(xiàn)錯(cuò)誤的地方,對(duì)學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)算法將會(huì)非常有幫助寥闪。
當(dāng)選用梯度下降算法時(shí)太惠,你可以看看這些能幫助你規(guī)避問題的小提示:
誤碼率——特定迭代之后,你應(yīng)該檢查訓(xùn)練誤差和測(cè)試誤差疲憋,并且確保訓(xùn)練誤差和測(cè)試誤差有所減少凿渊。如果事實(shí)并非如此,那么可能會(huì)出現(xiàn)問題缚柳!
隱含層數(shù)的梯度風(fēng)氣流——如果網(wǎng)絡(luò)沒有出現(xiàn)梯度消失或梯度爆炸問題埃脏,那么請(qǐng)檢查一下網(wǎng)絡(luò)。
學(xué)習(xí)率——選用自適應(yīng)技術(shù)時(shí)秋忙,你應(yīng)該檢測(cè)一下學(xué)習(xí)率彩掐。
本篇文章參考了梯度下降優(yōu)化算法概述(https://arxiv.org/abs/1609.04747)。
梯度下降 CS231n 課程教材(http://cs231n.github.io/neural-networks-3/)灰追。
深度學(xué)習(xí)這本書的第四章(數(shù)值優(yōu)化算法堵幽,http://www.deeplearningbook.org/contents/numerical.html)和第八章(深度學(xué)習(xí)模型的優(yōu)化狗超,http://www.deeplearningbook.org/contents/optimization.html)。
我希望你喜歡這篇文章谐檀。在閱讀完本篇文章后抡谐,你會(huì)對(duì)梯度下降算法及其變式有一定的了解。與此同時(shí)桐猬,我還在文章中向大家提供了執(zhí)行梯度下降算法以及其變式算法的實(shí)用小貼士麦撵。希望對(duì)你有所幫助!
本文作者?Faizan Shaikh?是一名數(shù)據(jù)科學(xué)愛好者溃肪,目前正在研究深度學(xué)習(xí)免胃,目標(biāo)是利用自己的技能,推動(dòng) AI 研究的發(fā)展惫撰。