记录一下schedule设置学习率变化过程的使用和方法
pytorch提供数种优化器的实现,优化器根据计算图的结构,进行梯度计算,根据loss信息实现自动的BP过程。常用的就是Adam
,将网络参数传入,设置初始的learning-rate
学习率即可:
optimizer = torch.optim.Adam(model.parameters(), lr=args.learn_rate)
在训练中:
optimizer.zero_grad()
loss.backward()
optimizer.step()
即可实现BP环节。
lr_scheduler
提供了随着训练的迭代次数对optimizer的学习率进行修改的类和方法,通过在循环过程中调用:
scheduler.step()
每次调用step方法,类中内置的计数器就会+1,即epoch
轮次数增加。根据不同的当前epoch
,scheduler类会对optimizer中的learning-rate进行修改。利用optimizer.param_groups[0]['lr']
可查看当前的学习率大小。
这边整理三个常用的类:LambdaLR,StepLR和MultiStepLR。个人觉得这三种就能应对大部分的调整需求了。
完整的类包为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参数,从而改变整体训练的学习率。
完整的类包为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
设定间隔和γ值即可。
完整的类包为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
scheduler初始化的时候都有个last_epoch
的参数,当训练中止保存后,重开的时候就会调用last_epoch
作为当前epoch,以继续训练,默认为-1从头开始。
lr_scheduler文档:https://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html