13

我的训练数据集有大约 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))
}

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))
}

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

4

2 回答 2

30

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

这是 cv.glmnet 手册页中“并行”参数的文档:

并行:如果为“真”,则使用并行“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)

这个对 cv.glmnet 的调用将使用四个工作线程并行执行。在 Linux 和 Mac OS X 上,它将使用“mclapply”执行任务,而在 Windows 上,它将使用“clusterApplyLB”。

嵌套并行变得棘手,仅 4 个工作人员可能无济于事。我会尝试在 cv.glmnet 周围使用正常的 for 循环(如在您的第二个示例中)并注册并行后端,并在添加另一个并行度之前查看性能。

另请注意,当您注册并行后端时,第一个示例中对“模型”的分配将不起作用。当并行运行时,副作用通常会被丢弃,就像大多数并行编程包一样。

于 2014-02-11T19:03:24.457 回答
7

偶然发现了这个旧线程,并认为在未来的框架中提及它会很有用,可以进行嵌套和并行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)

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

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

plan(list(
  sequential,
  tweak(multiprocess, workers = 4L)
))

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

plan(list(
  tweak(multiprocess, workers = 4L),
  sequential
))

,或者等价地plan(multiprocess, workers = 4L),在目标上并行化。

于 2017-10-02T20:45:04.063 回答