Pytorch系列:(八)學習率調整方法

Neo0oeN 發表於 2021-07-27
PyTorch

學習率的調整會對網路模型的訓練造成巨大的影響,本文總結了pytorch自帶的學習率調整函式,以及其使用方法。

設定網路固定學習率

設定固定學習率的方法有兩種,第一種是直接設定一些學習率,網路從頭到尾都使用這個學習率,一個例子如下:

optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

第二種方法是,可以針對不同的引數設定不同的學習率,設定方法如下:這裡給subnet2子結構設定的學習率為0.01 ,如果對某個引數不指定學習率,就使用最外層的預設學習率,這裡其他結構預設使用0.03

optimizer =optim.SGD([
    {'params': net.subnet1.parameters()}, # lr=0.03
    {'params': net.subnet2.parameters(), 'lr': 0.01}
], lr=0.03)

學習率基類

學習率調整的方法有一個基類,這個基類包含了三個屬性:

optimizer: 關聯的優化器

last_epoch: 記錄epoch數

base_lrs: 初始學習率

然後有兩個方法,其中,get_lr() 方法,可以計算下一個epoch的學習率,而step() 則表示更新下一個學習率 ,學習率基類如下:

class _LRScheduler(object):
  def __init__(self,optimizer,last_epoch=-1)
  
  def get_lr(self):
     raise NotImplementedError
     
  def step(self):
      pass 
  

Pytorch自帶學習率方法

StepLR

第一個跟新策略是每隔多少步就去乘以一個係數,這裡的step_size表示執行這麼多次的step()才會更新一次

lr_scheduler.StepLR(
  optimizer,
  step_size,
  gamma=0.1,
  last_epoch=-1

)

計算方法:\(lr = lr*gamma\)

MultiStepLR

第二種方法如下,milestones是一個list,這裡會根據list裡面出現的次數進行調整, list中設定想要的epoch數量,例如 [ 100, 200, 500 ] , 模型就會在設定的epoch進行下一步學習率的計算

lr_scheduler.MultiStepLR(
optimier,
milestones,
gamma=0.1,
last_epoch=-1
) 

計算方法:\(lr = lr*gamma\)

ExponentialLR

第三種方法是,通過 \(gamma^{epoch}\)這個指數函式,對學習率進行更新

lr_scheduler.ExponentialLR(
optimizer,
gamma,
last_epoch=-1
) 

計算方式:\(lr = lr*gamma^{epoch}\)

CosineAnnealingLR

第四種學習率是CosineAnnealingLR,是類似於cosine函式的波動式的進行學習率更新,其中,T_max是指半個週期,就是從最高點到最低點的間隔,eta_min是最低點的值,預設設定為0

lr_scheduler.CosineAnnealingLR(
optimizer,
T_max,
eta_min=0,
last_epoch=-1
) 

計算方式:\(\eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} - \eta_{min})(1+cos(\frac{T_{cur}}{T_{max}}\pi))\)

其中:\(\eta_{max}\)表示學習率最大值,\(\eta_{min}\)表示學習率最小值,\(T_{cur}\)表示當前的epoch數量,\(T_{max}\)是一個固定值,通過設定這個值,可以決定cos函式的週期。

ReduceLRonPlateau

這個方法是對梯度進行監控,其中mode是模式設定,具有兩種模式,min 和max指的是如果梯度不下降,或者不上升,就進行調整;factor是調整因子;patience指的是連續多少次不變化就調整;threshold表示只有超過閾值之後,才關注學習率的變化;threshold_mode有兩種模式,rel模式:max模式下如果超過best(1+threshold)為顯著,min模式下如果低於best(1-threshold)為顯著,abs模式:max模式下如果超過best+threshold為顯著,min模式下如果低於best-threshold為顯著;cooldown是指調整後,有一段冷卻時間,多少次不對學習率進行監控;verbose表示是否列印日誌;min_lr表示學習率下限;eps 表示學習率衰減最小值;

lr_scheduler.ReduceLROnPlateau(
optimizer,
mode='min',
factor=0.1,
patience=10,
verbose=False,
threshold = 0.0001,
threshold_mode = 'rel',
cooldown=0,
min_lr = 0,
eps = 1e-08
) 

LambdaLR

最後一個是可以自定義方法, 這個方法中,可以通過一個lambda來自定義學習率計算方式

lr_scheduler.LambdaLR(
optimizer,
lr_lambda,
last_epoch=-1
)

其中lr_lambda 表示自定義的函式,一個例子如下

scheduler = LambdaLR(optimizer, lr_lambda = lambda epoch: 0.1 ** ( eopch // 10 ))

學習率使用方法

下面介紹的學習率使用方法不管使用什麼樣的學習率,基本流程都差不多,只不過替換了不同的學習率方法而已,因此只看一個例子即可。注意,pytorch1.0 版本之後,官方建議將lr_scheduler 更新放到優化器更新後面。

用法
import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Conv2d(3, 64, 3)
optimizer = optim.SGD(model.parameters(), lr=0.5)
lr_scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=2)

for i in range(5):
    optimizer.zero_grad()
    x = model(torch.randn(3, 3, 64, 64))
    loss = x.sum()
    loss.backward()
    print('{} optim: {}'.format(i, optimizer.param_groups[0]['lr']))
    optimizer.step() 
    print('{} scheduler: {}'.format(i, lr_scheduler.get_lr()[0]))
    lr_scheduler.step() 

相關文章