天天看點

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

在實踐中常用到一階優化函數,典型的一階優化函數包括 BGD、SGD、mini-batch GD、Momentum、Adagrad、RMSProp、Adadelta、Adam 等等,一階優化函數在優化過程中求解的是參數的一階導數,這些一階導數的值就是模型中參數的微調值。另外,近年來二階優化函數也開始慢慢被研究起來,二階方法因為計算量的問題,現在還沒有被廣泛地使用。

深度學習模型的優化是一個非凸函數優化問題,這是與凸函數優化問題對應的。對于凸函數優化,任何局部最優解即為全局最優解。幾乎所有用梯度下降的優化方法都能收斂到全局最優解,損失曲面如下:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

而非凸函數優化問題則可能存在無數個局部最優點,損失曲面如下,可以看出有非常多的極值點,有極大值也有極小值。

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

本文将從原理、公式、代碼、loss曲線圖、優缺點等方面詳解論述:

    • 一、BGD/SGD/mini-batch GD
      • 1.1 BGD
      • 1.2 SGD
      • 1.3 Mini-batch GD
      • 1.4 GD法的缺點
    • 二、Momentum/NAG
      • 2.1 Momentum
      • 2.2 NAG
    • 三、Adagrad/RMSProp/Adadelta
      • 3.1 Adagrad
      • 3.2 RMSProp
      • 3.3 AdaDelta
    • 四、Adam\AMSgrad
      • 4.1 Adam
      • 4.2 AMSgrad
    • 五、不同優化函數比較
    • 六、pytorch不同優化函數的定義

一、BGD/SGD/mini-batch GD

梯度下降算法主要有BGD、SGD、mini-batch GD,後面還有梯度下降算法的改進,即Momentum、Adagrad 等方法

1.1 BGD

BGD(Batch gradient descent,批量梯度下降),是拿所有樣本的loss計算梯度來更新參數的,更新公式如下:

θ = θ − η ⋅ ∇ θ J ( θ ) \theta=\theta-\eta· \nabla_\theta J(\theta) θ=θ−η⋅∇θ​J(θ)

在有的文獻中,稱GD是拿所有樣本的loss計算梯度來更新參數,也就是全局梯度下降,和這裡的BGD是一個意思

其中, θ \theta θ為要更新的參數,即weight、bias; η \eta η 為學習率; J J J為損失函數,即 loss function ; ∇ θ J ( θ ) \nabla_\theta J(\theta) ∇θ​J(θ) 是指對 loss function 的 θ \theta θ 求梯度。

令 Δ θ t = − η ⋅ ∇ θ J ( θ ) \Delta\theta_t=-\eta· \nabla_\theta J(\theta) Δθt​=−η⋅∇θ​J(θ),則 θ t + 1 = θ t + Δ θ t \theta_{t+1}=\theta_{t}+\Delta\theta_t θt+1​=θt​+Δθt​, θ 1 \theta_{1} θ1​ 即初始化的weight、bias。

寫成僞代碼如下:

# all_input和all_target是所有樣本的特征向量和label
for i in range(epochs):
    optimizer.zero_grad()
    output = model(all_input)
    loss = loss_fn(output,all_target)
    loss.backward()
    optimizer.step()
           

在loss的等值線圖中,随着 weight 的變化loss降低的曲線走向(紅線)如下所示:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中 x1是縱軸,x2是橫軸 ; w e i g h t = [ x 1 , x 2 ] weight=[x1,x2] weight=[x1,x2] ,即兩個坐标軸對應的點; X i = [ x 1 i , x 2 i ] X_i=[x1_i,x2_i] Xi​=[x1i​,x2i​],即weight不同時刻的取值; X 0 = [ x 1 0 , x 2 0 ] X_0=[x1_0,x2_0] X0​=[x10​,x20​]是weight的初始化值。

從上圖中可以看出,BGD的loss曲線走向相對平滑,每一次優化都是朝着最優點走。

由于BGD在每次計算損失值時都是針對整個參與訓練的樣本而言的,是以會出現記憶體裝不下,速度也很慢的情況。能不能一次取一個樣本呢?于是就有了随機梯度下降(Stochastic gradient descent),簡稱 sgd。

1.2 SGD

SGD(Stochastic gradient descent,随機梯度下降)是一次拿一個樣本的loss計算梯度來更新參數,其更新公式如下:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中, x ( i ) x^{(i)} x(i) 是第一個樣本的特征向量, y ( i ) y^{(i)} y(i) 是第i個樣本的真實值。

