我正在尝试使用snow包在R中对弹性网模型进行评分,但我无法弄清楚如何让预测函数在集群中的多个节点上运行。下面的代码包含时序基准和产生错误的实际代码:
##############
#Snow example#
##############
library(snow)
library(glmnet)
library(mlbench)
data(BostonHousing)
BostonHousing$chas<-as.numeric(BostonHousing$chas)
ind<-as.matrix(BostonHousing[,1:13],col.names=TRUE)
dep<-as.matrix(BostonHousing[,14],col.names=TRUE)
fit_lambda<-cv.glmnet(ind,dep)
#fit elastic net
fit_en<<-glmnet(ind,dep,family="gaussian",alpha=0.5,lambda=fit_lambda$lambda.min)
ind_exp<-rbind(ind,ind)
#single thread baseline
i<-0
while(i < 2000){
ind_exp<-rbind(ind_exp,ind)
i = i+1
}
system.time(st<-predict(fit_en,ind_exp))
#formula for parallel execution
pred_en<-function(x){
x<-as.matrix(x)
return(predict(fit_en,x))
}
#make the cluster
cl<-makeSOCKcluster(4)
clusterExport(cl,"fit_en")
clusterExport(cl,"pred_en")
#parallel baseline
system.time(mt<-parRapply(cl,ind_exp,pred_en))
我已经能够通过使用多核的Linux机箱上的分叉并行化,但我最终不得不使用性能相当差的mclapply结合unlist并且正在寻找一种更好的方法来实现雪(这将是偶然的工作在我的开发Windows PC和我的prod Linux服务器上)。谢谢你。
答案 0 :(得分:2)
我首先应该说predict.glmnet
函数似乎不够计算,不值得并行化。但这是一个有趣的例子,我的回答可能对你有所帮助,即使这个特殊情况不值得并行化。
主要问题是parRapply
函数是apply
周围的并行包装器,它反过来在子矩阵的行上调用函数,这不是你想要的。您希望直接在子矩阵上调用函数。 Snow不包含这样做的便利功能,但是写一个很容易:
rowchunkapply <- function(cl, x, fun, ...) {
do.call('rbind', clusterApply(cl, splitRows(x, length(cl)), fun, ...))
}
您的示例中的另一个问题是您需要在worker上加载glmnet,以便调用正确的预测函数。您也不需要显式导出pred_en
函数,因为这是为您处理的。
以下是我的示例版本:
library(snow)
library(glmnet)
library(mlbench)
data(BostonHousing)
BostonHousing$chas <- as.numeric(BostonHousing$chas)
ind <- as.matrix(BostonHousing[,1:13], col.names=TRUE)
dep <- as.matrix(BostonHousing[,14], col.names=TRUE)
fit_lambda <- cv.glmnet(ind, dep)
fit_en <- glmnet(ind, dep, family="gaussian", alpha=0.5,
lambda=fit_lambda$lambda.min)
ind_exp <- do.call("rbind", rep(list(ind), 2002))
# make and initialize the cluster
cl <- makeSOCKcluster(4)
clusterEvalQ(cl, library(glmnet))
clusterExport(cl, "fit_en")
# execute a function on row chunks of x and rbind the results
rowchunkapply <- function(cl, x, fun, ...) {
do.call('rbind', clusterApply(cl, splitRows(x, length(cl)), fun, ...))
}
# worker function
pred_en <- function(x) {
predict(fit_en, x)
}
mt <- rowchunkapply(cl, ind_exp, pred_en)
您可能还有兴趣使用cv.glmnet
parallel
选项,该选项使用foreach包。