2012-05-01 19 views
6

Zrobiłem zacząć tworzyć pewne zestawy treningowe i testowe stosując 10-krotny oceny krzyżowej na sztucznej zbiorze:warstwowy 10 krotnie krzyż walidacja

rows <- 1000 

X1<- sort(runif(n = rows, min = -1, max =1)) 
occ.prob <- 1/(1+exp(-(0.0 + 3.0*X1))) 
true.presence <- rbinom(n = rows, size = 1, prob = occ.prob) 

# combine data as data frame and save 
data <- data.frame(X1, true.presence) 

id <- sample(1:10,nrow(data),replace=TRUE) 
ListX <- split(data,id) 
fold1 <- data[id==1,] 
fold2 <- data[id==2,] 
fold3 <- data[id==3,] 
fold4 <- data[id==4,] 
fold5 <- data[id==5,] 
fold6 <- data[id==6,] 
fold7 <- data[id==7,] 
fold8 <- data[id==8,] 
fold9 <- data[id==9,] 
fold10 <- data[id==10,] 

trainingset <- subset(data, id %in% c(2,3,4,5,6,7,8,9,10)) 
testset <- subset(data, id %in% c(1)) 

jestem po prostu zastanawiasz się, czy istnieją prostsze sposoby, aby to osiągnąć i jak Mogłabym wykonać warstwowe crossvalidation, które zapewnia, że ​​klasa priors (true.presence) jest mniej więcej taka sama we wszystkich fałdach?

+0

może być łatwiejsze w użyciu kilka fabrycznie wbudowane funkcje, jak w 'errorest' ** pakiet ipred **. – joran

+0

Dzięki temu doszedłem do tego, ale nie jestem pewien, jak z niego korzystać. Jeśli mógłbyś być tak miły i napisać odpowiedź, zaakceptuję to. Należy pamiętać, że nie chcę używać formuły i modelu itp. Chcę tylko podzielić (tj. Utworzyć 10 zestawów treningowych/testowych). Dzięki. – cs0815

+0

Jeśli chcesz tylko fałdy, ** ipred ** prawdopodobnie nie pomoże wiele. Jestem pewien, że musi istnieć paczka z funkcją, która gdzieś to robi, ale w międzyczasie dodałem odpowiedź z kodem. – joran

Odpowiedz

9

Jestem pewien, że (a) istnieje skuteczniejszy sposób kodowania tego i (b) prawie na pewno jest funkcja gdzieś w pakiecie, który po prostu zwróci fałdy, ale oto prosty kod, który daje ci pomysł, jak można to zrobić:

rows <- 1000 

X1<- sort(runif(n = rows, min = -1, max =1)) 
occ.prob <- 1/(1+exp(-(0.0 + 3.0*X1))) 
true.presence <- rbinom(n = rows, size = 1, prob = occ.prob) 

# combine data as data frame and save 
dat <- data.frame(X1, true.presence) 

require(plyr) 
createFolds <- function(x,k){ 
    n <- nrow(x) 
    x$folds <- rep(1:k,length.out = n)[sample(n,n)] 
    x 
} 

folds <- ddply(dat,.(true.presence),createFolds,k = 10) 

#Proportion of true.presence in each fold: 
ddply(folds,.(folds),summarise,prop = sum(true.presence)/length(true.presence)) 

    folds  prop 
1  1 0.5049505 
2  2 0.5049505 
3  3 0.5100000 
4  4 0.5100000 
5  5 0.5100000 
6  6 0.5100000 
7  7 0.5100000 
8  8 0.5100000 
9  9 0.5050505 
10 10 0.5050505 
6

@joran ma rację (co do jego założenia (b)). dismo :: kfold() jest tym, czego szukasz.

więc stosując data z początkowego pytania:

require(dismo) 
folds <- kfold(data, k=10, by=data$true.presence) 

daje wektor o długości nrow(data) zawierający wielokrotność skojarzenie każdego wiersza danych. Dlatego data[fold==1,] zwraca pierwszą krotkę, a data[fold!=1,] może być używana do sprawdzania poprawności.

15

createFolds metoda przeprowadzania partycjonowania warstwowego. Oto akapit ze strony pomocy:

... Losowe próbkowanie odbywa się w obrębie poziomów y (= wyników), gdy y jest czynnikiem, który próbuje zrównoważyć rozkłady klas w obrębie podziałów.

Oto odpowiedź od Twojego problemu:

library(caret) 
folds <- createFolds(factor(data$true.presence), k = 10, list = FALSE) 

i proporcje:

> library(plyr) 
> data$fold <- folds 
> ddply(data, 'fold', summarise, prop=mean(true.presence)) 
    fold  prop 
1  1 0.5000000 
2  2 0.5050505 
3  3 0.5000000 
4  4 0.5000000 
5  5 0.5000000 
6  6 0.5049505 
7  7 0.5000000 
8  8 0.5049505 
9  9 0.5000000 
10  10 0.5050505 
+0

Dzięki za to. Udostępnienie etykiet jako czynników 'createFolds()' poprawia proporcje podczas partycjonowania. –