AdamW 和 Adam 的权重衰减

Aer*_*ysS 16 pytorch

有什么区别torch.optim.Adam(weight_decay=0.01)torch.optim.AdamW(weight_decay=0.01)

链接到文档:torch.optim

kHa*_*hit 15

是的,Adam 和 AdamW 的权重衰减是不同的。

Hutter 在他们的论文(Decoupled Weight Decay Regularization)中指出,在 Adam 中每个库中实现权重衰减的方式似乎是错误的,并提出了一种简单的方法(他们称之为 AdamW)来修复它。

在 Adam 中,权重衰减通常是通过将wd*wwd这里是权重衰减)添加到梯度(Ist 情况)来实现的,而不是实际从权重中减去(IInd 情况)。

# Ist: Adam weight decay implementation (L2 regularization)
final_loss = loss + wd * all_weights.pow(2).sum() / 2
# IInd: equivalent to this in SGD
w = w - lr * w.grad - lr * wd * w
Run Code Online (Sandbox Code Playgroud)

这些方法对于普通 SGD 是相同的,但是一旦我们添加动量,或者使用更复杂的优化器(如 Adam),L2 正则化(第一个方程)和权重衰减(第二个方程)就会变得不同。

AdamW 遵循权重衰减的第二个方程。

在亚当

weight_decay (float, optional) – 权重衰减(L2 惩罚)(默认值:0)

在亚当W

weight_decay (float, optional) – 权重衰减系数(默认值:1e-2)

fastai 博客上阅读更多内容。

  • 除此之外,目前 torch.optim.adam 的文档中似乎存在某种误导性的陈述,(错误地)表明 Adam 也在使用较新版本的权重衰减,这将使其相当于亚当·W. https://github.com/pytorch/pytorch/issues/48793 https://github.com/pytorch/pytorch/pull/50464 (2认同)

cot*_*ail 8

Pytorch中,Adam 和 AdamW 的实现是不同的。在Adam 源代码中,权重衰减实现为

grad = grad.add(param, alpha=weight_decay)
Run Code Online (Sandbox Code Playgroud)

而在AdamW 源代码中,它的实现为

param.mul_(1 - lr * weight_decay)
Run Code Online (Sandbox Code Playgroud)

因此,在每次迭代中,在 Adam 中,梯度都会根据前一次迭代的估计参数(按权重衰减加权)进行更新。另一方面,在 AdamW 中,参数由前一次迭代的参数通过权重衰减加权进行更新。文档中的伪代码清楚地显示了差异(用框表示强调),其中 lambda 是权重衰减。

伪代码


然而在Keras中,即使默认实现不同,因为 Adam 有weight_decay=None而 AdamW 有weight_decay=0.004(事实上,它不能是 None),如果weight_decay不是 None,Adam 与 A​​damW 相同。两者都是子类optimizer.Optimizer,事实上,它们的源代码几乎相同;特别是,每次迭代中更新的变量是相同的。唯一的区别是Adam 的 定义weight_decay被推迟到父类,而AdamW 的 weight_decay定义在 AdamW 类本身中定义。

  • 这很有趣。所以在 PyTorch 中,它们是不同的,但在 Keras 中,它们是相同的 (2认同)