首页 文章

在`r`的`插入符号'包中训练测试分裂

提问于
浏览
5

我已经熟悉了 rcaret 软件包,但是,来自其他编程语言,它让我很困惑 .

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

  • 采取训练集,在我的例子中是虹膜数据集

  • 将其拆分为训练和测试集(80-20分割)

  • 对于 1120 的每个 k ,训练训练集上的 k 最近邻分类器

  • 在测试集上测试它

我知道如何做第一部分,因为 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 执行:

  • test 获取一个bootstrap样本 .

  • 使用给定样本评估 k -nn方法的性能

我想要它做什么:

  • 对于每个 k ,训练模型 on the same train set which I constructed earlier

  • 在我之前构建的同一测试集上评估性能** .

所以我需要类似的东西

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"

这些似乎没有做我想做的事 .

2 回答

  • 8

    如果我正确地理解了这个问题,可以使用LGOCV(Leave-group-out-CV =重复训练/测试分割)并将训练百分比 p = 0.8 和训练百分比的重复分割为 number = 1 (如果你真的只想在测试集上测试每个 k 一个模型 . 设置 number > 1将重复评估 number 不同列车/测试拆分的模型性能 .

    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))
    

    如果 savePredictions = T ,则测试集上的不同模型所做的所有预测都在 mod$pred 中 . 注意 rowIndex :这些是已经采样到测试集中的行 . 对于 k 的所有不同值,它们是相等的,因此每次使用相同的训练/测试集 .

    > 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
    

    除非需要某种嵌套验证程序,否则无需在插入符之外手动构建训练/测试集 . 您还可以通过 plot(mod) 绘制 k 的不同值的验证曲线 .

  • 2

    请仔细阅读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)
    

    EDIT based on comment:

    一个火车对象无法实现您的目标 . Train将使用tunegrid找到最佳k并在finalModel中使用该结果 . 此finalModel将用于进行预测 .

    如果你想概述所有k,你可能不想使用插入符号的列车功能,但为自己编写一个功能 . 也许就像下面这样 . 请注意,knn3是来自插入符号的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将包含所有预测 .

相关问题