前言
关于学习率调整与权重衰减,是机器学习中模型优化的重要部分。一些经典的方法在各类数据集取得了令人瞩目的成绩,如SGD、学习率衰减、预热、周期性学习率调整、AdaGrad、RMSprop、Adam,此外,一些小众的、同样有效的技巧也层出不穷,如LR Range Test、AdamW等。在接下来的一段时间里,本专栏将分期逐步对这些方法进行收录、总结。
1 LR Range Test(学习率范围测试)与Cyclical LR(周期性学习率调整)
部分知识转自知乎专栏 :https://zhuanlan.zhihu.com/p/52084949?utm_source=wechat_timeline
代码参考:https://github.com/anandsaha/pytorch.cyclic.learning.rate/blob/master/cls.py
2015年,Leslie N. Smith提出了该技术。其核心是将模型进行几次迭代,在最初的时候,将学习率设置的足够小,然后,随着迭代次数的增加,逐渐增加学习率,记录下每个学习率对应的损失,并绘图:
LR Range Test 图应该包括三个区域,第一个区域中学习率太小以至于损失几乎没有减少,第二个区域里损失收敛很快,最后一个区域中学习率太大以至于损失开始发散。因此,第二个区域中的学习率范围就是我们在训练时应该采用的。
在一些经典方法中,学习率总是逐步下降的,从而保证模型能够稳定收敛,但Leslie Smith对此提出了质疑,Leslie Smith认为让学习率在合理的范围内周期性变化(即Cyclical LR)是更合理的方法,能够以更小的步骤提高模型准确率。
如上图所示,max_lr 与 lr 可以通过 LR Range test 确定,作者认为:最优学习率将在处于这个范围内,所以如果学习率在这歌区间变化,大多数情况下你将得到一个接近最优学习率的学习率。
总结:
(1)Cyclical LR是一种有效避开鞍点的方法,因为在鞍点附近梯度较小,通过增加学习率可以让模型走出困境。
(2)Cyclical LR能够加速模型训练过程
(3)Cyclical LR在一定程度上可以提高模型的泛化能力(将模型带入平坦最小值区域)
2 The 1cycle policy(一周期策略)
参考链接:https://sgugger.github.io/the-1cycle-policy.html
在Cyclical LR和LR Range Test的基础上,Leslie 继续改进,提出了The 1cycle policy。即周期性学习率调整中,周期被设置为1。在一周期策略中,最大学习率被设置为 LR Range test 中可以找到的最高值,最小学习率比最大学习率小几个数量级(比如设为最大值的0.1倍)。
如上图,一整个训练周期约400个iter,前175个iter用来warm-up,中间175个iter用来退火到初始学习率,最后几十个iter学习率进行进一步衰减。我们将上述三个过程称为三个阶段。
- 第一阶段:线性warm-up,其效果与一般的warm-up效果类似,防止冷启动导致的一些问题。
- 第二阶段:线性下降至初始学习率。由于第一、第二阶段中有相当大的时间模型处于较高的学习率,作者认为,这将起到一定的正则化作用,防止模型在陡峭最小值驻留,从而更倾向于寻找平坦的局部最小值。
- 第三阶段:学习率衰减至0,将使得模型在一个‘平坦’区域内收敛至一个较为‘陡峭’的局部最小值。
上图展示了一周期策略训练时,模型在训练集和验证集上的损失变化,可见,在学习率较大时,验证集损失变得不稳定,但平均来看,验证集损失与训练集损失的差值没有变化太多,说明这个阶段模型学习到的知识具有较好的泛化能力(即大学习率一定程度上起到了正则化的作用)。而在训练末期,学习率不断衰减,这时训练集损失有明显下降,而验证集损失没有明显下降,两者的差值扩大了,因此,在训练末期,模型开始产生了一定的过拟合(个人理解:某种意义上讲,这种过拟合是使得模型能够稳定地停留在平坦最小值区域的一种手段)。
3 AdamW算法
参考链接:https://blog.csdn.net/yinyu19950811/article/details/90476956#161_Adamw_89
2014年提出的Adam算法有很多优点,它集合了动量与RMSprop两种方式的优点。但是在实际应用过程中,却经历了过山车一般的发展历程:一经提出,非常火热,但是后来却受到很多质疑,质疑者认为在训练时,简单的SGD+动量能够取得更好的效果,直到AdamW提出后,Adam才又焕发活力。
AdamW的作者认为,Adam存在以下问题:
- 1) L2正则化在Adam中并不等价于权重衰减:这里需要讲一下,在使用L2正则化的时候,我们想要达到的目的是控制权重的大小,防止过拟合,从而将L2正则加入到损失函数中,即
final_loss = loss + L2 = loss + 0.5*sum(w^2)
,对上述函数求导时,可以看到导数为loss的导数 + w
,因此参数进行梯度更新时,就会在原来的基础上减去一个w
,因此我们说L2正则化是权重衰减。但是权重衰减与L2正则等价仅仅是在采用SGD的情况下,当使用Adam时,减去w
这一项会变得很复杂(大家可以自己推到一下)。 - 2)使用Adam优化带L2正则的损失并不有效,如果引入L2正则化项,在计算梯度的时候会加上正则项求梯度的结果。正常的权重衰减是对所有的权重都采用相同的系数进行更新,本身比较大的一些权重对应的梯度也会比较大,惩罚也越大。但由于Adam计算步骤中减去项会有除以梯度平方的累积,使得梯度大的减去项偏小,从而具有大梯度的权重不会像解耦权重衰减那样得到正则化。 这导致自适应梯度算法的L2和解耦权重衰减正则化的不等价。
因此,权重衰减和L2正则这两件事要分开来看,我们使用L2正则的目的是为了在所有参数上进行相同尺度的惩罚(权重衰减),但是由于Adam独特的计算公式,使得不同参数惩罚的尺度不一样了,这也就是AdamW的改进点,即先进行损失计算(不包含),然后算进行Adam中的动量和RMSprop项目,然后在最后参数更新的时候进行权重衰减,看图:
如果是SGD,L2正则化项和梯度衰减是等同的。但是由于Adam加入了一阶动量和二阶动量,基于包含L2正则化项的梯度来计算一阶动量和二阶动量,使得参数的更新系数就会变化,与单纯的权重衰减就会变得不同。
另外,在fastAI的一篇文章中(https://www.fast.ai/2018/07/02/adam-weight-decay/)指出,即使是原始的Adam也是有效的,前提是超参数设置正确。