【问题标题】:How to perform k-fold CV in R?如何在 R 中执行 k-fold CV?
【发布时间】:2019-11-09 11:25:58
【问题描述】:

我有一个 Python 代码,可以很好地在数据集上执行 k-fold CV。我的 Python 代码如下所示:

import pandas
import numpy as np
from sklearn.model_selection import KFold
from sklearn.preprocessing import MinMaxScaler
from sklearn.svm import SVR
from sklearn.utils import shuffle

# Load the dataset.
dataset = pandas.read_csv('values.csv')

# Preprocessing the dataset.
X = dataset.iloc[:, 0:8] 
Y = dataset.iloc[:, 8]   # The class value is the last column and is called Outcome.

# Scale all values to 0,1.
scaler = MinMaxScaler(feature_range=(0, 1))
X = scaler.fit_transform(X)

# 3-fold CV computation.
scores = []
svr_rbf = SVR(kernel='rbf', gamma='auto')

cv = KFold(n_splits=3, random_state=42, shuffle=False)
for train_index, test_index in cv.split(X):
    X_train, X_test = X[train_index], X[test_index]
    Y_train, Y_test = Y[train_index], Y[test_index]

    svr_rbf.fit(X_train, Y_train)
    scores.append(svr_rbf.score(X_test, Y_test))

现在,我想用 R 重写同样的东西,我尝试做这样的事情:

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

dataset <- read_csv("values.csv", col_names=TRUE)

results <- train(Outcome~.,
                 data=dataset,
                 method="smvLinear",
                 trControl=trainControl(
                   method="cv",
                   number=3,
                   savePredictions=TRUE,
                   verboseIter=TRUE
                 ))
print(results)
print(results$pred)

我的数据和这个类似:https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.data 除了这个有 12 个属性,第 13 列是类,在我的例子中,有 8 个属性,第 9 个是类。但是,就价值而言,它是相似的。

现在,我可以看到打印的结果,但是有一些我不清楚的地方。

1) 在我的 Python 代码中,我对值进行了这种缩放,我如何在 R 中做到这一点?

2) 我已经使用带有rbf 内核的 SVR,如何在 R 中使用带有该内核的 SVR 而不是 SMV?

3) 另外,在 Python 版本中,我使用 random_state=42(只是一个随机数)来生成折叠的拆分,因此它使用不同的折叠。但它在不同的执行过程中是一致的。如何在 R 中做到这一点?

4) 最后,在 Python 中,我在每个折叠的 for 循环中进行训练。我在 R 中也需要这样的东西,因为每次折叠后,我都想执行一些其他的统计和计算。在 R 中如何做到这一点?

5) 我应该坚持使用caret 还是使用mlr 包? mlr 也做 k 折简历吗?如果是怎么办?

编辑:

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

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

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)

rfCaret <- caret::train(X, Y, method = "svmLinear", trControl = fit.control)
print(rfCaret)

