在Caret中进行5折交叉验证时,是否可以分别为每个折叠的训练集和测试集绘制ROC曲线?
library(caret)train_control <- trainControl(method="cv", number=5,savePredictions = TRUE,classProbs = TRUE)output <- train(Species~., data=iris, trControl=train_control, method="rf")
我可以执行以下操作,但不知道返回的是Fold1的训练集还是测试集的ROC曲线:
library(pROC) selectedIndices <- rfmodel$pred$Resample == "Fold1"plot.roc(rfmodel$pred$obs[selectedIndices],rfmodel$pred$setosa[selectedIndices])
回答:
确实,文档对于rfmodel$pred
的内容说明并不清晰——我猜测包含的预测是用于测试集的折叠,但我在文档中找不到任何证据;然而,无论如何,你在获取ROC曲线的方式上还有一些不足之处。
首先,让我们将rfmodel$pred
隔离到一个单独的数据框中,以便更容易处理:
dd <- rfmodel$prednrow(dd)# 450
为什么是450行?因为你尝试了3个不同的参数设置(在你的案例中只是mtry
的3个不同值):
rfmodel$results# output: mtry Accuracy Kappa AccuracySD KappaSD1 2 0.96 0.94 0.04346135 0.065192022 3 0.96 0.94 0.04346135 0.065192023 4 0.96 0.94 0.04346135 0.06519202
150行乘以3个设置等于450行。
让我们更仔细地查看rfmodel$pred
的内容:
head(dd)# result: pred obs setosa versicolor virginica rowIndex mtry Resample1 setosa setosa 1.000 0.000 0 2 2 Fold12 setosa setosa 1.000 0.000 0 3 2 Fold13 setosa setosa 1.000 0.000 0 6 2 Fold14 setosa setosa 0.998 0.002 0 24 2 Fold15 setosa setosa 1.000 0.000 0 33 2 Fold16 setosa setosa 1.000 0.000 0 38 2 Fold1
obs
列包含真实值setosa
、versicolor
和virginica
三列包含为每个类别计算的相应概率,每行总和为1pred
列包含最终预测,即上述三列中概率最大类的类别
如果这就是全部,那么你绘制ROC曲线的方式是可以的,即:
selectedIndices <- rfmodel$pred$Resample == "Fold1"plot.roc(rfmodel$pred$obs[selectedIndices],rfmodel$pred$setosa[selectedIndices])
但这不是全部(仅仅存在450行而不是150行就应该已经给出提示了):注意存在一个名为mtry
的列;实际上,rfmodel$pred
包括了交叉验证的所有运行结果(即所有参数设置):
tail(dd)# result: pred obs setosa versicolor virginica rowIndex mtry Resample445 virginica virginica 0 0.004 0.996 112 4 Fold5446 virginica virginica 0 0.000 1.000 113 4 Fold5447 virginica virginica 0 0.020 0.980 115 4 Fold5448 virginica virginica 0 0.000 1.000 118 4 Fold5449 virginica virginica 0 0.394 0.606 135 4 Fold5450 virginica virginica 0 0.000 1.000 140 4 Fold5
这就是为什么你的selectedIndices
计算不正确的最终原因;它还应该包括对mtry
的具体选择,否则ROC曲线毫无意义,因为它“聚合”了多个模型:
selectedIndices <- rfmodel$pred$Resample == "Fold1" & rfmodel$pred$mtry == 2
—
正如我一开始所说,我猜测rfmodel$pred
中的预测是用于测试集的折叠;实际上,如果我们手动计算准确率,它们与上面显示的rfmodel$results
中报告的准确率一致(所有3个设置均为0.96),我们知道这些是用于测试的折叠的准确率(可以说,相应的训练准确率为1.0):
for (i in 2:4) { # mtry values in {2, 3, 4}acc = (length(which(dd$pred == dd$obs & dd$mtry==i & dd$Resample=='Fold1'))/30 + length(which(dd$pred == dd$obs & dd$mtry==i & dd$Resample=='Fold2'))/30 + length(which(dd$pred == dd$obs & dd$mtry==i & dd$Resample=='Fold3'))/30 + length(which(dd$pred == dd$obs & dd$mtry==i & dd$Resample=='Fold4'))/30 + length(which(dd$pred == dd$obs & dd$mtry==i & dd$Resample=='Fold5'))/30)/5print(acc) }# result:[1] 0.96[1] 0.96[1] 0.96