如何用scheduler实现learning-rate学习率动态变化

 更新时间:2023年09月11日 14:46:19   作者:回炉重造P  
这篇文章主要介绍了如何用scheduler实现learning-rate学习率动态变化问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

记录下schedule设置学习率变化过程的使用和方法

优化器optimizer

pytorch提供数种优化器的实现,优化器根据计算图的结构,进行梯度计算,根据loss信息实现自动的BP过程。

常用的就是 Adam ,将网络参数传入,设置初始的 learning-rate 学习率即可:

optimizer = torch.optim.Adam(model.parameters(), lr=args.learn_rate)

在训练中:

optimizer.zero_grad()
loss.backward()
optimizer.step()

即可实现BP环节。

scheduler

lr_scheduler 提供了随着训练的迭代次数对optimizer的学习率进行修改的类和方法,通过在循环过程中调用:

scheduler.step()

每次调用step方法,类中内置的计数器就会+1,即 epoch 轮次数增加。

根据不同的当前 epoch ,scheduler类会对optimizer中的learning-rate进行修改。

利用 optimizer.param_groups[0]['lr'] 可查看当前的学习率大小。

这边整理三个常用的类:LambdaLRStepLRMultiStepLR

个人觉得这三种就能应对大部分的调整需求了。

LambdaLR

完整的类包为 torch.optim.lr_scheduler.LambdaLR

该类实现的学习率变化策略为当前学习率乘以值 λ λ 的大小由一个自定函数确定,该函数输入为epoch,即类中的循环次数计数(也就是调用 scheduler.step() 的次数)。

learing-rate = λ * learing-rate

LambdaLR(optimizer, lr_lambda, last_epoch=-1)

其中 lr_lambda 为λ的计算函数。

给个使用例子:

# 简单写个Moudle生成parameter
class MyModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.liner = nn.Linear(10, 10)
model = MyModel()
# 生成optimizer
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

计算函数:

def lb_func(epoch):
    return 1 / (epoch + 1)

在循环中使用:

lambda_scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lb_func)
for epoch in range(10):
    optimizer.zero_grad()
    optimizer.step()
    print("当前lr为{}".format(optimizer.param_groups[0]['lr']))
    lambda_scheduler.step()

输出:

当前lr为0.01
当前lr为0.005
当前lr为0.003333333333333333
当前lr为0.0025
当前lr为0.002
当前lr为0.0016666666666666666
当前lr为0.0014285714285714286
当前lr为0.00125
当前lr为0.0011111111111111111
当前lr为0.001

当scheduler调用step之后,就能修改对应的optimizer的lr参数,从而改变整体训练的学习率。

StepLR

完整的类包为 torch.optim.lr_scheduler.StepLR

该类的学习策略为设定某个间隔 step_size ,在经过间隔次数的循环之后,就将学习率乘以γ得到新的学习率。

learning_rate = learning_rate * (γ ^ (epoch//step_size))

StepLR(optimizer, step_size, gamma)

给个使用例子:

step_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.1)
for epoch in range(10):
    optimizer.zero_grad()
    optimizer.step()
    print("当前lr为{}".format(optimizer.param_groups[0]['lr']))
    step_scheduler.step()

输出:

当前lr为0.01
当前lr为0.01
当前lr为0.01
当前lr为0.001
当前lr为0.001
当前lr为0.001
当前lr为0.0001
当前lr为0.0001
当前lr为0.0001
当前lr为1e-05

设定间隔和γ值即可。

MultiStepLR

完整的类包为 torch.optim.lr_scheduler.MultiStepLR

这个类更新策略和step差不多,但其不一定为等间隔更新,有里程碑 milestones 参数,用来传入更新的轮次list,每次迭代次数到达 milestones 中的某值,即进行学习率的更新。

MultiStepLR(optimizer, milestones, gamma)

milestones 需要顺序排列。

给个使用例子:

multi_scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[2, 4, 6, 8], gamma=0.1)
for epoch in range(10):
    optimizer.zero_grad()
    optimizer.step()
    print("当前lr为{}".format(optimizer.param_groups[0]['lr']))
    multi_scheduler.step()

输出:

当前lr为0.01
当前lr为0.01
当前lr为0.001
当前lr为0.001
当前lr为0.0001
当前lr为0.0001
当前lr为1e-05
当前lr为1e-05
当前lr为1.0000000000000002e-06
当前lr为1.0000000000000002e-06

last_epoch

scheduler初始化的时候都有个 last_epoch 的参数,当训练中止保存后,重开的时候就会调用 last_epoch 作为当前epoch,以继续训练,默认为-1从头开始。

参考文档

lr_scheduler文档:https://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

最新评论