当前所在位置: 主页 > 耀世新闻 > 行业动态

训练时的学习率调整:optimizer和scheduler

最近在用mmdection框架修改网络的时候发现,网络训练起来一直都不收敛,训练一小会就换全部变nan,检测了好久都没有发现什么问题,最终修改了学习率,终于可以收敛了。但是关于怎么调整学习率一直都还没有掌握。因此特意写了这一篇进行总结。

optimizer.step()和scheduler.step()是我们在训练网络之前都需要设置。我理解的是optimizer是指定使用哪个优化器,scheduler是对优化器的学习率进行调整,正常情况下训练的步骤越大,学习率应该变得越小。optimizer.step()通常用在每个mini-batch之中,而scheduler.step()通常用在epoch里面,但是不绝对。可以根据具体的需求来做。只有用了optimizer.step(),模型才会更新,而scheduler.step()是对lr进行调整。通常我们在scheduler的step_size表示scheduler.step()每调用step_size次,对应的学习率就会按照策略调整一次。所以如果scheduler.step()是放在mini-batch里面,那么step_size指的是经过这么多次迭代,学习率改变一次。下面为一个简单的使用实例:

optimizer=optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
scheduler=lr_scheduler.StepLR(optimizer, step_size=100, gamma=0.1)
model=net.train(model, loss_function, optimizer, scheduler, num_epochs=100)



pytorch有torch.optim.lr_scheduler模块提供了一些根据epoch训练次数来调整学习率(learning rate)的方法。一般情况下我们会设置随着epoch的增大而逐渐减小学习率从而达到更好的训练效果。学习率的调整应该放在optimizer更新之后,下面是一个参考伪代码:

scheduler=...
for epoch in range(100):
     train(...)
     validate(...)
     scheduler.step()

本文介绍的调整学习率的函数都是基于epoch大小变化进行调整的。


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

学习率的更新公式为: \	ext{ new_l }r=\\lambda \	imes \	ext{ initial_l }r

\	ext{ new_l }r 是得到的新的学习率, \	ext{ initial_l }r 是初始的学习率,λ是通过参数lr_lambda和epoch得到的。

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import LambdaLR

initial_lr=0.1
net_1=model()

optimizer_1=torch.optim.Adam(net_1.parameters(), lr=initial_lr)
scheduler_1=LambdaLR(optimizer_1, lr_lambda=lambda epoch: 1/(epoch+1))

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train
    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

初始化的学习率: 0.1
第1个epoch的学习率:0.100000
第2个epoch的学习率:0.050000
第3个epoch的学习率:0.033333
第4个epoch的学习率:0.025000
第5个epoch的学习率:0.020000
第6个epoch的学习率:0.016667
第7个epoch的学习率:0.014286
第8个epoch的学习率:0.012500
第9个epoch的学习率:0.011111
第10个epoch的学习率:0.010000


class torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)

学习率的更新公式为: \	ext{ new_l }r=\	ext{ initial_l }r \	imes \\gamma^{\	ext{epoch }/ / \	ext{ step_size }}

参数:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import StepLR

initial_lr=0.1
net_1=model()

optimizer_1=torch.optim.Adam(net_1.parameters(), lr=initial_lr)
scheduler_1=StepLR(optimizer_1, step_size=3, gamma=0.1)

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train
    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

初始化的学习率: 0.1
第1个epoch的学习率:0.100000
第2个epoch的学习率:0.100000
第3个epoch的学习率:0.100000
第4个epoch的学习率:0.010000
第5个epoch的学习率:0.010000
第6个epoch的学习率:0.010000
第7个epoch的学习率:0.001000
第8个epoch的学习率:0.001000
第9个epoch的学习率:0.001000
第10个epoch的学习率:0.000100


class torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)

学习率的更新公式为: n e w_{-l}r=\	ext{ initial_lr }\	imes \\gamma^{\	ext{bisect_right }(\	ext{ milestones,epoch })}

参数:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import MultiStepLR

initial_lr=0.1
net_1=model()

optimizer_1=torch.optim.Adam(net_1.parameters(), lr=initial_lr)
scheduler_1=MultiStepLR(optimizer_1, milestones=[3, 7], gamma=0.1)

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train
    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

初始化的学习率: 0.1
第1个epoch的学习率:0.100000
第2个epoch的学习率:0.100000
第3个epoch的学习率:0.100000
第4个epoch的学习率:0.010000
第5个epoch的学习率:0.010000
第6个epoch的学习率:0.010000
第7个epoch的学习率:0.010000
第8个epoch的学习率:0.001000
第9个epoch的学习率:0.001000
第10个epoch的学习率:0.001000


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

学习率的更新公式为: n e w_{-l}r=\	ext{ initial_l }r \	imes \\gamma^{\	ext{epoch }}


参数:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import ExponentialLR

initial_lr=0.1
net_1=model()

optimizer_1=torch.optim.Adam(net_1.parameters(), lr=initial_lr)
scheduler_1=ExponentialLR(optimizer_1, gamma=0.1)

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train
    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

初始化的学习率: 0.1
第1个epoch的学习率:0.100000
第2个epoch的学习率:0.010000
第3个epoch的学习率:0.001000
第4个epoch的学习率:0.000100
第5个epoch的学习率:0.000010
第6个epoch的学习率:0.000001
第7个epoch的学习率:0.000000
第8个epoch的学习率:0.000000
第9个epoch的学习率:0.000000
第10个epoch的学习率:0.000000



参考资料:

1.optimizer.step()和scheduler.step()_于小勇的博客-CSDN博客

2.[pytorch]torch.optimizer.lr_scheduler调整学习率

3.醒了么:PyTorch--lr_scheduler.step()和optimizer.step()的先后顺序


平台注册入口