使用foreach在R中并行运行PLSR预测

时间:2013-05-09 22:23:03

标签: r parallel-processing

用户,

我正在寻找一种“并行化”我的PLSR预测的解决方案,以节省处理时间。我试图使用“foreach”构造和“doPar”(参见下面的代码的第二部分),但我无法将预测值以及模型性能参数(RMSEP)分配给输出变量。

代码:

set.seed(10000)   # generate some data...
mat <- replicate(100, rnorm(100))
y <- as.matrix(mat[,1], drop=F)
x <- mat[,2:100]
eD <- dist(x, method = "euclidean")  # distance matrix to find close samples
eDm <- as.matrix(eD)
kns <- matrix(NA,nrow(x),10)  # empty matrix to allocate 10 closest samples
for (i in 1:nrow(eDm)) {   # identify closest samples in a loop and allocate to kns
     kns[i,] <- head(order(eDm[,i]), 11)[-1]
}

到目前为止,我认为代码是“安全的”,但下一部分对我提出了挑战,因为我之前从未使用过“foreach”构造:

  library(pls)
    library(foreach)
    library(doParallel)
    cl <- makeCluster(2)
    registerDoParallel(cl)
    out <- foreach(j = 1:nrow(mat), .combine="rbind", .packages="pls") %dopar% {
                    pls <- plsr(y ~ x, ncomp=5, validation="CV", , subset=kns[j,])
                    predict(pls, ncomp=5, newdata=x[j,,drop=F])
                    RMSEP(pls, estimate="CV")$val[1,1,5]
    }
    stopCluster(cl)

据我所知,以“RMSEP(pls,...”)开头的代码行只是覆盖了“预测”代码行中先前写入的数据。不知怎的,我假设.combine选项会照顾这个?

非常感谢你的帮助!

Best,Chega

2 个答案:

答案 0 :(得分:1)

如果要从foreach循环的主体返回两个对象,则需要将它们放入诸如列表之类的对象中:

out <- foreach(j = 1:nrow(mat), .packages="pls") %dopar% {
    pls <- plsr(y ~ x, ncomp=5, validation="CV", , subset=kns[j,])
    list(p=predict(pls, ncomp=5, newdata=x[j,,drop=F]),
         r=RMSEP(pls, estimate="CV")$val[1,1,5])
}

只有循环体的“最终值”返回给主体,然后由.combine函数处理。

请注意,我删除了.combine参数,以便结果将是长度为2的列表。我不清楚rbind是用于处理结果的适当函数。

答案 1 :(得分:0)

由于此问题最初得到解答,因此pls包已修改为allow the cross-validation to be run in parallel。实现过程非常简单 - 只需在pls.options中定义持久性集群或瞬态集群中使用的核心数即可。

如果使用瞬态集群,实现只需要两行代码:

library(parallel) 
pls.options(parallel=NumberOfCoresToUse)

不需要更改输出变量。

我没有检查在校准级别进行并行化,如问题所示,是否会更有效。我怀疑它会是这样,特别是当校准迭代次数远大于交叉验证步骤的数量时(特别是当CV的数量不是所用核心数的倍数时),但这种方法非常简单额外的编码工作可能不值得。