2013-10-03 60 views
9

我是R(第2天)的新手,並且負責構建隨機森林。每個單獨的隨機森林將使用不同的訓練集來構建,我們將結合所有森林進行預測。我在R中實現了這個功能,並且在將兩個未使用相同集合構建的森林相結合時遇到了一些困難。我嘗試如下:結合隨機森林建立不同的訓練集在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) 

當然,這會產生錯誤:

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 

我已瀏覽了一段時間看這個線索網絡但沒有成功還。任何幫助在這裏將不勝感激。

+0

這兩個數據集的確切結構是什麼? (使用'str'來查看)。他們是否有完全相同的變量,都以同樣的方式命名? – joran

+0

@joran他們做的。他們都是我手動拆分的較大訓練集的子集。當我運行'str'時,第一行是:''data.frame':\t 38735 obs。 55個變量:'對於d1和''data.frame':\t 38734 obs。 55個變量:'對於d2。後面是每個數據集的相同名稱。 – josh

+0

檢查每個射頻對象的投票對象的維數。並非所有因素水平都存在於您的訓練數據的每個子集中。 – joran

回答

20

啊。這要麼是combine的疏忽,要麼是你想要做的事情是荒謬的,這取決於你的觀點。

投票矩陣記錄每個回覆類別的訓練數據中每個案例在森林中的投票數。當然,它將具有與訓練數據中的行數相同的行數。

combine假設您在相同的數據集上運行了兩次隨機森林,因此這些矩陣的維數將是相同的。它是這樣做的,因爲它想爲您提供組合森林的一些「總體」誤差估計值。

但是,如果兩個數據集是不同相結合的投票矩陣變得簡單無稽之談。您可以通過簡單地從較大的訓練數據集中刪除一行來運行combine,但組合森林中的結果投票矩陣將是混亂的,因爲每行都是兩個不同訓練案例的投票組合。

所以也許這只是一個應該是可以在combine中關閉的選項。因爲它應該仍然是合理的結合實際的樹木和predict結果對象。但是從combine輸出的一些「組合」誤差估計將毫無意義。

長話短說,使每個訓練數據集的大小相同,並且它會運行。但是如果你這樣做了,除了做出新的預測之外,我不會使用最終的對象。總結森林表現的任何事情都是無稽之談。

不過,我認爲使用combine預期的方法是,以適應在數據集多重隨機森林,而是樹木一個數量減少,然後對這些森林相結合。

編輯

我繼續修改combine「處理」不平等訓練集大小。所有這些意思都是因爲我刪除了一大堆試圖將事情拼湊在一起而無法匹配的代碼。但我一直認爲結合了森林的部分,所以你仍然可以使用predict

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 
} 

然後你就可以測試它是這樣的:

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) 

顯然,這種帶有絕對沒有保修! :)

+0

感謝@joran的詳細回覆。我想知道如果投票矩陣的大小相同,如果合併和預測會有意義,因爲如您所說,每一行都是兩個不同訓練案例的組合。感謝您的鏈接,我會檢查出來。可悲的是,在我的情況下,將每個訓練集設置爲相同的大小並不是一種選擇,因爲我希望看到的是,數據偏斜會影響此係統的整體性能。在頂部更大和(希望)更好的想法! – josh

+0

@Josh沒問題。查看我的編輯可能的解決方法。 – joran

+0

再次感謝,這真的很棒。我最終做的是創建一堆森林並分別對每一個進行預測。然後我將這些矩陣組合成一個更大的預測矩陣。再次感謝! – josh