2013-10-03 6 views
9

Ich bin neu in R (Tag 2) und wurden mit dem Aufbau eines Waldes von zufälligen Wäldern beauftragt. Jeder einzelne zufällige Wald wird mit einem anderen Trainingssatz gebaut und wir werden alle Wälder am Ende kombinieren, um Vorhersagen zu treffen. Ich führe dies in R durch und habe Schwierigkeiten, zwei nicht zusammengesetzte Wälder zu kombinieren. Mein Versuch ist wie folgt:Kombinieren von zufälligen Wäldern mit verschiedenen Trainingssätzen in R

d1 = read.csv("../data/rr/train/10/chunk0.csv",header=TRUE) 
d2 = read.csv("../data/rr/train/10/chunk1.csv",header=TRUE) 

rf1 = randomForest(A55~., data=d1, ntree=10) 
rf2 = randomForest(A55~., data=d2, ntree=10) 

rf = combine(rf1,rf2) 

Dies natürlich erzeugt einen Fehler:

Error in rf$votes + ifelse(is.na(rflist[[i]]$votes), 0, rflist[[i]]$votes) : 
non-conformable arrays 
In addition: Warning message: 
In rf$oob.times + rflist[[i]]$oob.times : 
longer object length is not a multiple of shorter object length 

Ich habe Suche im Internet nach einiger Zeit gerade in einem Anhaltspunkt für diese haben aber keinen Erfolg hatte noch . Jede Hilfe hier würde am meisten geschätzt werden.

+0

Was sind die genauen Strukturen der beiden Datensätze? (Verwenden Sie 'str', um zu sehen). Haben sie genau die gleichen Variablen, alle auf die gleiche Weise benannt? – joran

+0

@joran sie tun. Sie sind beide Teilmengen eines größeren Trainingssets, das ich manuell aufgeteilt habe. Wenn ich 'str' starte, sind die ersten Zeilen:' 'data.frame': \t 38735 obs. von 55 Variablen: 'für d1 und' 'data.frame': \t 38734 obs. von 55 Variablen: 'für d2. gefolgt von den gleichen Namen für jeden Datensatz. – josh

+0

Überprüfen Sie die Dimensionen der Votes-Objekte jedes RF-Objekts. Es ist möglich, dass nicht alle Faktorstufen in jeder Teilmenge Ihrer Trainingsdaten vorhanden waren. – joran

Antwort

20

Ah. Dies ist entweder ein Versehen in combine oder was Sie versuchen, ist unsinnig, je nach Ihrer Sichtweise.

Die Stimmenmatrix zeichnet die Anzahl der Stimmen in der Gesamtstruktur für jeden Fall in den Trainingsdaten für jede Antwortkategorie auf. Natürlich wird es die gleiche Anzahl von Zeilen haben wie die Anzahl der Zeilen in Ihren Trainingsdaten.

combine wird davon ausgegangen, dass Sie Ihre zufälligen Wälder zweimal auf dem gleichen Datensatz ausgeführt, so dass die Dimensionen dieser Matrizen gleich sein werden. Es macht das, weil es Ihnen einige "allgemeine" Fehlerschätzungen für die kombinierte Gesamtstruktur bereitstellen möchte.

Aber wenn die beiden Datensätze sind Kombination der Stimmen Matrizen wird einfach unsinnig. Sie könnten combine ausführen, indem Sie einfach eine Zeile aus Ihrem größeren Trainingsdatensatz entfernen, aber die resultierende Stimmenmatrix in der kombinierten Gesamtstruktur wäre Kauderwelsch, da jede Zeile eine Kombination von Stimmen für zwei verschiedene Trainingsfälle wäre.

Also vielleicht ist dies einfach etwas, das eine Option sein sollte, die in combine ausgeschaltet werden kann. Weil es sollte immer noch sinnvoll sein, die tatsächlichen Bäume und predict auf dem resultierenden Objekt zu kombinieren. Aber einige "kombinierte" Fehlerschätzungen in der Ausgabe von combine werden bedeutungslos sein.

Lange Rede kurzer Sinn, machen Sie jedes Training Datensatz die gleiche Größe, und es wird ausgeführt. Aber wenn Sie das tun, würde ich das resultierende Objekt nicht für etwas anderes als neue Vorhersagen verwenden. Alles, was die Leistung der Wälder zusammenfasst, wird Unsinn sein.

Aber ich denke, der sollte Weg combine zu verwenden ist, mehrere zufälligen Wälder auf den voll Datensatz, aber mit einer reduzierten Anzahl von Bäumen und dann zu verbinden, diese Wälder zu passen.

bearbeiten

ich vor combine ging und modifizierte Größen ungleichen Trainingssatz zu „behandeln“. Das bedeutet wirklich, dass ich einen großen Teil des Codes entfernt habe, der versuchte, Dinge zusammenzuheften, die nicht zusammenpassen würden.Aber ich hielt den Teil, der die Wälder kombiniert, so können Sie immer noch predict verwenden:

