關於深度學習優化器 optimizer 的選擇,你需要了解這些

2020-11-30 雷鋒網

雷鋒網按:本文作者楊熹,原文載於作者個人博客,雷鋒網已獲授權。

在很多機器學習和深度學習的應用中,我們發現用的最多的優化器是 Adam,為什麼呢?

下面是 TensorFlow 中的優化器:

詳情參見:https://www.tensorflow.org/api_guides/python/train

在 keras 中也有 SGD,RMSprop,Adagrad,Adadelta,Adam 等,詳情:

https://keras.io/optimizers/

我們可以發現除了常見的梯度下降,還有 Adadelta,Adagrad,RMSProp 等幾種優化器,都是什麼呢,又該怎麼選擇呢?

在 Sebastian Ruder 的這篇論文中給出了常用優化器的比較,今天來學習一下: 

原文連結:https://arxiv.org/pdf/1609.04747.pdf

本文將梳理:

● 每個算法的梯度更新規則和缺點

● 為了應對這個不足而提出的下一個算法

● 超參數的一般設定值

● 幾種算法的效果比較

● 選擇哪種算法

  優化器算法簡述

首先來看一下梯度下降最常見的三種變形 BGD,SGD,MBGD, 

這三種形式的區別就是取決於我們用多少數據來計算目標函數的梯度, 

這樣的話自然就涉及到一個 trade-off,即參數更新的準確率和運行時間。

1. Batch gradient descent

梯度更新規則: 

BGD 採用整個訓練集的數據來計算 cost function 對參數的梯度: 

缺點: 

由於這種方法是在一次更新中,就對整個數據集計算梯度,所以計算起來非常慢,遇到很大量的數據集也會非常棘手,而且不能投入新數據實時更新模型

for i in range(nb_epochs):

  params_grad = evaluate_gradient(loss_function, data, params)

  params = params - learning_rate * params_grad

我們會事先定義一個迭代次數 epoch,首先計算梯度向量 params_grad,然後沿著梯度的方向更新參數 params,learning rate 決定了我們每一步邁多大。

Batch gradient descent 對於凸函數可以收斂到全局極小值,對於非凸函數可以收斂到局部極小值。

2. Stochastic gradient descent

梯度更新規則: 

和 BGD 的一次用所有數據計算梯度相比,SGD 每次更新時對每個樣本進行梯度更新, 

對於很大的數據集來說,可能會有相似的樣本,這樣 BGD 在計算梯度時會出現冗餘, 

而 SGD 一次只進行一次更新,就沒有冗餘,而且比較快,並且可以新增樣本。

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

看代碼,可以看到區別,就是整體數據集是個循環,其中對每個樣本進行一次參數更新。

缺點: 

但是 SGD 因為更新比較頻繁,會造成 cost function 有嚴重的震蕩。

BGD 可以收斂到局部極小值,當然 SGD 的震蕩可能會跳到更好的局部極小值處。

當我們稍微減小 learning rate,SGD 和 BGD 的收斂性是一樣的。

3. Mini-batch gradient descent

梯度更新規則: 

MBGD 每一次利用一小批樣本,即 n 個樣本進行計算, 

這樣它可以降低參數更新時的方差,收斂更穩定, 

另一方面可以充分地利用深度學習庫中高度優化的矩陣操作來進行更有效的梯度計算。

和 SGD 的區別是每一次循環不是作用於每個樣本,而是具有 n 個樣本的批次

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

超參數設定值: 

n 一般取值在 50~256

缺點: 

不過 Mini-batch gradient descent 不能保證很好的收斂性:

1. learning rate 如果選擇的太小,收斂速度會很慢,如果太大,loss function 就會在極小值處不停地震蕩甚至偏離。

(有一種措施是先設定大一點的學習率,當兩次迭代之間的變化低於某個閾值後,就減小 learning rate,不過這個閾值的設定需要提前寫好,這樣的話就不能夠適應數據集的特點)

2. 此外,這種方法是對所有參數更新時應用同樣的 learning rate,如果我們的數據是稀疏的,我們更希望對出現頻率低的特徵進行大一點的更新。

3. 另外,對於非凸函數,還要避免陷於局部極小值處,或者鞍點處,因為鞍點周圍的error 是一樣的,所有維度的梯度都接近於0,SGD 很容易被困在這裡。

鞍點就是:一個光滑函數的鞍點鄰域的曲線,曲面,或超曲面,都位於這點的切線的不同邊。 

例如下圖這個二維圖形,像個馬鞍:在x-軸方向往上曲,在y-軸方向往下曲,鞍點就是(0,0)

為了應對上述這三點挑戰,於是就有了下面這些算法。

[應對挑戰 1]

4. Momentum

