學習率的調整會對網路模型的訓練造成巨大的影響,本文總結了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()