对于预测建模,机器学习模型性能通常会随着数据集大小的增加而提高。
这取决于具体的数据集和模型的选择,尽管它通常意味着使用更多数据可以带来更好的性能,并且使用较小数据集进行的模型性能估计的发现通常可以扩展到使用较大的数据集。
问题在于,对于给定的数据集和模型,这种关系是未知的,并且对于某些数据集和模型可能不存在。此外,如果存在这种关系,可能会出现收益递减的点或多个点,此时添加更多数据可能不会提高模型性能,或者数据集太小而无法在更大规模上有效捕获模型的性能。
可以通过执行**敏感性分析**来解决这些问题,以量化数据集大小与模型性能之间的关系。一旦计算出来,我们就可以解释分析结果,并就多少数据足够,以及数据集有多小才能有效估计更大数据集上的性能做出决定。
在本教程中,您将了解如何执行数据集大小与模型性能的敏感性分析。
完成本教程后,您将了解:
- 为机器学习选择数据集大小是一个具有挑战性的开放性问题。
- 敏感性分析提供了一种方法,用于量化给定模型和预测问题的模型性能与数据集大小之间的关系。
- 如何执行数据集大小的敏感性分析并解释结果。
让我们开始吧。

数据集大小与模型性能的敏感性分析
照片作者:Graeme Churchard,部分权利保留。
教程概述
本教程分为三个部分;它们是:
- 数据集大小敏感性分析
- 合成预测任务和基线模型
- 数据集大小敏感性分析
数据集大小敏感性分析
机器学习预测模型所需的训练数据量是一个开放性问题。
这取决于您的模型选择、数据准备方式以及数据本身的具体情况。
有关选择训练数据集大小的挑战的更多信息,请参阅本教程
解决此问题的一种方法是执行敏感性分析,并发现您的模型在数据集上的性能如何随更多或更少的数据而变化。
这可能包括评估相同模型在不同大小的数据集上的性能,并寻找数据集大小与性能之间的关系或收益递减点。
通常,训练数据集大小与模型性能之间存在很强的关系,特别是对于非线性模型。这种关系通常涉及性能的提高到一定程度,以及随着数据集大小的增加,模型的预期方差普遍降低。
了解这种关系对于您的模型和数据集有很多好处,例如
- 评估更多模型。
- 找到更好的模型。
- 决定收集更多数据。
您可以在数据集的小样本上快速评估大量模型和模型配置,并确信性能可能以特定方式泛化到更大的训练数据集。
这可能允许您评估比您可能在可用时间内能够做到的更多的模型和配置,并可能发现一个整体性能更好的模型。
您还可以推广和估计模型性能在更大数据集上的预期性能,并估计收集更多训练数据的努力或成本是否值得。
现在我们熟悉了模型性能对数据集大小的敏感性分析的思想,让我们来看一个实际示例。
合成预测任务和基线模型
在进行敏感性分析之前,让我们为调查选择一个数据集和一个基线模型。
在本教程中,我们将使用一个合成二元(两类)分类数据集。这是理想的,因为它允许我们根据需要扩展生成样本的数量以解决相同的问题。
scikit-learn 的 make_classification() 函数 可用于创建合成分类数据集。在这种情况下,我们将使用 20 个输入特征(列)并生成 1,000 个样本(行)。伪随机数生成器的种子是固定的,以确保每次生成样本时都使用相同的基本“问题”。
下面的示例生成合成分类数据集并总结了生成数据的形状。
1 2 3 4 5 6 |
# 测试分类数据集 from sklearn.datasets import make_classification # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1) # 汇总数据集 print(X.shape, y.shape) |
运行示例生成数据并报告输入和输出组件的大小,确认了预期的形状。
1 |
(1000, 20) (1000,) |
接下来,我们可以在此数据集上评估预测模型。
我们将使用决策树(DecisionTreeClassifier)作为预测模型。选择它是因为它是一种非线性算法并且具有高方差,这意味着我们期望性能随着训练数据集大小的增加而提高。
我们将使用重复分层 k 折交叉验证的最佳实践来评估模型在数据集上的性能,其中包含 3 次重复和 10 折。
在合成分类数据集上评估决策树模型的完整示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 在合成分类数据集上评估决策树模型 from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.tree import DecisionTreeClassifier # 加载数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1) # 定义模型评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义模型 model = DecisionTreeClassifier() # 评估模型 scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # 报告表现 print('Mean Accuracy: %.3f (%.3f)' % (scores.mean(), scores.std())) |
运行示例会创建数据集,然后使用选定的测试框架估计模型在此问题上的性能。
注意:鉴于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到平均分类准确率约为 82.7%。
1 |
平均准确率:0.827 (0.042) |
接下来,让我们看看如何对模型性能进行数据集大小的敏感性分析。
数据集大小敏感性分析
上一节展示了如何评估所选模型在可用数据集上的性能。
这会引发一些问题,例如
模型在更多数据上表现会更好吗?
更广泛地说,我们可能有更复杂的问题,例如
估计的性能在问题域的较小或较大样本上是否仍然有效?
这些是难以回答的问题,但我们可以通过使用敏感性分析来解决它们。具体来说,我们可以使用敏感性分析来了解
模型性能对数据集大小有多敏感?
或者更普遍地
数据集大小与模型性能的关系是什么?
进行敏感性分析的方法有很多,但也许最简单的方法是定义一个测试框架来评估模型性能,然后在具有不同大小数据集的相同问题上评估同一模型。
这将允许训练和测试数据集部分随着整体数据集的大小而增加。
为了使代码更易于阅读,我们将将其分解为函数。
首先,我们可以定义一个函数来准备(或加载)给定大小的数据集。数据集中的行数由函数的参数指定。
如果您将此代码用作模板,则可以更改此函数以从文件中加载您的数据集并选择给定大小的随机样本。
1 2 3 4 5 |
# 加载数据集 def load_dataset(n_samples): # 定义数据集 X, y = make_classification(n_samples=int(n_samples), n_features=20, n_informative=15, n_redundant=5, random_state=1) return X, y |
接下来,我们需要一个函数来评估加载数据集上的模型。
我们将定义一个函数,该函数接收数据集并返回在数据集上使用测试框架评估的模型性能的摘要。
此函数列在下方,接收数据集的输入和输出元素,并返回决策树模型在数据集上的均值和标准差。
1 2 3 4 5 6 7 8 9 10 |
# 评估模型 def evaluate_model(X, y): # 定义模型评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义模型 model = DecisionTreeClassifier() # 评估模型 scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # 返回摘要统计数据 return [scores.mean(), scores.std()] |
接下来,我们可以定义一个要评估的不同数据集大小的范围。
大小的选择应与您拥有的数据量和愿意花费的运行时间成比例。
在这种情况下,我们将保持适中的大小以限制运行时间,从 50 到一百万行,大致呈 log10 尺度。
1 2 3 |
... # 定义要考虑的样本数量 sizes = [50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000] |
接下来,我们可以枚举每个数据集的大小,创建数据集,在数据集上评估模型,并将结果存储以供以后分析。
1 2 3 4 5 6 7 8 9 10 11 |
... # 评估每个样本数量 means, stds = list(), list() for n_samples in sizes: # 获取数据集 X, y = load_dataset(n_samples) # 在此数据集大小上评估模型 mean, std = evaluate_model(X, y) # 存储 means.append(mean) stds.append(std) |
接下来,我们可以总结数据集大小与模型性能之间的关系。
在这种情况下,我们将简单地绘制结果并带有误差条,以便我们可以直观地发现任何趋势。
我们将使用标准差作为估计模型性能的不确定性度量。这可以通过将值乘以 2 来实现,以覆盖约 95% 的预期性能(如果性能遵循正态分布)。
这可以在图中显示为估计模型性能平均值的误差条。
1 2 3 4 5 |
... # 定义误差条为均值或 95% 的 2 个标准差 err = [min(1, s * 2) for s in stds] # 绘制数据集大小与带误差线的平均性能 pyplot.errorbar(sizes, means, yerr=err, fmt='-o') |
为了使图形更具可读性,我们可以将 x 轴的比例更改为对数,因为我们的数据集大小大致呈 log10 尺度。
1 2 3 4 5 6 |
... # 将 x 轴的比例更改为对数 ax = pyplot.gca() ax.set_xscale("log", nonpositive='clip') # 显示绘图 pyplot.show() |
就是这样。
我们通常期望平均模型性能随数据集大小而提高。我们也期望模型性能的不确定性随数据集大小而降低。
将所有内容结合起来,执行数据集大小对模型性能敏感性分析的完整示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# 模型性能对数据集大小的敏感性分析 from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.tree import DecisionTreeClassifier from matplotlib import pyplot # 加载数据集 def load_dataset(n_samples): # 定义数据集 X, y = make_classification(n_samples=int(n_samples), n_features=20, n_informative=15, n_redundant=5, random_state=1) 返回 X, y # 评估模型 def evaluate_model(X, y): # 定义模型评估过程 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义模型 model = DecisionTreeClassifier() # 评估模型 scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # 返回摘要统计数据 return [scores.mean(), scores.std()] # 定义要考虑的样本数量 sizes = [50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000] # 评估每个样本数量 means, stds = list(), list() for n_samples in sizes: # 获取数据集 X, y = load_dataset(n_samples) # 在此数据集大小上评估模型 mean, std = evaluate_model(X, y) # 存储 means.append(mean) stds.append(std) # 总结性能 print('>%d: %.3f (%.3f)' % (n_samples, mean, std)) # 定义误差条为均值或 95% 的 2 个标准差 err = [min(1, s * 2) for s in stds] # 绘制数据集大小与带误差线的平均性能 pyplot.errorbar(sizes, means, yerr=err, fmt='-o') # 将 x 轴的比例更改为对数 ax = pyplot.gca() ax.set_xscale("log", nonpositive='clip') # 显示绘图 pyplot.show() |
运行示例会报告数据集大小与估计模型性能之间的进展状态。
注意:鉴于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到平均模型性能随数据集大小增加的预期趋势,以及模型方差(通过分类准确率的标准差衡量)的降低。
我们可以看到,在 10,000 或 50,000 行左右,估计模型性能可能存在一个收益递减点。
具体来说,我们确实看到了随着行数增加而带来的性能提升,但我们可能只需要 10K 或 50K 行数据就能以很小的方差捕捉到这种关系。
我们还可以看到估计性能在 1,000,000 行数据时有所下降,这表明我们可能在 100,000 行以上就达到了模型的极限,而实际上是在测量估计中的统计噪声。
这可能意味着预期性能的上限,并且很可能超过此点的数据不会改进特定模型以及在选定测试框架上的配置。
1 2 3 4 5 6 7 8 9 10 |
>50: 0.673 (0.141) >100: 0.703 (0.135) >500: 0.809 (0.055) >1000: 0.826 (0.044) >5000: 0.835 (0.016) >10000: 0.866 (0.011) >50000: 0.900 (0.005) >100000: 0.912 (0.003) >500000: 0.938 (0.001) >1000000: 0.936 (0.001) |
该图更清晰地展示了数据集大小与估计模型性能之间的关系。
与对数数据集大小相比,这种关系几乎是线性的。不确定性的变化(显示为误差条)也急剧减小,从 50 或 100 个样本的大值,到 5,000 和 10,000 个样本的适中值,并且在这些大小之后几乎消失。
鉴于 5,000 和 10,000 个样本的适度分布以及几乎呈对数线性关系,我们可能可以使用 5K 或 10K 行来近似模型性能。

