優化算法(從梯度下降到Adam算法)

從梯度下降、動量法、AdaGrad、RMSProp、AdaDelta到Adam算法總結。
1.優化與深度學習
在一個深度學習問題中,我能通常會預先定義一個損失函數。有了損失函數以後,我們就可以使用優化算法試圖將其最小化。在優化中,這樣的損失函數通常被稱作優化問題的目標函數(objective function)。一般來說,優化算法通常只考慮最小化目標函數。其實,任何最大化問題都可以很容易地轉換爲最小化問題,只需令目標函數的相反數作爲新的目標函數即可。
由於優化算法的目標函數通常是一個基於訓練數據集的損失函數,優化的目標在於降低訓練誤差。而深度學習的目標在於降低泛化誤差。爲了降低泛化誤差,除了使用優化算法降低訓練誤差以外,還需要注意應對過擬合。
深度學習中絕大多數目標函數都複雜。因此,很多優化問題並不存在解析解,而需要使用基於數值方法的優化算法找到近似解,即數值解。爲了求得最小化目標函數的數值解,我們將通過優化算法有限次迭代模型參數來儘可能降低損失函數的值。優化在深度學習中有很多的挑戰,下面是其中兩個比較重要的挑戰:
(1)局部最小值
(2)鞍點
局部最小值:對於目標函數f(x)f(x),如果f(x)f(x)xx上的值比在xx鄰近的其他點的值更小,那麼f(x)f(x)可能是一個局部最小值(local minimum)。如果f(x)f(x)xx上的值是目標函數在整個定義域上的最小值,那麼f(x)f(x)是全局最小值(global minimum)。
在這裏插入圖片描述
深度學習模型的目標函數可能有若干局部最優值。當一個優化問題的數值解在局部最優解附近時,由於目標函數有關解的梯度接近或變成零,最終迭代求得的數值解可能只能令目標函數局部最小化而非全局最小化。
鞍點:剛剛在局部最小值中提到,梯度接近或變成零可能是由於當前解在局部最優解附近造成的。事實上,另一種可能性是當前解在鞍點(saddle point)附近。
在這裏插入圖片描述
在深度學習中,雖然找到目標函數的全局最優解很難,但這並非必要。下面將介紹深度學習中常用的優化算法,它們在很多實際問題中都能夠訓練出十分有效的深度學習模型。

2.梯度下降和隨機梯度下降

雖然梯度下降(gradient descent)在深度學習中很少被直接使用,但理解梯度的意義以及沿着梯度反方向更新自變量可能降低目標函數值的原因是學習後續優化算法的基礎。

2.1 一維梯度下降

首先以簡單的一維梯度下降爲例,解釋梯度下降算法可能降低目標函數的原因。假設連續可導的函數f:RRf:\mathbb{R} \rightarrow \mathbb{R}的輸入和輸出都是標量。給定絕對值足夠小的數ϵ\epsilon,根據泰勒展開公式,我們得到以下的近似:
f(x+ϵ)f(x)+ϵf(x)f(x+\epsilon) \approx f(x)+\epsilon {f}'(x)

