持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情
导语
在以往的实验中,我们尝尝会遇到这样的情形:训练集上的loss一直持续下降,最终几乎接近于0,而验证集上的loss却先降后升。同时,由于验证集上loss先降后升,导致模型在验证集上的performance先升后降。本文提出了一种修改loss的非常简洁优雅的方式,在pytorch中只需要一行代码就可以解决以上问题。同时,论文也发表在了2020年的ICML上,得到广泛关注
- 会议:ICML 2022
- 链接:arxiv.org/abs/2002.08…
过拟合问题的由来与解决
“过拟合”是机器学习中一个令人头疼的问题,如果不加以限制,随着训练的进行,模型会越来越倾向于完全贴近于训练集上的样本数据,从而造成泛化性能极差。
如下图的ac所示,训练集上的loss值一直在下降,而验证集上的loss值则是先下降再上升。
为此,人们提出了很多有效的方法来解决,主要有:
- Early stopping:即不用等训练完全完成,可以提前中止训练;
- Weight decay: 对模型参数进行正则化,保证不出现怪异的参数值;
- Label smoothing:在输出y中添加噪声,实现对模型进行约束;
- Dropout:对神经网络中的神经元进行随机失活。 等等方法。
最近的研究表明,学习到训练误差为零对获得更低的泛化误差是有意义的。然而,在实现零训练错误后,是否需要零训练损失仍然是一个悬而未决的问题。
使用flooding解决过拟合问题
本文提出了一种简单却又行之有效的解决过拟合问题的方法,即对training loss做一个下限的“抬升”,具体来说,就是将loss的下界由0强行改为b(一个正数常量)。公式如下:
它的一个形象解释就是如图1的b所示,我们往training loss曲线下方“灌水”,使得整个training loss的曲线漂浮在水面之上(下面可以养鱼啊,虾啊,螃蟹之类的)。当loss低于这个水平面时,就会受到“浮力”的作用,强制loss抬升(对应到网络中就是梯度上升)。
这样操作之后,training loss将保持在一个常量值b(即“水面”)附近,模型在此持续进行“random walk”,防止参数被优化到一个不好的极小值,解决过拟合问题。
flooding的代码实现
flooding的代码实现非常简单,在pytorch代码中,只需要更改一行代码就可以实现:
outputs = model(inputs)
loss = criterion(outputs, labels)
flood = (loss-b).abs()+b # This is it!
optimizer.zero_grad()
flood.backward()
optimizer.step()
所做的修改即在原训练代码中添加第3行即可,非常的简介与优雅。
实验
仅仅这一点点小的修改,在实验上得到的表现也很亮眼。
可以看到,在使用和不使用early stop技术时,flooding都可以较大提升实验性能。
参考
- 【论文】一行代码发一篇ICML?zhuanlan.zhihu.com/p/163676138