如何评价深度学习模型的技能
我经常看到实践者对如何评估深度学习模型表示困惑。
这一点通常从像这样的问题中表现得很明显:
- 我应该使用什么随机种子?
- 我需要随机的种子吗?
- 为什么我在后续运行中得不到相同的结果?
在这篇文章中,你会发现你可以用来评估深度学习模型的程序,以及使用它的基本原理。
你还将发现有用的相关统计数据,你可以计算这些统计数据来展示模型的技能,例如标准偏差、标准误差和置信区间。
我们开始吧。
初学者的错误
你将模型与你的培训数据相匹配,并在测试数据集上对其进行评估,然后报告技能。
也许你使用k倍交叉验证来评估模型,然后报告模型的技巧。
这是初学者犯的错误。
看起来你在做正确的事情,但有一个关键问题你还没有考虑到:
深度学习模型是随机的。
人工神经网络在拟合数据集的同时使用随机性,例如随机初始权重和随机梯度下降过程中每个训练时段的数据随机洗牌。
这意味着,每次相同的模型适用于相同的数据,它可能会给出不同的预测,进而拥有不同的整体技能。
估算模型技能(控制模型差异)
我们没有所有可能的数据;如果有,我们就不需要做预测了。
我们有一个有限的数据样本,我们需要从这些数据中发现我们能找到的最佳模型。
使用训练-测试分离
为此,我们将数据分成两部分,在第一部分数据上拟合一个模型或特定的模型配置,并使用拟合模型对其余部分进行预测,然后评估这些预测的技巧。这被称为训练测试分离,我们使用这项技能来估计当模型对新数据进行预测时,我们认为模型在实践中的表现会有多好。
例如,下面是使用训练测试分离评估模型的一些伪代码:
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倍交叉验证评估模型的一些伪代码:
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)
技能分数总体更有用,因为我们可以取平均值并报告模型的平均预期性能,这可能更接近模型在实践中的实际性能。例如:
mean_skill = sum(scores) / count(scores)
我们还可以使用mean_skill计算标准差,以了解mean_skill周围分数的平均分布情况:
standard_deviation = sqrt(1/count(scores) * sum( (score - mean_skill)^2 ))
估计随机模型的技巧(控制模型稳定性)
随机模型,如深度神经网络,增加了额外的随机性来源。
这种额外的随机性使模型在学习时具有更大的灵活性,但可能会使模型不太稳定(例如,当相同的模型在相同的数据上训练时,结果不同)。
这与模型方差不同,模型方差在同一模型对不同数据进行训练时会产生不同的结果。
为了对随机模型的技巧有一个稳健的估计,我们必须考虑到这个额外的方差来源;我们必须对其进行控制。
固定随机种子
一种方法是每次模型拟合时使用相同的随机性。我们可以通过固定系统使用的随机数种子,然后评估或拟合模型来做到这一点。例如:
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)
当你的代码每次运行时都需要相同的结果时,这对于教程和演示非常有用。
这很脆弱,不建议用于评估模型。
请参见文章:
重复评价实验。
一种更稳健的方法是重复多次评估非随机模型的实验。
例如:
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可能有多错误)。
standard_error = standard_deviation / sqrt(count(scores))
此外,我们可以使用standard_error来计算mean_skill的置信区间。这假设结果的分布是高斯的,你可以通过查看直方图、Q-Q图或对收集到的分数进行统计测试来检查这一点。
例如,95%的间隔是(1.96*standard_error)在平均技能附近。
interval = standard_error * 1.96 lower_interval = mean_skill - interval upper_interval = mean_skill + interval
与使用总体平均值的标准误差相比,还有其他可能在统计上更稳健的方法来计算置信区间,例如:
神经网络有多不稳定?
这取决于你的问题、网络及其配置。
我建议做一个敏感性分析来找出答案。
对相同的数据多次评估相同的模型(30次、100次或数千次),并且只改变随机数生成器的种子。
然后检查产生的技能分数的平均值和标准差。标准差(分数与平均分数的平均距离)可以让你了解模型的不稳定程度。
重复几次?
我建议至少30个,也许100个,甚至数千个,只受你的时间和计算机资源的限制,并且回报递减(例如,Mean_Skill上的标准误差)。
更严格地说,我会推荐一个实验,看看对估计模型技能的影响与重复次数和标准误差的计算(平均估计性能与真正的潜在总体平均水平相差多少)。
进一步阅读。
摘要
在这篇文章中,你发现了如何评估深度学习模型的技能。
具体地说,你了解到:
- 初学者在评估深度学习模型时常犯的错误。
- 使用重复k倍交叉验证评估深度学习模型的基本原理。
- 如何计算相关的模型技能统计,如标准差、标准差和置信区间。