這裏f(x){f}'(x)是函數ffxx處的梯度。一維函數的梯度是一個標量,也稱導數。
接下來,找到一個常數η>0\eta>0使得ηf(x)|\eta{f}'(x)|足夠小,那麼可以將ϵ\epsilon替換爲ηf(x)-\eta {f}'(x)並得到:
f(xηf(x))f(x)ηf(x)2f(x-\eta {f}'(x)) \approx f(x)-\eta {f}'(x)^{2}

如果導數f(x)0{f}'(x) \neq 0,那麼ηf(x)2>0\eta {f}'(x)^{2}>0,所以:
f(xηf(x))f(x)f(x-\eta {f}'(x)) \leq f(x)

這意味着,如果通過
xηf(x)x \leftarrow \eta{f}'(x)

來迭代xx,函數f(x)f(x)的值可能會降低。因此在梯度下降中,我們先選取一個初始值xx和常數η>0\eta > 0,然後不斷通過上式來迭代xx,直到達到停止條件,例如f(x){f}'(x)的值已足夠小或迭代次數已達到某個值。
上述梯度下降算法中的正數η\eta通常叫作學習率。這是一個超參數,需要人工設定,如果使用過小的學習率,會導致xx更新緩慢從而需要更多的迭代才能得到較好的解。

2.2 多維梯度下降

下面考慮一種更廣義的情況:目標函數的輸入爲向量,輸出爲標量。假設目標函數f:RdRf:\mathbb{R}^{d}\rightarrow \mathbb{R}的輸入是一個dd維向量x=[x1,x2,...,xd]T\boldsymbol{x}=[x_{1}, x_{2},...,x_{d}]^{T}。目標函數f(x)f(\boldsymbol{x})有關x\boldsymbol{x}的梯度是一個由dd個偏導數組成的向量:
xf(x)=[f(x)x1,f(x)x2,...,f(x)xd]T\bigtriangledown_{x}f(\boldsymbol{x})=\begin{bmatrix} \frac{\partial f(\boldsymbol{x})}{\partial x_{1}},& \frac{\partial f(\boldsymbol{x})}{\partial x_{2}}, & ... &,\frac{\partial f(\boldsymbol{x})}{\partial x_{d}} \end{bmatrix}^{T}

爲表示簡潔,我們用f(x)\bigtriangledown f(\boldsymbol{x})代替fx(x)\bigtriangledown f_{x}(\boldsymbol{x})。梯度中每個偏導數元素f(x)xi\frac{\partial f(\boldsymbol{x})}{\partial x_{i}}代表着ffx\boldsymbol{x}有關輸入xix_{i}的變化率。爲了測量ff沿着單位向量u\boldsymbol{u}(即∥u∥ = 1)方向上的變化率,在多元微積分中,我們定義ffx\boldsymbol{x}上沿着u\boldsymbol{u}方向的方向導數爲:
Duf(x)=limh0f(x+hu)f(x)hD_{\boldsymbol{u}}f(\boldsymbol{x})=\lim_{h\rightarrow 0}\frac{f(\boldsymbol{x}+h\boldsymbol{u})-f(\boldsymbol{x})}{h}

根據導數性質,上面的方向導數可以改寫爲:
Duf(x)=f(x)uD_{\boldsymbol{u}}f(\boldsymbol{x})=\bigtriangledown f(\boldsymbol{x})·\boldsymbol{u}

方向導數Duf(x)D_{\boldsymbol{u}}f(\boldsymbol{x})給出了ffx\boldsymbol{x}上沿着所有可能方向的變化率。爲了最小化ff,我們希望找到ff能被降低最快的方向。因此,我們可以通過單位向量u\boldsymbol{u}來最小化方向導數Duf(x)D_{\boldsymbol{u}}f(\boldsymbol{x})
由於Duf(x)=f(x)ucos(θ)=f(x)cos(θ)D_{\boldsymbol{u}}f(\boldsymbol{x})=||\bigtriangledown f(\boldsymbol{x})||·||\boldsymbol{u}||·cos(\theta)=||\bigtriangledown f(\boldsymbol{x})||·cos(\theta),其中θ\theta爲梯度f(x)\bigtriangledown f(\boldsymbol{x})和單位向量u\boldsymbol{u}之間的夾角,當θ=π\theta = \pi時,cos(θ)cos(\theta)取最小值-1。因此,當u\boldsymbol{u}在梯度方向f(x)\bigtriangledown f(\boldsymbol{x})的相反方向時,方向導數Duf(x)D_{\boldsymbol{u}}f(\boldsymbol{x})被最小化。因此,我們可以通過梯度下降算法來不斷降低目標函數ff的值:
xxηf(x)x \leftarrow x - \eta \bigtriangledown f(\boldsymbol{x})

2.3 隨機梯度下降

在機器學習或者深度學習裏,目標函數通常是訓練數據集中有關各個樣本的損失函數的平均。設fi(x)f_{i}(\boldsymbol{x})是有關索引爲ii的訓練數據樣本的損失函數,nn是訓練數據樣本數,x\boldsymbol{x}是模型的參數向量,那麼目標函數定義爲:
f(x)=1ni=1nfi(x)f(\boldsymbol{x})=\frac{1}{n}\sum_{i=1}^{n}f_{i}(\boldsymbol{x})

目標函數在xx處的梯度計算爲:
f(x)=1ni=1nfi(x)\bigtriangledown f(\boldsymbol{x})=\frac{1}{n}\sum_{i=1}^{n}\bigtriangledown f_{i}(\boldsymbol{x})

如果使用梯度下降,每次自變量迭代的計算開銷爲O(n)O(n),它隨着nn線性增長。因此,當訓練數據樣本數很大時,梯度下降每次迭代的計算開銷很高。
隨機梯度下降(SGD)減少了每次迭代的計算開銷。在隨機梯度下降的每次迭代中,我們隨機均勻採樣一個樣本索引i1,...,ni \in {1, ..., n},並計算梯度fi(x)\bigtriangledown f_{i}(\boldsymbol{x})來迭代x\boldsymbol{x}:
xxηfi(x)\boldsymbol{x} \leftarrow \boldsymbol{x}-\eta \bigtriangledown f_{i}(\boldsymbol{x})

可以看到每次迭代的計算開銷從梯度下降的O(n)O(n)降到了常數O(1)O(1)。值得強調的是,隨機梯度fi(x)\bigtriangledown f_{i}(\boldsymbol{x})是對梯度 f(x)\bigtriangledown f(\boldsymbol{x})的無偏估計:
Eifi(x)=1ni=1nfi(x)=f(x)E_{i}\bigtriangledown f_{i}(\boldsymbol{x})=\frac{1}{n}\sum_{i=1}^{n}\bigtriangledown f_{i}(\boldsymbol{x})=\bigtriangledown f(\boldsymbol{x})

這意味着,平均來說,隨機梯度是對梯度的一個良好的估計。

2.4 小批量隨機梯度下降

在每一次迭代中,梯度下降使用整個訓練數據集來計算梯度,因此它有時也被稱爲批量梯度下降算法(batch gradient descent)。而隨機梯度下降在每次迭代中只隨機採樣一個樣本來計算梯度。當然,我們還可以在每次迭代中隨機均勻採樣多個樣本來組成一個小批量,然後使用整個小批量來計算梯度。這就是小批量隨機梯度下降。
假設在時間步tt,小批量隨機梯度下降隨機均勻採樣一個由訓練數據樣本索引組成的小批量BtB_{t}。然後使用:
gtfBt(xt1)=1BiBtfi(xt1)\boldsymbol{g}_{t}\leftarrow \bigtriangledown f_{B_{t}}(\boldsymbol{x}_{t-1})=\frac{1}{|B|}\sum_{i\in B_{t}}\bigtriangledown f_{i}(\boldsymbol{x}_{t-1})

然後給定學習率,小批量隨機梯度下降對自變量的迭代如下:
xtxt1ηtgt\boldsymbol{x}_{t}\leftarrow \boldsymbol{x}_{t-1}-\eta_{t}g_{t}

3.動量法

在梯度下降和隨機梯度下降算法中我們提到,目標函數有關自變量的梯度代表了目標函數在自變量當前位置下降最快的方向。因此,梯度下降算法也叫作最陡下降。在每次迭代中,梯度下降根據自變量當前位置,沿着當前位置的梯度更新自變量。然而,如果自變量的迭代方向僅僅取決於自變量當前位置,這可能會帶來一些問題。

3.1 梯度下降算法的問題
在這裏插入圖片描述
可以看到,同一位置上,目標函數在豎直方向(x2方向)比在水平方向上的斜率的絕對值更大。因此,給定學習率,梯度下降迭代自變量時會使得自變量在豎直方向上比在水平方向上移動幅度更大。那麼,我們需要一個較小的學習率從而避免自變量在豎直方向上越過目標函數最優解。然而,這會造成自變量在水平方向上朝着最優解移動變慢。
但如果我們將學習率調的更大一點,此時自變量在豎直方向不斷越過最優解併發散。
在這裏插入圖片描述
3.2 動量法

動量法的提出是爲了解決梯度下降的上述問題。由於小批量隨機梯度下降比梯度下降更爲廣義,後面都採用時間步·tt的小批量隨機梯度gtg_{t}
的定義。設時間步tt的自變量爲xtx_{t},學習率爲ηt\eta_{t}。在時間步0,動量法創建的速度變量v0v_{0},並將其初始化爲0.在時間步t>0t>0,動量法對每次迭代的步驟做如下修改:
vtγvt1+ηtgtxtxt1vtv_{t} \leftarrow \gamma v_{t-1} + \eta_{t}g_{t} \newline x_{t} \leftarrow x_{t-1} - v_{t}
其中,動量超參數0γ<10\leq\gamma<1。當γ=0\gamma=0的時候,動量法等價於小批量隨機梯度下降算法。
在這裏插入圖片描述
可以看到使用較小的學習率η=0.4\eta=0.4和動量超參數γ=0.5\gamma=0.5。動量法在豎直方向上的移動更加平滑,且在水平方向上更快逼近最優解。
當使用較大的學習率η=0.6\eta=0.6,此時自變量也不再發散。
在這裏插入圖片描述
指數加權移動平均理解動量法:由指數加權移動平均的形式可得,速度變量vtv_{t}實際上對序列{ηtigti/(1γ):i=0,...,1/(1γ)1\eta_{t-i}g_{t-i}/(1-\gamma):i=0,...,1/(1-\gamma)-1}做了指數加權移動平均。換句話說,相比於小批量隨機梯度下降算法,動量法在每個時間步的自變量更新量近似於將前者對應的最近1/(1γ)1/(1-\gamma)個時間步的更新量做了指數加權移動平均後再除以1γ1-\gamma。所以,在動量法中,自變量在各個方向上的移動幅度不僅取決於當前的梯度,還取決於過去的各個梯度在各個方向上是否一致。
小結:動量法使用了指數加權移動平均的思想。它將過去時間步的梯度做了加權平均,且權重按照時間步指數衰減。動量法使得相鄰時間步的自變量更新在方向上更加一致。

4.AdaGrad算法

在之前介紹的優化算法中,目標函數自變量的每一個元素在相同時間步都使用同一個學習率η\eta來自我迭代。
我們知道當x1x_{1}x2x_{2}的梯度值由較大差異時,需要選擇小的學習率使得自變量在梯度值較大的緯度上不發散。但這樣會導致自變量在梯度值較小的緯度上迭代過慢。動量法依賴指數加權移動平均使得自變量的更新方向更加一致,從而降低散發的可能。
AdaGrad算法,它根據自變量在每個緯度的梯度值的大小來調整各個緯度上的學習率,從而避免統一的學習率難以適應所有緯度的問題[Adaptive subgradien methods for online learning and stochastic optimization]。

4.1 算法

AdaGrad算法會使用一個小批量隨機梯度gtg_{t}按元素平方的累加變量sts_{t}。在時間步0,AdaGrad算法將s0s_{0}中每個元素初始化爲0.在時間步tt,首先將小批量隨機梯度gtg_{t}按照元素平方後累加到變量sts_{t}
stst1+gtgts_{t} \leftarrow s_{t-1}+g_{t}\odot g_{t}
其中\odot是按元素相乘。接着,我們將目標函數自變量中每個元素的學習率通過按元素運算後重新調整一下:
xtxtηst+ϵgtx_{t} \leftarrow x_{t}-\frac{\eta}{\sqrt{s_{t}+\epsilon}}\odot g_{t}
其中η\eta是學習率,ϵ\epsilon是爲了維持數值穩定性而添加的常數,如10610^{-6}。這裏開方、除法和乘法的運算都是按照元素運算的。這些按元素運算使得目標函數自變量中每個元素都分別擁有自己的學習率。

4.2 特點

需要強調的是,小批量隨機梯度按元素平方的累加變量sts_{t}出現在學習率的分母項中。因此,如果目標函數有關自變量中某個元素的偏導數一直都很大,那麼該元素的學習率將下降的越快;反之,如果目標函數有關自變量中某個元素的偏導數一直都較小,那麼該元素的學習率將下降的較慢。然而,由於sts_{t}一直在累加按元素平方的梯度,自變量中每個元素的學習率在迭代過程中一直再降低(或不變)。所以,當學習率在迭代早起降的較快且當前解依然不佳時,AdaGrad算法在迭代後期由於學習率過小,可能較難找到一個有用的解。
小結:AdaGrad算法在迭代過程中不斷調整學習率,並讓目標函數自變量中每個元素都分別擁有自己的學習率。使用AdaGrad算法時,自變量中每個元素的學習率在迭代過程中一直在降低(或不變)。

5.RMSProp算法

在AdaGrad算法中,因爲調整學習率時分母上的變量sts_{t}一直在累加按元素平方的小批量隨機梯度,所以目標函數自變量每個元素的學習率在迭代過程中一直在降低(或不變)。
因此,當學習率在迭代早期降的較快且當前解依然不佳時,AdaGrad算法在迭代後期由於學習率過小,可能教難找到一個有用的解。爲了解決這個問題,RMSProp算法對AdaGrad算法做了一點小小的修改。該算法源自Coursera上的一門課程,“機器學習的神經網絡” [Divide the gradient by a running average of its recent magnitude]

動量法使用的是指數加權移動平均。不同於AdaGrad算法裏狀態變量sts_{t}是截至時間步t所有小批量隨機梯度gtg_{t}按元素平方和,RMSProp算法將這些梯度按元素平方做指數加權移動平均。具體來說,給定超參數0γ<10\leq \gamma<1,RMSPro算法在時間步t>0t>0計算
stγst+(1γ)gtgts_{t} \leftarrow \gamma s_{t}+(1-\gamma)g_{t} \odot g_{t}和AdaGrad算法一樣,RMSProp算法將目標函數自變量中每個元素的學習率通過按元素運算重新調整,然後更新自變量xtxtηst+ϵgtx_{t} \leftarrow x_{t}-\frac{\eta}{\sqrt{s_{t}+\epsilon}}\odot g_{t}
其中η\eta是學習率,ϵ\epsilon是爲了維持數值穩定性而添加的常數,如10610^{-6}。因爲RMSProp算法的狀態變量sts_{t}是對平方項gtgtg_{t}\odot g_{t}的指數加權移動平均,所以可以看作是最近1/(1γ)1/(1-\gamma)。如此一來,自變量每個元素的學習率在迭代過程中就不再一直降低(或不變)。

6.AdaDelta算法

除了RMSProp算法以外,另一個常用優化算法AdaDelta算法也針對AdaGrad算法在迭代後期可能較難找到有用解的問題做了改進[ADADELTA: an adaptive learning rate method.]。有意思的是,AdaDelta算法沒有學習率這一超參數。
AdaDelta算法也像RMSProp算法一樣,使用了小批量隨機梯度gtg_{t}按元素平方的指數加權移動平均變量sts_{t}。在時間步0,它的所有元素被初始化爲0。給定超參數0ρ<10\leq \rho < 1 (對應RMSProp算法中的γ\gamma),在時間步t>0t>0,同RMSProp算法一樣計算
stρst1+(1ρ)gtgts_{t} \leftarrow \rho s_{t-1} + (1-\rho)g_{t}\odot g_{t}
與RMSProp算法不同的是,AdaDelta算法還維護一個額外的狀態變量Δxt\Delta x_{t},其元素同樣在時間步0時被初始化爲0。我們使用Δxt1\Delta x_{t-1}來計算自變量的變化量:
gtΔxt+ϵst+ϵgtg^{'}_{t} \leftarrow \sqrt{\frac{\Delta x_{t}+\epsilon}{s_{t}+\epsilon}}\odot g_{t}
其中ϵ\epsilon是爲了維持數值穩定性而添加的常數,如10510^{-5}。接着更新自變量:
xtxt1gtx_{t} \leftarrow x_{t-1} - g^{'}_{t}
最後,我們使用Δxt\Delta x_{t}來記錄自變量變化量gtg^{'}_{t}按元素平方的指數加權移動平均:
ΔxtρΔxt1+(1ρ)gtgt\Delta x_{t} \leftarrow \rho \Delta x_{t-1} + (1-\rho)g^{'}_{t}\odot g^{'}_{t}
可以看到,如不考慮ϵ\epsilon的影響,AdaDelta算法跟RMSProp算法的不同之處在於使用Δxt1\sqrt{\Delta x_{t-1}}來替換超參數η\eta

7.Adam算法

Adam算法在RMSProp算法基礎上對小批量隨機梯度也做了指數加權移動平均[Adam: A method for stochastic optimization]
Adam算法使用了動量變量vtv_{t}和RMSProp算法中小批量隨機梯度按元素平方的指數加權移動平均變量sts_{t},並在時間步0將它們中每個元素初始化爲0。給定超參數0β1<10\leq \beta_{1} < 1(算法作者建議設置爲0.9),時間步tt的動量變量vtv_{t}即小批量隨機梯度gtg_{t}的指數加權移動平均:
vtβ1vt1+(1β1)gtv_{t} \leftarrow \beta_{1}v_{t-1}+(1-\beta_{1})g_{t}

和RMSProp算法中一樣,給定超參數0β2<10\leq \beta_{2} < 1(算法作者建議設置爲0.999),將小批量隨機梯度按元素平方後的項gtgtg_{t}\odot g_{t}做指數加權平均得到sts_{t}
stβ2st1+(1β2)gtgts_{t} \leftarrow \beta_{2}s_{t-1}+(1-\beta_{2})g_{t}\odot g_{t}

由於我們將v0v_{0}s0s_{0}中的元素都初始化爲0,在時間步tt我們得到vt=(1β1)i=1tβ1tigiv_{t}=(1-\beta_{1})\sum_{i=1}^{t}\beta_{1}^{t-i}g_{i}。將過去各時間步小批量隨機梯度的權值相加,得到(1β1)i=1tβ1ti=1β1t(1-\beta_{1})\sum_{i=1}^{t}\beta_{1}^{t-i}=1-\beta_{1}^{t}。需要注意的是,當tt較小時,過去各時間步小批量隨機梯度權值之和會較小。例如,當β1=0.9\beta_{1}=0.9時,v1=0.1g1v_{1}=0.1g_{1}。爲了消除這樣的影響,對於任意時間步tt,我們可以將vtv_{t}再除以1β1t1-\beta_{1}^{t},從而使過去各時間步小批量隨機梯度權值之和爲1。這也叫作偏差修正。在Adam算法中,我們對變量vtv_{t}sts_{t}均作偏差修正:
v^tvt1β1t\hat{v}_{t}\leftarrow \frac{v_{t}}{1-\beta_{1}^{t}} s^tst1β2t\hat{s}_{t}\leftarrow \frac{s_{t}}{1-\beta_{2}^{t}}

接下來,Adam算法使用以上偏差修正後的變量v^t\hat{v}_{t}s^t\hat{s}_{t},將模型參數中每個元素的學習率通過按元素運算重新調整:
gtηv^ts^t+ϵg_{t}^{'}\leftarrow \frac{\eta \hat{v}_{t}}{\sqrt{\hat{s}_{t}}+\epsilon}其中η\eta使學習率,ϵ\epsilon使爲了維持數值穩定而添加的常數,如10810^{-8}。和AdaGrad算法、RMSProp算法以及AdaDelta算法一樣,目標函數自變量中每個元素都分別擁有自己的學習率。最後使用gtg^{'}_{t}迭代自變量:
xtxt1gtx_{t}\leftarrow x_{t-1}-g_{t}^{'}


【參考文獻】:
【1】全文參考動手學習DP

發佈了86 篇原創文章 · 獲贊 52 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章