[機(jī)器學(xué)習(xí)] Gradient descent (Adagrad 、 SGD)

前言

??這篇文章是李宏毅的《機(jī)器學(xué)習(xí)》課程的筆記,主要目的是讓我自己梳理一遍課程的內(nèi)容,加深理解,找到課上沒(méi)弄懂的地方,并將新的知識(shí)點(diǎn)與我以前的一些認(rèn)知結(jié)合起來(lái)。如有寫(xiě)錯(cuò)的地方或者理解有問(wèn)題的地方希望能得到糾正,歡迎相關(guān)的問(wèn)題。

正文

??回顧在前面線性回歸處使用的梯度下降來(lái)尋找損失函數(shù) J (或記為 L) 最小時(shí)的參數(shù) \boldsymbol\theta ,我們的目標(biāo)函數(shù)是:
\boldsymbol \theta^*=\arg \min_{\boldsymbol \theta} J(\boldsymbol \theta)
??其中, \boldsymbol \theta^* 是最優(yōu)條件下的參數(shù) \boldsymbol \theta 值。

??梯度下降的方法的過(guò)程就是隨機(jī)選取一個(gè)起始點(diǎn) \boldsymbol \theta^{0}= \begin{bmatrix} \theta^0_1 \\ \theta^0_2\end{bmatrix} ,然后計(jì)算在這一點(diǎn)的梯度向量 \nabla J(\boldsymbol \theta^0) = \begin{bmatrix} \partial J(\boldsymbol \theta^0_1) / \partial \theta_1 \\ \partial J(\boldsymbol \theta^0_2) / \partial \theta_2 \end{bmatrix} ,并設(shè)定一個(gè)學(xué)習(xí)率參數(shù) \eta ,然后更新參數(shù) \boldsymbol \theta 得到一個(gè)新的 \boldsymbol \theta^1
\boldsymbol \theta^1 = \boldsymbol \theta^0 - \eta \nabla J(\boldsymbol \theta^0)
??然后不斷重復(fù)這個(gè)過(guò)程,直到找到 J 最小的點(diǎn)。上面這個(gè)是 \boldsymbol \theta 只有兩個(gè)參數(shù)的情況,也就是二維的情況,如果把 J\boldsymbol \theta 的關(guān)系圖以等高線的形式畫(huà)在圖上,那么梯度的方向向量其實(shí)就是那一點(diǎn)等高線的垂線方向。梯度下降就是不斷重復(fù)找當(dāng)前所在位置的等高線的梯度方向,然后往其反方向走一步的過(guò)程,過(guò)程如圖所示,紅線是梯度方向,藍(lán)線是移動(dòng)方向,圖中 L 就是上面的 J 表示損失函數(shù)。(PS: 學(xué)習(xí)率在李宏毅的課程中是記為 \eta 的,而在吳恩達(dá) Coursera 上是記為 \alpha ,我是先看的吳恩達(dá)的課,所以習(xí)慣用 \alpha ,不過(guò)貌似好像 \eta 作為學(xué)習(xí)率更常用,所以以后都寫(xiě)成 \eta)

Learning rate

學(xué)習(xí)率的設(shè)置

??在上面所說(shuō)的梯度下降的方法中,學(xué)習(xí)率是一個(gè)不變的常數(shù),那么如何來(lái)設(shè)置這個(gè)參數(shù)其實(shí)是一個(gè)很重要的問(wèn)題,因?yàn)槿绻O(shè)的太大的話,可能因?yàn)槊看胃聟?shù)的幅度太大了而無(wú)法收斂到最低點(diǎn)(下圖綠線),甚至變得發(fā)散了(下圖黃線)。如果設(shè)的太小的話可能收斂的速度會(huì)很慢(下圖藍(lán)線)。

??上面這個(gè)圖是在參數(shù)為一維的情況下才能畫(huà)出來(lái)的,如果參數(shù)大于等于三維,其實(shí)是沒(méi)有辦法可視化畫(huà)出 \boldsymbol \thetaJ 之間的關(guān)系圖的,所以也就沒(méi)法從圖中觀察到我的學(xué)習(xí)率時(shí)候設(shè)置的太小了或者太大了。但是我們可以畫(huà)出每次迭代時(shí)的當(dāng)前 J 的圖,如下圖所示,可以看到當(dāng)學(xué)習(xí)率過(guò)大而損失值發(fā)散的時(shí)候會(huì)像黃線那樣,當(dāng)太小的時(shí)候會(huì)像藍(lán)線那樣。所以畫(huà)迭代次數(shù)與損失值的關(guān)系圖可以幫我們了解到我們的學(xué)習(xí)率 \eta 是否合適。