my_combine <- function (...) 
{ 
    pad0 <- function(x, len) c(x, rep(0, len - length(x))) 
    padm0 <- function(x, len) rbind(x, matrix(0, nrow = len - 
     nrow(x), ncol = ncol(x))) 
    rflist <- list(...) 
    areForest <- sapply(rflist, function(x) inherits(x, "randomForest")) 
    if (any(!areForest)) 
     stop("Argument must be a list of randomForest objects") 
    rf <- rflist[[1]] 
    classRF <- rf$type == "classification" 
    trees <- sapply(rflist, function(x) x$ntree) 
    ntree <- sum(trees) 
    rf$ntree <- ntree 
    nforest <- length(rflist) 
    haveTest <- !any(sapply(rflist, function(x) is.null(x$test))) 
    vlist <- lapply(rflist, function(x) rownames(importance(x))) 
    numvars <- sapply(vlist, length) 
    if (!all(numvars[1] == numvars[-1])) 
     stop("Unequal number of predictor variables in the randomForest objects.") 
    for (i in seq_along(vlist)) { 
     if (!all(vlist[[i]] == vlist[[1]])) 
      stop("Predictor variables are different in the randomForest objects.") 
    } 
    haveForest <- sapply(rflist, function(x) !is.null(x$forest)) 
    if (all(haveForest)) { 
     nrnodes <- max(sapply(rflist, function(x) x$forest$nrnodes)) 
     rf$forest$nrnodes <- nrnodes 
     rf$forest$ndbigtree <- unlist(sapply(rflist, function(x) x$forest$ndbigtree)) 
     rf$forest$nodestatus <- do.call("cbind", lapply(rflist, 
      function(x) padm0(x$forest$nodestatus, nrnodes))) 
     rf$forest$bestvar <- do.call("cbind", lapply(rflist, 
      function(x) padm0(x$forest$bestvar, nrnodes))) 
     rf$forest$xbestsplit <- do.call("cbind", lapply(rflist, 
      function(x) padm0(x$forest$xbestsplit, nrnodes))) 
     rf$forest$nodepred <- do.call("cbind", lapply(rflist, 
      function(x) padm0(x$forest$nodepred, nrnodes))) 
     tree.dim <- dim(rf$forest$treemap) 
     if (classRF) { 
      rf$forest$treemap <- array(unlist(lapply(rflist, 
       function(x) apply(x$forest$treemap, 2:3, pad0, 
        nrnodes))), c(nrnodes, 2, ntree)) 
     } 
     else { 
      rf$forest$leftDaughter <- do.call("cbind", lapply(rflist, 
       function(x) padm0(x$forest$leftDaughter, nrnodes))) 
      rf$forest$rightDaughter <- do.call("cbind", lapply(rflist, 
       function(x) padm0(x$forest$rightDaughter, nrnodes))) 
     } 
     rf$forest$ntree <- ntree 
     if (classRF) 
      rf$forest$cutoff <- rflist[[1]]$forest$cutoff 
    } 
    else { 
     rf$forest <- NULL 
    } 
    # 
    #Tons of stuff removed here... 
    # 
    if (classRF) { 
     rf$confusion <- NULL 
     rf$err.rate <- NULL 
     if (haveTest) { 
      rf$test$confusion <- NULL 
      rf$err.rate <- NULL 
     } 
    } 
    else { 
     rf$mse <- rf$rsq <- NULL 
     if (haveTest) 
      rf$test$mse <- rf$test$rsq <- NULL 
    } 
    rf 
} 

Und dann können Sie es wie folgt testen:

data(iris) 
d <- iris[sample(150,150),] 
d1 <- d[1:70,] 
d2 <- d[71:150,] 
rf1 <- randomForest(Species ~ ., d1, ntree=50, norm.votes=FALSE) 
rf2 <- randomForest(Species ~ ., d2, ntree=50, norm.votes=FALSE) 

rf.all <- my_combine(rf1,rf2) 
predict(rf.all,newdata = iris) 

Offensichtlich ist dies kommt mit absolut keine Garantie! :)

+0

Danke für die detaillierte Antwort @joran. Ich frage mich, ob die Wahlmatrizen dieselbe Größe hätten, wenn Kombination und Vorhersage sinnvoll wären, da jede Zeile, wie Sie sagen, eine Kombination aus zwei verschiedenen Trainingsfällen ist. Danke auch für den Link. Ich werde das überprüfen. Leider ist es in meinem Fall nicht möglich, jedes Trainingssatz auf die gleiche Größe zu bringen, da eine Sache, die ich gerne sehen würde, darin besteht, wie sich verzerrte Daten auf die Gesamtleistung dieses Systems auswirken. Am Anfang größere und (hoffentlich) bessere Ideen! – josh

+0

@Josh Kein Problem. Siehe meine Bearbeitung für eine mögliche Problemumgehung. – joran

+0

Danke nochmal, das ist wirklich toll. Was ich getan habe, war, eine Reihe von Wäldern zu erstellen und eine Vorhersage für jede einzelne zu machen. Dann habe ich diese Matrizen zu einer größeren Vorhersage-Matrix kombiniert. Danke nochmal! – josh

Verwandte Themen