你如何有效地比较不同机器学习算法的估计准确度?
在这篇文章中,你将发现 8 种可以在 R 中比较机器学习算法的技术。
你可以使用这些技术选择最准确的模型,并能够评论其统计显著性以及它超越其他算法的绝对优势。
使用我的新书《R 语言机器学习精通》**启动你的项目**,其中包括**分步教程**和所有示例的**R 源代码**文件。
让我们开始吧。

在 R 中比较机器学习算法的性能
图片由 Matt Reinbold 提供,保留部分权利。
选择最佳机器学习模型
你如何为你的问题选择最佳模型?
在进行机器学习项目时,你通常会得到多个不错的模型可供选择。每个模型都将具有不同的性能特征。
使用交叉验证等重采样方法,你可以估算出每个模型在未见过的数据上的准确度。你需要能够利用这些估计值从你创建的模型套件中选择一两个最佳模型。
需要更多关于R机器学习的帮助吗?
参加我为期14天的免费电子邮件课程,了解如何在您的项目中使用R(附带示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
仔细比较机器学习模型
当你有一个新数据集时,最好使用多种不同的绘图技术来可视化数据,以便从不同角度审视数据。
同样的思想也适用于模型选择。你应该使用多种不同的方式来查看机器学习算法的估计准确度,以便选择一两个最终确定的算法。
你可以通过使用不同的可视化方法来显示模型准确度分布的平均准确度、方差和其他属性。
在下一节中,你将确切地了解如何在 R 中实现这一点。
在 R 中比较和选择机器学习模型
在本节中,你将了解如何在 R 中客观地比较机器学习模型。
通过本节中的案例研究,你将为 Pima 印第安人糖尿病数据集创建一些机器学习模型。然后,你将使用一套不同的可视化技术来比较模型的估计准确度。
本案例研究分为三个部分:
- 准备数据集。加载库和数据集,准备训练模型。
- 训练模型。在数据集上训练标准机器学习模型,准备评估。
- 比较模型。使用 8 种不同技术比较训练好的模型。
1. 准备数据集
本案例研究中使用的数据集是 Pima 印第安人糖尿病数据集,可在 UCI 机器学习存储库中获取。它也包含在 R 的 mlbench 包中。
这是一个二元分类问题,预测患者在未来 5 年内是否会患糖尿病。输入属性是数值型,描述了女性患者的医疗细节。
让我们为本案例研究加载库和数据集。
1 2 3 4 5 |
# 加载库 library(mlbench) library(caret) # 加载数据集 data(PimaIndiansDiabetes) |
2. 训练模型
在本节中,我们将训练 5 个机器学习模型,并将在下一节中进行比较。
我们将使用重复交叉验证,10 折和 3 次重复,这是比较模型的常见标准配置。评估指标是准确率和 Kappa,因为它们易于解释。
算法的选择是半随机的,以体现其表示和学习风格的多样性。它们包括:
- 分类与回归树
- 线性判别分析
- 带径向基函数的支持向量机
- k-近邻
- 随机森林
模型训练完成后,将它们添加到一个列表中,并对模型列表调用 `resamples()` 函数。此函数检查模型是否可比较,以及它们是否使用了相同的训练方案(`trainControl` 配置)。此对象包含每个算法在每个折叠和每次重复的评估指标。
下一节中使用的所有函数都期望一个包含这些数据的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 准备训练方案 control <- trainControl(method="repeatedcv", number=10, repeats=3) # CART set.seed(7) fit.cart <- train(diabetes~., data=PimaIndiansDiabetes, method="rpart", trControl=control) # LDA set.seed(7) fit.lda <- train(diabetes~., data=PimaIndiansDiabetes, method="lda", trControl=control) # SVM set.seed(7) fit.svm <- train(diabetes~., data=PimaIndiansDiabetes, method="svmRadial", trControl=control) # kNN set.seed(7) fit.knn <- train(diabetes~., data=PimaIndiansDiabetes, method="knn", trControl=control) # 随机森林 set.seed(7) fit.rf <- train(diabetes~., data=PimaIndiansDiabetes, method="rf", trControl=control) # 收集重采样结果 results <- resamples(list(CART=fit.cart, LDA=fit.lda, SVM=fit.svm, KNN=fit.knn, RF=fit.rf)) |
3. 比较模型
在本节中,我们将介绍 8 种不同的技术,用于比较构建模型的估计准确性。
表格摘要
这是最简单的比较方法,只需调用 `summary()` 函数并将重采样结果传递给它即可。它将创建一个表格,每行一个算法,每列一个评估指标。在这种情况下,我们已经排序。
1 2 |
# 总结模型之间的差异 summary(results) |
我发现查看平均值和最大值列很有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
准确度 最小值 1st Qu. 中位数 平均值 3rd Qu. 最大值 NA's CART 0.6234 0.7115 0.7403 0.7382 0.7760 0.8442 0 LDA 0.6711 0.7532 0.7662 0.7759 0.8052 0.8701 0 SVM 0.6711 0.7403 0.7582 0.7651 0.7890 0.8961 0 KNN 0.6184 0.6984 0.7321 0.7299 0.7532 0.8182 0 RF 0.6711 0.7273 0.7516 0.7617 0.7890 0.8571 0 Kappa 最小值 1st Qu. 中位数 平均值 3rd Qu. 最大值 NA's CART 0.1585 0.3296 0.3765 0.3934 0.4685 0.6393 0 LDA 0.2484 0.4196 0.4516 0.4801 0.5512 0.7048 0 SVM 0.2187 0.3889 0.4167 0.4520 0.5003 0.7638 0 KNN 0.1113 0.3228 0.3867 0.3819 0.4382 0.5867 0 RF 0.2624 0.3787 0.4516 0.4588 0.5193 0.6781 0 |
箱线图
这是一种查看不同方法的估计准确度分布及其相互关系的有用的方法。
1 2 3 |
# 箱线图比较模型 scales <- list(x=list(relation="free"), y=list(relation="free")) bwplot(results, scales=scales) |
请注意,这些箱子按平均准确度从高到低排序。我发现查看平均值(点)和箱子重叠部分(结果的中间 50%)很有用。

在 R 中比较机器学习算法的箱线图
密度图
你可以将模型准确度的分布显示为密度图。这是一种评估算法估计行为重叠的有用方法。
1 2 3 |
# 准确率密度图 scales <- list(x=list(relation="free"), y=list(relation="free")) densityplot(results, scales=scales, pch = "|") |
我喜欢观察峰值的差异以及分布的宽度或基部。

R 中机器学习算法的密度图比较
点图
这些图很有用,因为它们同时显示了平均估计准确度以及 95% 置信区间(例如,95% 的观测分数落入的范围)。
1 2 3 |
# 准确度点图 scales <- list(x=list(relation="free"), y=list(relation="free")) dotplot(results, scales=scales) |
我发现比较平均值并目测算法之间分布的重叠很有用。

R 中机器学习算法的点图比较
平行图
这是另一种查看数据的方式。它显示了每个交叉验证折叠的每次试验中,每个测试算法的表现。它可以帮助你了解那些对某个算法来说很困难的保留子集对其他算法的表现如何。
1 2 |
# 平行图比较模型 parallelplot(results) |
这可能有点难以解释。我倾向于认为这有助于思考如何在以后将不同的方法组合成集成预测(例如,堆叠),特别是当你看到相反方向的关联运动时。

R 中机器学习算法的平行图比较
散点图矩阵
这将为每个算法创建一个所有折叠-试验结果的散点图矩阵,并与其他所有算法的相同折叠-试验结果进行比较。所有配对都进行了比较。
1 2 |
# 预测的成对散点图以比较模型 splom(results) |
当考虑来自两种不同算法的预测是否相关时,这非常宝贵。如果它们弱相关,它们是组合成集成预测的良好候选者。
例如,通过目测图表,看起来 LDA 和 SVM 似乎高度相关,SVM 和 RF 也是如此。SVM 和 CART 看起来弱相关。

R 中机器学习算法的散点图矩阵
成对 XY 图
你可以使用 xyplot 放大两个机器学习算法的试验-折叠准确度的成对比较。
1 2 |
# xyplot 图比较模型 xyplot(results, models=c("LDA", "SVM")) |
在这种情况下,我们可以看到 LDA 和 SVM 模型似乎相关的准确性。

R 中机器学习算法的成对散点图
统计显著性检验
你可以计算不同机器学习算法之间度量分布差异的显著性。我们可以通过直接调用 `summary()` 函数来汇总结果。
1 2 3 4 |
# 模型预测的差异 diffs <- diff(results) # 总结成对比较的 p 值 summary(diffs) |
我们可以看到一个成对统计显著性分数的表格。表格的下三角显示了原假设(分布相同)的 p 值,越小越好。我们可以看到 CART 和 kNN 之间没有差异,我们也可以看到 LDA 和 SVM 的分布之间几乎没有差异。
表格的上三角显示了分布之间的估计差异。如果我们认为 LDA 是从前面的图表中看出的最准确模型,我们可以估算出它在绝对准确性方面比特定其他模型好多少。
这些分数可以帮助你对特定算法之间的准确性主张进行任何声明。
1 2 3 4 5 6 7 8 9 10 11 |
p 值调整:Bonferroni 上三角:差异估计值 下三角:H0: 差异 = 0 的 p 值 准确度 CART LDA SVM KNN RF CART -0.037759 -0.026908 0.008248 -0.023473 LDA 0.0050068 0.010851 0.046007 0.014286 SVM 0.0919580 0.3390336 0.035156 0.003435 KNN 1.0000000 1.218e-05 0.0007092 -0.031721 RF 0.1722106 0.1349151 1.0000000 0.0034441 |
一个好的建议是增加试验次数,以增加样本量,从而可能获得更精确的 p 值。你也可以绘制差异图,但我发现这些图远不如上面的摘要表格有用。
总结
在这篇文章中,你发现了 8 种不同的技术,可以用来比较 R 中机器学习模型的估计准确度。
你发现的 8 种技术是:
- 表格摘要
- 箱线图
- 密度图
- 点图
- 平行图
- 散点图矩阵
- 成对 XY 图
- 统计显著性检验
我是否遗漏了你最喜欢的比较 R 中机器学习算法估计准确度的方法之一?请留言,我很乐意听取你的意见!
下一步
您是否尝试过这些食谱?
- 启动您的 R 交互式环境。
- 键入或复制粘贴上述食谱并进行尝试。
- 使用 R 中的内置帮助来了解有关所用函数的更多信息。
您有问题吗?在评论中提问,我将尽力回答。
请将神经网络(MLP)也加入其中。
你可以修改上面的例子,并添加一个神经网络。
你可以在这篇文章中找到 R 中神经网络的代码
https://machinelearning.org.cn/non-linear-classification-in-r/
你好,Jason。
你能告诉我如何解释这些模型的统计显著性检验吗?我无法理解。非常感谢你。
Jimmy
你好 Jimmy,
你可以使用测试来指示两组结果之间的差异是否显著。如果是这样,你就可以开始声称 A 优于 B。
希望这能有所帮助。
如果你像本例中那样使用重复交叉验证,则预测结果不是相互独立的。增加重复次数会人为地增加样本量。
是的,如果你想对结果进行统计,你需要修正自由度。
这个可能会有帮助
https://machinelearning.org.cn/statistical-significance-tests-for-comparing-machine-learning-algorithms/
当我执行上述代码时,我没有得到准确率和 kappa 值。我得到了 RMSE 和平方值。我想做分类而不是回归。请帮助我解决这个问题。
警告信息
在 `train.default(traindata, trainclass, method = "knn", tunelength = 2,`
你正在尝试进行回归,并且你的结果只有两个可能的值。你是否想进行分类?如果是这样,请使用一个具有 2 个水平的因子作为你的结果列。
你需要将输出变量转换为因子。
使用 `as.factor()`
更多信息在这里
https://stat.ethz.ch/R-manual/R-devel/library/base/html/factor.html
非常感谢你,JASON BROWNLEE
不客气!
在散点图矩阵部分,我无法理解这句话:
“当考虑来自两种不同算法的预测是否相关时,这非常宝贵。如果它们弱相关,它们是组合成集成预测的良好候选者。”
这意味着弱相关是好的吗???
结果是,我必须选择一两个算法来选择合适的算法。
那么……在散点图矩阵中,如何判断呢?
祝你有美好的一天!
如果你想将两个模型组合成一个模型集成,弱相关的预测是好的。
嗨,Jason
SVM 是否需要对数据进行缩放,然后将其重新转换为原始数据以用于随机森林?
模型之间的比较在统计显著性方面会相同吗?
谢谢!🙂
不,不需要,只要所有预测都在同一尺度上,这样分数才能进行同类比较。
这里我们比较的是训练数据的准确性。如何使用测试集进行预测?
你好,先生,
我们不能根据它们的 RMSE 值来比较这些算法吗?
RMSE 值最低的将被认为是最佳算法。
您的帮助将不胜感激!
在这种情况下,我们正在处理一个分类数据集,因此 RMSE 没有意义。我们改用准确度。
嗨,Jason,
我喜欢你的平行图和密度图。但是,你没有为模型提供图例,因此很难解释这些图表。
在我看来,提供它会非常有帮助
感谢您的建议。
嗨,Jason,
首先,感谢这篇精彩而详细的文章。
我正在尝试运行一个函数,该函数接受原始形式的预测变量矩阵,并输出一个预测值向量。(例如,Boston 数据集)。到目前为止,在对每个模型执行 summary 函数之后,我根据 summary() 选择了最佳模型。我正在尝试编写一个函数来执行此操作。
提前感谢!
Karen
听起来很棒,我不确定你具体想问我什么。
出色的教程,我关注你的所有工作!一个问题是,如果每次执行模型时都有不同的种子,这似乎会使模型之间的比较不恰当。基本上,结果与你使用种子 7 得到的结果相似,但至少有一两个图表看起来非常不同。你能评论一下种子的影响吗?
是的,我在这里有更详细的解释
https://machinelearning.org.cn/faq/single-faq/what-value-should-i-set-for-the-random-number-seed
解决方案是使用重复交叉验证进行模型评估。
嗨,Jason,
感谢这些有用的信息,
这里有一个小问题,我可以在 Python 中重复“统计显著性检验”这个主题吗?
我想在 Bonferroni 调整后计算每个模型之间的 p 值,
Python 中是否有合适的包或函数来解决这个问题?
是的,statsmodels 有许多测试,也许可以从这里开始
https://machinelearning.org.cn/statistical-significance-tests-for-comparing-machine-learning-algorithms/
然后这里
https://machinelearning.org.cn/parametric-statistical-significance-tests-in-python/
我正在尝试将此推广到另一个数据集。我在这行卡住了
fit.rf <- train(diabetes~., data=PimaIndiansDiabetes, method="rf", trControl=control)
1. diabetes 变量从何而来,它是什么?
2. 在此实例中,~ 和 . 运算符/变量的作用是什么?
3. control 变量从何而来,它是什么?
4. trControl=control 的含义是什么?
这是一个已加载的数据集。
有关公式符号的更多信息,请参阅此处
https://www.datacamp.com/community/tutorials/r-formula-tutorial#using
我们定义了控制变量。
我们正在为我们的变量指定参数。
我仍在努力理解这篇文章。
结果表明,`~.` 字符是一个组合运算符,它会生成一个排除运算符之前命名列的数据框……
尽管如此,我仍然不确定你生成/使用 `results` 变量的统计方法。看起来你正在结合交叉验证和重采样。我不确定我是否理解你在这里想做什么,并且理解所有剩余的可视化都取决于这种理解。
你能更详细地解释一下你在开头关于拟合/采样/交叉验证的决定吗?
你是如何从 `resamples` 函数中获得准确性和 Kappa 值的?
我阅读了 `train` 函数的文档,但我仍然不理解你在这里所做的事情。
感谢您的帮助!
不客气。
k 折交叉验证是一种重采样方法,你可以在这里了解它如何工作以及我们为何使用它
https://machinelearning.org.cn/k-fold-cross-validation/
在本教程中,我们使用 10 折交叉验证,并将此过程重复 3 次以获得均值的均值。在使用 k 折交叉验证时,重复该过程以减少结果的方差是一个很好的实践。
希望这能有所帮助。
哈哈!我感觉每个答案都让我更困惑了。😀
如果我们进行10折交叉验证并重复3次,怎么会有一个5x5的准确率图网格呢?准确率图的单元格对应什么?
所有算法都使用相同的数据分割,因此我们可以绘制每个算法在每个数据分割(测试集)上的准确率,并查看它们的相关性。
每个图都是两个算法的成对比较。
这在考虑将哪些方法组合成一个集成模型时很有用。
布朗利博士您好,
您是否有机会将类似的方法应用于连续的因变量?如果可以,请分享您的发现。
谢谢你
我不记得了,抱歉。
您是否使用所有数据来训练模型?有没有办法将数据分成训练集/测试集?并比较模型在测试数据上的性能?
不,模型通常在训练集上训练,并在测试集上评估。
我建议使用交叉验证来创建多个分割,在此处了解更多信息
https://machinelearning.org.cn/k-fold-cross-validation/
尊敬的教授
这个项目对我很有帮助。但我需要知道
1. 如何获取从模型生成的值。
2. 如何绘制应用于糖尿病数据集的不同机器学习算法的准确率和错误率比较图
糖尿病数据集
再次感谢
Dilshad
我相信您可以调用模型的 predict() 函数。
上面的教程向您展示了如何比较算法,您可以将其应用于您喜欢的任何数据集。
感谢您发布有用的示例代码!
我想知道您如何(以何种比例)分割数据集的训练集和测试集?
您的代码中是否有办法调整此设置?
这是 caret 中的 trainControl() 函数。它设置了 number=10,所以它是10折(即总样本的1/10作为测试集)。您可以将其更改为4折,例如。
我发现它对我的情况很有用,因为我有不平衡数据(稀有事件类别),我正在寻求比较以下模型的性能:LR、DT、RF、KNN和SVM(这些是我从在线资源中推荐用于稀有事件的模型)。在这种情况下,我的目标是为我的特征选择(特征重要性)选择最佳模型,以用于我即将进行的模型拟合。因此,我需要相同的R代码用于交叉验证和预测模型,以及AUC和ROC作为性能度量(您已经提供了模型训练的代码)。提前感谢!
你好 Getahun…你可能会发现以下资源很有趣。
https://www.statology.org/k-fold-cross-validation-in-r/
谢谢,James Carmichael:我需要更多关于这些模型的预测和性能评估(AUC和ROC)的内容(所有设置在一起)。
你好。我想比较一些ML算法用于模拟数据。我应该如何编写代码?我为 Rasch 模型生成了数据。
你好 genius…以下资源可能对您有用
https://machinelearning.org.cn/compare-the-performance-of-machine-learning-algorithms-in-r/