我经常看到从业者对如何评估深度学习模型感到困惑。
这通常可以从类似这样的问题中看出:
- 我应该使用什么随机种子?
- 我需要随机种子吗?
- 为什么我每次运行得到的结果都不一样?
在这篇文章中,您将了解可以用来评估深度学习模型的程序及其使用原理。
您还将了解可以计算以展示模型技能的有用相关统计数据,例如标准差、标准误差和置信区间。
开始您的项目,阅读我的新书《Python 深度学习》,其中包括分步教程和所有示例的Python 源代码文件。
让我们开始吧。

如何评估深度学习模型的技能
照片来源:Allagash Brewing,部分权利保留。
初学者的错误
您将模型拟合到训练数据,然后在测试数据集上进行评估,然后报告其技能。
也许您使用 k 折交叉验证来评估模型,然后报告模型的技能。
这是初学者常犯的错误。
看起来您在做正确的事情,但有一个关键问题您没有考虑到
深度学习模型是随机的。
人工神经网络在拟合数据集时使用随机性,例如随机初始权重和在随机梯度下降过程中每个训练周期中的数据随机洗牌。
这意味着每次用相同的数据拟合相同的模型时,它可能会给出不同的预测,从而导致不同的整体技能。
评估模型技能
(控制模型方差)
我们没有所有可能的数据;如果我们有,我们就不需要进行预测了。
我们拥有的数据是一个有限的样本,从中我们需要发现我们可以找到的最佳模型。
使用训练-测试拆分
我们通过将数据分成两部分来做到这一点,在第一部分数据上拟合模型或特定的模型配置,并使用拟合的模型对剩余部分进行预测,然后评估这些预测的技能。这被称为训练-测试拆分,我们使用该技能来估计模型在实际应用中进行预测时的表现。此为估计值。
例如,以下是使用训练-测试拆分评估模型的伪代码:
1 2 3 4 |
train, test = split(data) model = fit(train.X, train.y) predictions = model.predict(test.X) skill = compare(test.y, predictions) |
如果数据量很大或模型训练速度很慢,训练-测试拆分是一个好方法,但由于数据中的随机性(模型方差),由此产生的模型技能得分会很嘈杂。
这意味着在不同数据上拟合的同一模型将产生不同的模型技能得分。
使用 k 折交叉验证
我们通常可以通过 k 折交叉验证等技术来收紧这一点,并获得更准确的模型技能估计。这是一种系统地将可用数据分成 k 折的技术,在 k-1 折上拟合模型,在保留的折上进行评估,并为每一折重复此过程。
这将产生 k 个不同的模型,它们有 k 个不同的预测集,进而有 k 个不同的技能得分。
例如,以下是使用 k 折交叉验证评估模型的伪代码:
1 2 3 4 5 6 7 |
scores = list() for i in k train, test = split_old(data, i) model = fit(train.X, train.y) predictions = model.predict(test.X) skill = compare(test.y, predictions) scores.append(skill) |
技能得分的总体比我们更能说明问题,因为我们可以取平均值并报告模型的平均预期性能,这可能更接近模型在实际中的实际性能。例如:
1 |
mean_skill = sum(scores) / count(scores) |
我们还可以使用 mean_skill 计算标准差,以了解得分在 mean_skill 周围的平均分布情况。
1 |
standard_deviation = sqrt(1/count(scores) * sum( (score - mean_skill)^2 )) |
估计随机模型的技能
(控制模型稳定性)
像深度神经网络这样的随机模型会增加额外的随机性。
这种额外的随机性使模型在学习时具有更大的灵活性,但可能会导致模型不太稳定(例如,在用相同数据训练相同模型时结果不同)。
这与模型方差不同,模型方差是指用不同数据训练相同模型时会产生不同结果。
为了获得随机模型技能的稳健估计,我们必须考虑这种额外的方差来源;我们必须对其进行控制。
固定随机种子
一种方法是每次拟合模型时都使用相同的随机性。我们可以通过固定系统使用的随机数种子来做到这一点,然后评估或拟合模型。例如:
1 2 3 4 5 6 7 8 |
seed(1) scores = list() for i in k train, test = split_old(data, i) model = fit(train.X, train.y) predictions = model.predict(test.X) skill = compare(test.y, predictions) scores.append(skill) |
这对于需要每次运行代码都能获得相同结果的教程和演示很有用。
这很脆弱,不建议用于评估模型。
请参阅这篇博文
重复评估实验
更稳健的方法是多次重复评估非随机模型。
例如
1 2 3 4 5 6 7 8 9 10 |
scores = list() for i in repeats run_scores = list() for j in k train, test = split_old(data, j) model = fit(train.X, train.y) predictions = model.predict(test.X) skill = compare(test.y, predictions) run_scores.append(skill) scores.append(mean(run_scores)) |
请注意,我们计算的是估计的平均模型技能的平均值,即所谓的总体均值。
这是我推荐的用于估计深度学习模型技能的程序。
因为重复次数通常 >=30,我们可以轻松计算平均模型技能的标准误差,即估计的平均模型技能得分与未知实际平均模型技能的差异程度(例如,mean_skill 可能有多错误)。
1 |
standard_error = standard_deviation / sqrt(count(scores)) |
此外,我们可以使用标准误差来计算 mean_skill 的置信区间。这假设结果的分布是高斯分布,您可以通过查看直方图、Q-Q 图或在收集的得分上使用统计测试来检查。
例如,95% 的区间是(1.96 * standard_error)在平均技能周围。
1 2 3 |
interval = standard_error * 1.96 lower_interval = mean_skill - interval upper_interval = mean_skill + interval |
有一些其他可能比使用总体均值标准误差更具统计稳健性的方法来计算置信区间,例如:
神经网络有多不稳定?
这取决于您的问题、网络及其配置。
我建议执行敏感性分析来找出原因。
多次(30、100 或数千次)在相同数据集上评估同一模型,只改变随机数生成器的种子。
然后查看生成的技能得分的平均值和标准差。标准差(得分与平均得分的平均距离)将让您了解模型的که有多不稳定。
需要多少次重复?
我建议至少 30 次,也许 100 次,甚至数千次,仅受限于您的时间和计算机资源,以及边际效益递减(例如,mean_skill 的标准误差)。
更严谨地说,我建议进行一项实验,研究估计的模型技能与重复次数的影响以及标准误差的计算(平均估计性能与真实潜在总体均值的差异程度)。
进一步阅读
- 在机器学习中拥抱随机性
- 如何训练最终的机器学习模型
- 比较不同种类的交叉验证
- 人工智能的经验方法,Cohen,1995。
- 标准误差维基百科
总结
在这篇文章中,您了解了如何评估深度学习模型的技能。
具体来说,你学到了:
- 初学者在评估深度学习模型时常犯的错误。
- 使用重复的 k 折交叉验证来评估深度学习模型的原理。
- 如何计算相关的模型技能统计数据,例如标准差、标准误差和置信区间。
您对估计深度学习模型的技能有任何疑问吗?
在评论区发布您的问题,我会尽力回答。
在相同数据集上运行训练与通过多个 epoch 运行相同数据的训练有什么区别?
我能说通过深度学习的多个 epoch 数据与减少深度学习算法的随机性导致的变异性结果相同吗?
每个 epoch 都会更新网络权重。
通过所有 epoch 的每次运行都会产生不同的模型,因为初始随机条件不同。
这有帮助吗?
这对我很有帮助。我不知道为什么这些基本的东西在书籍和课程中没有得到更强调(甚至没有提到)。
谢谢,这可能也会有帮助
https://machinelearning.org.cn/difference-between-a-batch-and-an-epoch/
我在 ERP 咨询服务行业有扎实的背景,但过去几年我没有做过编程。我想知道如果我学习机器学习,我是否可以利用它来创办一家小型初创公司。
是的。考虑从 Weka 开始学习应用机器学习,而无需任何编程。
https://machinelearning.org.cn/start-here/#weka
非常感谢您的精彩文章。您介意我问三个问题吗?
1. 请问我们什么时候评估深度学习模型的技能?是在超参数调整之前还是在选定最佳模型之后?根据我的理解,我选择的是之后。如果我错了,请纠正我。
2. 对于深度学习来说,这是一个非常耗时的过程。如果我们必须进行 30 次,甚至 100 或 1000 次重复,这对于实际项目可行吗?
3. 如果最终模型是一个集成模型,包含几个不同的模型,我该如何评估模型的技能?
1. 评估任何情况下的技能。
2. 对于大型项目来说,这可能并不可行,使用检查点来保存训练过程中看到的“最佳”模型可能是一种更好的方法。
3. 理论上,可以使用相同的方法。
有点离题,但您认为深度学习泡沫什么时候会破裂?
当技术不再为企业普遍创造价值,或者从业者继续未能交付承诺的价值时。
嗨,Jason,
是否有选择重复次数的经验法则?我在这方面有点困惑,因为我的数据库很大,我的 CNN 网络有 500 个 epoch。
很好的问题。
您可以进行敏感性分析来找出得分中的方差以及重复次数的边际效益递减点。也许 30 次,也许 100 次。在我读研究生的时候,我们用了 1000 次。
谢谢 Jason。我会照做的。
此致
嗨,Jason,
假设在 k 折交叉验证运行后,标准差非常小,以至于我们可以说模型相对独立于给定数据上的数据划分。
是否仍有必要重复 k 折交叉验证 30 次以上?难道不能只进行一次 k 折交叉验证,如果它令人满意,然后进行 30 次以上的训练重复并对这些结果进行统计摘要吗?
在相同训练数据上运行 30 次将测量模型的随机属性。
在不同训练数据上运行 30 次将同时测量模型方差和随机属性。
Jason,在每次分割训练数据和测试数据时,相同的训练数据是否意味着我需要提供相同的 random_state?
您好 Qingyan…是的。您可以选择进行真正随机的分割或一致的分割。
您好 Jason。一如既往的好文章。我有一个问题,可能与此主题无关。我如何知道我的神经网络模型何时/可能会失败?有什么方法可以检查我的神经网络模型泛化得有多好吗?
k 折交叉验证分数旨在提供模型泛化到新数据的能力的 ধারণা。
这有帮助吗?
您好 Jason。精彩的文章!!
如果您不介意,我有几个问题……
1.当我更改训练模型的 random_state 值,例如 random_state(45) 或 random_state(32) 时,我的模型会给出不同的准确率?这是什么原因?
2. random_state 是否有最佳值?
3. random_seed 和 random_state 之间有区别吗?
感谢您的时间。
该算法是随机的,在此了解更多。
https://machinelearning.org.cn/randomness-in-machine-learning/
没有最佳随机种子,我们正在评估平均性能,在此了解更多关于随机数的信息。
https://machinelearning.org.cn/introduction-to-random-number-generators-for-machine-learning/
random_state/seed 是相同的。
嗨,Jason,
感谢这篇精彩的文章。
请告诉我我是否理解正确:当我重复评估实验时,我会在每次运行中随机分割数据,对吗?(与 k 折交叉验证不同,后者分割是固定的)。分割的百分比,例如 70% 的训练数据和 30% 的测试数据,是否取决于可用数据的量?
提前感谢您的回复。
此致,
大卫
是的。
好的!那么比较仅在训练数据上有所不同的两个深度卷积神经网络(例如数据增强与无数据增强)呢?您是否会运行每个算法几次,并对在数据的随机部分上确定的性能进行平均(作为测试集)?或者在每次运行时在同一保留的测试集上评估两个算法以确保公平比较是否重要?
再次感谢您的回答!
很好的问题。
需要使用相同的data split(训练/测试)来评估每个情况,尽管用于训练case的具体数据会因数据增强而不同。
对每个case在相同的数据split上重复评估将衡量模型在随机初始化/训练下的方差。
对每个case在不同但成对的split(为每个case使用相同的split)上重复评估将更广泛地衡量模型行为的方差——跨越特定的训练数据,我认为这正是您想达到的目标。
这有帮助吗?
是的,这很有帮助!非常感谢!
嗨,Jason,
几个问题
1) 在评估并获得平均性能后,我该如何选择最佳模型?这甚至是正确的问题吗?
2) 就像我们进行网格搜索可以得到“最佳”模型一样,有什么类似的吗?
3) 如果这不是我们要做的,我该如何在生产环境中进行?
4) 我可以 pickle 整个东西(.h5)吗?然后只用 predict() 来处理新值。
这适用于任何深度学习算法。我从未获得过一致的结果,我尝试了所有方法。
谢谢你,
Satish
选择最能满足项目/利益相关者目标的模型,例如,复杂度低且技能高。
您可以保存最终模型,这里有一个例子。
https://machinelearning.org.cn/save-load-keras-deep-learning-models/
这是一篇很棒的文章。我目前正在进行情感分析,并使用 LSTM 模型。数据严重不平衡,正类、负类和中性类的分布分别为 46%、45% 和 8.7%。所以,我的模型有点过拟合。我使用了最大句子长度 100,但实际长度是 5000(但如果我使用 5000 我会遇到内存问题)。您能给我一些建议吗?
也许可以尝试一个成本敏感模型。
https://machinelearning.org.cn/cost-sensitive-neural-network-for-imbalanced-classification/
您好 Jason,感谢您的见解。
有没有办法可视化我的神经网络在 kfold 交叉验证后的表现?也就是说,有没有办法在对神经网络应用 kfold 交叉验证后绘制学习曲线?
您可以使用 k 折交叉验证来估计模型性能。
您可以为每个 k 折计算学习曲线并将它们全部绘制在一起——我相信我在博客上有一些例子,例如:
https://machinelearning.org.cn/how-to-develop-a-cnn-from-scratch-for-fashion-mnist-clothing-classification/
嗨,Jason,
我想问一个非常具体的问题……我一直没有得到任何答案
我理解在机器学习中我们需要提取数据的特征以创建特征向量。这是一个艰难的过程,但它是必需的。
另一方面,深度学习会自动进行这种特征提取(它学习表示数据的最佳方式),然后它会进行“预测”。
然而,在网上检查我们所有的例子(特别是文档),我看到所有人都先应用机器学习过程,然后应用深度学习(这意味着去除停用词、词干提取、词形还原、分词、删除重复单词、词嵌入、独热编码等等)。
这是正确的吗……?我应该在训练前通过操纵数据来帮助深度学习,而不是使用原始数据吗?
这是个好习惯吗?
如果您能帮到我,我将不胜感激。
祝好
Carlos G
是的,减小 NLP 问题中的词汇量会使问题更简单、更容易建模——去除无关数据。
这可能需要也可能不需要,但在实践中,它有助于加快模型速度并提高性能。自己试试——带有和不带此类准备。
当然,感谢您的辛勤工作。
祝好
Carlos G.
不客气。
你好,
您提到了使用平均值和标准差来总结给定网络(即固定的网络类型、层数、层激活函数等)基于重复重新拟合网络的性能(使用相同的数据集)。我想深入研究一下汇总统计量的问题。
我的问题:您认为是否可以使用中位数和例如四分位距来代替平均值和标准差?
我之所以这么问,是因为我认为,总的来说,性能指标的分布在重复拟合网络时不会是正态的,所以平均值+标准差可能是错误的统计数据。
我特别对模型重新拟合次数在 100-300 次的范围内的案例感兴趣(这只是我正在面临的计算边界……),即使我们假设(非常粗略地说)中心极限定理适用于使用的性能指标,100-300 次也可能无法提供足够好的收敛。
无论如何,对于我正在处理的问题(这不一定具有普遍性……),中位数或平均值的用途似乎没有太大区别。
此致!
您好 Artur……以下资源可能对您感兴趣。
https://machinelearning.org.cn/regression-metrics-for-machine-learning/