5.3 學習率調整策略
深度學習模型訓練中調整最頻繁的就屬學習率了,好的學習率可以使模型逐漸收斂並獲得更好的精度。
本小節將介紹pytorch提供的十四種學習率調整方法,首先瞭解lr_scheduler整體結構設計,然後以StepLR為例,深度剖析一個學習率調整器的原始程式碼實現細節,最後總結十四個學習率調整策略。
lr_scheduler 設計
lr_scheduler模組的設計與優化器一樣,定義了一個核心基類_LRScheduler,在_LRScheduler中設計好學習率調整器的屬性與方法。
核心屬性有optimizer、base_lrs和last_epoch。
optimizer是調整器所管理的優化器,優化器中所管理的參數組有對應的學習率,調整器要調整的內容就在那裡。
base_lrs是基礎學習率,來自於optimizer一開始設定的那個值。self.base_lrs = [group['initial_lr'] for group in optimizer.param_groups]
last_epoch是記錄反覆運算次數,通常用於計算下一輪學習率。注意,默認初始值是-1,因為last_epoch的管理邏輯是執行一次,自加1。
核心方法有state_dict()、load_state_dict()、get_last_lr()、get_lr()、print_lr()、step()。
state_dict()和load_state_dict()分別是獲取調整器的狀態資料與載入狀態資料。
get_last_lr()、get_lr() 分別為獲取上一次和當前的學習率。
print_lr()是列印學習率。
step()為更新學習率的介面函數,使用者調用 scheduler.step()即完成一次更新。
lr_scheduler 使用流程
第一步:產生實體。scheduler = optim.lr_scheduler.StepLR(optimizer, gamma=0.1, step_size=50)
第二步:合適的位置執行step()。大家要注意,不同的調整器的更新策略是不一樣的,有的是基於epoch維度,有的是基於iteration維度,這個需要注意。
StepLR 原始程式碼解讀
StepLR是依據設定的step_size,以固定的間隔進行調整,調整規則為 lr_new = lr_old * gamma, 通常gamma設置為0.1,即一定次數訓練後,學習率下降10倍。
下面觀察代碼,在代碼104行與146行打斷點進行調試,依次觀察初始化過程、step更新過程。
初始化過程:
StepLR類__init__()函數:
self.step_size = step_size
self.gamma = gamma
super(StepLR, self).__init__(optimizer, last_epoch, verbose)
Copy
跳轉到_LRScheduler類__init__()函數:
第一步:獲取初始學習率:group.setdefault('initial_lr', group['lr'])
第二步:記錄基礎學習率:self.base_lrs = [group['initial_lr'] for group in optimizer.param_groups]
self.last_epoch = last_epoch
第三步:執行首次step(),也就是在初始化的時候會自動執行一次step(),這也是為什麼last_epoch的預設值是-1的原因。
step中會進行第0個epoch的學習率獲取,具體過程如代碼所示:
torch/optim/lr_scheduler.py 151至168行
with _enable_get_lr_call(self):
if epoch is None:
self.last_epoch += 1
values = self.get_lr()
else:
warnings.warn(EPOCH_DEPRECATION_WARNING, UserWarning)
self.last_epoch = epoch
if hasattr(self, "_get_closed_form_lr"):
values = self._get_closed_form_lr()
else:
values = self.get_lr()
for i, data in enumerate(zip(self.optimizer.param_groups, values)):
param_group, lr = data
param_group['lr'] = lr
self.print_lr(self.verbose, i, lr, epoch)
self._last_lr = [group['lr'] for group in self.optimizer.param_groups]
Copy
step更新過程
在初始化過程已經進行過一次step,這裡再仔細分析一遍。
首先通過154行代碼,獲取新一輪學習率 values = self.get_lr()
然後通過165行代碼,對優化器中的學習率進行更新param_group['lr'] = lr
可以發現step()函數由基類_LRScheduler實現,即所有學習率調整器均採用這個流程,具體的一步更新策略則委託給子類的.get_lr()函數,這樣的架構設計值得學習。
此處,關注的是StepLR,下面深入 StepLR.get_lr()函數觀察。
if (self.last_epoch == 0) or (self.last_epoch % self.step_size != 0):
return [group['lr'] for group in self.optimizer.param_groups]
return [group['lr'] * self.gamma
for group in self.optimizer.param_groups]
Copy
可以看到,核心在兩個return行。
第一個return表示未達到step_size,新學習率保持不變
第二個return表示達到step_size,學習率均需要乘以 gamma。
至此,整個學習率更新過程及邏輯講解完畢,其餘十三個學習率調整整體邏輯一樣,均是step()與get_lr()的配合來實現學習率調整,請大家舉一反三,自行深入研究其它調整器。
十四個調整器匯總
Sets the learning rate of each parameter group to the initial lr times a given function. |
|
---|---|
Multiply the learning rate of each parameter group by the factor given in the specified function. |
|
Decays the learning rate of each parameter group by gamma every step_size epochs. |
|
Decays the learning rate of each parameter group by gamma once the number of epoch reaches one of the milestones. |
|
Decays the learning rate of each parameter group by a small constant factor until the number of epoch reaches a pre-defined milestone: total_iters. |
|
Decays the learning rate of each parameter group by linearly changing small multiplicative factor until the number of epoch reaches a pre-defined milestone: total_iters. |
|
Decays the learning rate of each parameter group by gamma every epoch. |
|
Set the learning rate of each parameter group using a cosine annealing schedule, where \eta{max}ηmax is set to the initial lr and T{cur}Tcu**r is the number of epochs since the last restart in SGDR: |
|
Chains list of learning rate schedulers. |
|
Receives the list of schedulers that is expected to be called sequentially during optimization process and milestone points that provides exact intervals to reflect which scheduler is supposed to be called at a given epoch. |
|
Reduce learning rate when a metric has stopped improving. |
|
Sets the learning rate of each parameter group according to cyclical learning rate policy (CLR). |
|
Sets the learning rate of each parameter group according to the 1cycle learning rate policy. |
|
Set the learning rate of each parameter group using a cosine annealing schedule, where \eta{max}ηmax is set to the initial lr, T{cur}Tcu**r is the number of epochs since the last restart and T_{i}T**i is the number of epochs between two warm restarts in SGDR: |
小結
本小節通過lr_scheduler結構設計出發,分析十四個優化器是如何組織實現的,並通過_LRScheduler基類與StepLR的代碼講解學習率調整的機制。
總結下來即:初始化時建立scheduler與optimizer的聯繫,scheduler在每次step()時修改optimizer中的lr,step()獲取新lr的功能委託給get_lr()函數實現。
最後對六個學習率調整器進行了測試並繪圖,繪圖代碼位於配套代碼
留言列表