2013-05-28 76 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