天天看點

把RAdam和LookAhead合二為一

RAdam 和 LookAhead 有可能形成互補嗎?

毋庸置疑,在訓練的初始階段,RAdam 能為優化器提供最棒的基礎值。借助一個動态整流器,RAdam 可以根據變差大小來調整 Adam 優化器中的自适應動量,并且可以提供一個高效的自動預熱過程;這些都可以針對目前的資料集運作,進而為深度神經網絡的訓練提供一個紮實的開頭。

LookAhead 的設計得益于對神經網絡損失空間了解的最新進展,為整個訓練過程的魯棒、穩定探索都提供了突破性的改進。用 LookAhead 論文作者們自己的話說,LookAhead「減少了超參數調節的工作量」,同時「在許多不同的深度學習任務中都有更快的收斂速度、最小的計算開銷」。還有,「我們通過實驗表明,LookAhead 可以顯著提高 SGD 和 Adam 的表現,即便是用預設的超參數直接在 ImageNet、CIFAR-10/100、機器翻譯任務以及 Penn Treebank 上運作」。

把RAdam和LookAhead合二為一

那麼,既然兩種方法是從不同的角度對深度學習的優化過程提供了改進,我們全完可以猜測兩者合并以後可以起到協同作用,帶來更棒的結果;也許這就是我們在尋找更穩定更魯棒的優化方法之路上的最新一站。

在下文中,作者将會在 RAdam 介紹的基礎上解釋 LookAhead 的原理,以及如何把 RAdam 和 LookAhead 內建到同一個優化器(Ranger)中。在作者的實驗中,訓練隻運作了前 20 個 epoch,模型就給出了一個讓作者喜出望外的準确率;實際上這個準确率要比 FastAI 的排行榜第一名還要高出 1%。

把RAdam和LookAhead合二為一

第一次測試就快速達到 93% 準确率

把RAdam和LookAhead合二為一

FastAI 的 20 個 epoch 準确率排行榜第一名,92%

更重要的是,文中有詳盡的源代碼和使用資訊介紹,任何人都可以運作這個 Ranger 優化器,看看能否看到穩定性和準确率的提升。

下面我們先分别認識一下 RAdam 和 LookAhead。

什麼是 RAdam

簡單來說,RAdam 的作者們研究了為什麼帶有自适應動量的優化器(Adam, RMSProp 等等)都需要一個預熱階段,不然在訓練剛剛啟動的時候就很容易陷入不好的、可能有問題的局部最優。

把RAdam和LookAhead合二為一

他們找到的原因是,在訓練剛開始時有非常大的變動,可以說是優化器還沒見到足夠多的資料,沒法做出準确的自适應動量選擇。預熱過程就可以在訓練的初始階段減小變差。根據上面這張圖可以看到,沒有預熱階段的時候,疊代早期的誤差分布會發生劇烈變化。不過,多長的預熱過程才算夠需要手動調整,而且在不同的資料集上也會有所不同。

是以,RAdam 的設計思路就是采用了一個整流器函數,它可以基于實際遇到的變差計算出一個「預熱啟發值」。然後這個整流器可以動态地對自适應動量進行開、關或者加阻尼,避免它以全速運動,直到來自資料的變差開始穩定為止。這樣的做法就避免了用人工方法執行一個預熱階段,訓練過程也就自動穩定下來了。

當變差穩定下來之後,RAdam 在剩下的訓練過程中基本就等效于 Adam 甚至 SGD。也是以,RAdam 隻能為訓練的開始階段帶來改善。

需要各位讀者注意的是,雖然在 RAdam 論文中的實驗結果小節裡 RAdam 的表現比 Adam 好,但是如果運作非常長的時間,那麼 SGD 最終會追上來,而且會得到比 RAdam 和 Adam 更高的最終準确率。

現在我們就需要轉頭看看 LookAhead 了,我們需要內建一種新的探索機制,能在超過 1000 個 epoch 的訓練之後仍然比 SGD 表現更好。

把RAdam和LookAhead合二為一

LookAhead - 探索損失空間的搭檔系統,更快、更穩定的探索和收斂

在介紹 LookAhead 之前,我們首先需要知道,在 SGD 基礎上改進而來的大多數成功的優化器都可以歸為以下兩類:

  1. 增加自适應動量,Adam、AdaGrad
  2. 增加某種加速機制,Nesterov 動量或 Polyak Heavy Ball

它們用這些做法來改進探索和訓練過程,最終讓模型收斂。

把RAdam和LookAhead合二為一

