深度學習中的優化方法(二)

ZhiboZhao 發表於 2021-08-04
深度學習

在上一篇文章中 深度學習中的優化方法(一) - ZhiboZhao - 部落格園 (cnblogs.com) 我們主要講到了一維函式 \(f(x):R \rightarrow R\) 的優化方法,在實際情況中,待優化的函式往往是多維的 \(f(x):R^{n} \rightarrow R\),因此本文我們來探討一下更普遍的多維函式的優化演算法。

一、常用的優化演算法總結

  1. 一階方法:隨機梯度下降(SGD)、動量(Momentum)、牛頓動量法(Nesterov動量)、AdaGrad(自適應梯度)、RMSProp(均方差傳播)、Adam、Nadam。
  2. 二階方法:牛頓法、擬牛頓法、共軛梯度法(CG)、BFGS、L-BFGS。
  3. 自適應優化演算法有哪些?(Adagrad(累積梯度平方)、RMSProp(累積梯度平方的滑動平均)、Adam(帶動量的RMSProp,即同時使用梯度的一、二階矩))。
  4. 梯度下降陷入區域性最優有什麼解決辦法?可以用BGD、SGD、MBGD、momentum,RMSprop,Adam等方法來避免陷入區域性最優。

二、梯度下降法

2.1 梯度下降法的基本原理

對於函式 \(f:R^{n} \rightarrow R\) ,滿足 \(f(\text{x}) = c, \text{x} \in R^{n}\) 的所有 \(\text{x}\) 組成的集合,稱為函式 \(f\) 的水平集。如下圖所示:

深度學習中的優化方法(二)

如果函式在 \(\text{x}_{0}\) 處的梯度 \(\nabla f(\text{x}_{0})\) 不是0向量,那麼它與水平集 \(f(\text{x})=c\) 中任意一條經過 \(\text{x}_{0}\) 的曲線的切向量正交。因此一個實值可微函式在某點處的函式值增加最快額方向正交於經過該點的函式水平集。梯度下降法根據上述的性質,首先給定一個初始點 \(\text{x}^{k}\),由該點出發沿著該點的負梯度方向更新一段距離 \(\alpha_{k}\),稱為步長,構造出新的點 \(\text{x}^{k+1}\),如此往復便可得到迭代公式:

\[\text{x}^{k+1} = \text{x}^{k}-\alpha_{k}\nabla f(\text{x}^{k}) \]

這種方法便稱為梯度下降法,在搜尋過程中,梯度不斷變化,越接近極小值梯度就越小,變化越緩慢,因此要適當對步長 \(\alpha_{k}\) 進行調整。梯度下降法是一個類,其中包括很多種不同的具體演算法,下面就來簡單地介紹一下。

2.2 梯度下降法的具體實現

在介紹具體的演算法之前,我們先確定待優化的損失函式:

\[J(\Theta) = \dfrac{1}{2m}\sum_{i=1}^{m}[f_{\Theta}(x^{i})-y^{i}]^{2} \]

其中,\(J(θ)\) 是損失函式,\(m\) 代表每次取多少樣本進行訓練, \(\Theta \in R^{n}\) 表示待優化的引數。於是便可計算出損失函式在任意點處的梯度:

\[\dfrac{\partial J(\Theta)}{\partial \Theta_{j}} = \dfrac{1}{m}\sum_{i=1}^{m}[f_{\Theta}(x^{i})-y^{i}] \times \dfrac{\partial f_{\Theta}(x^{i})}{\partial \Theta_{j}} = \dfrac{1}{m}\nabla f_{\Theta}(x^{i})\sum_{i=1}^{m}[f_{\Theta}(x^{i})-y^{i}] \]

於是,最小化損失函式,所以引數 \(\Theta_{j}\) 按照負梯度的方向來更新:

\[\Theta_{j} := \Theta_{j}-\alpha \dfrac{1}{m}\nabla f_{\Theta}(x^{i})\sum_{i=1}^{m}[f_{\Theta}(x^{i})-y^{i}] \]