也可以寫成如下形式:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中, g t , i g_{t,i} gt,i​ 是第i個樣本的梯度。

寫成僞代碼如下:

for i in range(epochs):
    # batch=1,每次從dataset取出一個樣本
    for input_i,target_i in dataset:
        optimizer.zero_grad()
        output = model(all_input)
        loss = loss_fn(output,all_target)
        loss.backward()
        optimizer.step()
           

在loss的等值線圖中,随着 weight 的變化loss降低的曲線走向如下所示:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

從上圖中可以看出,SGD的loss曲線走向是破浪式的,相對于BGD的方式,波動大,在非凸函數優化問題中,SGD可能使梯度下降到更好的另一個局部最優解,但從另一方面來講,SGD的更新可能導緻梯度一直在局部最優解附近波動。

SGD的不确定性較大,可能跳出一個局部最優解到另一個更好的局部最優解,也可能跳不出局部最優解,一直在局部最優解附近波動

由于同一類别樣本的特征是相似的,是以某一個樣本的特征能在一定程度代表該類樣本,是以SGD最終也能夠達到一個不錯的結果,但是,SGD的更新方式的波動大,更新方向前後有抵消,存在浪費算力的情況。于是,就有了後來大家常用的小批量梯度下降算法(Mini-batch gradient descent)。

1.3 Mini-batch GD

Mini-batch GD(Mini-batch gradient descent,小批量梯度下降)是一次拿一個batch的樣本的loss計算梯度來更新參數,其更新公式如下:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中,batch_size=n。

寫成僞代碼如下:

for i in range(epochs):
    # batch_size=n,每次從dataset取n個樣本
    for input,target in dataset:
        optimizer.zero_grad()
        output = model(all_input)
        loss = loss_fn(output,all_target)
        loss.backward()
        optimizer.step()
           

在loss的等值線圖中,随着 weight 的變化loss降低的曲線走向如下所示:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

從上圖可以看出,mini-batch GD 的loss走向曲線在BGD和SGD之間,mini-batch GD 既解決了SGD更新方式波動大的問題,又可以盡量去計算多個樣本的loss,提高參數的更新效率。

1.4 GD法的缺點

梯度下降算法雖然取得了一定的效果,但是仍然有以下缺點:

  • 學習率大小比較難缺難确定,需要反複去試
  • 學習率不夠智能,對每個參數的各個次元一視同仁
  • mini-batch GD算法中,雖然一定程度上提高參數的更新效率,并沒有完全解決SGD中的問題,即更新方向仍然前後有抵消,仍然有浪費算力的情況
  • SGD和mini-batch GD由于每次參數訓練的樣本是随機選取的,模型會受到随機訓練樣本中噪聲資料的影響,又因為有随機的因素,是以也容易導緻模型最終得到局部最優解。

二、Momentum/NAG

知道了GD法的缺點,動量法通過之前積累梯度來替代真正的梯度進而避免GD法浪費算力的缺點,加快更新速度,我們現在來看動量法(momentum)和其改進方法NAG吧。

2.1 Momentum

在使用梯度下降算法的時,剛開始的時候梯度不穩定,波動性大,導緻做了很多無用的疊代,浪費了算力,動量法(momentum)解決SGD/mini-batch GD中參數更新震蕩的問題,通過之前積累梯度來替代真正的梯度,進而加快更新速度,其更新公式如下:

υ t = γ υ t − 1 + η ⋅ ∇ θ J ( θ ) θ = θ − υ t \begin{array}{l} \upsilon_t=\gamma\upsilon_{t-1}+\eta· \nabla_\theta J(\theta)\\ \theta=\theta-\upsilon_t \end{array} υt​=γυt−1​+η⋅∇θ​J(θ)θ=θ−υt​​

其中, θ \theta θ是要更新的參數即weight, ∇ θ J ( θ ) \nabla_\theta J(\theta) ∇θ​J(θ)是損失函數關于weight的梯度, γ \gamma γ為動量因子,通常設為0.9; η \eta η 為學習率。這裡新出現了一個變量 υ \upsilon υ,對應實體上的速度。

也可以寫成下面的形式(不常用):

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中, ρ \rho ρ為動量因子,通常設為0.9; α \alpha α為學習率。

隻看公式可能不好了解,我們來代入計算下吧。