自適應(yīng)學(xué)習(xí)率 (Adaptive learning rates)

??上面所說(shuō)的學(xué)習(xí)率是不變的,那么我們想讓我們的學(xué)習(xí)率能夠自適應(yīng)迭代的過(guò)程要怎么辦呢?一個(gè)大的原則是希望隨著參數(shù)的不斷更新,學(xué)習(xí)率會(huì)變的越來(lái)越小,以便更好的收斂。那么很容易可以想到可以讓學(xué)習(xí)率隨著迭代的次數(shù)而衰變,例如第 t 次迭代時(shí)的學(xué)習(xí)率 \eta^t 為:
\eta^t = \frac \eta {\sqrt{t+1}}
??使用上面這種學(xué)習(xí)率自適應(yīng)方法的梯度下降叫做 vanilla gradient descent,至此為止,學(xué)習(xí)率對(duì)于每一個(gè)參數(shù) \{\theta_1, \theta_2 ,...,\theta_n\}都是一樣的,但是應(yīng)該為不同的參數(shù)設(shè)定不同的學(xué)習(xí)率。所以有另一種學(xué)習(xí)率自適應(yīng)的算法,叫做 Adagrad

Adagrad

??Adagrad 每次的學(xué)習(xí)率不是只關(guān)于迭代次數(shù) t 來(lái)衰減,還與這 t 次迭代時(shí)每次的微分有關(guān)。記任意一個(gè)參數(shù)為 w ,改參數(shù)第 t 次的微分為 g^t 。則 使用 Adagrad 進(jìn)行梯度下降的參數(shù)更新方法如下:
w^{t+1} \leftarrow w^t - \frac {\eta^t} {\sigma^t} g^t
??其中 \eta^t = \frac \eta {\sqrt{t+1}} ,\sigma^t = \sqrt {\frac 1 {t+1} \sum _{i=0}^t(g^i)^2} ,g^t =\partial J(\boldsymbol \theta^t) / \partial w 。可以發(fā)現(xiàn),分子分母都有 \frac 1 {\sqrt{t+1}} ,所以約掉后變成:
w^{t+1} \leftarrow w^t - \frac {\eta} {\sqrt { \sum _{i=0}^t(g^i)^2}} g^t

??對(duì)比 vanilla gradient descent 和 Adagrad ,當(dāng)在某一點(diǎn)偏微項(xiàng) g^t 算出來(lái)比較大時(shí),vanilla gradient descent 也會(huì)更新的比較大,而 Adagrad 的 g^t 變大時(shí), \sqrt { \sum _{i=0}^t(g^i)^2} 會(huì)導(dǎo)致更新的一步變小,這一個(gè)變大時(shí)另一個(gè)會(huì)變小,相乘后不一定會(huì)變大,怎樣來(lái)理解這種設(shè)定呢?

??一種理解是 Adagrad 想要考慮的是這個(gè)梯度的反差有多大,就是如果前面的梯度算出來(lái)都很小,突然來(lái)了一個(gè)比原來(lái)的大了幾個(gè)數(shù)量級(jí)的就會(huì)覺(jué)得這個(gè)特別大,這樣就會(huì)更新一個(gè)接近 \eta 的一步。如果原來(lái)都很大,突然來(lái)了個(gè)小一兩個(gè)數(shù)量級(jí)的梯度,那么就會(huì)基本不更新。所以是把原來(lái)的依據(jù)絕對(duì)的微分的大小決定更新的大小變成了現(xiàn)在依據(jù)相對(duì)的微分的大小絕對(duì)更新的大小了。就像下面這個(gè)表格,有兩個(gè)參數(shù)比如說(shuō)是 \theta_1\theta_2 在第五次迭代微分(偏導(dǎo))算出來(lái)都是 0.1 ,如果用 vanilla gradient descent 來(lái)更新的話,兩個(gè)參數(shù)更新的大小會(huì)是一樣的,但是使用了 Adagrad 后,\theta_1 會(huì)更新的很大,接近 \eta ,而 \theta_2 則基本不更新。那么為什么要這么更新呢?

