R中的R caret / 如何在rfe中进行训练交叉验证的工作

9
我有一个问题,涉及到caret库中的rfe函数。在caret主页的链接中,他们给出了以下RFE算法: 算法 对于这个例子,我使用了带有3折交叉验证的rfe函数和带有线性SVM和5折交叉验证的train函数。请注意保留HTML标记。
library(kernlab)
library(caret)
data(iris)

# parameters for the tune function, used for fitting the svm
trControl <- trainControl(method = "cv", number = 5)

# parameters for the RFE function
rfeControl <- rfeControl(functions = caretFuncs, method = "cv",
                     number= 4, verbose = FALSE )

rf1 <- rfe(as.matrix(iris[,1:4]), as.factor(iris[,5]) ,sizes = c( 2,3) ,  
           rfeControl = rfeControl, trControl = trControl, method = "svmLinear")
  • 根据上述算法,我假设算法将使用2个嵌套的交叉验证:
    1. rfe 将数据(150个样本)分为3个折叠
    2. 使用5倍交叉验证在训练集(100个样本)上运行 train 函数来调整模型参数,并进行后续的RFE。

令人困惑的是,当我查看 rfe 函数的结果时:

> lapply(rf1$control$index, length)
$Fold1
[1] 100
$Fold2
[1] 101
$Fold3
[1] 99

> lapply(rf1$fit$control$index, length)
$Fold1
[1] 120
$Fold2
[1] 120
$Fold3
[1] 120
$Fold4
[1] 120
$Fold5
[1] 120

从这个结果来看,使用5倍交叉验证的训练集大小为120个样本,而预期大小为80个。??

如果有人能澄清rfetrain如何协同工作,那就太好了。

干杯

> sessionInfo()
R version 2.15.1 (2012-06-22)
Platform: i386-apple-darwin9.8.0/i386 (32-bit)

locale:
[1] C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] pROC_1.5.4      e1071_1.6-1     class_7.3-5     caret_5.15-048 
 [5] foreach_1.4.0   cluster_1.14.3  plyr_1.7.1      reshape2_1.2.1 
 [9] lattice_0.20-10 kernlab_0.9-15 

loaded via a namespace (and not attached):
 [1] codetools_0.2-8 compiler_2.15.1 grid_2.15.1     iterators_1.0.6
 [5] stringr_0.6.1   tools_2.15.1   

1
5折交叉验证每次会将数据集的五分之一排除作为验证集。因此,每次训练使用120个样本,测试集则是剩余的30个样本。30个样本*5=150个样本。 - tcash21
是的,但根据算法描述,5折交叉验证应该应用于由3折交叉验证得出的训练数据。因此,第一个训练集= 150/3 * 2,第二个训练集= 100/5 * 4 = 80。 - Fabian_G
@Fabian_G 你解决了这个问题吗?我也遇到了同样的问题,正在考虑联系 topepo 或提交错误报告。 - Reilstein
1个回答

1
问题在于lapply(rf1$fit$control$index, length)没有存储我们认为的内容。
为了理解这一点,我需要查看代码。它发生的情况如下:
当您调用rfe时,整个数据传递给nominalRfeWorkflow
nominalRfeWorkflow中,根据rfeControl(在我们的示例中根据3倍交叉验证规则分成3次)拆分的训练和测试数据被传递给rfeIter
我们可以在结果中找到这些拆分,其位于rf1$control$index下。
rfeIter中,约100个训练样本(我们的例子)被用于找到最终变量(即该函数的输出)。据我所知,约50个测试样本(我们的例子)被用于计算不同变量集的性能,但它们仅作为外部性能存储,而不用于选择最终变量。选择这些变量时,使用5倍交叉验证的性能估计值。但我们在rfe返回的最终结果中找不到这些索引。如果我们确实需要它们,我们需要从rfeIter中的fitObject$control$index获取它们,将它们返回给nominalRfeWorkflow,然后返回给rfe,并从那里在由rfe返回的结果中的rfe-Class对象中获取它们。
那么lapply(rf1$fit$control$index, length)中存储了什么?当rfe找到最佳变量后,使用最佳变量和完整的参考数据(150)创建最终模型拟合。rfe中如下创建rf1$fit

fit <- rfeControl$functions$fit(x[, bestVar, drop = FALSE], y, first = FALSE, last = TRUE, ...)

这个函数再次运行train函数,并使用完整的参考数据,最终的特征集和通过省略号(...)给出的trControl进行最终交叉验证。 由于我们的trControl应该进行5折交叉验证,因此lapply(rf1$fit$control$index, length)返回120是正确的,因为我们需要计算150/5*4=120。


你能指出caret文档或代码中哪里写到rfeControl$functions$fit运行了train吗?@ben - blueskyddd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接