为什么需要学习率调度?
在训练初期时,参数随机初始化时,需要较大的学习率快速接近最优解区域。在训练后期接近收敛时,需要小学习率精细调整参数,避免跳过最优解。
1 分步学习率调度
一种动态调整学习率的策略,它会在训练过程中按照预定的规则或时间点分段调整学习率。
比如每隔50个epoch,学习率乘以0.1。或者手动设置当到达[120, 160]的epoch时,学习率乘以0.1,降低10倍。
2 余弦学习率调度(余弦退火)[1]
2.1 公式
\(\eta_t = \eta_{min} + \frac{1}{2} (\eta_{max} – \eta_{min}) \bigg( 1 + cos \bigg( \frac{T_{cur}}{T_{max}} \pi \bigg) \bigg) \)- \(\eta_t\):当前学习率
- \(\eta_{max}\):学习率最大值
- \(\eta_{min}\):学习率最小值
- \(T_{cur}\):当前epoch
- \(T_{max}\):最大epoch
2.2 解释
cos(x) 函数在[0, \(\pi\)]的值域为[-1, 1],变化为:先缓慢下降,然后快速下降,最后缓慢下降。这是可以利用的性质。(1+cos(x)) / 2值域为[0, 1],乘以 (nmax – nmin),再加上nmin,值域为[nmin, nmax]。
2.3 PyTorch API及其解释
torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1, verbose=False)
optimizer:该学习率调整器作用于的优化器,在初始化optimizer时就设定了初始学习率,同时也是最大学习率。
T_max:最大迭代次数。
eta_min:最小学习率。
last_epoch:最后一个epoch的index,默认值为-1。如果是训练了很多个epoch后中断了,继续训练,这个值就设置为加载模型的epoch,-1表示总是从头开始训练。
verbose:若为true,每次更新时会打印一些信息。
如果T_max等于总epoch,则学习率从nmax到nmin单调变化:
若小于总epoch,则学习率在每两个T_max间隔内完成一次从nmax到nmin,再从nmin到nmax的变化,直至总epoch结束。
对于另一个API:
torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizer, T_0, T_mult=1, eta_min=0, last_epoch=-1, verbose=False)
最大不同在于,每个间隔内完成一次从nmax到nmin的变化,然后就从nmax重启(restart),不会有缓慢上升的过程。
optimizer、eta_min、last_epoch、verbose:同上。
T_0:第一次restart所需的epoch次数,
T_mult:第一次restart后,下一次restart所需epoch,为上一次epoch的几倍,若为1则每次间隔都不变。
T_mult=1如下:
T_mult=2如下:
参考来源
1.DEDSEC_Roger. CosineAnnealingLR(余弦退火调整学习率). CSDN