??這就要從數(shù)學(xué)上來(lái)理解了。我們?cè)诟聟?shù) \theta 時(shí),都會(huì)有一種直覺(jué),就是當(dāng)微分比較大時(shí),那么離最小值點(diǎn)會(huì)比較遠(yuǎn),而微分比較大時(shí),會(huì)離最小值點(diǎn)比較近。例如在一個(gè)二次曲線上,a 點(diǎn)微分比 b 點(diǎn)大,離最小值點(diǎn)也比 b 點(diǎn)遠(yuǎn)。

??但是這在多維上就不一定成立了,比如在一個(gè)二維的損失值與 \theta (圖中的 w ) 的圖上,分別用兩個(gè)平面去切,得到兩個(gè)曲線,雖然在 c 點(diǎn)的微分會(huì)比在 a 點(diǎn)的更大,但實(shí)際是 c 點(diǎn)離的更遠(yuǎn),更應(yīng)該進(jìn)行大的參數(shù)更新。那么為什么 Adagrad 能讓藍(lán)線中的 a 點(diǎn)更新的比 c 點(diǎn)更多一點(diǎn)呢?我們先來(lái)看一下另一個(gè)問(wèn)題。

??假如我們有一個(gè)二次曲線 y = ax^2+bx +c,還有一個(gè)起始點(diǎn) x_0 ,那么我們想要更新以后能夠到達(dá)最小值點(diǎn),最好的一步應(yīng)該是這一點(diǎn)到最小值點(diǎn)的距離 |x_0+\frac b {2a}| ,不管這個(gè)曲線是像上面藍(lán)色的那樣緩慢變化的,還是像綠線那樣陡峭變化的,最好的更新的距離都是 |x_0+\frac b {2a}| ,當(dāng)然各自的 a, b, x_0 是不一樣的。那么怎么得到這個(gè) |x_0+\frac b {2a}| 呢?把他變成一個(gè)分式,分子其實(shí)是 y 的一階導(dǎo)數(shù),即在這一點(diǎn)的微分值,而分母是二次微分。所以我們知道了,在這種情況下,最好的一步不是函數(shù)的一次微分(vanilla gradient descent 的更新方式),而是一次微分除以二次微分。

??那么這和 Adagrad 有什么關(guān)系呢?難道 \sqrt { \sum _{i=0}^t(g^i)^2} 是在那一點(diǎn)的二次微分?沒(méi)錯(cuò), \sqrt { \sum _{i=0}^t(g^i)^2} 其實(shí)就是二次微分的估計(jì)。那么是怎么估計(jì)的呢? Adagrad 所做的其實(shí)就是在一次微分上采樣,在比較平滑的曲線上,一次微分會(huì)比較小,在比較陡峭的曲線上,一次微分會(huì)比較大,采多個(gè)點(diǎn)求平方和在開(kāi)根號(hào)就能夠反映二次微分的大小,因?yàn)楸容^平滑的取消上的 \sqrt { \sum _{i=0}^t(g^i)^2} 會(huì)比比較陡峭的 \sqrt { \sum _{i=0}^t(g^i)^2} 大,二次微分也是這樣的。

??那么不可避免的會(huì)問(wèn),\sqrt { \sum _{i=0}^t(g^i)^2} 和二次微分應(yīng)該還是不一樣的,這應(yīng)該只能反映不同參數(shù)上二次微分的大小關(guān)系,為什么不直接計(jì)算二次微分呢?其實(shí)是因?yàn)樵跀?shù)據(jù)比較大的時(shí)候,往往是不能忍受需要額外計(jì)算二次微分的計(jì)算開(kāi)銷(xiāo)的,而 Adagrad 沒(méi)有增加過(guò)多的運(yùn)算,用的是原來(lái)已經(jīng)算好的一次微分來(lái)盡可能達(dá)到同樣的效果,所以是很有效的。

Stochastic Gradient Descent

