用户,
我正在寻找一种“并行化”我的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
答案 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的数量不是所用核心数的倍数时),但这种方法非常简单额外的编码工作可能不值得。