假設 η \eta η 學習率為0.1,用 g 表示損失函數關于weight的梯度,則可計算如下:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

動量法(momentum)更新示意圖如下所示:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

這樣, 每個參數的實際更新內插補點取決于最近一段時間内梯度的權重平均值。當某個參數在最近一段時間内的梯度方向不一緻時, 其真實的參數更新幅度變小,增加穩定性; 相反, 當在最近一段時間内的梯度方向都一緻時, 其真實的參數更新幅度變大, 起到加速作用。

一般而言, 在疊代初期, 梯度方向都比較一緻, 動量法會起到加速作用, 可以更快地到達最優點。在疊代後期, 梯度方向會不一緻, 在收斂值附近振蕩, 動量法會起到減速作用, 增加穩定性。動量法也能解決稀疏梯度和噪聲問題,這個到Adam那裡會有詳細解釋。

2.2 NAG

NAG(Nesterov Accelerated Gradient,Nesterov加速梯度)是一種對動量法的改進方法, 也稱為 Nesterov 動量法(Nesterov Momentum)。其公式如下:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中, ∇ θ J ( θ − γ υ t − 1 ) \nabla_\theta J(\theta-\gamma\upsilon_{t-1}) ∇θ​J(θ−γυt−1​)是損失函數關于下一次(提前點)weight的梯度。

也可以寫為(不常用):

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

NAG更新示意圖如下所示:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

由于momentum剛開始時梯度方向都比較一緻,收斂較快,但是到後期,由于momentum慣性的存在,很可能導緻在loss極值點的附近來回震蕩,而NAG向前計算了一次梯度,當梯度方向快要改變的時候,它提前獲得了該資訊,進而減弱了這個過程,再次減少了無用的疊代,并保證能順利更新到loss的極小值點。

三、Adagrad/RMSProp/Adadelta

在神經網絡的學習中,學習率( η \eta η)的值很重要。學習率過小,會導緻學習花費過多時間;反過來,學習率過大,則會導緻學習發散而不能正确進行。

在關于學習率的有效技巧中,有一種被稱為學習率衰減(learning rate decay)的方法,即随着學習的進行,使學習率逐漸減小。實際上,一開始“多”學,然後逐漸“少”學的方法,在神經網絡的學習中經常被使用。逐漸減國小習率的想法,相當于将“全體”參數的學習率值一起降低。而AdaGrad進一步發展了這個想法,針對“一個一個”的參數,賦予其“定制”的值,現在我們來看Adagrad/RMSProp/Adadelta吧。

3.1 Adagrad

AdaGrad(Adaptive Grad,自适應梯度)為參數的每個參數自适應地調整學習率,讓不同的參數具有不同的學習率,其公式如下:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中,W表示要更新的權重參數, ∂ L ∂ W \frac{{\partial L}}{{\partial W}} ∂W∂L​表示損失函數關于W的梯度, η \eta η表示學習率,這裡新出現了變量 h h h,它儲存了以前的所有梯度值的平方和, ⊙ \odot ⊙表示對應矩陣元素的乘法。然後,在更新參數時,通過乘以 1 h \frac{1}{\sqrt h} h

​1​,就可以調整學習的尺度。這意味着,參數的元素中變動較大(被大幅更新)的元素的學習率将變小。也就是說,可以按參數的元素進行學習率衰減,使變動大的參數的學習率逐漸減小。

Adagrad公式也可以寫為:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中, g τ ∈ R g_\tau \in R gτ​∈R 是第 τ \tau τ次疊代時的梯度, α \alpha α為初始的學習率, ε \varepsilon ε是為了保持數值穩定性而設定的非常小的常數, 一般取值 e − 7 e^{−7} e−7 到 e − 10 e^{−10} e−10,此外, 這裡的開平方、 除、 加運算都是按元素進行的操作。

由于Adagrad學習率衰減用了所有的梯度,如果在經過一定次數的疊代依然沒有找到最優點時,累加的梯度幅值是越來越大的,導緻學習率越來越小, 很難再繼續找到最優點,為了改善這個問題,進而提出RMSProp算法。

3.2 RMSProp

與AdaGrad不同,RMSProp(Root Mean Square Propagation,均方根傳播) 方法并不是将過去所有的梯度一視同仁地相加,而是逐漸地遺忘過去的梯度,在做加法運算時将新梯度的資訊更多地反映出來,這種操作從專業上講,稱為“指數移動平均”,呈指數函數式地減小過去的梯度的尺度。

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中, β \beta β 為衰減率, 一般取值為 0.9, α \alpha α為初始的學習率, 比如 0.001。