SGD 在 ravines 的情況下容易被困住, ravines 就是曲面的一個方向比另一個方向更陡,這時 SGD 會發生震蕩而遲遲不能接近極小值:

梯度更新規則: 

Momentum 通過加入 γv_t−1 ,可以加速 SGD, 並且抑制震蕩

當我們將一個小球從山上滾下來時,沒有阻力的話,它的動量會越來越大,但是如果遇到了阻力,速度就會變小。 

加入的這一項,可以使得梯度方向不變的維度上速度變快,梯度方向有所改變的維度上的更新速度變慢,這樣就可以加快收斂並減小震蕩。

超參數設定值: 

一般 γ 取值 0.9 左右。

缺點: 

這種情況相當於小球從山上滾下來時是在盲目地沿著坡滾,如果它能具備一些先知,例如快要上坡時,就知道需要減速了的話,適應性會更好。

5. Nesterov accelerated gradient

梯度更新規則: 

用 θ−γv_t−1 來近似當做參數下一步會變成的值,則在計算梯度時,不是在當前位置,而是未來的位置上

超參數設定值: 

γ 仍然取值 0.9 左右。

效果比較: 

藍色是 Momentum 的過程,會先計算當前的梯度,然後在更新後的累積梯度後會有一個大的跳躍。 

而 NAG 會先在前一步的累積梯度上(brown vector)有一個大的跳躍,然後衡量一下梯度做一下修正(red vector),這種預期的更新可以避免我們走的太快。

NAG 可以使 RNN 在很多任務上有更好的表現。

目前為止,我們可以做到,在更新梯度時順應 loss function 的梯度來調整速度,並且對 SGD 進行加速。

我們還希望可以根據參數的重要性而對不同的參數進行不同程度的更新。

[應對挑戰 2]

6. Adagrad

這個算法就可以對低頻的參數做較大的更新,對高頻的做較小的更新,也因此,對於稀疏的數據它的表現很好,很好地提高了 SGD 的魯棒性,例如識別 Youtube 視頻裡面的貓,訓練 GloVe word embeddings,因為它們都是需要在低頻的特徵上有更大的更新。

梯度更新規則:

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

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

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

其中 G_t 是個對角矩陣, (i,i) 元素就是 t 時刻參數 θ_i 的梯度平方和。

Adagrad 的優點是減少了學習率的手動調節

超參數設定值: 

一般 η 就取 0.01。

缺點: 

它的缺點是分母會不斷積累,這樣學習率就會收縮並最終會變得非常小。

7. Adadelta

這個算法是對 Adagrad 的改進,和 Adagrad 相比,就是分母的 G 換成了過去的梯度平方的衰減平均值:

這個分母相當於梯度的均方根 root mean squared (RMS) ,所以可以用 RMS 簡寫:

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

梯度更新規則:

此外,還將學習率 η 換成了 RMS[Δθ],這樣的話,我們甚至都不需要提前設定學習率了:

超參數設定值: 

γ 一般設定為 0.9。

8. RMSprop

RMSprop 是 Geoff Hinton 提出的一種自適應學習率方法。

RMSprop 和 Adadelta 都是為了解決 Adagrad 學習率急劇下降問題的,

梯度更新規則: 

RMSprop 與 Adadelta 的第一種形式相同:

超參數設定值: 

Hinton 建議設定 γ 為 0.9, 學習率 η 為 0.001。

9. Adam

這個算法是另一種計算每個參數的自適應學習率的方法。

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

如果 mt 和 vt 被初始化為 0 向量,那它們就會向 0 偏置,所以做了偏差校正, 

通過計算偏差校正後的 mt 和 vt 來抵消這些偏差:

梯度更新規則:

超參數設定值: 

建議 β1 = 0.9,β2 = 0.999,ϵ = 10e−8

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

  效果比較

下面看一下幾種算法在鞍點和等高線上的表現:

上面兩種情況都可以看出,Adagrad, Adadelta, RMSprop 幾乎很快就找到了正確的方向並前進,收斂速度也相當快,而其它方法要麼很慢,要麼走了很多彎路才找到。

由圖可知自適應學習率方法即 Adagrad, Adadelta, RMSprop, Adam 在這種情景下會更合適而且收斂性更好。

  如何選擇

如果數據是稀疏的,就用自適用方法,即 Adagrad, Adadelta, RMSprop, Adam。

RMSprop, Adadelta, Adam 在很多情況下的效果是相似的。

Adam 就是在 RMSprop 的基礎上加了 bias-correction 和 momentum,

隨著梯度變的稀疏,Adam 比 RMSprop 效果會好。

整體來講,Adam 是最好的選擇。

很多論文裡都會用 SGD,沒有 momentum 等。SGD 雖然能達到極小值,但是比其它算法用的時間長,而且可能會被困在鞍點。

