2016-09-14 2 views
0

J'ai d'énormes données d'entraînement pour la forêt aléatoire (dim: 47600811 * 9). Je veux prendre plusieurs (disons 1000) échantillon bootstrap de dimension 10000 * 9 (en prenant 9000 classes de classes négatives et 1000 classes de données positives dans chaque exécution) et générer itérativement des arbres pour chacun d'entre eux, puis combiner tous ces arbres en 1 forêt. Une idée approximative du code requis est donnée ci-dessous. Quelqu'un peut-il me guider comment puis-je générer un échantillon aléatoire avec remplacement de mes données de train réelles et générer de manière optimale des arbres pour eux de manière itérative? Ce sera une aide précieuse. MerciEntraînement par bootstrap aléatoire et génération de forêt

library(doSNOW) 
library(randomForest) 
cl <- makeCluster(8) 
registerDoSNOW(cl) 

for (i=1:1000){ 
B <- 1000 
U <- 9000 
dataB <- trainData[sample(which(trainData$class == "B"), B,replace=TRUE),] 
dataU <- trainData[sample(which(trainData$class == "U"), U,replace=TRUE),] 
subset <- rbind(dataB, dataU) 

Je ne suis pas sûr que ce soit la meilleure façon de produire un sous-ensemble encore et encore (1000 fois) de trainData réelle.

rf <- foreach(ntree=rep(125, 8), .packages='randomForest') %dopar% { 
    randomForest(subset[,-1], subset$class, ntree=ntree) 
} 
} 
crf <- do.call('combine', rf) 
print(crf) 
stopCluster(cl) 
+0

Avez-vous essayé de définir l'argument randomForest sampsize sur une valeur plus petite? Définir sampsize plus petit et ntree plus haut peut être similaire à ce que vous faites. –

+0

@ steve-weston J'essaie de créer un sous-ensemble de données réelles par 'i = répliquer (3, {c (échantillon (qui (trainData $ class ==" B "), 50, remplacer = T), échantillon (qui (trainData $ class == "U"), 50, remplacez = T))}) ', puis appliquez foreach' rf <- foreach (ntree = rep (125, 8), .packages = 'randomForest')% dopar% {randomForest (trainData [i, -1], trainData [i,] classe $, ntree = ntree, sampsize = rep (2,2))} 'et plus tard combinent les arbres par' crf <- do.call ('combine' , rf) '. Ensuite, je reçois seulement 1000 arbres alors que mon 'i 'contient 3 sous-ensembles et pour chaque sous-ensemble je génère 1000 arbres alors je devrais obtenir 3000 arbres. Comment le corriger? – Newbie

+0

Votre programme contient un bogue que je décris et corrige dans ma réponse. –

Répondre

1

Bien que votre exemple parallélise l'intérieur plutôt que la boucle extérieure, il peut fonctionner raisonnablement bien tant que la boucle foreach interne prend plus de quelques secondes à exécuter, ce qui est presque certainement le cas. Cependant, votre programme a un bug: il jette les premiers 999 résultats foreach et ne traite que le dernier résultat. Pour résoudre ce problème, vous pouvez préallouer une liste de longueur 1000 * 8 et affecter les résultats de foreach à chaque itération de la boucle for externe. Par exemple:

library(doSNOW) 
library(randomForest) 
trainData <- data.frame(a=rnorm(20), b=rnorm(20), 
         class=c(rep("U", 10), rep("B", 10))) 
n <- 1000   # outer loop count 
chunksize <- 125 # value of ntree used in inner loop 
nw <- 8   # number of cluster workers 
cl <- makeCluster(nw) 
registerDoSNOW(cl) 
rf <- vector('list', n * nw) 
for (i in 1:n) { 
    B <- 1000 
    U <- 9000 
    dataB <- trainData[sample(which(trainData$class == "B"), B,replace=TRUE),] 
    dataU <- trainData[sample(which(trainData$class == "U"), U,replace=TRUE),] 
    subset <- rbind(dataB, dataU) 
    ix <- seq((i-1) * nw + 1, i * nw) 
    rf[ix] <- foreach(ntree=rep(chunksize, nw), 
        .packages='randomForest') %dopar% { 
    randomForest(subset[,-1], subset$class, ntree=ntree) 
    } 
} 
cat(sprintf("# models: %d; expected # models: %d\n", length(rf), n * nw)) 
cat(sprintf("expected total # trees: %d\n", n * nw * chunksize)) 
crf <- do.call('combine', rf) 
print(crf) 

Cela devrait résoudre le problème que vous mentionnez dans le commentaire que vous me dirigé vers.

+0

Je vous remercie pour une réponse détaillée.Je l'essaie sur mes données réelles, Voyons voir si cela fonctionne .. Merci beaucoup – Newbie

+0

J'ai généré une liste de 100 * 100 puis j'ai fait une boucle pour i = 1: 100, puis je génère (125 * 8) arbres dans chaque foreach. obtenir 125 * 8 * 100 = 100000 arbres mais en fait je reçois 1250000. Pouvez-vous me guider pourquoi est-ce qui se passe ..? Merci – Newbie

+0

@Newbie J'ai fait mon exemple complet, donc vous pouvez le faire fonctionner vous-même. Dans le processus, j'ai corrigé quelques problèmes. Je calculais incorrectement la longueur de la liste de résultats parce que je mélangeais le nombre de résultats et le nombre total d'arbres. –

1

Quelque chose comme ça fonctionnerait

# Replicate expression 1000 times, store output of each replication in a list 
# Find indices of class B and sample 9000 times with replacement 
# Do the same 1000 times for class U. Combine the two vectors of indices 

i = replicate(1000, {c(sample(which(trainData$class == "B"), 9000, replace = T), sample(which(trainData$class == "U"), 1000, replace = T))}) 

nourrir ensuite i dans une version parallèle de lapply

mclapply(i, function(i, ntree) randomForest(trainData[i,-1], trainData[i,]$class, ntree=ntree) 
+0

Pouvez-vous me guider comment puis-je utiliser cette version parallèle de lapply dans la commande 'foreach' ci-dessus pour calculer les arbres pour chaque' i' (sous-ensemble de trainData), de sorte que plus tard je peux combiner tous les arbres en forêt. En fait, ce dont j'ai besoin est de passer ce 'i' à cette ligne de code dans l'exemple ci-dessus' randomForest (sous-ensemble [, - 1], sous-ensemble $ class, ntree = ntree) 'le premier argument sera tout sous-ensemble qui est 'class' et le second argument sera la colonne' class' de cette trame de sous-ensemble. – Newbie

+0

Je pense que ce que vous avez suggéré ici est de remplacer la ligne après le '% dopar%', qui est { randomForest (sous-ensemble [, - 1], sous-ensemble $ class, ntree = ntree) } 'avec {mclapply (je, fonction (i, ntree) randomForest (trainData [i, -1], trainData [i,] $ class, ntree = ntree)} '. Ai-je raison? – Newbie

+0

Je l'ai essayé de cette façon' rf <- foreach (ntree = rep (4,8), .packages = "randomForest")% dopar% mclapply (i, fonction (i, ntree) randomForest (données_train [i, -1], données_train [i,] $ class, ntree = ntree)) 'mais il donne l'erreur:' tâche 1 a échoué - "impossible de trouver la fonction" mclapply "" 'bien qu'un simple test de la fonction mclapply fonctionne:' simplify2array (mclapply (rep (4, 5), rnorm, mc. preschedule = FALSE, mc.set.seed = FALSE)) ' – Newbie