從上式可以看出, RMSProp 算法和 AdaGrad 算法的差別在于 G t G_t Gt​ 的計算由累積方式變成了指數衰減移動平均。在疊代過程中, 并且,每個參數的學習率并不是呈衰減趨勢, 既可以變小也可以變大(把 β \beta β設的更小些,每個參數的學習率就呈變大趨勢)。

這裡不得不提一下RProp,Rprop可以看做 RMSProp的簡單版,它是依據符号來改變學習率的大小:當最後兩次梯度符号一樣,增大學習率,當最後兩次梯度符号不同,減國小習率。

3.3 AdaDelta

AdaDelta 與 RMSprop 算法類似, AdaDelta 算法也是通過梯度平方的指數衰減移動平均來調整學習率。此外, AdaDelta 算法還引入了每次參數更新內插補點Δ𝜃 的平方的指數衰減權移動平均。

第 t 次疊代時, 參數更新內插補點 Δ𝜃 的平方的指數衰減權移動平均為

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

AdaDelta 算法的參數更新公式為:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中 G t G_t Gt​ 的計算方式和 RMSprop 算法一樣 , Δ X t − 1 2 \Delta X_{t - 1}^2 ΔXt−12​ 為參數更新內插補點 Δ𝜃 的指數衰減權移動平均。

從上式可以看出, AdaDelta 算法将 RMSprop 算法中的初始學習率 𝛽 改為動态計算的 Δ X t − 1 2 \sqrt {\Delta X_{t - 1}^2} ΔXt−12​

​ ,在一定程度上平抑了學習率的波動。除此之外,AdaDelta連初始的學習率都不要設定了,提升了參數變化量的自适應能力。

除此之外,AdaDelta公式還有一個常用的表示方法:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

四、Adam\AMSgrad

現在來介紹比較好用的方法Adam和其改進方法AMSgrad。

4.1 Adam

Adam 算法 (Adaptive Moment Estimation Algorithm)可以看作動量法和 RMSprop 算法的結合, 不但使用動量作為參數更新方向, 而且可以自适應調整學習率。

Adam 算法一方面計算梯度平方 g t 2 g^2_t gt2​ 的指數衰減移動平均(和 RMSprop 算法類似), 另一方面計算梯度 g t g_t gt​ 的指數衰減移動平均 (和動量法類似),如下所示:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中 β 1 \beta_1 β1​ 和 β 2 \beta_2 β2​ 分别為兩個移動平均的衰減率, 通常取值為 β 1 \beta_1 β1​ = 0.9, β 2 \beta_2 β2​ = 0.999。 我們可以把 M t M_t Mt​ 和 G t G_t Gt​ 分别看作梯度的均值(一階矩估計)和未減去均值的方差(二階矩估計)。其中, M t M_t Mt​ 來自momentum,用來穩定梯度, G t G_t Gt​ 來自RMSProp,用來是梯度自适應化。

對 M t M_t Mt​ 和 G t G_t Gt​偏差進行修正:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

Adam 算法的參數更新公式為:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

其中,其中學習率 $\alpha $ 通常設為 0.001, 并且也可以進行衰減, 比如 α t = α 0 t \alpha_t=\frac{\alpha_{0}}{\sqrt t} αt​=t

​α0​​ 。

Adam, 結合了 動量法 和 RMSProp 算法最優的性能,它還是能提供解決稀疏梯度和噪聲問題的優化方法,在深度學習中使用較多。這裡解釋一下為什麼Adam能夠解決稀疏梯度和噪聲問題:稀疏梯度是指梯度較多為0的情況,由于adam引入了動量法,在梯度是0的時候,還有之前更新時的梯度存在(道理跟momentum一樣),還能繼續更新;噪聲問題是對于梯度來說有一個小波折(類似于下山時路不平有個小坑)即多個小極值點,可以跨過去,不至于陷在裡面。

Adam 算法是 RMSProp 算法與動量法的結合, 是以一種自然的 Adam 算法的改進方法是引入 Nesterov 加速梯度, 稱為Nadam 算法

這裡思考一個問題:為什麼對Adam偏差進行修正?

網上沒找到好的解釋,那來看一下原文吧!

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