【问题讨论】:

    标签: python r machine-learning r-caret


    【解决方案1】:

    查看caret 包中的createFolds 以获得固定折叠。

    这里有一些代码可以修改以适合您的特定建模案例;此示例将构建一个随机森林模型,但您可以将模型切换为 SVM。如果您遵循包指南,则有一个链接(为方便起见,在此处复制:http://topepo.github.io/caret/train-models-by-tag.html#support-vector-machines)-第 7.0.47 节列出了所有可用的 SVM 模型及其参数。请注意,您可能需要安装一些额外的包,例如 kernlab,使用特定的模型。

    有一个名为 rngtools 的包应该允许您跨多个内核创建可重现的模型(并行处理),但如果您想确定,那么根据我的经验,单核可能是最好的方法。

    folds <- 3
    set.seed(42)
    cvIndex <- createFolds(your_data, folds, returnTrain = T)
    
    fit.control <- trainControl(method = "cv",
                                index = cvIndex,
                                number = folds,
                                classProbs = TRUE, 
                                summaryFunction = twoClassSummary,
                                allowParallel = FALSE)
    
    search.grid <- expand.grid(.mtry = c(seq.int(1:sqrt(length(your_data)))+1))
    
    rfCaret <- train(your_data_x, your_data_y, method = "rf", 
                         metric = 'ROC', ntree = 500,
                         trControl = fit.control, tuneGrid = search.grid,
    )
    

    根据我的经验,插入符号非常适合覆盖几乎所有基础。如果您还想预处理您的数据(例如中心、比例) - 那么您需要函数 preProcess - 再次,如果您键入 ?train 则在插入符号包中提供详细信息 - 但例如您想要

    preProcess(yourData, method = c("center", "scale"))
    

    Caret 的聪明之处在于它可以了解是否接受了预处理输入,并将相同的缩放比例应用于您的测试数据集。

    编辑 - 附加:未使用的参数问题 要回答有关未使用参数的后续问题 - 这可能是因为您使用的是随机森林参数 mtry。

    这是一个简单 SVM 的版本:

    folds <- 3
    set.seed(42)
    cvIndex <- createFolds(dataset$Outcome, folds, returnTrain = T)
    
    fit.control <- trainControl(method = "cv",
                                index = cvIndex,
                                number = folds,
                                classProbs = TRUE, 
                                summaryFunction = twoClassSummary,
                                allowParallel = FALSE)
    
    
    SVMCaret <- train(Outcome ~ ., data = dataset, method = "svmLinear", 
                     metric = 'ROC', 
                     trControl = fit.control)
    

    您不需要调整网格; Caret 会随机生成一个。当然,如果您想测试特定的成本值,请自行创建一个,就像我为 randomForests 的 .mtry 参数所做的那样。

    【讨论】:

    • 感谢您的回答。 search.grid 的目的是什么?另外,我看到了preProcess,但我不清楚如何像在 Python 中那样将数据集中的所有值缩放为 0-1。
    • 还要检查我编辑的代码,cvIndex 在我的情况下打印介于 1 到 8 之间的值,因为我有那么多列,而我有超过 700 行。我希望它选择行作为索引,就像 Python 中发生的那样。
    • 使用您的 SVM,您可能希望使用不同的参数来优化算法 - 例如成本价值。搜索网格将导致插入符号针对每个成本值运行多次,对其进行评估(例如,针对 ROC 分数、Kappa 或准确性) - 然后返回这些模型的分数并记录最佳分数。 preProcess 函数具有“rangeBounds” - 所以使用 scale 参数以及 rangeBounds (0,1)。
    • 我不知道为什么在 R 中实现这一点看起来如此复杂,而 Python 似乎很容易处理它。给出两个列表,其中包括用于训练的索引列表和用于测试的其他列表,我可以根据我的 X 和 Y 拟合,然后进行测试。
    • 我不确定是不是。 Caret 是一个如此深入的包,您几乎可以使用 set.seed() 中的循环然后训练函数来完成您尝试执行的所有操作,并且生成的对象具有您需要的详细信息。 CreateFolds 为您提供了一个可以引用的显式对象。我添加的代码为您提供了极大的灵活性来指定模型、调整参数(如 gamma)、指定所需的模型类型(回归与分类)、调整指标(例如 ROC/AUC、Kappa 等)。这一切都包含大约 4-5 行代码。也许玩一下它,看看你会得到什么?
    【解决方案2】:

    1) caret::train 函数有一个 preProcess 参数,允许您选择预处理。详情请见?caret::train

    2) svmRadial 可用于caret。您可以在 caret/train-models-by-tag 查看示例和所有可用算法。

    3) 使用set.seed(123) 修复随机种子以保持一致性。您可以访问 train 对象中的训练折叠(results$trainingData 此处)。

    4) 不要循环,直接通过您的 train 对象访问您的折叠并在需要时计算您的统计数据(请参阅results$resample

    5) mlr 也有交叉验证,这取决于你喜欢哪种口味。

    【讨论】:

    • 4) 我不想访问折叠,而是想在每次折叠后访问经过训练的模型。这就是我想循环训练的原因。
    • first_holdout stats.stackexchange.com/questions/114168/…)。
    猜你喜欢
    • 2019-11-09
    • 2014-05-19
    • 2019-03-02
    • 2019-01-23
    • 2019-02-18
    • 2021-12-13
    • 2020-07-30
    • 2021-09-16
    • 1970-01-01
    相关资源
    最近更新 更多