在 r 的 caret 包中训练测试拆分

Train test split in `r`'s `caret` package

我越来越熟悉 rcaret 包,但是,来自其他编程语言,它让我很困惑。

我现在要做的是一个相当简单的机器学习工作流程,即:

  1. 获取一个训练集,在我的例子中是鸢尾花数据集
  2. 将其分成训练集和测试集(80-20 分割)
  3. 对于从120的每个k,在训练集
  4. 上训练k最近邻分类器
  5. 在测试集上测试

我知道如何做第一部分,因为 iris 已经加载了。然后,第二部分通过调用

完成
a <- createDataPartition(iris$Species, list=FALSE)
training <- iris[a,]
test <- iris[-a,]

现在,我也知道我可以通过调用

来训练模型
library(caret)
knnFit <- train()
knnFit <- train(Species~., data=training, method="knn")

但是,这将导致 r 已经对参数 k 执行了一些优化。当然,我可以限制方法应该尝试的 k 的值,比如

knnFit <- train(Species~., data=training, method="knn", tuneGrid=data.frame(k=1:20))

效果很好,但仍然不完全符合我的要求。此代码现在将对每个 k:

  1. test 中提取 bootstrap 个样本。
  2. 使用给定样本
  3. 评估k-nn方法的性能

我想要它做什么:

  1. 对于每个 k,在我之前构建的相同训练集上训练模型
  2. 在我之前构建的同一测试集上评估性能**。

所以我需要像

这样的东西
knnFit <- train(Species~., training_data=training, test_data=test, method="knn", tuneGrid=data.frame(k=1:20))

但这当然不行。

我知道我应该用 trainControl 参数做一些事情,但我看到它可能的方法是:

"boot", "boot632", "cv", "repeatedcv", "LOOCV", "LGOCV", "none"

和 none 似乎符合我的要求。

请通读 caret website 以了解一切如何运作。或者阅读 Max Kuhn 撰写的 "Applied Predictive Modeling" 一书,了解有关插入符工作原理的更多信息。

粗略地说,trainControl 包含一组不同的训练函数参数,例如交叉验证设置、要应用的指标(ROC/RMSE)、采样、预处理等。

在火车中,您可以设置其他设置,例如网格搜索。我扩展了您的代码示例,因此它可以正常工作。确保检查 createDataPartition 是如何工作的,因为默认设置将数据分成两半。

library(caret)

a <- createDataPartition(iris$Species, p = 0.8, list=FALSE)
training <- iris[a,]
test <- iris[-a,]

knnFit <- train(Species ~ ., 
                data = training, 
                method="knn",  
                tuneGrid=data.frame(k=1:20))

knn_pred <- predict(knnFit, newdata = test)

根据评论进行编辑:

一个火车对象无法满足您的需求。 Train 将使用 tunegrid 找到最佳 k 并在最终模型中使用该结果。这个 finalModel 将用于进行预测。

如果您想了解所有 k 的概况,您可能不想使用 caret 的 train 函数,而是自己编写一个函数。也许像下面这样。请注意,knn3 是来自 caret 的 knn 模型。

k <- 20
knn_fit_list <- list()
knn_pred_list <- list()

for (i in 1:k) {
  knn_fit_list[[i]] <- knn3(Species ~ ., 
                            data = training, 
                            k = i)
  knn_pred_list[[i]] <- predict(knn_fit_list[[i]], newdata = test, type = "class")

}

knn_fit_list 将包含指定数量 k 的所有拟合模型。 knn_pred_list 将包含所有预测。

如果我对问题的理解正确,可以使用 LGOCV(Leave-group-out-CV = repeated train/test split)并设置训练百分比 p = 0.8 和如果您真的想要在测试集上测试的每个 k 只适合一个模型,则将 train/test 重复拆分为 number = 1。设置 number > 1 将重复评估 number 不同 train/test 拆分的模型性能。

data(iris)
library(caret)
set.seed(123)
mod <- train(Species ~ ., data = iris, method = "knn", 
             tuneGrid = expand.grid(k=1:20),
             trControl = trainControl(method = "LGOCV", p = 0.8, number = 1,
                                      savePredictions = T))

不同模型在测试集上做出的所有预测都在 mod$pred if savePredictions = T 中。注意 rowIndex:这些是已采样到测试集中的行。这些对于 k 的所有不同值都是相等的,因此每次都使用相同的 training/test 集。

> head(mod$pred)
    pred    obs rowIndex k  Resample
1 setosa setosa        5 1 Resample1
2 setosa setosa        6 1 Resample1
3 setosa setosa       10 1 Resample1
4 setosa setosa       12 1 Resample1
5 setosa setosa       16 1 Resample1
6 setosa setosa       17 1 Resample1
> tail(mod$pred)
         pred       obs rowIndex  k  Resample
595 virginica virginica      130 20 Resample1
596 virginica virginica      131 20 Resample1
597 virginica virginica      135 20 Resample1
598 virginica virginica      137 20 Resample1
599 virginica virginica      145 20 Resample1
600 virginica virginica      148 20 Resample1 

除非需要某种嵌套的验证程序,否则无需在插入符之外手动构造 train/test 集。您还可以通过 plot(mod).

k 的不同值绘制验证曲线