本日將介紹另一個Learning Rate的技巧,也就是Warmup,並整合到Lightning-module當中。
Warmup的本質,實際上就是一種Learning Rate的使用策略。最早是在Deep Residual Learning for Image Recognition內有討論到「過大的Learning Rate似乎不易於收斂」這樣的可能性,後來才在Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour中作為一個Learning Rate策略廣為人知。
主要是為了避免初期Learning Rate過大,導致收斂的狀態不好(不收斂、或是收斂到Local Optimal之類的)。warmup主要採取的策略就是在訓練初期時,使用比較小的learning rate,在指定的epoch之後才恢復成原先的learning rate這樣的一個策略。也就是所謂訓練前要先暖身(warm-up)這樣的一個概念。
在論文中主要分成,下列兩種:
精神上都差不多,主要就是gradual是屬於一個緩步上升的版本,逐漸暖升。下圖則是論文中的實驗結果,主要是展示在不同的batch size底下,有warmup相對會比較穩定收斂:
那麼在Lightning-Module
內該如何實作這個warm-up的機制呢?實際上有很多種方法都可行,最簡單的方法就是設置一個learning rate scheduler去達成這個功能,例如依上面的式子直接設置一個lr_scheduler.LambdaLR
就也可以達成。不過依照epoch、step的單位變化就稍微要調整一下,而且若要跟其他Scheduler一併使用也會讓lambda function的定義上更為複雜。
因此另外一個實作方法則是,利用lightning-module
內的optimization_step
(參考文件)。首先在超參數內新增一個:
train:
optimizer:
name: 'Adam'
learning_rate: 0.001
warmup_epochs: 5
這邊參照論文中一樣設定為5個epoch,沒有太多額外的理由。
接著定義具有warm-up功能的optimization_step
:
# learning rate warm-up
def optimizer_step(
self,
epoch,
batch_idx,
optimizer,
optimizer_idx,
optimizer_closure,
on_tpu=False,
using_native_amp=False,
using_lbfgs=False,):
# update params
optimizer.step(closure=optimizer_closure)
# skip the first epochs
if self.CONFIG['train']['optimizer']['warmup_epochs'] > 0:
if (self.trainer.global_step < self.CONFIG['train']['optimizer']['warmup_epochs'] * self.trainer.num_training_batches) :
lr_scale = min(1.0, float(self.trainer.global_step + 1) / float(self.CONFIG['train']['optimizer']['warmup_epochs'] * self.trainer.num_training_batches))
for pg in optimizer.param_groups:
pg["lr"] = lr_scale * self.trainer.lr_scheduler_configs[0].scheduler._get_closed_form_lr()[0]
其中主要就是利用先找到每個epoch內batch的數量self.trainer.num_training_batches
接著就能計算出該step應當的變化量,在乘上根據初始learning rate以及scheduler當下本該有的learning rateself.trainer.lr_scheduler_configs[0].scheduler._get_closed_form_lr()[0]
,就能scale出warm-up所需要設定的量了!
接著我們進實作面,改好的檔案可以參考model.py,之後在同個commit之下便可以執行train.py。一樣參考wandb的結果圖,可以看到Learning的變化囉!
那一樣的有使用pretrained的情況可以看一下Loss與AUC的表現:
是不是相對來說有warm-up的版本平穩了許多呢?而且即使過度訓練,AUC的表顯距離上個峰值的差距也來的比較小了一些!