第16章 學習速率調度器
第16章 學習速率調度器
上一章中我們在訓練MiniVGGNet時,在應用SGD優化網絡時新引入了一個decay參數。本章我們將討論學習速率調度器(learning rate schedules)的概念,有時稱為學習速率退火或自適應學習速率。通過epoch-to-epoch的方式調整學習速率,我們可以降低損失、提高精確率,甚至在某些特定場景下降低訓練網絡的總時間。
1 降低學習速率
最簡單的學習速率調度器是隨著時間推移逐步降低學習速率。為了考慮為什麽學習速率調度器是一種可以提高模型精確率的方法,我們考慮標準的權重更新公式:
學習率α乘以梯度來更新權重,即α越大更新的一步越大反之越小,當α為零時將不會更新權重。在我們之前的例子中,我們都是固定α,通常設置α={0.1,0.01},之後以固定的epoch數目訓練網絡且在訓練中不改變α值。這種方式在某些場景下是合適的,但隨著時間推移降低學習速率α值是更有優勢的做法。
當訓練網絡時,我們嘗試沿著梯度方向找到精確率低的位置,常常不能獲得全局最低甚至是局部最低,能夠找到具有合理較低損失的位置就足夠好了。如果我們設置固定的學習速率,那麽可能在這些位置由於步幅太大從而錯過該位置,因此我們隨著時間推移降低學習速率允許網絡能夠以較小的步幅移動。
因此,學習速率調度器的過程可看做:
(1)在訓練早期用較高學習率獲得合理的好的權重值;
(2)在訓練過程中使用較小學習率調整權重獲得更優的權重。
我們可能遇到兩種主要的學習速率調度器類型:
(1)基於epoch數目周期性降低的學習速率調度器(像線性、二次、指數函數)。
(2)基於特定epoch降低的學習速率調度器(例如分段函數)。
1.1 Keras中標準的decay調度
Keras庫使用基於時間的學習速率調度器,它通過優化器類(如SGD)的decay參數控制。我們看在MiniVGGNet中SGD的初始化代碼塊:
這裏我們以學習率α=0.01、動量γ=0.9初始化SGD優化器,且使用Nesterov加速梯度方法。我們之後設置decay為學習率除以epoch總數目(這常是一般法則)。
Keras在每一輪epoch之後,通過下式調整學習率:
可看到,如果我們設置decay=0(在keras中默認配置為0,除非顯示提供該值),那麽學習率將不會改變。
我們重新對第15章的MiniVGGNet進行試驗,這一次去掉decay參數,重新訓練後的曲線與具有decay參數的曲線如圖16.1所示:
圖16.1 學習速率decay參數對比圖
我們註意到兩個結果都獲得了大約83%的驗證精確率,但是在不具有學習速率decay的左圖中,在25epoch後隨著驗證損失增加使得訓練過擬合了。相對的,設置了decay後,我們獲得了更平滑的學習曲線,通過使用學習速率decay參數我們不僅能提高分類精確率而且能夠減輕過擬合的影響,即提高了模型泛化的能力。
1.2 基於step的decay
另一種流行的學習速率調度器是基於步的decay,即在訓練過程中經過特定epoch後我們系統的降低學習率。這種方式可看做是分段函數,一定epoch內學習率為固定值,然後降低它,再在一定epoch內固定另一個學習率值,然後在降低它,持續進行。
當應用step decay學習率時,我們有兩個做法:
(1)定義一個分段函數,模擬我們想要的分段降低的效果;
(2)使用作者稱為的ctrl+c方法訓練深度學習網絡,即我們在給定學習率下訓練一定的epoch數目,最終註意到驗證性能停止,之後ctrl+c停止腳本,調整學習率,再次訓練。
在本章中我們主要應用基於公式的分段函數降低學習率方法。至於ctrl+c方法更高級通常用於使用深度神經網絡的更大的數據集上,這個深度神經網絡要獲得合理的精確度通常epoch數目是不確定的。這種方法將在Practitioner Bundle和ImageNet Bundle中討論。
當應用step decay時,通常在一定數目的epoch後通過(1)或(2)做法降低前一個學習率,然後更新為下一個學習率。
1.3 使用keras實現自定義學習率調度器
方便的,keras庫提供了一個LearningRateScheduler類允許我們自定義一個學習速率函數之後在訓練過程中自動應用它。這個函數以epoch作為參數之後基於我們定義的函數計算我們期望的學習率。
本章中我們自定義一個分段函數來模擬降低學習率:
這裏為初始化的學習率,F是控制學習率降低速率的因子,D為降低速率的epoch周期,E為當前epoch數目。F越大我們學習率降低越慢,F越小學習率降低越快。該等式用python實現如下:
我們使用cifar10_lr_decay.py來實現該功能,具體程序見GitHub的chapter15/。通過from keras.callbacks import LearningRateScheduler,該類使我們自定義我們的學習速率調度器。我們定義完學習速率調度器函數後,通過callbacks = [LearningRateScheduler(step_decay)]讓keras調度該函數,基於如何定義的callback,keras在每次epoch、mini-batch更新的開始或結束調用該函數。這個LearningRateScheduler方法將在每一次epoch開始時調用step_decay函數,允許我們在下一次epoch開始時更新學習率。註意,在初始化SGD時,作者喜歡將lr參數在這裏顯式指出,且與學習率調度函數中的initAlpha匹配。
為了評估drop factor在學習率調度和全局網絡分類正確率的影響,我們分別使用drop factor為0.25和0.5時運行結果。降低因子為0.25時將下降的比0.5更快。
圖16.2 不同降低因子下評估性能
由圖16.2可看出不同降低因子下性能評估。可看出降低因子在0.25時,分類正確率在79%左右,並且在15epoch後學習率僅為0.00125這意味著網絡以非常小的步幅優化,即15epoch後訓練損失和驗證損失都比較平穩了。
當學習率的降低為0.5時,我們獲得了接近82%的準確率。我們看到網絡在25-30epoch後仍在繼續學習,直到損失穩定。
2 總結
本章回顧了學習率調度的概念,我們討論了兩種調度類型。整體上說,與花費大量的時間訓練網絡和評估不同參數相比,即使簡單的數據集和項目也需要10到100次試驗來獲得更高的精確率模型。
從學習深度學習這點上說,你應當理解了訓練深度神經網絡是半科學半藝術的。本書的目標是為你提供訓練網絡背後的科學以及作者使用的經驗法則,這樣你就可以學習它背後的“藝術”,但是要記住沒有什麽比親自試驗更好的了。
你在訓練神經網絡、記錄有用或沒用的結果上的練習越多,你就會變得越好。掌握這門藝術沒有捷徑可走,你需要花費時間且熟悉SGD優化器(和其它優化器)和它的參數上。
第16章 學習速率調度器