2013-05-28 119 views
0

我是R的新生。我想在R中執行randomForest,數據有1000行和28列。這個想法是測試所有的測試(1:27),每個測試10次重複測試10次。問題是需要這麼長時間,仍然沒有結果!我嘗試使用'foreach'循環而不是'for',但我不知道如何去做。代碼如下所示:foreach而不是FOR IN R

library(randomForest) 
n <- nrow(data) 
a1 <- 1:n 
a2 <- rep(1:10,ceiling(n/10))[1:n] 
k <- ncol(data)-1  
trainrf <- testrf <- list() 
for(i in 1:k){ # tune mtry from 1 to 27 
    rftrain <- rftest <- NULL 
    for(x in 1:10){ # 10 repeats 10-fold CV 
     set.seed(1981) 
     a2 <- sample(a2,n) 
     train.rf <- test.rf <- rep(0,10) 
     for(j in 1:10){ 
      m <- a1[a2 == j] 
      n1 <- n-length(m) 
      n2 <- length(m) 
      set.seed(2013) 
      rf.data <- randomForest(level~., data=data[-m,], mtry=i, ntree=1000) 
      train.rf[j] <- sum(data[-m,28] == predict(rf.data, data[-m,]))/n1 
      test.rf[j] <- sum(data[m,28] == predict(rf.data, data[m,]))/n2 
     } 
     rftrain[x] <- mean(train.rf); rftest[x] <- mean(test.rf) 
    } 
    trainrf[[i]] <- rftrain; testrf[[i]] <- rftest 
} 

我的筆記本電腦是I7的Windows 7 64位,我寫了幾碼,因爲我知道:

library(foreach) 
library(doParallel) 
cl <- makeCluster(4) 
registerDoParallel(cl) 

請幫助我,非常感謝!

+0

對不起,你的例子似乎並沒有使用foreach,所以我不知道該糾正什麼。此外ntree = 1000是相當大的,可能爲什麼你看到如此長的延遲。你有沒有嘗試從較小的森林開始? –

+0

如果你不知道如何做,你應該閱讀一些小插曲。 – Roland

回答

2

你或許應該閱讀一些foreach小插曲,因爲雖然這是一個相當直接使用的foreach,這是不平凡,像許多例子。

這是我在翻譯你的腳本foreach嘗試,雖然我無法測試它,因爲你的例子是不可重現:

library(doParallel) 
cl <- makeCluster(4) 
registerDoParallel(cl) 
n <- nrow(data) 
a1 <- 1:n 
a2 <- rep(1:10,ceiling(n/10))[1:n] 
k <- ncol(data)-1 
outercomb <- function(...) { 
    lapply(1:2, function(i) lapply(list(...), function(p) p[[i]])) 
} 
innercomb <- function(...) { 
    lapply(1:2, function(i) sapply(list(...), function(p) p[[i]])) 
} 
r <- foreach(i=1:k, .combine='outercomb', .multicombine=TRUE, 
     .packages='randomForest') %:% 
    foreach(1:10, .combine='innercomb', .multicombine=TRUE) %dopar% { 
     set.seed(1981) 
     Xa2 <- sample(a2, n) 
     train.rf <- double(10) 
     test.rf <- double(10) 
     for(j in 1:10){ 
      m <- a1[Xa2 == j] 
      n1 <- n-length(m) 
      n2 <- length(m) 
      set.seed(2013) 
      rf.data <- randomForest(level~., data=data[-m,], mtry=i, ntree=1000) 
      train.rf[j] <- sum(data[-m,28] == predict(rf.data, data[-m,]))/n1 
      test.rf[j] <- sum(data[m,28] == predict(rf.data, data[m,]))/n2 
     } 
     c(mean(train.rf), mean(test.rf)) 
    } 
trainrf <- r[[1]] 
testrf <- r[[2]] 

這裏有一些評論:

  • 您應該調查caret包。我認爲它可以很容易地爲你做這種東西,它使用foreach並行執行。
  • 儘管我在外部兩個循環之間並行化,但如果您有權訪問集羣,那麼您可能會走得更遠。這裏有很多並行性。
  • 這使用嵌套的foreach循環是一種高級功能,但對於這類問題非常有用。
  • 我用Xa2而不是a2來強調foreach循環無法更新循環迭代變量a2。我不確定我的版本是否符合您的要求,因此您必須考慮這一點。
  • .combine功能有點棘手,但需要產生兩個結果。他們都執行各種轉置。
  • 您應該避免使用公式接口randomForest,因爲它使用更多的內存並且速度可能會變慢。
  • 我假定您使用set.seed僅用於測試。
+0

對不起,這是關於這個問題的主題,但是當你說'randomForrest'的公式接口應該被避免時,你是什麼意思? –

+0

@DeanMacGregor「randomForest」有兩個S3方法:一個用於「公式」類,另一個用於獲取數據幀或矩陣和響應向量的默認方法。配方版本使用更多的記憶,我聽說Andy Liaw說這導致了很多問題。 –

+0

在我看到你在說什麼之前,我不得不盯着randomForest的CRAN頁面5分鐘。謝謝。 –

0

我無法執行您的示例,因爲data未定義。但是,也許一個很小foreach -example可以幫助:

library(foreach) 
library(doParallel) 
cl <- makeCluster(4) 
registerDoParallel(cl) 

testList <- foreach(i=1:5) %dopar% { 
    1:i 
} 

i=1:5每次運行的結果合併到一個列表,並保存在變量testList

> testList 
[[1]] 
[1] 1 

[[2]] 
[1] 1 2 

[[3]] 
[1] 1 2 3 

[[4]] 
[1] 1 2 3 4 

[[5]] 
[1] 1 2 3 4 5 

你可以指定其他有機結合起來的方法:

> testList <- foreach(i=1:5, .combine="c") %dopar% { 
+ 1:i 
+ } 
> 
> testList 
[1] 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 

我認爲你必須做兩個foreach循環,一個trainrf,一個用於testrf