数据集大小与模型性能的带误差线的折线图
我们可以将这些发现作为测试其他模型配置甚至不同模型类型的依据。
危险在于,不同的模型在数据量增减时可能会表现出截然不同的性能,因此最好使用不同的模型重复敏感性分析以确认关系是否成立。或者,使用一套不同的模型类型重复分析可能很有趣。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
教程
API
文章
总结
在本教程中,您了解了如何执行数据集大小与模型性能的敏感性分析。
具体来说,你学到了:
- 为机器学习选择数据集大小是一个具有挑战性的开放性问题。
- 敏感性分析提供了一种方法,用于量化给定模型和预测问题的模型性能与数据集大小之间的关系。
- 如何执行数据集大小的敏感性分析并解释结果。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
嗨,Jason
非常感谢您提供的精彩教程
我有 2 个问题,相关或不相关。
1- 我正在使用 cnn-lstm 模型对多通道脑电图信号进行分类。
我将脑电图片段转换为 2D 图像,然后使用一系列五个 2D 图像创建一个输入样本。
与我只接受 2D 图像的单个 cnn 模型相比,cnn-lstm 模型更复杂,并且输入更少。
但是,在我的案例中,cnn-lstm 网络的预测准确率高于 cnn 模型!使用更少的数据和更复杂的模型是否符合您的解释?
2- 我知道 keras datagenerator 只适用于图像。但我正在开发一个 cnn-lstm 模型,需要将图像序列作为样本(如视频)读取。我认为我需要编写类似 keras datagenerator 的东西来按我喜欢的方式读取图像,但不知道如何做到。你能帮我吗?(这个问题将我的数据集大小限制在我的 PC 的 RAM 大小)
不客气。
也许可以尝试处理数据的轨迹(数字)而不是图像?
您必须发现最适合您数据集的数据准备、模型和模型配置。对于每个数据集,它都会有所不同。
您可以实现自己的生成器,它会为模型生成一批数据。它只是一个 python 生成器——非常简单。我在博客上的图像字幕部分有示例。
感谢这篇文章!
线性模型的性能对数据大小有多敏感?
如果我考虑一个具有高方差的线性模型怎么办?
对于简单的线性回归模型,能否也用同样的方式进行此分析?我猜随机生成的数据集不能用于此。
不客气。
这取决于被建模问题的复杂性。简单的问题只需要少量数据,复杂的问题可能需要更多数据。
亲爱的 Jason,
感谢您有趣的指南。这可能是一个愚蠢的问题。但您能向我解释一下为什么准确率在数据集大小超过阈值时会下降吗?
这可能是均值中的统计噪声。
非常有见地和有用的文章。感谢您付出的努力和时间分享!
不客气。
感谢这篇文章。
我尝试将类似的代码实现到具有连续变量的数据集和随机森林回归器 API 上。但我遇到了以下错误。
支持的目标类型为:(“二进制”,“多类”)。得到的是“连续”。
您能帮我一下吗?
不客气。
尝试使用模型的回归版本而不是分类版本。
感谢您的快速回复。
我确实使用了回归版本。我首先使用了“from sklearn.ensemble import RandomForestRegressor”,但我不知道为什么又遇到了这个错误。
我估计当代码尝试通过此行评估分数时会出现错误
“scores = cross_val_score(model,X_train, y_train, scoring=’r2′, cv=cv, n_jobs=-1)”
当运行到此行时,错误就会出现。
您有什么建议吗?
也许您正在尝试使用“分层”版本的交叉验证?如果是这样,您不能将其用于回归。
谢谢 Jason,
是的,正是这样。
我还有另一个可能偏离主题的问题,但如果您能给我一些建议,我将非常感激。
我生成了一个包含 500,000 个样本的数据集,在运行算法、绘制学习曲线并进行本帖中解释的敏感性分析后,事实证明最佳样本数量约为 30,000-40,000。现在我想从我的原始数据集(500,000 个样本)中提取最佳的 30,000-40,000 个样本。我找到了一些用于图像相似性的方法,这些方法使用 MSE 和 SSI 函数。我想知道是否有类似的方法可以用于数值数据。
提前感谢。
我不太喜欢实例选择方法,至少在一般情况下是这样。我建议随机抽样。
您能提供 ANN 敏感性分析的代码吗?
您可以将上面的代码改编为您喜欢的任何模型。
另外,请参阅此处示例
https://machinelearning.org.cn/start-here/#better
布朗利教授您好,我有一个问题。我设计了一个依赖于统计检验的特征选择模型。我使用不同的分类器获得了具有高准确率的最优特征子集。您能告诉我如何对这些特征进行敏感性分析吗?我的意思是,我已经获得的最优子集。期待您的回复。
本教程详细描述了敏感性分析。您尝试了什么?
我尝试了不同的分类器来评估准确率,但我获得的最佳特征集,是否可以对这些少数特征与标签进行敏感性分析?
是的,当然可以。