首页 文章

在R中并行执行glmnet

提问于
浏览
9

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

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

2 回答

  • 3

    为了并行执行"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的调用将使用四个worker并行执行 . 在Linux和Mac OS X上,它将使用“mclapply”执行任务,而在Windows上,它将使用“clusterApplyLB” .

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

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

  • 20

    偶然发现这个旧线程并认为使用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)
    

    "outer" foreach循环将迭代目标,以便每个迭代由单独的机器处理 . 每次迭代都将使用四个工作人员在最终的任何机器上处理 cv.glmnet() .

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

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

    并行化 cv.glmnet() 呼叫,或者,

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

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

相关问题