2.2.1 隨機梯度下降(SGD)

隨機梯度下降法求梯度時選取一個樣本j來求梯度。

\[\Theta_{j} := \Theta_{j}-\alpha\nabla f_{\Theta}(x^{i})[f_{\Theta}(x^{i})-y^{i}] \]

寫成虛擬碼如下:

for i in range(nb_epochs):
    np.random.shuffle(data)
    for example in data:
        params_grad = evaluate_gradient(loss_function , example ,params)
        params = params - learning_rate * params_grad

優點:(1)由於不是在全部訓練資料上的損失函式,而是在每輪迭代中,隨機優化某一條訓練資料上的損失函式,這樣每一輪引數的更新速度大大加快。

缺點:(1)準確度下降。(2)可能會收斂到區域性最優,由於單個樣本並不能代表全體樣本的趨勢。(3)不易於並行實現。 SGD 因為更新比較頻繁,會造成 cost function 有嚴重的震盪。

2.2.2 批量梯度下降 (BGD)

批量梯度下降法,是梯度下降法最常用的形式,具體做法也就是在更新引數時使用所有的樣本來進行更新。寫成虛擬碼如下:

for i in range(nb_epochs):
    params_grad = evaluate_gradient(loss_function, data, params)
    params = params - learning_rate * params_grad

優點:(1)一次迭代是對所有樣本進行計算,此時利用矩陣進行操作,實現了並行。(2)由全資料集確定的方向能夠更好地代表樣本總體,從而更準確地朝向極值所在的方向。

缺點:(1)當樣本數目 m 很大時,每迭代一步都需要對所有樣本計算,訓練過程會很慢。(2)不能投入新資料實時更新模型。

2.2.3 部分批量梯度下降(mini-batch GD)

小批量梯度下降法是是對於m個樣本,我們採用x個樣子來迭代,1<x<m。一般可以取x=10,當然根據樣本的資料,可以調整這個x的值。虛擬碼如下:

for i in range(nb_epochs):
    np.random.shuffle(data)
    for batch in get_batches(data, batch_size=50):
        params_grad = evaluate_gradient(loss_function, batch, params)
        params = params - learning_rate * params_grad

優點:(1)通過矩陣運算,每次在一個batch上優化神經網路引數並不會比單個資料慢太多。(2)每次使用一個batch可以大大減小收斂所需要的迭代次數,同時可以使收斂到的結果更加接近梯度下降的效果。(比如上例中的30W,設定batch_size=100時,需要迭代3000次,遠小於SGD的30W次)(3)可實現並行化。

2.3 梯度下降法的改進

2.3.1 Momentum

上述梯度下降法僅僅考慮在當前迭代時刻的梯度,這樣容易落到極小值點。而動量法模擬的是物體在運動時候的慣性,即更新的時候在一定程度上保留之前更新的方向,同時利用當前batch的梯度微調最終的更新方向。這樣一來,可以在一定程度上增加穩定性,從而學習地更快,並且還有一定擺脫區域性最優的能力。

\[\begin{aligned} v_{t} &=\gamma v_{t-1}+\eta \nabla_{\theta} J(\theta) \\ \theta &=\theta-v_{t} \end{aligned} \]

2.3.2 Adagrad

在深度網路訓練中,對於經常更新的引數,我們已經積累了大量關於它的知識,不希望被單個樣本影響太大,希望學習速率慢一些;對於偶爾更新的引數,我們瞭解的資訊太少,希望能從每個偶然出現的樣本身上多學一些,即學習速率大一些。怎麼樣去度量歷史更新頻率呢?那就是二階動量——該維度上,迄今為止所有梯度值的平方和:

梯度更新規則:

\[\theta_{t+1, i}=\theta_{t, i}-\frac{\eta}{\sqrt{G_{t, i i}+\epsilon}} \cdot g_{t, i} \]

其中g為:t時刻引數θ_i的梯度

\[g_{t, i}=\nabla_{\theta} J\left(\theta_{i}\right) \]