大緻意思是說:剛開始,我們任意初始化了一個 m 0 m_0 m0​(注意:一般 m 0 m_0 m0​初始化為0,在Momentum算法中也是),并且根據公式 m t = β m t − 1 + ( 1 − β ) g t m_t=\beta m_{t-1}+(1-\beta)g_t mt​=βmt−1​+(1−β)gt​更新公式,得到 m 1 m_1 m1​,可以明顯的看到,第一步更新嚴重依賴初始化的 m 0 m_0 m0​,這樣可能會造成嚴重的偏差。

為了糾正這個,我們需要移除這個初始化 m 0 m_0 m0​(偏置)的影響,例如,可以把 m 1 = β m 0 + ( 1 − β ) g 1 m_1=\beta m_{0}+(1-\beta)g_1 m1​=βm0​+(1−β)g1​中的 β m 0 \beta m_{0} βm0​從 m 1 m_1 m1​移除(即 m 1 − β m 0 m_1-\beta m_0 m1​−βm0​),并且除以( 1 − β 1-\beta 1−β),這樣公式就變為了 m ^ = m 1 − β m 0 1 − β \hat{m}=\frac{m_1-\beta m_0}{1-\beta} m^=1−βm1​−βm0​​,當 m 0 m_0 m0​=0時, m t ^ = m t 1 − β t \hat{m_t}=\frac{m_t}{1-\beta^t} mt​^​=1−βtmt​​。同理,對于 G t G_t Gt​也是如此。

總的來說,在疊代初期, M t M_t Mt​ 和 G t G_t Gt​的更新嚴重依賴于初始化的 M 0 = 0 M_0=0 M0​=0、 G 0 = 0 G0=0 G0=0,當初始化 M t M_t Mt​ 和 G t G_t Gt​都為0時, M t M_t Mt​ 和 G t G_t Gt​都會接近于0,這個估計是有問題的,可能會造成嚴重的偏差(即可能使學習率和方向與真正需要優化的學習率和方向嚴重偏離),是以,我需要移除這個初始化的 M 0 M_0 M0​ 和 G 0 G0 G0(偏置)的影響, 故需要對偏差進行修正。

上面說了這麼多理論,分析起來頭頭是道,各種改進版本似乎各個碾壓 SGD 算法。但是否真的如呢?此外,Adam看起來都這麼厲害了,以後的優化函數都要使用Adam嗎?

來看一下下面的實驗:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

所有方法都采用作者們(原文)的預設配置,并且進行了參數調優,不好的結果就不拿出來了。

  • nesterov 方法,與 sgd 算法同樣的配置。
  • adam 算法,m1=0.9,m2=0.999,lr=0.001。
  • rms 算法,rms_decay=0.9,lr=0.001。
  • adagrad,adadelta 學習率不敏感。

看起來好像都不如 SGD 算法,實際上這是一個很普遍的現象,各類開源項目和論文都能夠印證這個結論。總體上來說,改進方法降低了調參工作量,隻要能夠達到與精細調參的 SGD 相當的性能,就很有意義了,這也是 Adam 流行的原因。但是,改進政策帶來的學習率和步長的不穩定還是有可能影響算法的性能,是以這也是一個研究的方向,不然哪來這麼多Adam 的變種呢。

這裡引用一位清華博士舉的例子:很多年以前,攝影離普羅大衆非常遙遠。十年前,傻瓜相機開始風靡,遊客幾乎人手一個。智能手機出現以後,攝影更是走進千家萬戶,手機随手一拍,前後兩千萬,照亮你的美(咦,這是什麼亂七八糟的)。但是專業攝影師還是喜歡用單反,孜孜不倦地調光圈、快門、ISO、白平衡……一堆自拍黨從不care的名詞。技術的進步,使得傻瓜式操作就可以得到不錯的效果,但是在特定的場景下,要拍出最好的效果,依然需要深入地了解光線、了解結構、了解器材。優化算法大抵也如此,大家都是殊途同歸,隻是相當于在SGD基礎上增加了各類學習率的主動控制。如果不想做精細的調優,那麼Adam顯然最便于直接拿來上手。

原文在Adam那麼棒,為什麼還對SGD念念不忘 (2)—— Adam的兩宗罪

Adam那麼棒,也不是沒有缺點,繼續往下面看!

4.2 AMSgrad

