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() 
Tags: