在R中使用Caret创建k-fold CV的折叠

12
我正在尝试使用位于http://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data的可用数据,制作几种分类方法/超参数的k-fold CV。
该数据集由208行组成,每行有60个属性。 我使用read.table函数将其读入数据框中。
下一步是将我的数据分成k个折叠,假设k = 5。 我的第一次尝试是使用:
test <- createFolds(t, k=5)

我对此有两个问题。首先,折叠的长度不相邻:

       Length Class  Mode   
Fold1 29     -none- numeric <br />
Fold2 14     -none- numeric <br />
Fold3  7     -none- numeric <br />
Fold4  5     -none- numeric <br />
Fold5  5     -none- numeric

另一个问题是,它显然是根据属性索引拆分了我的数据,但我想要拆分数据本身。我认为通过转置我的数据框,使用:
test <- t(myDataNumericValues)

但是当我调用createFolds函数时,它会给我返回类似这样的结果:
       Length Class  Mode   
Fold1 2496   -none- numeric <br />
Fold2 2496   -none- numeric <br />
Fold3 2495   -none- numeric <br />
Fold4 2496   -none- numeric <br />
Fold5 2497   -none- numeric

长度问题已经解决,但是它仍然没有按照我的208数据进行分割。
我该怎么办?caret包可能不是最合适的选择吗?
2个回答

35

请阅读?createFolds以了解该函数的作用。它创建定义哪些数据被保留在不同折叠中的索引(请参见返回相反选项):

  > library(caret)
  > library(mlbench)
  > data(Sonar)
  > 
  > folds <- createFolds(Sonar$Class)
  > str(folds)
  List of 10
   $ Fold01: int [1:21] 25 39 58 63 69 73 80 85 90 95 ...
   $ Fold02: int [1:21] 19 21 42 48 52 66 72 81 88 89 ...
   $ Fold03: int [1:21] 4 5 17 34 35 47 54 68 86 100 ...
   $ Fold04: int [1:21] 2 6 22 29 32 40 60 65 67 92 ...
   $ Fold05: int [1:20] 3 14 36 41 45 75 78 84 94 104 ...
   $ Fold06: int [1:21] 10 11 24 33 43 46 50 55 56 97 ...
   $ Fold07: int [1:21] 1 7 8 20 23 28 31 44 71 76 ...
   $ Fold08: int [1:20] 16 18 26 27 38 57 77 79 91 99 ...
   $ Fold09: int [1:21] 13 15 30 37 49 53 74 83 93 96 ...
   $ Fold10: int [1:21] 9 12 51 59 61 62 64 70 82 87 ...

使用这些来分割数据:

   > split_up <- lapply(folds, function(ind, dat) dat[ind,], dat = Sonar)
   > dim(Sonar)
   [1] 208  61
   > unlist(lapply(split_up, nrow))
   Fold01 Fold02 Fold03 Fold04 Fold05 Fold06 Fold07 Fold08 Fold09 Fold10 
       21     21     21     21     20     21     21     20     21     21 

在这个软件包中,train 函数用于进行实际建模(通常不需要自己进行拆分,详见此页面)。


谢谢你的帮助,Max。现在我又遇到了一个问题,我在这里链接了它:http://stackoverflow.com/questions/22972854/how-to-implement-a-hold-out-validation-in-r。希望也有人能帮我解决这个问题。 - gcolucci
2
这个回答很有用,但并不是“createFolds提供了答案”这种说法是正确的。在“createFolds”的内容中从未提到“它创建了定义哪些数据被保留在单独折叠中的索引”。 - lourencoj

0

我不熟悉 caret 包,但我曾经使用 rpart 包中的决策树编写了一个计算 CV 的函数。当然,为了适应您的目的,该函数需要进行修改。

CV <- function(form, x, fold = 10, cp = 0.01) {
  # x is the data
  n <- nrow(x)
  prop <- n%/%fold
  set.seed(7)
  newseq <- rank(runif(n))
  k <- as.factor((newseq - 1)%/%prop + 1)

  y <- unlist(strsplit(as.character(form), " "))[2]
  vec.accuracy <- vector(length = fold)
  for (i in seq(fold)) {
    # It depends on which classification method you use
    fit <- rpart(form, data = x[k != i, ], method = "class")
    fit.prune <- prune(fit, cp = cp)
    fcast <- predict(fit.prune, newdata = x[k == i, ], type = "class")
    cm <- table(x[k == i, y], fcast)
    accuracy <- (cm[1, 1] + cm[2, 2])/sum(cm)
    vec.accuracy[i] <- accuracy
  }
avg.accuracy <- mean(vec.accuracy)
avg.error <- 1 - avg.accuracy
cv <- data.frame(Accuracy = avg.accuracy, Error = avg.error)
return(cv)

}


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