在R中并行执行glmnet

Rou*_*use 12 parallel-processing foreach r glmnet

我的训练数据集有大约200,000条记录,我有500个功能.(这些是来自零售组织的销售数据).大多数功能都是0/1,并存储为稀疏矩阵.

目标是预测约200种产品的购买概率.因此,我需要使用相同的500个功能来预测200种产品的购买概率.由于glmnet是模型创建的自然选择,我想到了为200个产品并行实现glmnet.(因为所有200个型号都是独立的)但是我被困在使用foreach.我执行的代码是:

foreach(i = 1:ncol(target)) %dopar%
{
assign(model[i],cv.glmnet(x,target[,i],family="binomial",alpha=0,type.measure="auc",grouped=FALSE,standardize=FALSE,parallel=TRUE))
}
Run Code Online (Sandbox Code Playgroud)

model是一个列表 - 包含200个模型名称的列表,我想在其中存储各自的模型.

以下代码有效.但它没有利用并行结构,需要大约一天才能完成!

for(i in 1:ncol(target))
{ assign(model[i],cv.glmnet(x,target[,i],family="binomial",alpha=0,type.measure="auc",grouped=FALSE,standardize=FALSE,parallel=TRUE))
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,有人能指出如何利用并行结构吗?

Ste*_*ton 23

为了并行执行"cv.glmnet",您必须指定该parallel=TRUE选项,注册foreach并行后端.这允许您选择最适合您的计算环境的并行后端.

以下是cv.glmnet手册页中"并行"参数的文档:

parallel:如果为'TRUE',请使用并行'foreach'来适合每个折叠.必须事先注册并行,例如'doMC'或其他.请参阅下面的示例.

以下是使用适用于Windows,Mac OS X和Linux的doParallel软件包的示例:

library(doParallel)
registerDoParallel(4)
m <- cv.glmnet(x, target[,1], family="binomial", alpha=0, type.measure="auc",
               grouped=FALSE, standardize=FALSE, parallel=TRUE)
Run Code Online (Sandbox Code Playgroud)

这个对cv.glmnet的调用将使用四个worker并行执行.在Linux和Mac OS X上,它将使用"mclapply"执行任务,而在Windows上,它将使用"clusterApplyLB".

嵌套并行性变得棘手,并且对于仅有4个工作者可能没有帮助.我会尝试在cv.glmnet周围使用正常for循环(如第二个示例中所示)并注册并行后端,并在添加另一个并行级别之前查看性能.

另请注意,在注册并行后端时,第一个示例中对"model"的赋值不起作用.当并行运行时,副作用通常会被抛弃,就像大多数并行编程包一样.

  • (+1)这个答案是正确的。但是,我发现,如果我的设计矩阵太大,R不会利用额外的工作程序,因为我没有足够的内存来存储它的其他副本! (2认同)

Hen*_*ikB 6

偶然发现了这个旧线程,并认为提及在未来的框架中可以进行嵌套和并行foreach()调用会很有用。例如,假设您有三台本地机器(通过 SSH 访问)并且您希望在每台机器上运行四个内核,那么您可以使用:

library("doFuture")
registerDoFuture()
plan(list(
  tweak(cluster, workers = c("machine1", "machine2", "machine3")),
  tweak(multiprocess, workers = 4L)
))


model_fit <- foreach(ii = seq_len(ncol(target))) %dopar% {
  cv.glmnet(x, target[,ii], family = "binomial", alpha = 0,
            type.measure = "auc", grouped = FALSE, standardize = FALSE,
            parallel = TRUE)
}
str(model_fit)
Run Code Online (Sandbox Code Playgroud)

“外部” foreach 循环将迭代目标,以便每次迭代都由单独的机器处理。每次迭代将依次cv.glmnet()使用四名工人在它最终使用的任何机器上进行处理。

(当然,如果你只能访问一台机器,那么做嵌套并行处理就没有意义了。我这种情况,你可以使用:

plan(list(
  sequential,
  tweak(multiprocess, workers = 4L)
))
Run Code Online (Sandbox Code Playgroud)

并行化cv.glmnet()调用,或者,

plan(list(
  tweak(multiprocess, workers = 4L),
  sequential
))
Run Code Online (Sandbox Code Playgroud)

,或等效地只是plan(multiprocess, workers = 4L),以并行化目标。