2

用户,

我正在寻找一种解决方案来“并行化”我的 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选项会解决这个问题?

非常感谢您的帮助!

最好的,切加

4

2 回答 2

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是用于处理结果的适当函数。

于 2013-05-10T18:27:43.030 回答
0

由于最初回答了这个问题,因此修改了 pls 包以允许并行运行交叉验证。实现非常简单——只需在pls.options.

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

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

无需更改输出变量。

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

于 2015-04-23T16:39:41.247 回答