你在评估机器学习算法时所使用的测试选项,可能决定了你是过度学习、得到一个平庸的结果,还是得到一个你可以自信地向全世界宣告的可用、顶尖的结果(有时你真的会有这种冲动)。
在这篇文章中,你将发现可以在算法评估测试工具中使用的标准测试选项,以及下次如何选择正确的选项。
随机性
选择正确测试选项的困难根源在于随机性。大多数(几乎所有)机器学习算法都以某种方式使用随机性。这种随机性可能在算法中是显式的,也可能在于为训练算法而选择的数据样本中。

随机性
照片由 afoncubierta 拍摄,保留部分权利
这并不意味着算法会产生随机结果,而是意味着它们产生的结果带有一定的噪声或方差。我们将这种有限的方差称为随机性,而利用它的算法称为随机算法。
在相同数据上训练和测试
如果你有一个数据集,你可能想用这个数据集来训练模型,然后报告模型在该数据集上的结果。这就是模型的优劣,对吧?
这种评估算法方法的问题在于,你确实会知道算法在数据集上的表现,但无法得知该算法在模型未曾训练过的数据(即所谓的未见数据)上的表现如何。
只有当你想用这个模型对未见数据进行预测时,这一点才重要。
划分测试
使用一个数据集既能训练模型,又能估计算法在未见数据上的表现,一个简单的方法是划分数据集。你取一个数据集,将其划分为训练数据集和测试数据集。例如,你随机选择66%的实例用于训练,剩下的34%作为测试数据集。
算法在训练数据集上运行,创建一个模型,并在测试数据集上进行评估,你会得到一个性能准确率,比如说87%的分类准确率。
当数据量很大,或者训练模型成本很高(无论是资源还是时间)时,划分测试速度很快,效果也很好。在非常大的数据集上进行划分测试,可以对算法的实际性能产生准确的估计。
算法在数据上的表现有多好?我们能自信地说它能达到87%的准确率吗?
一个问题是,如果我们再次将训练数据集以不同的66%/34%比例划分,我们的算法会得到不同的结果。这被称为模型方差。
多次划分测试
解决划分测试在不同数据集划分上得到不同结果的问题的一个方法是,减少随机过程的方差,并多次进行。我们可以收集相当多次运行(比如10次)的结果,然后取平均值。
例如,假设我们按66%/34%的比例划分数据集,运行算法得到一个准确率,然后我们用10次不同的划分重复这个过程10次。我们可能会得到10个准确率分数,如下所示:87, 87, 88, 89, 88, 86, 88, 87, 88, 87。
我们模型的平均性能是87.5,标准差约为0.85。