如果是普通的 SGD, 那麼 θ_i 在每一時刻的梯度更新公式為:

\[\theta_{t+1, i}=\theta_{t, i}-\eta \cdot g_{t, i} \]

但這裡的learning rate η也隨t和i而變:

\[\theta_{t+1, i}=\theta_{t, i}-\frac{\eta}{\sqrt{G_{t, i i}+\epsilon}} \cdot g_{t, i} \]

其中 Gt 是個對角矩陣, (i,i) 元素就是 t 時刻引數 θi 的梯度平方和。這一方法在稀疏資料場景下表現非常好。它的缺點是分母會不斷積累,這樣學習率就會收縮並最終會變得非常小,甚至會使得優化過程提前結束。

2.3.3 RMSProp

由於AdaGrad單調遞減的學習率變化過於激進,我們考慮一個改變二階動量計算方法的策略:不累積全部歷史梯度,而只關注過去一段時間視窗的下降梯度。梯度更新規則為:

\[\begin{array}{l} \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{E\left[g^{2}\right]_{t}+\epsilon}} g_{t} \end{array} \]

其中 E 的計算公式如下,t 時刻的依賴於前一時刻的平均和當前的梯度:

\[E\left[g^{2}\right]_{t}=0.9 E\left[g^{2}\right]_{t-1}+0.1 g_{t}^{2} \]

2.3.4 Adam

Adam 演算法和傳統的隨機梯度下降不同。隨機梯度下降保持單一的學習率(即 alpha)更新所有的權重,學習率在訓練過程中並不會改變。而 Adam 通過計算梯度的一階矩估計和二階矩估計而為不同的引數設計獨立的自適應性學習率。這個演算法是另一種計算每個引數的自適應學習率的方法,相當於 RMSprop + Momentum。

除了像 Adadelta 和 RMSprop 一樣儲存了過去梯度的平方 vt 的指數衰減平均值 ,也像 momentum 一樣保持了過去梯度 mt 的指數衰減平均值:

\[\begin{array}{l} m_{t}=\beta_{1} m_{t-1}+\left(1-\beta_{1}\right) g_{t} \\ v_{t}=\beta_{2} v_{t-1}+\left(1-\beta_{2}\right) g_{t}^{2} \end{array} \]

如果mt和vt被初始化為0向量,那它們就會向0偏置,所以做了偏差校正,通過計算偏差校正後的mt和vt來抵消這些偏差:

\[\begin{array}{l} \hat{m}_{t}=\frac{m_{t}}{1-\beta_{1}^{t}} \\ \hat{v}_{t}=\frac{v_{t}}{1-\beta_{2}^{t}} \end{array} \]

梯度更新規則:

\[\theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{\hat{v}_{t}}+\epsilon} \hat{m}_{t} \]

超引數設定值:建議 β1 = 0.9,β2 = 0.999,ϵ = 10e−8。

實踐表明,Adam 比其他適應性學習方法效果要好。

Adam 和 SGD 區別:Adam = Adaptive + Momentum,顧名思義Adam整合了SGD的一階動量和RMSProp的二階動量。

三、牛頓法

在確定搜尋方向時,梯度下降法只用到了目標函式的一階導數(梯度),然而如果能在迭代過程中引入二階導數,其效率有可能會超過梯度下降法。牛頓法就是如此,它同時使用一階和二階導數來確定搜尋方向。其具體原理如下:

當目標函式 \(f:R^{n} \rightarrow R\) 二階連續可微時,將函式在 \(x^{k}\) 處進行泰勒展開,得到二次型近似函式:

\[f(x) \approx f(x^{k}) + (x-x^{k})^{T}\nabla f(x^{k}) + \dfrac{1}{2}(x-x^{k})^{T}F(x^{k})(x-x^{k}) \]

其中,\(F(x^{k})\) 代表優化函式 \(f(x)\)\(x^{k}\) 處的黑塞矩陣。因此求 \(f(x)\) 的最小值,等效為:

\[\dfrac{\partial f(x)}{\partial x} = \nabla f(x^{k}) + F(x^{k})(x-x^{k}) = 0 \]

進一步可得,迭代過程為:

\[x^{k+1} = x^{k}-F^{-1}(x^{k})\nabla f(x^{k}) \]

類似於一維牛頓搜尋法,當 \(f''(x) < 0\) 時,牛頓法無法收斂極小值點,因此當黑塞矩陣 \(F(x^{k})\) 為非正定時,牛頓法確定的搜尋方向不一定是目標函式值的下降方向。下面簡單回顧一下黑塞矩陣極其性質。

在介紹黑塞矩陣之前,我們先來回顧一下一維函式 \(y=f(x), x \in R\)\(x_{0}\) 處存在極值的充要條件:\(f'(x_{0})=0\)\(f''(x_{0}) != 0\) ,當 $f''(x_{0})>0 $ 時, \(x_{0}\) 為極小值,當 \(f''(x_{0}) < 0\) 時,\(x_{0}\) 為極大值。

對於二維函式 \(z = f(x,y)\) 來說,假設 \(A=f_{xx}(x_{0},y_{0}), B = f_{xy}(x_{0},y_{0}), C_{yy}(x_{0},y_{0})\),那麼 \((x_{0}, y_{0})\) 為極值的充要條件為:\(f'(x_{0},y_{0})=0\), 且 \(AC - B^{2} > 0\)。當 \(A>0\) 時為極小值點,當\(A<0\) 時為極大值點。可以寫成:

\[H=\begin{bmatrix} A&B\\ B&C\\ \end{bmatrix}=\begin{bmatrix} \dfrac{\partial^{2} f(x)}{\partial x^{2}}&\dfrac{\partial^{2} f(x)}{\partial xy}\\ \dfrac{\partial^{2} f(x)}{\partial xy}&\dfrac{\partial^{2} f(x)}{\partial y^{2}}\\ \end{bmatrix} \]

其中,矩陣 \(H\) 就是黑塞矩陣,其他維度的黑塞矩陣類似。那麼對於二維變數來說,判斷極值點的條件就等價為:

  1. \(f'(x_{0},y_{0})=0\)
  2. \(|H|>0\)\(A>0\),為極小值;\(|H|>0\)\(A<0\),為極大值;

那麼對於多維函式 \(f:R^{n} \rightarrow R\) 而言,判斷極值點的條件可以推廣為:

  1. \(f'(x_{1}, x_{2},...x_{n})=0\)
  2. \(|H|>0\)\(H\) 的順序主子式均大於 0 ,為極小值(\(H\) 為正定矩陣);\(|H|>0\) 且 ,且 \(H\) 的順序主子式均小於 0(\(H\) 為負定矩陣),為極大值;

因此,牛頓法的缺點為:

  1. 對目標函式有較嚴格的要求。函式必須具有連續的一、二階偏導數,海海森矩陣必須正定。
  2. 計算相當複雜,除需要計算梯度以外,還需要計算二階偏導數矩陣和它的逆矩陣。計算量、儲存量均很⼤,且均以維數N的平⽅增加,當N很⼤時這個問題更加突出。

⽜頓法雖然收斂速度快,但是計算過程中需要計算目標函式的二階偏導數,計算複雜度較⼤。而且有時目標函式的海森矩陣無法保持正定,從而使⽜頓法失效。為了克服這兩個問題,⼈們提出了擬⽜牛頓法。這個方法的基本思想是:不⽤⼆階偏導數而構造出可以近似海森矩陣或者海森矩陣的逆的正定對稱陣,在擬⽜頓的條件下優化⽬目標函式。不同的構造⽅法就產生了不同的擬牛頓法。

四、參考資料

《最優化導論第四版》孫志強,白聖建等譯

CV總複習-深度學習機器學習基礎篇(一),作者燈會

https://zhuanlan.zhihu.com/p/32230623

https://www.cnblogs.com/bigmonkey/p/8319082.html

https://blog.csdn.net/qq_34562355/article/details/109225384