??在原來(lái)的梯度下降中,我們每次迭代用到了所有樣本的,因?yàn)樵瓉?lái)的損失函數(shù)是:
J(\boldsymbol \theta) = \frac 1 {2m}\sum_{i=1}^m(h_{\boldsymbol \theta}(\boldsymbol x^{(i)})-y^{(i)})^2
??Stochastic Gradient Descent 說(shuō),我不要用這個(gè)多樣本,每次我只用一個(gè),然后依次取訓(xùn)練集的所有樣本來(lái)更新。那么使用第 i 個(gè)數(shù)據(jù)進(jìn)行梯度下降時(shí)的損失函數(shù)就變成了:
J(\boldsymbol \theta) = (h_{\boldsymbol \theta}(\boldsymbol x^{(i)})-y^{(i)})^2
??那么原來(lái)掃描一遍數(shù)據(jù)只能更新 1 次,現(xiàn)在掃描一遍能更新 m 次了,下圖是 m=20 時(shí)的兩種梯度下降的對(duì)比,(其中 w,b 等同于我所寫(xiě)的 \theta_1,\theta_0 ) 。可以看到雖然每次更新不一定會(huì)朝著總體損失減小的方向進(jìn)行,但大部分更新還是會(huì)朝著損失減小的方向進(jìn)行的,同樣掃描一遍訓(xùn)練集,Stochastic Gradient Descent 離最優(yōu)點(diǎn)更近一些。

Feature scaling

??通常,在進(jìn)行梯度下降的時(shí)候,需要將不同屬性的數(shù)據(jù)縮放到相近的取值范圍,縮放的方式可以采取減均值再除以方差的方式進(jìn)行,公式如下:
x_j^r \leftarrow \frac {x^r_j-m_j} {\sigma_j^2}
??其中,x_j^r 是第 r 個(gè)數(shù)據(jù)的第 j 個(gè)屬性的取值, m_j 是所有數(shù)據(jù)的第 j 的屬性數(shù)據(jù)的均值, m_j = \sum_{i=1}^mx_j^m ,\sigma_j^2 是 所有數(shù)據(jù)的第 j 的屬性數(shù)據(jù)的方差??s放后,所有屬性的均值為 0 ,方差為 1 。

??那么為什么要將不同屬性的數(shù)據(jù)縮放到類(lèi)似大小的范圍呢?讓我們來(lái)分別看下縮放前和縮放后的效果,假設(shè)有一個(gè)函數(shù)是 y=b+w_1x_1+w_2x_2 (這里的 b,w_1,w_2 分別對(duì)應(yīng)前面的 \theta_0,\theta_1,\theta_2 ),如果不縮放的話,就如下圖左圖那樣,y 的等值線是一個(gè)橢圓。縮放后就像右邊那樣是一個(gè)原。我們知道梯度下降每次的方向是等值線的發(fā)現(xiàn)方向,那么在橢圓上,法線方向一般不是指向圓心的,如果進(jìn)行梯度下降,就會(huì)像圖中那樣繞個(gè)大彎,如果是一個(gè)圓的話,無(wú)論在哪里法線都是指向圓心的,只需要更少的次數(shù)就能收斂。所以特征縮放可以加速梯度下降收斂的速度,更快的找到最小值點(diǎn)。

Theory (梯度下降的數(shù)學(xué)原理)

??梯度下降的基本原理是在當(dāng)前所處位置的周?chē)苄〉姆秶鷥?nèi)(下圖紅圈內(nèi))看一看哪一點(diǎn)是最低的,然后朝著那個(gè)方向走一步,直到走到最低點(diǎn),那么怎么才能找到哪一點(diǎn)是紅圈里最低的點(diǎn)呢?

圖片18.png

??讓我們先來(lái)回顧一下泰勒展開(kāi)式,泰勒展開(kāi)說(shuō),當(dāng) f(x)x_0n 階可導(dǎo)的時(shí)候,那么可以寫(xiě)成:
\begin{aligned} f(x) &= \sum_{k=0}^{n+1} \frac {f^{(k)}(x_0)} {k!} (x-x_0)^k + 0(x-x_0)\\ &=f(x_0) + f'(x_0)(x-x_0)+\frac {f''(x_0)} {2!}(x-x_0)^2 + \cdots \end{aligned}
??所以當(dāng) xx_0 很接近的時(shí)候,f(x) \approx f(x_0) + f'(x_0)(x-x_0) ,因?yàn)楹竺娑我粋€(gè)很小的數(shù)約等于 0 ,更高次就更小了。從一個(gè) sin 函數(shù)的展開(kāi)可以直觀的看到這一點(diǎn)。將一個(gè)正弦函數(shù)在 \pi/4 位置展開(kāi),畫(huà)出各次項(xiàng)的曲線。0 次的時(shí)候就是一條水平線,1 次的時(shí)候是一條斜線,更高次更擬合橙色的正弦曲線,在 \pi/4 周?chē)苄〉姆秶?,一次?xiàng)是可以擬合正弦曲線的。

