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