如何使用R中的k倍CV手动对数据进行训练?

时间:2019-06-27 17:18:35

标签: r machine-learning cross-validation r-caret

我有以下适用于我的代码段,我得到了模型结果:

library(base)
library(caret)
library(tidyverse)

dataset <- read_csv("https://gist.githubusercontent.com/dmpe/bfe07a29c7fc1e3a70d0522956d8e4a9/raw/7ea71f7432302bb78e58348fede926142ade6992/pima-indians-diabetes.csv", col_names=FALSE)
X = dataset[, 1:8]
Y = as.factor(ifelse(dataset$X9 == 1, 'diabetes', 'nondiabetes'))

set.seed(88)

nfolds <- 3
cvIndex <- createFolds(Y, nfolds, returnTrain = T)

fit.control <- trainControl(method="cv",
                            index=cvIndex,
                            number=nfolds,
                            classProbs=TRUE,
                            savePredictions=TRUE,
                            verboseIter=TRUE,
                            summaryFunction=twoClassSummary,
                            allowParallel=FALSE)

model <- caret::train(X, Y,
                      method = "svmLinear",
                      trControl = fit.control,
                      preProcess=c("center","scale"),
                      tuneLength=10)

使用它我可以以model$finalModel的形式访问最终模型,但是,在这种情况下,我实际上希望拥有3个模型,而不是拥有一个最终模型,因为我拥有3折。因此,我想在第一折之后,第二折之后,第三折之后得到训练后的模型,这与实际的最终模型相对应。有什么想法如何在R中实现这一目标?请注意,caret的使用并不严格,如果可以使用mlr也可以使用。

3 个答案:

答案 0 :(得分:1)

插入符号中的训练功能简化了模型评估和训练 https://cran.r-project.org/web/packages/caret/vignettes/caret.html

”,通过重采样评估模型调整参数对性能的影响 在这些参数中选择“最佳”模型 从训练集中估计模型性能”

因此,它提供的模型是最佳的最终模型。 没有理由使用每次折叠训练的模型。我不知道如何在R

中执行此操作

答案 1 :(得分:0)

既不是插入符号也不是机器学习专家,但是为什么不只是对随机样本训练模型并将结果存储在列表中呢?

   data <- read_csv("https://gist.githubusercontent.com/dmpe/bfe07a29c7fc1e3a70d0522956d8e4a9/raw/7ea71f7432302bb78e58348fede926142ade6992/pima-indians-diabetes.csv", col_names=FALSE)

    train_multiple_models <- function(data, kfolds) {
        resultlist <- list()
        for(i in 1:kfolds) {

            sample <- sample.int(n = nrow(data), size = floor(.75*nrow(data)), replace = F)
            train <- data[sample, ]

            X = train[, 1:8]
            Y = as.factor(ifelse(train$X9 == 1, 'diabetes', 'nondiabetes'))

            model <- caret::train(X, Y,
                                  method = "svmLinear",
                                  preProcess=c("center","scale"),
                                  tuneLength=10)
            resultlist[[i]] <- model
        }
        return(resultlist)
    }

    result <- train_multiple_models(data, kfolds = 3)


    > result[[1]]$finalModel
    Support Vector Machine object of class "ksvm" 

    SV type: C-svc  (classification) 
     parameter : cost C = 1 

    Linear (vanilla) kernel function. 

    Number of Support Vectors : 307 

    Objective Function Value : -302.065 
    Training error : 0.230903 

答案 2 :(得分:0)

以下是使用mlr软件包的方法:

library(mlr)
library(base)
library(tidyverse)

dataset <- read_csv("https://gist.githubusercontent.com/dmpe/bfe07a29c7fc1e3a70d0522956d8e4a9/raw/7ea71f7432302bb78e58348fede926142ade6992/pima-indians-diabetes.csv", col_names=FALSE)
X = dataset[, 1:8]
Y = as.factor(ifelse(dataset$X9 == 1, 'diabetes', 'nondiabetes'))

创建mlr任务:

mlr_task <-  makeClassifTask(data = data.frame(X, Y),
                             target = "Y",
                             positive = "diabetes")

定义重采样:

set.seed(7)

cv3 <- makeResampleInstance(makeResampleDesc("CV", iters = 3),
                            task = mlr_task)

定义超参数搜索的类型

ctrl <- makeTuneControlRandom(maxit = 10L)

定义学习者

lrn <- makeLearner("classif.ksvm", predict.type = "prob")

(可选)检查学习者参数以查看需要调整的参数

mlr::getLearnerParamSet(lrn)

定义搜索空间(vanerndot是kernlab软件包中的线性内核,在内部被“ classif.ksvm”调用)。有关mlr中的集成学习器的更多信息:https://mlr.mlr-org.com/articles/tutorial/integrated_learners.html

ps <- makeParamSet(makeDiscreteParam("kernel", "vanilladot"),
                   makeNumericParam("C", lower = 2e-6, upper = 2e-6))

调整超级参数。我只是设置了一些随机指标,列出的第一个指标用于评估效果,其他指标只是为了展示效果。

res <- tuneParams(lrn,
                  mlr_task,
                  cv3,
                  measures = list(auc, bac, f1),
                  par.set = ps,
                  control = ctrl)

为学习者设置最佳超参数

lrn <- setHyperPars(lrn, par.vals = res$x)

models = TRUE

重新采样
rsmpls <- resample(lrn,
                   mlr_task,
                   cv3,
                   measures = list(auc, bac, f1),
                   models = TRUE)

模型在

rsmpls$models[[1]]$learner.model  
rsmpls$models[[2]]$learner.model  
rsmpls$models[[3]]$learner.model  

这是什么,它首先调整超级参数,然后在相同的折叠上对调整后的参数执行另一组交叉验证。

一种替代方法,在我看来,一种更好的方法是在嵌套交叉验证的内部折叠中选择超参数,并在外部折叠上进行评估,以使外部折叠模型不易摆弄。

lrn <- makeLearner("classif.ksvm", predict.type = "prob")

定义内部重采样策略

cv3_inner <- makeResampleDesc("CV", iters = 3)

创建一个音乐包装器-定义内部交叉验证循环中发生的事情

lrn <- makeTuneWrapper(lrn,
                       resampling = cv3_inner,
                       measures = list(auc, bac, f1),
                       par.set = ps,
                       control = ctrl)

执行外部交叉验证

rsmpls <- resample(lrn,
                   mlr_task,
                   cv3,
                   measures = list(auc, bac, f1),
                   models = TRUE)

这将在外部循环中执行三倍CV,在每个训练实例中又执行一次三倍CV以调整超参数,并且模型在具有最佳超参数的整个训练实例上拟合,这些模型在外循环测试实例。这样做是为了减少评估偏差。另请参阅:https://mlr.mlr-org.com/articles/tutorial/nested_resampling.html