文章目录
- PyTorch动态调整学习率
- torch.optim.lr_scheduler
- torch.optim.lr_scheduler.LambdaLR
- torch.optim.lr_scheduler.StepLR
- torch.optim.lr_scheduler.ExponetialLR
- torch.optim.lr_scheduler.MultiStepLR
- torch.optim.torch.optim.lr_scheduler.ReduceLROnPlateau
- 其他方法:
PyTorch动态调整学习率
在深度神经网络中,学习率是最重要的超参数之一。如何调整学习率是“炼丹玄学”中最重要的药方之一。作为当前最为流行的深度学习框架,PyTorch已经为我们封装好了一些在训练过程中动态调整学习率的方法,下面就让我们来看一下。
torch.optim.lr_scheduler
在torch.optim.lr_scheduler
上,基于当前epoch的数值,为我们封装了几种相应的动态学习率调整方法,该部分的官方手册传送门——optim.lr_scheduler官方文档。需要注意的是学习率的调整需要应用在优化器参数更新之后,其应用的简要代码示例如下:
>>> optimizer = torch.optim.Adam(...) #选择一种优化器
>>> scheduler = torch.optim.lr_scheduler.... # 选择一种动态调整学习率的方法,可以是下面几种之一
>>> for epoch in range(100):
>>> train(...)
>>> validate(...)
>>> optimizer.step()
>>> scheduler.step() # 需要在优化器参数更新之后再动态调整学习率
下面将介绍一下torch.optim.lr_scheduler
中封装的各种动态调整学习率的方法。
torch.optim.lr_scheduler.LambdaLR
这种动态调整方法的原理是:将每一个参数组的学习率调整为初始化学习率lr的给定函数倍,在fine-tune中十分有用,我们不仅可以为不同的层设定不同的学习率,还可以为其设定不同的学习率调整策略。它的官方形参说明如上,第一个形参optimizer
是之前定义好的优化器的实例名(wrapped optimizer)。第二个形参lr_lambda
可以是function
或是function list
,一般是一个关于epoch数目的函数,从而计算出一个乘数因子,并根据该乘数因子调整初始学习率。第三个形参last_epoch
默认为-1,它一般不用设置,为-1时的作用是将人为设置的学习率设定为调整学习率的基础值lr。这里需要注意的是,last_epoch
默认为-1只能保证第一次调整学习率时,原始待调整的值为人工设定的初始学习率,而第二次调整学习率时,调整的基值就变成了第一次调整后的学习率。
它的使用示例如下:
>>> # 假设优化器有两组参数
>>> lambda1 = lambda epoch: epoch // 30 # 第一组参数的调整方法
>>> lambda2 = lambda epoch: 0.95 ** epoch # 第二组参数的调整方法
>>> optimizer = torch.optim.Adam(...) #选择Adam优化器
>>> scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=[lambda1, lambda2]) # 选定调整方法
>>> for epoch in range(100):
>>> train(...)
>>> validate(...)
>>> optimizer.step()
>>> scheduler.step() # 需要在优化器参数更新之后再动态调整学习率,每次更新是根据epoch数量在两个函数上计算得到的乘数因子进行更新
torch.optim.lr_scheduler.StepLR
这是比较常用的等间隔动态调整方法,该方法的原理为:每隔step_size个epoch就对每一参数组的学习率按gamma参数进行一次衰减。在它的形参中,第一个形参optimizer
是之前定义好的优化器的实例名(wrapped optimizer);第二个形参step_size
是学习率衰减的周期(隔多少个epoch衰减一次);第三个形参gamma
是学习率衰减的乘法因子(Multiplicative factor),默认值为0.1;第四个形参last_epoch
默认为-1,它一般不用设置,为-1时的作用是将人为设置的学习率设定为调整学习率的基础值lr。这里需要注意的是,last_epoch
默认为-1只能保证第一次调整学习率时,原始待调整的值为人工设定的初始学习率,而第二次调整学习率时,调整的基值就变成了第一次调整后的学习率。
该方法的使用示例如下:
>>> # 假定对于所有参数组的初始学习率为0.5,那么下列代码的学习率调整效果如下:
>>> # lr = 0.05 if epoch < 30
>>> # lr = 0.005 if 30 <= epoch < 60
>>> # lr = 0.0005 if 60 <= epoch < 90
>>> # ...
>>> scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
>>> for epoch in range(100):
>>> train(...)
>>> validate(...)
>>> scheduler.step()
torch.optim.lr_scheduler.ExponetialLR
这种方法是上面调整方法的简易版本,原理是每个epoch都对当前学习率根据gamma作一个动态调整,相当于做以gamma为底,epoch为幂次的指数运算。它的形参和上述方法中的作用一致,不再多言。
torch.optim.lr_scheduler.MultiStepLR
这种方法也是基于等间隔调整方法的翻版,它的原理是当epoch的数目增加到一个里程碑(milestones)时,对学习率基于gamma做一个动态调整。这个方法适合后期调试使用,可以通过观察loss曲线,为训练过程的不同阶段设定不同的学习率。在它的形参中,第一个形参optimizer
是之前定义好的优化器的实例名(wrapped optimizer);第二个形参milestones
是一个关于epoch数值的list
,表示在达到哪个epoch范围内开始变化,其变化原理如后例所示;第三个形参gamma
是学习率衰减的乘法因子(Multiplicative factor),默认值为0.1;第四个形参last_epoch
默认为-1,它一般不用设置,为-1时的作用是将人为设置的学习率设定为调整学习率的基础值lr。同样地,last_epoch
默认为-1只能保证第一次调整学习率时,原始待调整的值为人工设定的初始学习率,而第二次调整学习率时,调整的基值就变成了第一次调整后的学习率。
该方法的使用示例如下:
>>> # 假定优化器的初始学习率为0.05
>>> # lr = 0.05 if epoch < 30, 保存不变
>>> # lr = 0.005 if 30 <= epoch < 80, 衰减gamma倍
>>> # lr = 0.0005 if epoch >= 80, 再衰减gamma倍
>>> scheduler = MultiStepLR(optimizer, milestones=[30,80], gamma=0.1)
>>> for epoch in range(100):
>>> train(...)
>>> validate(...)
>>> scheduler.step()
torch.optim.torch.optim.lr_scheduler.ReduceLROnPlateau
与上述基于epoch数目调整学习率的方法不同,该方法是PyTorch提供的一种基于验证指标的调整方法。它的原理是:当指标停止改善时,降低学习率。当模型的学习停滞时,训练过程通常会受益于将学习率降低2~10倍。该种调整方法读取一个度量指标,如果在“耐心”期间内没有发现它有所改善,那么就会降低学习率。下面将一一讲解它的形参:
(1)optimizer
:和上述方法一致
(2)mode
:可选str
字符串数据,为min
或max
。当选择min
时,代表当度量指标停止下降时,开始减小学习率;当选择max
时,代表当度量指标停止上升时,开始减小学习率。
(3)factor
:float
类型数据,学习率调整的乘法因子,默认值为0.1。
(4)patience
:int
类型数据,可容忍的度量指标没有提升的epoch数目,默认为10。举例说明,当其设置为10时,我们可以容忍10个epoch内没有提升,如果在第11个epoch依然没有提升,那么就开始降低学习率。
(5)verbose
:bool
数据,如果设置为True
,输出每一次更新的信息,默认为False
。
(6)threshold
:float
类型数据,衡量新的最佳阈值,仅关注重大变化,默认为0.0001。
(7)threshold_mode
:可选str
字符串数据,为rel
或abs
,默认为rel
。在rel
模式下,如果mode
参数为max
,则动态阈值(dynamic_threshold)为best*(1+threshold)
,如果mode
参数为min
,则动态阈值为best+threshold
,如果mode
参数为min
,则动态阈值为best-threshold
。
(8)cooldown
:int
类型数据,减少lr后恢复正常操作之前要等待的epoch数,默认为0。
(9)min_lr
:float
或list
类型数据,学习率的下界,默认为0。
(10)eps
:float
类型数据,学习率的最小变化值。如果调整后的学习率和调整前的差距小于eps
的话,那么就不做任何调整,默认为1e-8
。
其使用案例为:
>>> optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
>>> scheduler = ReduceLROnPlateau(optimizer, 'min')
>>> for epoch in range(10):
>>> train(...)
>>> val_loss = validate(...) # 度量指标
>>> # Note that step should be called after validate()
>>> scheduler.step(val_loss) # 根据度量指标调整学习率
其他方法:
这种方法基于论文训练神经网络的循环学习率,根据周期性学习率策略(CLR)确定每个参数组的学习率。 该策略以恒定的频率在两个边界之间循环学习率,两个边界之间的距离可以在每次迭代或每个周期的基础上进行缩放。
使用示例:
>>> optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
>>> scheduler = torch.optim.CyclicLR(optimizer)
>>> data_loader = torch.utils.data.DataLoader(...)
>>> for epoch in range(10):
>>> for batch in data_loader:
>>> train_batch(...)
>>> scheduler.step()