PyTorch学习之学习率调整策略
PyTorch学习率调整策略通过torch.optim.lr_scheduler接口实现。PyTorch提供的学习率调整策略分为三大类,分别是:
a. 有序调整:等间隔调整(Step),按需调整学习率(MultiStep),指数衰减调整(Exponential)和 余弦退火CosineAnnealing。
b. 自适应调整:自适应调整学习率 ReduceLROnPlateau。
c. 自定义调整:自定义调整学习率 LambdaLR。
1 等间隔调整学习率 StepLR
等间隔调整学习率,调整倍数为 gamma 倍,调整间隔为 step_size。间隔单位是step。需要注意的是, step 通常是指 epoch,不要弄成 iteration 了。
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)
-
optimizer:为创建的优化器,例如SGD、Adam等。
-
step_size(int)- 学习率下降间隔数,若为 30,则会在 30、 60、 90…个 step(epoch) 时,将学习率调整为 lr*gamma。
-
gamma(float)- 学习率调整倍数,默认为 0.1 倍,即下降 10 倍。
-
last_epoch(int)- 上一个 epoch 数,这个变量用来指示学习率是否需要调整。当last_epoch 符合设定的间隔时,就会对学习率进行调整。当为-1 时,学习率设置为初始值。一般默认。
不同gamma值,学习率衰减曲线:
2、MultiStepLR (多步长衰减)
按设定的间隔调整学习率。这个方法适合后期调试使用,观察 loss 曲线,为每个实验定制学习率调整时机。
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)
-
milestones(list)- 一个 list类型,每一个元素代表何时调整学习率, list 元素必须是递增的。如 milestones=[30,80,120],单位是epoch。
-
gamma(float)- 学习率调整倍数,默认为 0.1 倍,即下降 10 倍。
一个例子如下图,其分别在200、300、320、340、400epoch处进行学习率调整。
3 指数衰减调整学习率 ExponentialLR
按指数衰减调整学习率,调整公式: lr=lr∗gamma^epoch
torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1)
-
gamma- 学习率调整倍数的底,指数为 epoch,即 gamma^epoch
不同的gamma值曲线:
4 余弦退火调整学习率 CosineAnnealingLR
其中的lr为初始学习率,也即余弦函数的最大值。
余弦衰减的学习率计算公式为:
global_step = min(global_step, decay_steps)
cosine_decay = 0.5 * (1 + cos(pi * global_step / decay_steps))
decayed = (1 - alpha) * cosine_decay + alpha
decayed_learning_rate = learning_rate * decayed
torch中对应的内置函数:
torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1)
-
T_max(int): 学习率下降到最小值时的epoch数,即当epoch=T_max时,学习率下降到余弦函数最小值,当epoch>T_max时,学习率将增大;
-
eta_min(float)- 学习率调整的最小值,即epoch=T_max时,
eta_min, 默认为0。
下图展示了不同周期下的余弦学习率更新曲线(下图中的蓝线和橙色线的T_max互换一下才正确):
5 自适应调整学习率 ReduceLROnPlateau
当某指标不再变化(下降或升高),调整学习率,这是非常实用的学习率调整策略。
例如,当验证集的 loss 不再下降时,进行学习率调整;或者监测验证集的 accuracy,当accuracy 不再上升时,则调整学习率。
torch.optim.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)
-
mode(str)- 模式选择,有 min 和 max 两种模式, min 表示当指标不再降低(如监测loss), max 表示当指标不再升高(如监测 accuracy)。
-
factor(float)- 学习率调整倍数(等同于其它方法的 gamma),即学习率更新为 lr = lr * factor
-
patience(int)- 忍受该指标多少个 step 不变化,当忍无可忍时,调整学习率。
-
verbose(bool)- 是否打印学习率信息, print(‘Epoch {:5d}: reducing learning rate of group {} to {:.4e}.’.format(epoch, i, new_lr))
-
threshold_mode(str)- 选择判断指标是否达最优的模式,有两种模式, rel 和 abs。
-
当 threshold_mode == rel,并且 mode == max 时, dynamic_threshold = best * ( 1 +threshold );
-
当 threshold_mode == rel,并且 mode == min 时, dynamic_threshold = best * ( 1 -threshold );
-
当 threshold_mode == abs,并且 mode== max 时, dynamic_threshold = best + threshold ;
-
当 threshold_mode == rel,并且 mode == max 时, dynamic_threshold = best - threshold;
-
threshold(float)- 配合 threshold_mode 使用。
-
cooldown(int)- “冷却时间“,当调整学习率之后,让学习率调整策略冷静一下,让模型再训练一段时间,再重启监测模式。
-
min_lr(float or list)- 学习率下限,可为 float,或者 list,当有多个参数组时,可用 list 进行设置。
-
eps(float)- 学习率衰减的最小值,当学习率变化小于 eps 时,则不调整学习率。
optimizer = torch.optim.SGD(model.parameters(), args.lr,
momentum=args.momentum, weight_decay=args.weight_decay)
scheduler = ReducelROnPlateau(optimizer,'min')
for epoch in range( args.start epoch, args.epochs ):
train(train_loader , model, criterion, optimizer, epoch )
result_avg, loss_val = validate(val_loader, model, criterion, epoch)
# Note that step should be called after validate()
scheduler.step(loss_val )
6 自定义调整学习率 LambdaLR
为不同参数组设定不同学习率调整策略。调整规则为:
lr=base_lr∗lambda(self.last_epoch)
fine-tune 中十分有用,我们不仅可为不同的层设定不同的学习率,还可以为其设定不同的学习率调整策略。
torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)
-
lr_lambda(function or list)- 一个计算学习率调整倍数的函数,输入通常为 step(epoch),当有多个参数组时,设为 list。
ignored_params = list(map(id, net.fc3.parameters()))
base_params = filter(lambda p: id(p) not in ignored_params, net.parameters())
optimizer = optim.SGD([
{'params': base_params},
{'params': net.fc3.parameters(), 'lr': 0.001*100}], 0.001, momentum=0.9,weight_decay=1e-4)
# Assuming optimizer has two groups.
lambda1 = lambda epoch: epoch // 3
lambda2 = lambda epoch: 0.95 ** epoch
scheduler = LambdaLR(optimizer, lr_lambda=[lambda1, lambda2])
for epoch in range(100):
train(...)
validate(...)
scheduler.step()
print('epoch: ', i, 'lr: ', scheduler.get_lr())
epoch: 0 lr: [0.0, 0.1]
epoch: 1 lr: [0.0, 0.095]
epoch: 2 lr: [0.0, 0.09025]
epoch: 3 lr: [0.001, 0.0857375]
epoch: 4 lr: [0.001, 0.081450625]
epoch: 5 lr: [0.001, 0.07737809374999999]
epoch: 6 lr: [0.002, 0.07350918906249998]
epoch: 7 lr: [0.002, 0.06983372960937498]
epoch: 8 lr: [0.002, 0.06634204312890622]
epoch: 9 lr: [0.003, 0.0630249409724609]
为什么第一个参数组的学习率会是 0 呢? 来看看学习率是如何计算的。
第一个参数组的初始学习率设置为 0.001,
lambda1 = lambda epoch: epoch // 3,
第 1 个 epoch 时,由 lr = base_lr * lmbda(self.last_epoch),
可知道 lr = 0.001 *(0//3) ,又因为 1//3 等于 0,所以导致学习率为 0。
第二个参数组的学习率变化,就很容易看啦,初始为 0.1, lr = 0.1 * 0.95^epoch ,当
epoch 为 0 时, lr=0.1 , epoch 为 1 时, lr=0.1*0.95。
7、warm up+余弦退火
warm up:
训练初期由于离目标较远,一般需要选择大的学习率,但是使用过大的学习率容易导致不稳定性。所以可以做一个学习率热身阶段,在开始的时候先使用一个较小的学习率,然后当训练过程稳定的时候再把学习率调回去。好比是在热身阶段,将学习率从0调到初始学习率。
余弦退火:
按照余弦函数将学习速率从初始值降低到0。
warm up+余弦退火策略示意图 :
8、在pytorch框架中调用方式
此外,根据pytorch官网上给出的说明,scheduler.step()函数的调用应该在训练代码以后:
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
def train(...):
for i, data in enumerate(train_loader):
......
y_ = model(x)
loss = criterion(y_,y)
loss.backward()
optimizer.step()
......
for epoch in range(epochs):
train(...)
test(...)
scheduler.step()
scheduler.step()函数完成对学习率的调整。其中scheduler为所选择的学习率衰减策略。例如:
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
9、为网络的不同层设置不同的学习率
定义一个简单的网络结构:
class net(nn.Module):
def __init__(self):
super(net, self).__init__()
self.conv1 = nn.Conv2d(3, 64, 1)
self.conv2 = nn.Conv2d(64, 64, 1)
self.conv3 = nn.Conv2d(64, 64, 1)
self.conv4 = nn.Conv2d(64, 64, 1)
self.conv5 = nn.Conv2d(64, 64, 1)
def forward(self, x):
out = conv5(conv4(conv3(conv2(conv1(x)))))
return out
我们希望conv5学习率是其他层的100倍,我们可以:
net = net()
lr = 0.001
#其中id()函数用于获取网络参数的内存地址
#map()函数用于将id()函数作用于net.conv5.parameters()得到的每个参数上
conv5_params = list(map(id, net.conv5.parameters()))
lamda表达式是python中用于定义匿名函数的方式,其后面定义的是一个函数操作,
冒号前的符号是函数的形式参数,用于接收参数,符合的个数表示需要接收的参数个数
冒号右边是具体的函数操作
filter()函数的作用是过滤掉不符合条件(False)的元素,返回一个迭代器对象
该函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,
然后返回True或False,最后返回值为True的元素
base_params = filter(lambda p: id(p) not in conv5_params,
net.parameters())
optimizer = torch.optim.SGD([
{'params': base_params},
{'params': net.conv5.parameters(), 'lr': lr * 100}], lr=lr, momentum=0.9)
如果多层,则:
conv5_params = list(map(id, net.conv5.parameters()))
conv4_params = list(map(id, net.conv4.parameters()))
base_params = filter(lambda p: id(p) not in conv5_params + conv4_params,
net.parameters())
optimizer = torch.optim.SGD([
{'params': base_params},
{'params': net.conv5.parameters(), 'lr': lr * 100},
{'params': net.conv4.parameters(), 'lr': lr * 100}], lr=lr, momentum=0.9)
10、画学习率变化图的程序
# -*- coding:utf-8 -*-
'''本文件用于测试pytorch学习率调整策略'''
__author__ = 'puxitong from UESTC'
import torch
import torch.optim as optim
from torch.optim import lr_scheduler
from torchvision.models import AlexNet
import matplotlib.pyplot as plt
model = AlexNet(num_classes=2)
optimizer = optim.SGD(params=model.parameters(), lr=0.1)
# 等间隔调整学习率,每训练step_size个epoch,lr*gamma
# scheduler = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
# 多间隔调整学习率,每训练至milestones中的epoch,lr*gamma
# scheduler = lr_scheduler.MultiStepLR(optimizer, milestones=[10, 30, 80], gamma=0.1)
# 指数学习率衰减,lr*gamma**epoch
# scheduler = lr_scheduler.ExponentialLR(optimizer, gamma=0.9)
# 余弦退火学习率衰减,T_max表示半个周期,lr的初始值作为余弦函数0处的极大值逐渐开始下降,
# 在epoch=T_max时lr降至最小值,即pi/2处,然后进入后半个周期,lr增大
# scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=100, eta_min=0)
plt.figure()
x = list(range(100))
y = []
for epoch in range(100):
scheduler.step()
y.append(scheduler.get_lr()[0])
plt.plot(x, y)
plt.show()
参考博客:
1)
https://blog.csdn.net/liuweiyuxiang/article/details/84647659
2)
https://blog.csdn.net/shanglianlm/article/details/85143614
3)
https://zhuanlan.zhihu.com/p/93624972
4)
https://www.jianshu.com/p/26a7dbc15246
PyTorch学习之学习率调整策略PyTorch学习率调整策略通过torch.optim.lr_scheduler接口实现。PyTorch提供的学习率调整策略分为三大类,分别是:a. 有序调整:等间隔调整(Step),按需调整学习率(MultiStep),指数衰减调整(Exponential)和 余弦退火CosineAnnealing。b. 自适应调整:自适应调整学习率 ReduceLR...
从形式上看, 动量算法引入了变量 z充当速度角色——它代表参数在参数空间移动的方向和速率。速度被设为负梯度的指数
衰减
平均。名称 动量(momentum),相当于引入动量前的梯度概念,指示着loss在参数空间下一步要下降的方向和大小。
其中wk+1w^{k+1}wk+1表示更新后权重;wkw^{k}wk表示更新前权重;zk+1z^{k+1}zk+1代表动量,,α表示
学习率
从公式zk+1=βzk+▽f(wk)z^{k+1}=βz^{k}+▽f(w^{k})zk+1=βzk+▽f(wk)可以看出,zk+1z^{
1 主要目标
不同
的参数可能需要
不同
的
学习率
,本文主要实现的是
不同
层
中参数的
不同
学习率
设置
。
尤其是当我们在使用预训练的模型时,需要对一些除了主干网络以外的分支进行单独修改并进行初始化,其他主干网络
层
的参数采用预训练的模型参数进行初始化,这个时候我们希望在进行训练过程中,除主干网络只进行微调,不需要过多改变参数,因此需要
设置
较小的
学习率
。而改正后的其它
层
则需要以较大的步子去收敛,
学习率
往往要
设置
大一点。
2 针对全局的统一
学习率
设置
根据你选择的优化器的类把具体
设置
的lr作为可选参数的一部分传入到新建的优化
PyTorch version: 1.4.0
IDE: PyCharm
文章目录0. 写在前面1. StepLR1.1 scheduler 常用的属性1.2 scheduler 常用的方法2. MultiStepLR3. ExponentialLR4. ReduceLROnPlateau5. LambdaLR
0. 写在前面
PyTorch 在 torch.optim.lr_scheduler 中提供了十种调整
学习率
的类,它们的基类为 torch.optim.lr_scheduler._LRSc
conv5_params = list(map(id, net.conv5.parameters()))
base_params = filter(lambda p: id(p) not in conv5_params,
net.parameters...
大家好,今天和大家分享一下如何使用 TensorFlow 自定义 指数
学习率
下降、阶梯
学习率
下降、余弦
学习率
下降 方法,并使用 Mnist数据集验证自定义的
学习率
下降策略。
创建的自定义
学习率
类方法,需要继承 tf.keras.optimizers.schedules.LearningRateSchedule
1. 指数
学习率
下降
指数
学习率
下降公式为:
其中代表初始的
学习率
,代表
学习率
衰减
系数,代表epoch,即每次迭代
学习率
衰减
一次
以初始
学习率
,
学习率
衰减
系数,为例指数学...
CosineAnnealingLR
torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1, verbose=False)
作用是让lr随着epoch的变化图类似于cos,公式如下
其中ηt表示新得到的
学习率
;
η_min表示
学习率
最小值(默认为0);
ηmax表示
学习率
最大值,即初始
学习率
;
Tcur表示已经记录的epoch数,即当前epoch数减1;
Tmax表示lr从初始预设值降低到最
优化器优化的是
学习率
,他发生在反向运算中。
学习率
衰减
,是每次迭代
衰减
的方法,在前向运算中。
学习率
设定思路是前期一个较大的
学习率
来确保加速收敛,后期用较小的
学习率
保证稳定。一般都是0.01,0.005,0.0001等等之类的,
设置
初始值。
指数
衰减
Pytorch
学习率
衰减
方法1.什么是
学习率
衰减
2.使用库函数进行调整2.1.有序调整2.1.1等间隔调整
学习率
2.1.2.多间隔调整
学习率
2.1.3.指数
衰减
调整
学习率
ExponentialLR2.1.4.余弦退火函数调整
学习率
2.2.根据指标调整
学习率
ReduceLROnPlateau2.3.自定义调整
学习率
3.手动调整
学习率
1.什么是
学习率
衰减
梯度下降算法需要我们指定一个
学习率
作为权重更新步幅的控制因子,常用的
学习率
有0.01、0.001以及0.0001等,
学习率
越大则权重更新。一般来说,我们