【问题标题】:executing cv.glmnet in parallel in R在 R 中并行执行 cv.glmnet
【发布时间】:2014-03-09 00:53:46
【问题描述】:

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

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

【问题讨论】:

  • 第二种情况你注册了并行后端吗?哪一个?您想在单台多核计算机上运行还是在集群上运行?
  • 第二个 - 我在 glmnet 中使用了并行选项。据我了解,它使用它来并行化 CV。我正在一台多核计算机上运行(四核,16 GB 内存)

标签: r foreach parallel-processing glmnet


【解决方案1】:

为了并行执行“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)

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

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

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

【讨论】:

  • (+1) 这个答案是正确的。不过,我发现,如果我的设计矩阵太大,R 将不会利用额外的工人,因为我没有足够的内存来存储它的额外副本!
  • @user777 您可能想尝试在多台计算机上使用工作程序,以便访问更多的聚合内存。这可以使用 doParallel 或 doMPI 来完成,但除非您可以访问设置良好的 Linux 集群,否则需要做一些工作。
  • 当然!真正的诀窍是让你的老板相信你需要电脑...... :) 我只是说要向 OP 指出他的桌面显示设置可能不够。
【解决方案2】:

偶然发现了这个旧线程,并认为使用future 框架可以进行嵌套和并行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-01-13
  • 2016-08-07
  • 2016-04-13
  • 1970-01-01
  • 2020-06-11
  • 2012-12-15
  • 2022-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多