LookAhead 和它們都有所不同,它采用了一種全新的設計:會維持兩套權重,并在兩者之間進行内插,可以說是,它允許更快的那一組權重「向前看」(也就是探索),同時更慢的那一組權重可以留在後面,帶來更好的長期穩定性。

這種做法帶來的效果就是降低了訓練過程中的變差,以及大大降低了對次優的超參數的敏感性(進而減少了大量嘗試超參數調節的需要);同時,它在許多種不同的深度學習任務中都可以達到更快的收斂速度。可以說這是一項飛躍式的進步。

把RAdam和LookAhead合二為一

可以打個簡單的比方,假想你在一個山頂區域,你周圍有很多條不同的路下山,有的也許可以讓你輕松到達山下,有的路則會遇到險惡的懸崖和斷層。如果你孤身一人,去探索這些路就會有點麻煩,你得一條條嘗試,假如選的路走不通,你很可能會卡在半路,回不到山頂、沒辦法試下一條路了。但是如果你有個好朋友一起,他可以在山頂等你,而且可以幫助你脫離險境的話,那麼你被卡在半路的機會就小多了、找到合适的下山路的機會就大多了。

可以說 LookAhead 基本就是這樣工作的,它會多存儲一份權重副本,然後讓那個内部的「快」優化器多探索 5 或 6 個批(在作者的 Ranger 實作中,快的優化器就是 RAdam,多探索的批的數量通過 k 參數指定)。每經過 k 個間隔,快優化器 RAdam 多探索了 k 個批,然後 LookAhead 會計算存儲的權重副本和最新的 RAdam 的權重的差,把這個差乘上 alpha 參數(預設為 0.5),然後更新 RAdam 的參數,再開始下 k 個間隔的探索。

把RAdam和LookAhead合二為一

這樣做的效果就是,LookAhead 從内部快優化器(這裡就是 RAdam)實作一個快速前進的均值的同時,還有一個慢一些的指數前進的均值。快速前進有更好的探索效果,慢的那個起到一個拖拽回歸的作用,也可以看作是一個穩定性維持機制 —— 一般情況下慢速前進的這個都落在後面,但也可以在快的優化器進入了一個更有潛力的下坡卻又跑出去的時候把它拽回來。整個優化器可以更細緻地探索整個空間,同時不需要怎麼擔心卡在不好的局部極值。

這種方法和上面提到的目前的兩種主流方法都完全不同,然後由于它的設計提升了訓練穩定性,是以它的探索速度更快、探索過程更魯棒,探索的結果也比 SGD 更好。

RAdam 加 LookAhead 的一個實作:Ranger

在解釋過 LookAhead 的工作原理以後我們可以看出來,其中的那個快優化器可以選用任意一個現有的優化器。在 LookAhead 論文中他們使用的是最初的 Adam,畢竟那時候 RAdam 還沒有釋出呢。

把RAdam和LookAhead合二為一

那麼顯然,要實作 RAdam 加 LookAhead,隻需要把原來的 LookAhead 中的 Adam 優化器替換成 RAdam 就可以了。

在 FastAI 中,合并 RAdam 和 LookAhead 的代碼是一件非常容易的事情,他使用的 LookAhead 代碼來自 LonePatient,RAdam 則來自論文作者們的官方代碼。Less Wright 把合并後的這個新優化器稱作 Ranger(其中的前兩個字母 RA 來自 RAdam,Ranger 整個單詞的意思“突擊隊員”則很好地展現出了 LookAhead 能出色地探索損失空間的特點)。

Ranger 的代碼開源在 ​​https://github.com/lessw2020/Ranger-Deep-Learning-Optimizer?source=post_page-----2dc83f79a48d----------------------​​

使用方法:

  1. 把 ranger.py 拷貝到工作目錄下
  2. import ranger
  3. 把RAdam和LookAhead合二為一
  4. 建立一個 partial,為 FastAI 調用 Ranger 做準備,然後把學習者的 opt_func 指向它
  5. 把RAdam和LookAhead合二為一
  6. 開始測試吧!
  7. 把RAdam和LookAhead合二為一
把RAdam和LookAhead合二為一
  • k - 它控制快優化器的權重和 LookAhead 中的慢優化器的權重協同更新的間隔。預設值一般是 5 或者 6,不過 LookAhead 論文裡最大也用過 20。
  • alpha - 它控制根據快慢優化器權重之差的多少比例來更新快優化器的權重。預設值是 0.5,LookAhead 論文作者 Hinton 等人在論文裡給出了一個強有力的證明,表示 0.5 可能就是理想值。不過大家也可以做自己的嘗試。
  • 他們也在論文中指出,未來一個可能的改進方向是根據訓練進行到不同的階段,規劃使用不同的 k 和 alpha 的值。

總結