利用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

你可能感兴趣的:(dl,python,pytorch,python,深度学习)