Skip to content

AdamW

接着 Adam 的例子:

【L2 正则化】 为了防止过拟合,我们会给登山者一个惩罚:“如果你携带的行李(权重)太多太重,我就要罚你时间(增加损失)。”

我们已经知道 Adam 是一个装备了“记忆球”和“地形感知器”的超级登山者,能又快又稳地走下山。但是,这个登山者有一个致命的缺点:他太聪明了,聪明到会“作弊”来应对惩罚。

在 Adam 的“地形感知器”里,每个方向的“灵敏度”是根据这个方向的历史梯度大小自动调整的。

  • 正常情况(SGD):登山者感受到背包重了(L2惩罚),他会自觉地扔掉一些东西(权重衰减)。
  • Adam 的情况:当 Adam 感受到惩罚带来的额外“重力”(正则化梯度)时,他的“地形感知器”会说:“哎呀,这个方向突然变陡了,是不是有风险?我得小心点,步子迈小点。”问题来了:这个惩罚是故意让他迈小步的,而 Adam 的自动调整却把惩罚的一部分给抵消了。结果,背包并没有真正变轻多少,惩罚的效果大打折扣。这就是 “L2正则化在Adam中不等于权重衰减”

L2正则化的目的很简单:哪个权重特别大,就狠狠惩罚它。

在代码里,这种惩罚是通过在梯度里加一项 λθ 实现的。也就是说,如果权重 θ 很大,梯度里就会多出一个很大的值,强迫它下降。

Adam 维护了一个“二阶矩 vt,它是过去梯度平方的指数移动平均。可以理解为 Adam 在监控每个方向的“典型梯度有多大”

  • 如果某个方向过去经常出现大梯度,vt 就大,Adam 就觉得:“这方向震荡厉害,我得小心点,步子迈小一点。”
  • 如果某个方向过去梯度很小,vt 就小,Adam 就觉得:“这方向很平缓,可以走快一点。”

这本身是一个很好的特性,能防止模型在陡峭的方向上 overshoot。

但这里就出现了矛盾:L2 惩罚的梯度 vs 自适应机制

假设有一个权重 θ,它本身比较大(所以你想惩罚它),而且它在训练过程中经常产生大梯度(所以 Adam 已经给它分配了一个较小的学习率)。

现在你给损失函数加了 L2 正则化。对 θ 的梯度就变成:

gt=( 数据梯度 )+λθ

Adam 看到这个 gt 很大(因为 λθ 这一项很大),它就想:

“天哪,这个方向的梯度还是这么大,看来真的很陡峭,我必须再小心一点,把步子再迈小一点。”

于是 Adam 会进一步降低这个方向的有效学习率

你原本想的是:让 θ 的更新幅度变大,好让它快点下降。

但 Adam 的反应是:因为更新幅度变大了,所以我要降低学习率。

结果是:

  • 目标更新量 = 学习率 × 总梯度
  • 总梯度确实变大了,但学习率也变小了
  • 两者相乘,最后的有效更新量可能几乎没变!

也就是说,L2 正则化的惩罚信号,被 Adam 的自适应机制“识别”为需要降低学习率的信号,从而抵消了惩罚的效果。

AdamW 的做法是:不让惩罚的梯度经过自适应计算。

在 AdamW 中,更新公式变成:

θ=θη×Adam( 数据梯度 )η×λ×θ

最后这一项 ηλθ独立于自适应机制的。不管 Adam 怎么调整,这一项都会实实在在地把权重往下拉。

总结

  • L2 + Adam:惩罚信号被 Adam 的“自适应”机制稀释了,大权重并没有真正变小。
  • AdamW:把惩罚拿出来单独做,确保大权重实实在在地被衰减。

所以 AdamW 能让模型真正变简单,泛化能力更好。