iT邦幫忙

2022 iThome 鐵人賽

DAY 23
1

前言

本日將介紹另一個Learning Rate的技巧,也就是Warmup,並整合到Lightning-module當中。

什麼是Warmup?

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內如何實作

那麼在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的表顯距離上個峰值的差距也來的比較小了一些!

本日小節

  • 介紹Warm-up的機制
  • 與其他的Scheduler一同實做Warm-up

上一篇
[Day22] Transfer learning
下一篇
[Day24] Regularization in Deep Learning
系列文
PyTorch 生態鏈實戰運用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言