如果需要更快的收斂,或者是訓練更深更複雜的神經網絡,需要用一種自適應的算法。

  參考:

http://sebastianruder.com/optimizing-gradient-descent/index.html#fn:24 

http://www.redcedartech.com/pdfs/Select_Optimization_Method.pdf 

https://stats.stackexchange.com/questions/55247/how-to-choose-the-right-optimization-algorithm

雷鋒網(公眾號:雷鋒網)相關閱讀:

谷歌開源計算機視覺模型MobileNets:專為不同級別行動裝置優化

OpenBLAS項目與矩陣乘法優化 | AI 研習社

雷鋒網版權文章,未經授權禁止轉載。詳情見轉載須知。

相關焦點

  • 優化器怎麼選?一文教你選擇適合不同ML項目的優化器
    編輯:小舟、杜偉為機器學習項目選擇合適的優化器不是一件簡單的事。優化器是深度學習領域的重要組成模塊之一,執行深度學習任務時採用不同的優化器會產生截然不同的效果。這也是研究者們不遺餘力「煉丹」的原因之一。
  • Adam 或許不是最佳的深度學習優化器
    這些實驗也很弱:在這些日子裡,同樣的實驗肯定會遭到拒絕。晚些時候人們還在證明中發現了一個錯誤以及該算法不收斂於某些一維隨機凸函數的事實。儘管如此,現在 Adam 被認為是優化算法之王。讓我明確一點:眾所周知, Adam 不會總實現最佳性能, 但大多數時候,人們認為可以利用 Adam 的默認參數在處理某個深度學習問題上實現至少次優的性能。換句話說,Adam 現在被認為是深度學習的默認優化器。
  • 自Adam 出現以來,深度學習優化器發生了什麼變化?
    選自medium作者:Phúc Lê機器之心編譯參與:高璇、王淑婷Adam 自出道以來,就一直是最流行的深度學習優化器,哪怕現在其實已經有幾種可能更好用的優化器……如果將 Adam 優化出現以來產生的關於優化過程的有趣想法按時間順序排列的話,結果如下:
  • 還不會使用PyTorch框架進行深度學習的小夥伴,看過來
    選自heartbeat.fritz.ai作者:Derrick Mwiti機器之心編譯參與:Geek AI、王淑婷這是一篇關於使用 PyTorch 框架進行深度學習的教程,讀完以後你可以輕鬆地將該框架應用於深度學習模型。
  • 教程| 斯坦福CS231n 2017最新課程:李飛飛詳解深度學習的框架實現...
    今天機器之心給大家分享的是其中的第八講——深度學習軟體(Deep Learning Software)。主要內容有:CPU 和 GPU 的對比;深度學習框架簡介;TensorFlow 和 PyTorch 的實例;以及各種深度學習框架的比較。
  • 一個簡單的深度學習模型,帶你深度了解背後原理
    全文共4431字,預計學習時長9分鐘深度學習是目前在實際數據科學應用中最流行的模型之一。從圖像到文本,再到語音/音樂等領域,它都是一個有效的模型。隨著使用量的上升,快速且可擴展地實現深度學習變得至關重要。Tensorflow等深度學習平臺的興起可以幫助簡化開發人員的實現方式。
  • 2012年至今,細數深度學習領域這些年取得的經典成果
    這些技術大部分應用於視覺、自然語言、語音與強化學習等領域。這些研究均已經過時間的考驗,並得到廣泛認可。本文不僅列舉了2012年以來的部分出色成果,還涉及到大量有利於了解當今深度學習研究現狀的基礎技術與知識。深度學習基礎技術的概念、方法和代碼等具有相似性,研究人員可以觸類旁通。
  • 深度學習的學習率調節實踐
    但過一段時間後,學習率會太高,因此損失會迅速回升:最佳學習率將略低於轉折點。然後,你可以重新初始化你的模型,並使用此良好的學習率對其進行正常訓練。)) self.losses.append(logs["loss"]) K.set_value(self.model.optimizer.lr, self.model.optimizer.lr * self.factor)現在我們的模型已經創建好了,我們只需調用它的compile()方法來指定要使用的loss函數和優化器。
  • 教程| 自動化機器學習第一步:使用Hyperopt自動選擇超參數
    點擊右上角即刻關注有時候在學習神經網絡教程時,我們通常會看到有的實驗似乎理所當然地就選定了某種神經網絡架構以及特定的網絡層數、激活函數、損失函數等等,卻沒有解釋原因。因為解釋起來有點難。是的,深度學習社區選擇 ReLU(或更現代的選擇 ELU 或 SELU)作為激活函數是「常態」,而且我們基本上也欣然接受,但我們通常並沒有思考這是否是正確的。
  • 十行代碼就能搞定深度學習?飛槳框架高層API,輕鬆玩轉AI
    機器之心發布機器之心編輯部嚮往深度學習技術,可是深度學習框架太難學怎麼辦?百度傾心打造飛槳框架高層 API,零基礎也能輕鬆上手深度學習,一起來看看吧?另:文末有福利,一定要看完呦~高層 API,What深度學習作為人工智慧時代的核心技術,近年來無論學術、還是工業領域,均發揮著愈加重要的作用。然而,深度學習理論太難學,開發過程太複雜,又將許多人拒之於深度學習的門外。
  • 谷歌大腦新型優化器LAMB加速大批量訓練
    BERT [4] 是當前最優的深度學習模型,它基於用於語言理解的深度雙向 transformer 而構建。當我們擴展批量大小時(比如批量大小超過 8192),之前的大批量訓練技術在 BERT 上的執行性能並不好。BERT 預訓練需要大量時間(使用 16 個 TPUv3 訓練 3 天)。
  • 哪一個才更適合編程實現深度神經網絡?
    我的回答是:別擔心,你從哪一個入門,你選擇哪一個並不重要,重要的是自己動手實踐!下面我們開始吧!這兩種框架都提供了編程神經網絡常用的機器學習步驟:導入所需的庫加載並預處理數據定義模型定義優化器和損失函數訓練模型評估模型這些步驟可以在任何一個框架中找到非常類似的實現(即使是像MindSpore這樣的框架)。
  • Deep CARs:使用Pytorch學習框架實現遷移學習
    更準確地說,是使用一個深度神經網絡,因此得名Deep CARs(深度計算機自動額定值系統)。想要實現這一目標,需要完成兩部分的學習,第1部分:構建汽車分類器;第2部分:部署分類器。本文將著重論述第1部分內容。我們將使用一種叫做遷移學習的方法來訓練分類器。什麼是遷移學習?
  • AI 教你投資:用深度學習預測虛擬貨幣價格
    這裡只是為了這個項目才這樣做的,在實際項目中,你應該始終將數據分為訓練、驗證、測試三個數據集(佔比可以分別為 60%、20%、20%)。它的主要優點是允許每個 LSTM 單元在一定時間內記住這個模式。需要注意的是,LSTM 能夠記住重要的信息,同時忘記不相關的信息。
  • 基於PyTorch圖像特徵工程的深度學習圖像增強
    介紹在深度學習黑客競賽中表現出色的技巧(或者坦率地說,是任何數據科學黑客競賽) 通常歸結為特徵工程。 當您獲得的數據不足以建立一個成功的深度學習模型時,你能發揮多少創造力?我是根據自己參加多次深度學習黑客競賽的經驗而談的,在這次深度黑客競賽中,我們獲得了包含數百張圖像的數據集——根本不足以贏得甚至完成排行榜的頂級排名。那我們怎麼處理這個問題呢?
  • AdaBelief:一個有「信仰」的優化器
    介紹 AdaBelief 前,先需要簡單介紹下 SGD(隨機梯度下降)和 Adam,因為論文中一直說的都是 AdaBelief 的最大優點就是集以上兩者的優點為一身。SGD 和 ADAMSGD 算是機器學習第一課裡的知識了,相信大部分同學也都很清楚其方法:根據損失函數給模型每個參數計算梯度,之後在梯度方向更新一小步。當然這只是 GD,還有 S(Stochastic),為提高效率,隨機選擇訓練樣本(一般為 batch),直到訓練模型到一個滿意的結果。
  • 從4個方面介紹Keras和Pytorch,並給你選擇其中一個學習庫的理由
    過去幾年裡,由於Keras和PyTorch比TensorFlow更容易使用,這兩個主要的深度學習庫已得到較廣的普及。本文將從四個方面來介紹Keras和Pytorch,以及選擇其中一個學習庫的理由。使用時,你有比Keras更多的靈活性和控制力,同時還無需冗長的聲明式編程。應該使用哪一個編程框架,是深度學習練習者一直在爭論的問題。一般來說,這取決於個人偏好。但在做選擇時,需要記住Keras和Pytorch的這幾個方面的知識。
  • 使用Python從頭開始實現深度學習庫
    理解深度學習平臺基本構建基礎的初學者指南。深度學習已在短時間內從簡單的神經網絡演變為非常複雜的架構。為了支持這種快速擴展,在此過程中開發了許多不同的深度學習平臺和庫。這些庫的主要目標之一是提供用於構建和訓練深度學習模型的易於使用的界面,使用戶可以將更多的精力放在手頭的任務上。
  • 一文弄清深度學習、TensorFlow和張量之間的關係
    圖:pixabay 「機器人圈導覽」關於深度學習系統,大家或多或少都有一些了解我們今天所用的許多深度學習系統都是基於張量代數的,比如谷歌的TensorFlow,但是張量代數與深度學習的關係到底如何?