抛硬币
照片由 ICMA Photos 拍摄,保留部分权利
多次划分测试的一个问题是,可能有些数据实例从未被包含在训练或测试中,而其他实例可能被多次选中。这可能会扭曲结果,并且可能无法给出算法准确率的有意义的概念。
交叉验证
确保每个实例被用于训练和测试的次数相等,同时减少准确率分数的方差,一个解决方案是使用交叉验证。具体来说是k折交叉验证,其中k是数据集划分的份数。
例如,我们选择k=10(非常常见)。这会将数据集分成10份(10折),算法将运行10次。每次算法运行时,它将在90%的数据上进行训练,在10%的数据上进行测试,并且每次运行算法时,用于测试的10%数据都会更换。
在这个例子中,每个数据实例将恰好被用作训练实例9次,用作测试实例1次。准确率将不再是平均值和标准差,而是一个确切的准确率分数,表示做出了多少个正确的预测。
k折交叉验证是评估算法在数据集上性能的首选方法。你需要选择一个k值,为你的算法提供大小合适的训练集和测试集。比例不能太不协调(训练集或测试集太大或太小)。如果你的数据量非常大,你可能不得不采用数据抽样或回归到划分测试的方法。
交叉验证确实能对算法在未见数据上的性能给出无偏估计,但如果算法本身使用了随机性呢?每次使用不同的随机数种子(伪随机序列的起点)进行训练时,算法会对相同的训练数据产生不同的结果。交叉验证没有考虑到算法预测中的方差。
另一个值得关注的点是,交叉验证本身也使用随机性来决定如何将数据集划分为k折。交叉验证并没有估计算法在不同折组合下的表现。
只有当你想了解算法在数据集上的鲁棒性时,这一点才重要。
多次交叉验证
考虑算法本身方差的一个方法是多次运行交叉验证,并计算每次运行中算法准确率的均值和标准差。
这将给你一个算法在数据集上性能的估计,以及性能鲁棒性(标准差的大小)的估计。
如果你有一个算法A的均值和标准差,以及另一个算法B的均值和标准差,并且它们不同(例如,算法A的准确率更高),你如何知道这种差异是否有意义?
只有当你想比较不同算法的结果时,这一点才重要。
统计显著性
在多次运行k折交叉验证时,比较算法性能度量的一个解决方案是使用统计显著性检验(比如学生t检验)。
多次k折交叉验证的结果是一组数字。我们喜欢用均值和标准差来总结这些数字。你可以把这些数字看作是从一个潜在总体中抽取的样本。统计显著性检验回答了这样一个问题:两个样本是否来自同一总体?(没有差异)。如果答案是“是”,那么,即使均值和标准差不同,这种差异也可以说是不具有统计显著性的。
当使用多次运行(如使用不同随机数种子的多次k折交叉验证)时,我们可以利用统计显著性检验来赋予算法结果之间差异(或无差异)的意义。这在我们想要对结果做出准确声明时(例如,算法A优于算法B,且差异具有统计显著性)非常有用。
故事到这里还没有结束,因为有不同的统计显著性检验(参数检验和非参数检验)以及这些检验的参数(p值)。我就此打住,因为如果你能跟到这里,你现在已经对选择测试选项以产生严谨(可发表!)的结果有了足够的了解。
总结
在这篇文章中,你发现了在设计测试工具以评估机器学习算法时,可用的主要测试选项之间的区别。
具体来说,你了解了以下方法的效用和问题:
- 在同一数据集上训练和测试
- 划分测试
- 多次划分测试
- 交叉验证
- 多次交叉验证
- 统计显著性
如有疑问,请使用k折交叉验证(k=10),当你想要有意义地比较你的数据集上的算法时,请使用多次k折交叉验证和统计显著性检验。
很棒的文章,Jason。非常清晰易懂。
谢谢,Mickael。
很棒的文章。
关于最后一部分,是否存在不同算法的性能比较需要非参数检验的情况?
如果存在,您能给我们举一些例子吗?
谢谢你的帮助。
结果的分布通常是高斯分布(正态分布)。
如果你因为某些原因认为情况并非如此,我建议你使用非参数检验。这是一个好问题,我一时想不出来什么。通常我会使用非参数检验来消除所有猜测。
谢谢;)
很棒的文章!谢谢!
您建议运行多次k折交叉验证并进行统计显著性检验,以帮助得出算法比较的结论。
我想知道如果我使用k折交叉验证,如何留出一折用于验证和调整模型。
运行多次训练/验证/测试数据集划分并进行统计显著性检验是否可行,即使某些数据可能在同一数据集划分中多次出现?
谢谢你的帮助!
Jason博士,您好,
这是另一篇很棒的文章。我从这篇文章中学到了很多。
请继续保持。
此致,
Surajit
嗨,Jason——我是机器学习和Python的新手。刚学习了您在Python中从零开始实现朴素贝叶斯的算法。首先感谢您精彩的解释。
也学习了用scikit-learn实现相同算法的方法。
需要一些帮助来理解classification_report中的精确率(precision)、召回率(recall)和f1分数(f1 score)这些术语。
Jason…您的文章既简单又精彩
谢谢。
谢谢
不客气,anbu。
非常感谢您这篇精彩的文章,Jason。请继续保持出色的工作。
非常欢迎,Mohammed。
我正在尝试理解K折交叉验证如何帮助评估使用反向传播训练的神经网络模型。据我理解,在K折交叉验证中,每个批次都用于训练一个单一的神经网络模型。这是否意味着,在每个批次结束时,模型或多或少地对该特定批次过拟合了?那么在10折交叉验证中,在最后一个批次结束时,我们得到的模型可能对最后一个批次过拟合,它可能在最后一个批次的90%训练数据上表现良好,但在测试的10%上表现很差?
这在时间序列数据上能行得通吗?
无论如何,感谢您的分享,您的文章对我非常有帮助。
你好,hew。
是的,会训练和评估10个不同的模型。我们报告平均分数,然后丢弃这些模型。交叉验证仅用于估计模型在未见数据上的性能,而不是用于训练模型。
如果我们对性能满意,我们就可以在整个训练数据集上训练模型,并开始使用它。
时间序列数据很难使用交叉验证。通常,我使用训练/测试划分和滑动窗口来评估时间序列数据的模型。
嗨,Jason,
谢谢你的回复。我不确定是否完全理解你的意思。为了评估我们的模型在未见数据上的性能?这里的模型定义是指所使用的机器学习方法吗?在k折练习中取得好成绩意味着什么?我只能假设,我们使用的数据集包含了均匀分布的共同特征,这些特征可以用于我们数据集的预测。这并不能证明它对样本外数据的有效性。也许我们为练习选择的数据集存在偏见,以至于我们发现的特征在样本外数据集中根本不起作用。
很好的评论。
预测建模的目标是从领域的数据样本中开发一个模型,以便在它以前未见过的数据上表现良好。对未见数据进行预测。
如果这不是目标,那么你是在做统计学,开发一个描述性而非预测性模型,并试图理解该领域。
了解一个模型在未见数据上的表现是一个难题。我们可以保留一个样本,并用它来估计模型的技能。一种更高级的技术是多次这样做——即交叉验证。
交叉验证并不能证明一个模型或建模方法(数据准备+模型)会表现良好,但它给了我们它会表现良好的信心。
确实,我们必须非常关注数据样本的质量,否则泛化能力将受到损害。
这有帮助吗?
嗨,Jason,
请问当数据点非常少(比如只有15到20个)但预测变量数量很大(例如9到10个)时,有什么替代方法来拟合数据?
Poonam,这是一个更难的问题类型。
你可能更适合使用小n统计学(例如统计方法)。你的观测值太少,机器学习方法无法从中学习和泛化。
嗨,Jason,
您能解释一下测试集和验证集的区别吗?如果我把数据分成测试集和训练集。我还需要设置一个验证集吗?
非常感谢!
你好,Rita,
训练集用于拟合模型,测试集用于评估模型。一个大的数据集可以被分成多个训练集和测试集——例如k折交叉验证。
验证数据集是保留下来用作最终检查的。它是可选的,但推荐使用。
你好 jason!这真是简单又好的信息!
我有两个问题。
.
1. 在最后一部分(统计显著性),如何计算统计显著性?是像p值那样吗?
2. 在数据划分中,您在上面的问题中说推荐使用验证数据集。那么,当我将数据集划分为60%(训练),20%(测试),20%(验证)时,测试集和验证集之间有什么区别?我认为算法是通过使用测试数据来评估的。所以……验证的作用是什么?它们的作用相同吗?我感到困惑……
祝你有美好的一天!
博士您好,
感谢您的出色工作。我想问一下,如何绘制K折交叉验证中开发的每个K折模型的准确率。
非常感谢Jason博士的详细解释。我看到在任何k折交叉验证的例子中,样本划分大小总是10。我们如何确定交叉验证的正确划分数呢?我的一些数据集有700行数据,有些有7000行数据。我认为总是将数据集划分为10折并不是正确的决定。
对于大多数数据集,报告的k值为10,因为更多的分组对平均技能分数的偏差/方差带来的回报递减。
你可以尝试进行敏感性分析,看看k值如何影响技能分数的分布。这不是一个坏主意。
最小化平均绝对误差的最佳技术是什么?
这取决于具体的数据和算法。可以尝试几种。
你好,Jason。我想学习如何评估回归模型的准确性。我读了这篇文章,但似乎跟不上。我需要从零开始学习机器学习……我的意思是从最基础的开始。请帮忙提供任何材料。谢谢
您可以通过查看预测误差来评估回归模型的技能。
通常使用均方根误差(RMSE)或平均绝对误差(MAE)来估计预测误差。
像scikit-learn、Weka和R中的caret这样的顶级平台都提供了这些度量。
我也有关于如何手动计算它们的文章。
希望这能有所帮助。
先生,对于一个二分类缺陷检测问题,除了准确率之外,还需要评估哪些其他参数?
考虑使用混淆矩阵,并查看矩阵的每个象限
https://machinelearning.org.cn/confusion-matrix-machine-learning/
同时考虑精确率和召回率。
你好,Jason
在构建预测模型时,我们需要使用交叉验证吗?它重要吗?
其次,如果我决定使用交叉验证,应该在什么时候使用它?是在训练数据上还是在测试数据上?
在我的场景中,我将使用训练数据集构建一些分类算法,然后我将使用测试集来评估我的模型的性能。
我应该在构建模型时还是在测试模型时使用交叉验证?
是的,交叉验证(CV)可能是我们拥有的用于开发无偏(或偏差较小)估计量的最佳方法。
如果你有大量数据,可以使用训练/测试集划分。
好文章,Jason。我真的很喜欢你在这里提供的工具。我有个问题:如果你时间紧迫(比如在比赛中或者面对一个非常不耐烦的老板),你会用什么方法?我这么问是因为尽管交叉验证(CV)和多次CV运行是让你对结果充满信心的好方法,但它们非常耗时。
提前感谢您的时间!
我似乎总是回归到重复交叉验证和显著性检验。这是我随机优化背景的原因,让我不满足于任何更低标准。
你好,
这是一篇很棒的文章,非常感谢。
您是否写过,或者知道有什么关于在交叉验证结果上应用显著性检验的介绍/教程可以推荐?那将会非常有用。
再次非常感谢!
是的,我计划了几篇关于这个主题的文章。
我推荐阅读这篇论文
http://web.cs.iastate.edu/~honavar/dietterich98approximate.pdf
你好,
在“交叉验证”部分,您说
在这个例子中,每个数据实例将恰好被用作训练实例9次,用作测试实例1次。准确率将不再是平均值和标准差,而是一个确切的准确率分数,表示做出了多少个正确的预测。
这是计算总体准确率的方式。但在论文“Steven L Salzberg. 1997. On comparing classifiers: Pitfalls to avoid and a recommended approach. Data mining and knowledge discovery 1, 3 (1997), 317-328”的“A recommended approach”部分,总体准确率是在所有k个分区上取平均值。这k个值也给出了算法方差的估计。然后为了比较算法,建议使用二项检验或McNemar检验。
那么你认为哪一个是有效的?
谢谢
有许多统计假设检验方法可以使用,我在这里有更详细的解释
https://machinelearning.org.cn/statistical-significance-tests-for-comparing-machine-learning-algorithms/
你好,我想知道所有机器学习算法的效率水平。我正在做一个项目,了解这一点对我来说非常重要。请尽快回复。谢谢
你是指计算效率吗?
或许对你选择的算法进行大O分析?
嗨,Jason,
交叉验证模型误差之间可接受的标准差(范围?)是多少?
此致,
这取决于具体问题。将你的结果与一个简单的基线模型进行比较。更多细节在这里
https://machinelearning.org.cn/faq/single-faq/how-to-know-if-a-model-has-good-performance
你好 Jason,我想向你澄清一下关于“在训练数据集上运行算法,模型在测试数据集上评估和创建”这句话?如何利用从训练数据集运行的结果在测试数据集上建立模型?我对这个说法不太清楚……能请您指点一下吗?
抱歉,我没跟上。
你具体想实现什么?
嗨,Jason,
我想和您确认一下:您在文章中提到的“多次交叉验证”,是否就是caret中“trainControl”函数里method=”repeatedcv”所指的“重复交叉验证”?谢谢!
是的。
我在训练数据集上训练了一个学习器,准确率达到了99%。当我用10折交叉验证训练同一个学习器时,我的准确率下降到了40%。显然我的模型过拟合了。在执行随机搜索交叉验证后,我得到了最佳估计器,其准确率为55%。我如何知道我调整过的超参数模型已经解决了过拟合问题?换句话说,我应该在哪个数据集上评估我调整过的学习器模型?显然我不能使用测试集,因为我对我学习器的信心还不够。
也许不是过拟合,可能只是第一种情况是对预期性能的糟糕估计,而交叉验证更可靠。
你可以在一个保留的数据集上进行网格搜索,或者在每个交叉验证折叠内进行网格搜索,这被称为嵌套交叉验证。
Brownlee先生您好,
很棒的文章。如果您不介意,我想请教您几个问题。
1. 在k折交叉验证技术中,数据集既被用来建立模型又被用来验证模型,这不理想,对吗?
2. 即使模型能被准确分类,它是否会受到数据特异性的限制?
3. 您如何计算分类一个全新的、未见过的样本的准确率?
提前感谢
k折交叉验证仅用于评估模型的性能
https://machinelearning.org.cn/k-fold-cross-validation/
模型的优劣取决于用于训练它的数据。
k折交叉验证评估的是模型在用于对训练期间未见过的新数据进行预测时的性能。
非常感谢您的精彩文章。
我想知道您对无监督模型有什么看法。
在模型用于生成合成数据的情况下,我们是否需要测试数据来评估无监督模型?
如何评估一个无监督模型?
提前感谢您的时间和回复。
这取决于模型的类型,例如,通常像评估分类模型一样评估聚类方法。
https://machinelearning.org.cn/faq/single-faq/how-do-i-evaluate-a-clustering-algorithm
尊敬的先生……您的文章总是非常棒……当我在做任何搜索时,如果您的文章在选项中,我总是优先阅读您的……我的问题是……我正在尝试使用交叉验证的RandomizedSearchCV来为F1分数选择超参数……它给了我类别1的F1分数的最佳模型,但我的少数类类别2的F1分数却非常差……我想为类别2的模型选择最佳超参数?在这种情况下我应该怎么做?
你好 Anjali…以下是一个很好的讨论,可能会让问题更清晰
https://stackoverflow.com/questions/62672842/how-to-improve-f1-score-for-classification