如何通过并行化加速tidymodels的Bootstrapping过程
解决rsample Bootstrap并行化及兼容int_pctl的方案
问题背景
我使用rsample包执行Bootstrapping并计算置信区间时,原代码运行速度极慢。尝试用parallel包的mcmapply实现并行化失败,需要找到能兼容int_pctl()函数的并行加速方案。
原代码
library(resample) library(broom) library(dplyr) library(purrr) library(tibble) lm_est <- function(split, ...) { lm(mpg ~ disp + hp, data = analysis(split)) %>% tidy() } set.seed(52156) car_rs <- bootstraps(mtcars, 500, apparent = TRUE) %>% mutate(results = map(splits, lm_est)) int_pctl(car_rs, results) # 关键步骤
原代码运行结果
> int_pctl(car_rs, results) # A tibble: 3 × 6 term .lower .estimate .upper .alpha .method <chr> <dbl> <dbl> <dbl> <dbl> <chr> 1 (Intercept) 27.7 31.0 34.1 0.05 percentile 2 disp -0.0431 -0.0295 -0.0123 0.05 percentile 3 hp -0.0643 -0.0281 -0.00930 0.05 percentile
失败的并行尝试代码
library(parallel) # 设置并行核心数 cores <- detectCores() - 1 cl <- makeCluster(cores) # 用mcmapply并行处理 car_rs$results <- mcmapply(lm_est, car_rs$splits, mc.cores = cores, mc.preschedule = TRUE) stopCluster(cl)
可行解决方案
方案1:用furrr实现并行(推荐,适配tidyverse/rsample生态)
furrr是purrr的并行扩展,完美兼容rsample的结果结构,直接替换map为future_map即可,无需额外调整就能让int_pctl()正常工作。
library(furrr) library(rsample) library(broom) library(dplyr) library(tibble) # 初始化并行环境,保留1个核心给系统 plan(multisession, workers = detectCores() - 1) lm_est <- function(split, ...) { lm(mpg ~ disp + hp, data = analysis(split)) %>% tidy() } set.seed(52156) car_rs <- bootstraps(mtcars, 500, apparent = TRUE) %>% mutate(results = future_map(splits, lm_est)) # 替换map为future_map # 正常调用int_pctl,结果和原代码一致 int_pctl(car_rs, results) # 结束并行环境(可选,R会话关闭时会自动清理) plan(sequential)
方案2:修复parallel包的使用方式
之前的mcmapply失败有两个原因:一是默认简化结果结构,破坏了int_pctl()需要的列表格式;二是并行节点未加载必要的包。修复后可正常运行:
library(parallel) library(rsample) library(broom) library(dplyr) library(tibble) cores <- detectCores() - 1 cl <- makeCluster(cores) # 在所有并行节点加载所需包 clusterEvalQ(cl, { library(rsample) library(broom) library(dplyr) }) # 把自定义函数传给并行节点 clusterExport(cl, "lm_est") lm_est <- function(split, ...) { lm(mpg ~ disp + hp, data = analysis(split)) %>% tidy() } set.seed(52156) car_rs <- bootstraps(mtcars, 500, apparent = TRUE) # 使用parLapply保持列表结构,或mcmapply加SIMPLIFY=FALSE car_rs$results <- parLapply(cl, car_rs$splits, lm_est) # 也可以用:car_rs$results <- mcmapply(lm_est, car_rs$splits, mc.cores = cores, SIMPLIFY = FALSE) stopCluster(cl) # 正常调用int_pctl int_pctl(car_rs, results)
失败原因说明
- 结构不兼容:mcmapply默认
SIMPLIFY=TRUE,会把多个tidy返回的数据框自动转为数组,破坏了int_pctl()需要的列表结构; - 环境缺失:并行节点未加载rsample、broom等包,无法识别
analysis()、tidy()这类函数。
内容的提问来源于stack exchange,提问作者littleworth
相关产品推荐
相关产品推荐

