前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

AdamW

作者头像
狼啸风云
修改2022-09-02 11:46:56
1.1K0
修改2022-09-02 11:46:56
举报

L2正则是一种减少过拟合的一种经典方法,它在损失函数中加入对模型所有权重的平方和,乘以给定的超参数(本文中的所有方程都使用python,numpy,和pytorch表示):

final_loss = loss + wd * all_weights.pow(2).sum() / 2

...其中wd是要设置的l2正则的超参数。这也称为weight decay,因为在应用普通的SGD时,它相当于采用如下所示来更新权重:

w = w - lr * w.grad - lr * wd * w

(注意,w 2相对于w的导数是2w。)在这个等式中,我们看到我们如何在每一步中减去一小部分权重,因此成为衰减。

我们查看过的所有深度学习库,都使用了第一种形式。(实际上,它几乎总是通过向gradients中添加wd * w来实现,而不是去改变损失函数:我们不希望在有更简单的方法时,通过修改损失来增加更多计算量。)

那么为什么要区分这两个概念,它们是否起到了相同的作用呢?答案是,它们对于vanilla SGD来说是一样的东西,但只要我们在公式中增加动量项,或者使用像Adam这样更复杂的一阶或二阶的optimizer,L2正则化(第一个等式)和权重衰减(第二个等式)就会变得不同。在本文的其余部分,当我们谈论weight decay时,我们将始终参考第二个公式(梯度更新时,稍微减轻权重)并谈谈L2正则化,如果我们想提一下经典的方法。

以SGD + momentum为例。使用L2正则化,并添加wd * w衰减项到公式中(如前所述),但不直接从权重中减去梯度。首先我们计算移动平均值(moving average):

moving_avg = alpha * moving_avg + (1-alpha) * (w.grad + wd*w)

...这个移动平均值将乘以学习率并从w中减去。因此,与将从w取得的正则化相关联的部分是lr *(1-alpha)* wd * w加上前一步的moving_avg值。

另一方面,weight decay的梯度更新如下式:

moving_avg = alpha * moving_avg + (1-alpha) * w.grad w = w - lr * moving_avg - lr * wd * w

我们可以看到,从与正则化相关联的w中减去的部分在两种方法中是不同的。当使用Adam optimizer时,它会变得更加不同:在L2正则化的情况下,我们将这个wd * w添加到gradients,然后计算gradients及其平方值的移动平均值,然后再使用它们进行梯度更新。而weight decay的方法只是在进行更新,然后减去每个权重。

显然,这是两种不同的方法。在尝试了这个之后,Ilya Loshchilov和Frank Hutter在他们的文章中建议我们应该使用Adam的权重衰减,而不是经典深度学习库实现的L2正则化方法。

1.2 实现AdamW

我们应该怎么做?基于fastai库为例,具体来说,如果使用fit函数,只需添加参数 use_wd_sched = True:

learn.fit(lr, 1, wds=1e-4, use_wd_sched=

True)

如果您更喜欢新的API,则可以在每个训练阶段使用参数wd_loss = False(计算损失函数时,不使用weight decay):

phases = [TrainingPhase(1, optim.Adam, lr, wds=1-e4, wd_loss=False)]

learn.fit_opt_sched(phases)

以下给出基于fast库的一个简单实现。在optimizer的step函数的内部,只使用gradients来更新参数,根本不使用参数本身的值(除了weight decay,但我们将在外围处理)。然后我们可以在optimizer处理之前,简单地执行权重衰减。在计算梯度之后仍然必须进行相同操作(否则会影响gradients值),所以在训练循环中,你必须找到这个位置。

loss.backward()

#Do the weight decay here!

optimizer.step()

当然,optimizer应该设置为wd = 0,否则它会进行L2正则化,这正是我们现在不想要的。现在,在那个位置,我们必须循环所有参数,并做weight decay更新。你的参数应该都在optimizer的字典param_groups中,因此循环看起来像这样:

loss.backward()

for group in optimizer.param_groups():

for param in group['params']:

param.data = param.data.add(-wd * group['lr'], param.data)

optimizer.step()

1.3 AdamW实验的结果:它有效吗?

我们在计算机视觉问题上第一次进行测试得到的结果非常令人惊讶。具体来说,我们采用Adam+L2正规化在30个epochs内获得的准确率(这是SGD通过去1 cycle policy达到94%准确度所需要的必要时间)的平均为93.96%,其中一半超过了94%。使用Adam + weight decay则达到94%和94.25%之间。为此,我们发现使用1 cycle policy时,beta2的最佳值为0.99。我们将beta1参数视为SGD的动量(意味着它随着学习率的增长从0.95变为0.85,然后当学习率变低时再回到0.95)。

L2正则化或权重衰减的准确性

更令人印象深刻的是,使用Test Time Augmentation(即对测试集上的一个图像,取四个和他相同data-augmented版本的预测的平均值作为最终预测结果),我们可以在18个epochs内达到94%的准确率(平均预测值为93.98%) )!通过简单的Adam和L2正规,超过20个epochs时,达到94%。

在这些比较中要考虑的一件事是,改变我们正则的方式会改变weight decay或学习率的最佳值。在我们进行的测试中,L2正则化的最佳学习率是1e-6(最大学习率为1e-3),而0.3是weight decay的最佳值(学习率为3e-3)。在我们的所有测试中,数量级的差异非常一致,主要原因是,L2正则于梯度的平均范数(相当小)相除后,变得非常有效,且Adam使用的学习速率非常小(因此,weight decay的更新需要更强的系数)。

那么,使用Adam时,权重衰减总是比L2正规化更好吗?我们还没有发现一个明显更糟的情况,但对于迁移学习问题或RNN而言(例如在Stanford cars数据集上对Resnet50进行微调),它没有获得更好的结果。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-08-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档