web-dev-qa-db-fra.com

Création de plis pour CV k-fold en R à l'aide de Caret

J'essaie de faire un CV k-fold pour plusieurs méthodes de classification/paramètres hiper en utilisant les données disponibles sur

http://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data .

Cet ensemble est composé de 208 lignes, chacune avec 60 attributs. Je le lis dans un data.frame en utilisant la fonction read.table.

L'étape suivante consiste à diviser mes données en k plis, disons k = 5. Ma première tentative a été d'utiliser

test <- createFolds (t, k = 5)

J'ai eu deux problèmes avec cela. La première est que les longueurs des plis ne sont pas côte à côte:

  Length Class  Mode   

Fold1 29 -none- numérique
Fold2 14 -aucun- numérique
Fold3 7 -aucun- numérique
Fold4 5 -aucun- numérique
Fold5 5 -aucun- numérique

L'autre est que cela a apparemment divisé mes données en fonction des index d'attributs, mais je veux diviser les données elles-mêmes. J'ai pensé qu'en transposant mon data.frame, en utilisant:

test <- t (myDataNumericValues)

Mais quand j'appelle la fonction createFolds, cela me donne quelque chose comme ceci:

  Length Class  Mode   

Fold1 2496 -aucun- numérique
Fold2 2496 -aucun- numérique
Fold3 2495 -aucun- numérique
Fold4 2496 -aucun- numérique
Fold5 2497 -aucun- numérique

Le problème de longueur a été résolu, mais il ne divise toujours pas mes 208 données en conséquence.

Avez-vous des réflexions sur ce que je peux faire? Pensez-vous que le package caret n'est pas le plus approprié?

Merci d'avance

11
gcolucci

Lisez s'il vous plaît ?createFolds pour comprendre ce que fait la fonction. Il crée les indices qui définissent quelles données sont tenues les plis séparés (voir les options pour retourner l'inverse):

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

Pour les utiliser pour diviser les données:

   > 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 

La fonction train est utilisée dans ce paquet pour faire la modélisation réelle (vous n'avez généralement pas besoin de faire le fractionnement vous-même. Voir cette page ).

Max

29
topepo

Je ne suis pas familier avec le package caret, mais j'avais l'habitude d'écrire une fonction calculant le CV basé sur l'arbre de décision du package rpart. Bien sûr, la fonction doit être motivée pour répondre à votre objectif.

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)

}

0
Earo Wang