ICLR 2018 最佳論文提出了 AMSgrad 方法,研究人員觀察到 Adam 類的方法之是以會不能收斂到很好的結果,是因為在優化算法中廣泛使用的指數衰減方法會使得梯度的記憶時間太短。

在深度學習中,每一個 mini-batch 對結果的優化貢獻是不一樣的,有的産生的梯度特别有效,但是也一視同仁地被時間所遺忘。

具體的做法是使用過去平方梯度的最大值來更新參數,而不是指數平均。其公式如下:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

五、不同優化函數比較

(1)不同優化函數的loss下降曲線如下:

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

(2)不同優化函數在 MNIST 資料集上收斂性的比較(學習率為0.001, 批量大小為 128):

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

(3)不同優化函數配對比較

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

橫縱坐标表示降維後的特征空間,區域顔色則表示目标函數值的變化,紅色是高原,藍色是窪地。他們做的是配對兒實驗,讓兩個算法從同一個初始化位置開始出發,然後對比優化的結果。可以看到,幾乎任何兩個算法都走到了不同的窪地,他們中間往往隔了一個很高的高原。這就說明,不同算法在高原的時候,選擇了不同的下降方向。

這裡參考 Adam那麼棒,為什麼還對SGD念念不忘 (3)—— 優化算法的選擇與使用政策述

六、pytorch不同優化函數的定義

這裡介紹幾種常用優化函數的參數定義和解釋

(1)torch.optim.SGD

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

重要參數解釋:

  • lr 學習率,用于控制梯度更新的快慢,如果學習速率過快,參數的更新跨步就會變大,極易出現震蕩;如果學習速率過慢,梯度更新的疊代次數就會增加,參數更新、優化的時間也會變長,是以選擇一個合理的學習速率是非常關鍵的。
  • momentum 動量因子,介于[0,1]之間,預設為0,一般設為0.9,當某個參數在最近一段時間内的梯度方向(即與動量 υ \upsilon υ方向)不一緻時, 其真實的參數更新幅度變小,增加穩定性; 相反, 當在最近一段時間内的梯度方向都一緻時, 其真實的參數更新幅度變大, 起到加速作用。
  • weight_decay 權重衰減(L2懲罰),預設為0,來看下原文吧:
    【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad
    大緻意思是說:為了避免過拟合,在這裡增加了一個L2懲罰項,推到如下:
    【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad
    其中, η \eta η為學習率,而 η   λ \eta\ \lambda η λ 就是weight_decay,不過pytorch讓使用者可以自由設定,有了更大的自由度
  • nesterov,布爾類型,預設為False,設為True,可使用NAG動量

使用方式:

optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
for i in range(epochs):
    # batch_size=n,每次從dataset取n個樣本
    for input,target in dataset:
        optimizer.zero_grad()
        output = model(all_input)
        loss = loss_fn(output,all_target)
        loss.backward()
        optimizer.step()
           

(2)torch.optim.Adagrad

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad

主要參數詳解:

  • lr-decay 學習率衰減,學習率衰減公式如下所示:
    【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad
    其中, l r i lr_i lri​為第i次疊代時的學習率, l r s t a r t lr_start lrs​tart為原始學習率,decay為一個介于[0.0, 1.0]的小數。可以看到,decay越小,學習率衰減地越慢,當decay = 0時,學習率保持不變。decay越大,學習率衰減地越快,當decay = 1時,學習率衰減最快。
  • eps,相當于 ε \varepsilon ε,是為了保持數值穩定性而設定的非常小的常數, 一般取值 e − 7 e^{−7} e−7 到 e − 10 e^{−10} e−10

(3)torch.optim.Adam

【超詳細】對比10種優化函數BGD、SGD、mini-batch GD、Momentum、NAG、Adagrad、RMSProp、Adadelta、Adam、AMSgrad
  • betas,預設值(0.9,0.999),即Adam裡的 β 1 \beta_1 β1​、 β 2 \beta_2 β2​
  • amsgrad,是否啟用Adam的改進方法AMSgrad,預設為False

這裡隻介紹了需要注意的幾個優化函數,更多函數定義,請查閱pytorch官方文檔

【參考文檔】

神經網絡與深度學習-邱錫鵬著

有三AI-深度學習視覺算法工程師指導手冊

深度學習入門:基于pytorch的理論與實作-陸宇傑譯

深度學習之pytorch實戰計算機視覺-唐進民著

optim.sgd學習參數

繼續閱讀