训练神经网络的一个主要挑战是训练多长时间。
训练不足会导致模型欠拟合训练集和测试集。训练过度会导致模型过拟合训练数据集,并在测试集上表现不佳。
一种折衷方法是在训练数据集上进行训练,但在验证数据集上的性能开始下降时停止训练。这种简单、有效且广泛使用的训练神经网络的方法称为早期停止。
在这篇文章中,您将发现,在神经网络过拟合训练数据集之前提前停止训练可以 减少过拟合,并提高深度神经网络的泛化能力。
阅读本文后,你将了解:
- 挑战在于训练神经网络足够长的时间以学习映射,但又不过度训练以至于过拟合训练数据。
- 在训练期间可以监控模型在独立验证数据集上的性能,并在泛化误差开始增加时停止训练。
- 使用早期停止需要选择要监控的性能度量、停止训练的触发器以及要使用的模型权重的选择。
用我的新书《更好的深度学习》来启动你的项目,书中包含分步教程和所有示例的 Python 源代码文件。
让我们开始吧。

早期停止以避免神经网络模型过拟合的温和介绍
照片由 Benson Kua 拍摄,部分权利保留。
概述
本教程分为五个部分;它们是:
- 训练恰到好处的问题
- 在泛化误差增加时停止训练
- 如何提前停止训练
- 早期停止的示例
- 早期停止技巧
训练恰到好处的问题
训练神经网络是具有挑战性的。
在训练大型网络时,训练过程中会出现一个点,此时模型将停止泛化并开始学习训练数据集中的统计噪声。
这种对训练数据集的过拟合将导致泛化误差增加,使得模型在新数据上进行预测的效用降低。
挑战在于训练网络的时间足够长,使其能够学习从输入到输出的映射,但训练时间又不过长以至于过拟合训练数据。
然而,所有标准的神经网络架构,例如全连接多层感知机,都容易过拟合[10]:虽然网络似乎越来越好,即训练集上的误差减小,但在训练过程中某个时刻,它实际上会开始变得更糟,即未见过示例上的误差增加。
— 早期停止——但何时?,2002。
解决此问题的一种方法是将 训练周期数 视为超参数,并多次训练模型,使用不同的值,然后选择产生最佳训练集或独立测试集性能的周期数。
这种方法的缺点是需要训练和丢弃多个模型。这在计算上可能效率低下且耗时,尤其是对于在大型数据集上花费数天或数周训练的大型模型。
在泛化误差增加时停止训练
另一种方法是一次性训练模型,进行大量训练周期。
在训练过程中,模型会在每个周期后在独立验证数据集上进行评估。如果模型在验证数据集上的性能开始下降(例如,损失开始增加或准确率开始下降),则停止训练过程。
… 相比独立数据测量的误差,通常称为验证集,往往先下降,然后在网络开始过拟合时上升。因此,训练可以在验证数据集上的最小误差点停止
— 第259页,模式识别与机器学习,2006。
训练停止时的模型将被使用,并且已知其具有良好的泛化性能。
此过程称为“早期停止”,可能是最古老、最广泛使用的神经网络正则化形式之一。
这种策略被称为早期停止。它是深度学习中最常用的正则化形式。它的流行归因于其有效性和简洁性。
— 第247页,深度学习,2016。
如果像权重衰减这样的正则化方法更新损失函数以鼓励更简单的模型被认为是“显式”正则化,那么早期停止可以被视为一种“隐式”正则化,就像使用容量较小的网络一样。
正则化也可以是隐式的,正如早期停止的情况。
— 理解深度学习需要重新思考泛化,2017。
想要通过深度学习获得更好的结果吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
如何提前停止训练
早期停止要求您将网络配置为欠约束,这意味着它的容量大于问题所需的容量。
在训练网络时,会使用比通常所需更多的训练周期,以便为网络提供充足的拟合机会,然后开始过拟合训练数据集。
使用早期停止有三个要素;它们是
- 监控模型性能。
- 停止训练的触发器。
- 模型选择。
监控性能
在训练过程中必须监控模型的性能。
这需要选择用于评估模型的训练数据集和用于评估模型的指标。
通常会将训练数据集拆分,并将一部分(例如30%)用作验证数据集,用于在训练过程中监控模型的性能。此验证集不用于训练模型。通常使用验证数据集上的损失作为要监控的指标,尽管您也可以在回归情况下使用预测误差,或在分类情况下使用准确率。
训练过程的一部分也将提供模型在训练数据集上的损失,并且还可以在训练数据集上计算和监控其他指标。
模型性能在每个周期结束时在验证集上进行评估,这会增加训练期间的额外计算成本。可以通过减少评估模型的频率来降低此成本,例如每2、5或10个训练周期。
早期停止触发器
一旦选择了评估模型的方案,就必须选择一个停止训练过程的触发器。
触发器将使用监控的性能指标来决定何时停止训练。这通常是模型在独立数据集上的性能,例如损失。
在最简单的情况下,只要模型在验证数据集上的性能相对于前一个训练周期的验证数据集上的性能下降(例如,损失增加),就会停止训练。
在实践中可能需要更复杂的触发器。这是因为神经网络的训练是随机的且可能充满噪声。绘制在图上,模型在验证数据集上的性能可能会上下波动多次。这意味着过拟合的第一个迹象可能不是停止训练的好时机。
… 即使在开始增加后,验证误差仍可进一步下降 […] 实际的验证误差曲线几乎总是有多个局部最小值。
— 早期停止——但何时?,2002。
一些更复杂的触发器可能包括
- 在给定数量的周期内指标没有变化。
- 指标的绝对变化。
- 在给定数量的周期内观察到性能下降。
- 在给定数量的周期内指标的平均变化。
几乎总是需要对停止设定一些延迟或“耐心”是一个好主意。
… 结果表明,“较慢”的标准,比其他标准停止得晚,平均而言,与“较快”的标准相比,泛化能力得到了改善。然而,为这些改进所必须付出的训练时间平均而言相当大,并且在使用较慢的标准时变化也很大。
— 早期停止——但何时?,2002。
模型选择
在训练停止时,模型比前一个周期的模型具有稍差的泛化误差。
因此,可能需要考虑确切地保存哪个模型。具体来说,从模型中保存到文件的权重来自哪个训练周期。
这将取决于选择停止训练过程的触发器。例如,如果触发器是从一个周期到下一个周期的性能简单下降,那么将优先考虑前一个周期的模型权重。
如果触发器需要观察在固定数量的周期内性能下降,则优先考虑触发器期间开始时的模型。
也许一个简单的方法是,如果模型在独立数据集上的性能优于前一个周期,则始终保存模型权重。这样,您将始终拥有在独立数据集上性能最好的模型。
每次验证集上的误差改善时,我们都会存储一份模型参数副本。当训练算法终止时,我们返回这些参数,而不是最新的参数。
— 第246页,深度学习,2016。
早期停止的示例
本节总结了一些使用早期停止的示例。
Yoon Kim 在其2014年关于卷积神经网络应用于情感分析的开创性论文《用于句子分类的卷积神经网络》中,使用了早期停止,其中10%的训练数据集用作验证集。
我们不进行任何其他特定于数据集的调整,除了在开发集上进行早期停止。对于没有标准开发集的数据集,我们随机选择10%的训练数据作为开发集。
Chiyuan Zhang 等人(来自 MIT、Berkeley 和 Google)在其2017年的论文《理解深度学习需要重新思考泛化》中指出,对于具有丰富数据集的非常深的卷积神经网络用于照片分类,早期停止可能不总是有益的,因为模型不太可能过拟合如此大的数据集。
[关于] ImageNet 上的训练和测试准确性 [结果表明] 早期停止可能带来潜在的性能提升。然而,在 CIFAR10 数据集上,我们没有观察到早期停止的任何潜在好处。
Yarin Gal 和 Zoubin Ghahramani(来自剑桥大学)在其2015年的论文《Dropout 在循环神经网络中理论上可行的应用》中,将早期停止用作 LSTM 模型在一系列语言建模问题上的“未正则化基线”。
RNN 模型缺乏正则化使得处理小数据变得困难,为了避免过拟合,研究人员经常使用早期停止,或小型且欠指定的模型
Alex Graves 等人(在其著名的2013年论文《使用深度循环神经网络进行语音识别》)在利用早期停止的同时,实现了最先进的 LSTM 语音识别结果。
对于 RNN 来说,正则化对获得良好性能至关重要,因为它们的灵活性使其容易过拟合。本文使用了两种正则化器:早期停止和权重噪声……
早期停止技巧
本节提供了一些将早期停止正则化与神经网络一起使用的技巧。
何时使用早期停止
早期停止非常易于使用,例如使用最简单的触发器,因此在训练神经网络时几乎没有理由不使用它。
早期停止的使用可能是现代深度神经网络训练的基石。
早期停止应几乎普遍使用。
— 第425页,深度学习,2016。
绘制学习曲线以选择触发器
在使用早期停止之前,拟合一个欠约束模型并监控模型在训练集和验证集上的性能可能很有趣。
实时或在长时间运行结束后绘制模型性能图将显示您特定的模型和数据集的训练过程有多么嘈杂。
这可能有助于选择早期停止的触发器。
监控重要指标
损失是在训练过程中监控和触发早期停止的简单指标。
问题在于,损失并不总是能捕捉到对您和您的项目最重要的模型内容。
选择一个最能定义模型性能的性能指标可能更好,特别是根据您打算使用它的方式。这可能是您打算用来报告模型性能的指标。
建议的训练周期
早期停止的一个问题是模型没有利用所有可用的训练数据。
尤其是在训练数据量非常有限的问题上,可能希望避免过拟合并利用所有可用数据进行训练。
一个推荐的方法是将训练周期数视为一个超参数,并通过网格搜索一系列不同的值,可能使用k折交叉验证。这将允许您固定训练周期数,并在所有可用数据上拟合最终模型。
可以使用早期停止代替。可以重复执行多次早期停止过程。可以记录停止训练时的周期数。然后,当在所有可用训练数据上拟合最终模型时,可以使用早期停止的每次重复的周期数的平均值。
此过程可以每次运行早期停止时使用不同的训练集拆分到训练集和验证集。
另一种方法可能是使用早期停止和验证数据集,然后使用对保留的验证集的进一步训练来更新最终模型。
带有交叉验证的早期停止
早期停止可以与 k 折交叉验证一起使用,尽管不推荐。
k 折交叉验证过程旨在通过重复拟合和在数据集的不同子集上进行评估来估计模型的泛化误差。
早期停止旨在监控一个模型的泛化误差,并在泛化误差开始下降时停止训练。
它们是矛盾的,因为交叉验证假设您不知道泛化误差,而早期停止则试图根据泛化误差的知识为您提供最佳模型。
为了估计具有不同超参数值(例如学习率或网络结构)的模型性能,同时使用早期停止,使用交叉验证可能是可取的。
在这种情况下,如果您有资源重复评估模型性能,那么训练周期数也可以作为要优化的超参数,而不是使用早期停止。
而不是将交叉验证与早期停止一起使用,在评估模型不同的超参数值(例如不同的学习率)时,可以直接使用早期停止,而无需重复评估。
一个可能的混淆点是,早期停止有时被称为“交叉验证训练”。此外,对早期停止的研究,比较触发器可能使用交叉验证来比较不同触发器的影响。
验证过拟合
重复多次早期停止过程可能会导致模型过拟合验证数据集。
这种情况可能和过拟合训练数据集一样容易发生。
一种方法是,只有当模型的所有其他超参数都已选择完毕后,才使用早期停止。
另一种策略可能是每次使用早期停止时,都使用训练数据集的不同拆分到训练集和验证集。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
书籍
- 第 7.8 节 早期停止,深度学习,2016。
- 第 5.5.2 节 早期停止,模式识别与机器学习,2006。
- 第 16.1 节 早期停止,神经计算:前馈人工神经网络的监督学习,1999。
论文
- 早期停止——但何时?, 2002.
- 通过非收敛方法改进模型选择, 1993.
- 使用交叉验证自动早期停止:量化标准, 1997.
- 理解深度学习需要重新思考泛化, 2017.
文章
文章
总结
在这篇文章中,您发现,在神经网络过拟合训练数据集之前提前停止训练可以减少过拟合,并提高深度神经网络的泛化能力。
具体来说,你学到了:
- 挑战在于训练神经网络足够长的时间以学习映射,但又不过度训练以至于过拟合训练数据。
- 在训练期间可以监控模型在独立验证数据集上的性能,并在泛化误差开始增加时停止训练。
- 使用早期停止需要选择要监控的性能度量、停止训练的触发器以及要使用的模型权重的选择。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
太棒了。非常感谢。
谢谢。
感谢这里的建议,我认为
“我感觉可以停止了,所以就提前停止训练”
这种做法需要被制止。
并且需要采取更受控制的方式。
感谢您为此提供的工具。
谢谢,很高兴它有帮助。
这是一个众所周知的事实。感谢您花费如此大的精力提供细节
谢谢。
嗨 Jason,如果我采用 K-fold CV 方法将早期停止点作为超参数之一来搜索,例如取平均值。那么,在 fold 上没有早期停止,对吗?然后,对于推理,用所有 fold 训练最终模型,此时应用早期停止。如何确定阈值,对于那个模型(推理),例如,准确率或在特定 FRR 处的 FAR,基于 N-fold CV 而不对最终模型应用早期停止?谢谢。
也许您可以简化实验,直接在多变量网格搜索中使用训练周期数作为超参数?
继续您的思路,在确定了 K 个 fold 的每个 fold 的训练周期数后(意味着在 fold 上没有早期停止,对吗?),然后取平均值作为最终模型(用于推理)在所有数据集(所有 fold)上训练使用。?那么如何确定 K 个阈值(用于分类或 ROC)的阈值呢?
这是个不错的开始!
嗨!
关于最佳实践的一个快速问题——由于我的数据很少,我只将数据分为训练和测试,并使用交叉验证进行超参数调整。我的问题是关于训练步骤中的迭代次数。目前,它不是超参数,我正在使用早期停止,其中验证是在训练集本身上进行的。我知道这不是最好的做法,所以我在考虑替代方法。一种方法是将迭代次数作为超参数进行调整,然后取最佳参数的1.1倍。但是,这样做的一个问题是我在超参数调整时使用0.05的学习率,而在训练时使用0.1。
如果您能就此发表看法,我将不胜感激!
非常感谢????
也许可以试试。
我认为要么将早期停止作为被评估的“系统”的一部分,要么固定周期数来调整学习率。
你好 Jason,我需要改进一个人的作品的通用数据集上的 F1_score。
通用数据集已分为训练集和测试集。
我稍微修改了他们的模型,并重新使用了他们的超参数模型。我应用了早期停止方法,我只使用训练数据集训练模型,并使用测试集通过 F1_score 来验证模型。这是我的伪代码
然后我选择具有最佳 F1 分数的模型作为最终模型。我没有寻找最佳超参数,因为我重复使用了它们。我没有将训练数据集拆分为训练集和验证集。
我的方法可以吗?
我很乐意提供帮助,但我没有能力审查/调试您的方法。
无论如何,非常感谢 Jason。
早上好!
感谢您提供如此清晰的介绍。
我想问一下,是否可以或应该同时使用早停和权重衰减正则化?如果可以,为什么?您有什么经验吗?
提前感谢您的回复,
此致!
我建议使用能带来最佳结果的方法,而不是试图挥舞我的手臂来支持理论上的论点。我们还没有稳健的理论。
试试看吧。
Jason,您好,我的数据集很小,所以我将其分为训练集和测试集。我可以在训练过程中使用测试集作为验证集,并使用“val_acc”(实际上应该是 test acc)作为早停的监控目标吗?这样做合理吗?会引起测试数据泄露吗?谢谢!
您可以这样做,但这可能会给出乐观的结果。
Jason,您好!您的教程非常有帮助。
不过我有一个问题。通过检查验证错误来停止训练过程,就像在说“如果在第 i 次迭代中的验证错误大于第 (i-1) 次迭代,则停止”吗?
如果真是这样,那感觉不对,
谢谢!
通常,这涉及到验证集上损失随多个 epoch 的变化,而不是一个 epoch。这被称为耐心。也许请重读上面的教程。
Jason,您好,感谢您提供的精彩教程。
我的理解是,无论我们是训练固定数量的 epoch,还是使用早停,我们都只在验证集上表现最佳的 epoch 保存模型。
我理解在训练过程中,当 epoch 增大时,模型会过拟合训练集。但是,我们只在验证准确率最佳的 epoch 保存模型,而不会真正保存过拟合训练集的模型,因为它们没有好的验证集结果。所以在我看来,只要我们在验证准确率最佳的 epoch 保存模型,就已经避免了过拟合问题,而早停只是节省了一些时间。
我觉得我在理解概念上有什么不对的地方……(当人们将 epoch 数量视为超参数时,他们实际上是在最后一个 epoch 保存模型,而不是在验证结果最佳的 epoch 保存模型?)请纠正我!谢谢。
是的,但我们可能没有足够的数据来用于完整的验证集。
嘿 Jason,谢谢你的帖子,一如既往的精彩文章。我有一个关于以下几行的问题
“早停过程可以重复多次。可以记录停止训练的 epoch 数量。然后,在所有早停重复运行中,可以使用计算出的 epoch 数量的平均值来拟合所有可用训练数据上的最终模型。”
当您说“可以重复多次”时,您的意思是将训练数据分成不同的数据集,分别在每个数据集上运行早停,然后取每个数据集中计算出的 epoch 数量的平均值吗?
您所说的可能是一种方法。或者,由于训练的随机性(还记得随机梯度下降吗?),您可以重复使用相同的数据集,但每次都重置/重新初始化模型。
感谢您的建议!