0

我是R的大一新生,想在R中执行randomForest,数据有1000行28列。这个想法是测试所有 mtry (1:27),每个 mtry 将通过 10 次重复 10 倍 CV 进行测试。问题是花了这么长时间还是没有结果!我尝试使用“foreach”循环而不是“for”,但我不知道该怎么做。代码如下所示:

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)

请帮助我,非常感谢!

4

2 回答 2

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仅用于测试。
于 2013-05-28T15:56:22.853 回答
0

我无法执行您的示例,因为data未定义。但也许一个最小的foreach例子可能会有所帮助:

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循环,一个 fortrainrf和一个 fortestrf

于 2013-05-28T11:02:46.570 回答