??二元的泰勒展開(kāi)是下面這樣的:
\begin{aligned} f(x,y) = &f(x_0,y_0) + \frac {\partial f(x_0,y_0)}{\partial x}(x-x_0) + \frac {\partial f(x_0,y_0)}{\partial y}(y-y_0) \\ &+ \text {something related to $(x-x_0)^2$ and $(y-y_0)^2$} + ... \end{aligned}
??所以可以 f(x,y) \approx f(x_0,y_0) + \frac {\partial f(x_0,y_0)}{\partial x}(x-x_0) + \frac {\partial f(x_0,y_0)}{\partial y}(y-y_0) 。讓我們回到上面那個(gè)二維情況下的梯度下降中,當(dāng)紅圈足夠的小的時(shí)候,我們可以用一次的泰勒展開(kāi)去近似原函數(shù)。假設(shè)當(dāng)前所在的位置是 (a,b) ,則在這個(gè)點(diǎn)周?chē)哪莻€(gè)紅圈里:
J(\boldsymbol \theta) \approx J(a,b) + \frac {\partial J(\boldsymbol \theta)} {\partial \theta_1}(\theta_1-a)+ \frac {\partial J(\boldsymbol \theta)} {\partial \theta_2}(\theta_2-b)
??其中 J(a,b) 其實(shí)是個(gè)常數(shù),后面兩項(xiàng)其實(shí)可以看作兩個(gè)向量的內(nèi)積,第一個(gè)向量是 \begin{bmatrix} \frac {\partial J(\boldsymbol \theta)} {\partial \theta_1} \\\frac {\partial J(\boldsymbol \theta)} {\partial \theta_2} \end{bmatrix} ,另一個(gè)是 \begin{bmatrix} \theta_1 -a \\ \theta_2 - b\end{bmatrix}\begin{bmatrix} \Delta \theta_1 \\ \Delta \theta_2\end{bmatrix} 。第一個(gè)其實(shí)就是在這一點(diǎn)的梯度方向,而要使 J(\boldsymbol \theta ) 最小,第二個(gè)向量最好是第一個(gè)向量的反方向最長(zhǎng)的位置,即梯度反方向的射線與紅圈的交點(diǎn)是最小值點(diǎn)。 這從數(shù)學(xué)上解釋了參數(shù)為什么要這么更新,以及為什么有的時(shí)候會(huì)導(dǎo)致更新后的 J 反而變大,因?yàn)楦碌牟阶犹罅硕沟募t圈變得太大了而不滿(mǎn)足一次泰勒展開(kāi)的近似關(guān)系了。

More Limitation of Gradient Descent

??我們前面就知道了,梯度下降會(huì)有落入局部最小的風(fēng)險(xiǎn),然后事情并沒(méi)有這么簡(jiǎn)單。梯度下降是按照梯度的大小來(lái)進(jìn)行更新的,但并不是只有最小值點(diǎn)的梯度可能是 0 ,鞍點(diǎn) (saddle point) 的梯度也可能是 0 ,比如 y = x^3 在 0 處的導(dǎo)數(shù)是 0 ,但并不是極值點(diǎn),所以我們可能會(huì)落入鞍點(diǎn)。除此之外,我們?cè)诰唧w實(shí)現(xiàn)的時(shí)候,并不是梯度嚴(yán)格等于 0 的時(shí)候才停止迭代,當(dāng)梯度約等于 0 時(shí),就會(huì)停,那么就會(huì)有一種風(fēng)險(xiǎn),可能只是函數(shù)在某一段比較平緩,其實(shí)離極值點(diǎn)還很遠(yuǎn)。這三種情況分別對(duì)應(yīng)了下圖三個(gè)點(diǎn):

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容