基于mlr3tuning包ti()函数的堆叠学习器调优并行化问题
堆叠学习器调优的并行计算问题
问题背景
我基于mlr3tuning包的ti()函数实现堆叠学习器调优,想集成并行计算提升效率。堆叠结构分为两层:第0层调优9个学习器(classif.gausspr、classif.glmnet、classif.rpart、classif.kknn、classif.svm、classif.gbm、classif.xgboost、classif.ranger、classif.nnet),第1层取这9个学习器预测结果的平均值。mlr3官方的并行调优示例不适用于堆叠场景,现有脚本运行时间极长无法出结果,不确定代码是否正确。
现有堆叠调优核心代码
inner_resampling <- mlr3::rsmp ("cv", folds = 2) performance_measures <- c(mlr3::msr("classif.sensitivity"), mlr3::msr("classif.specificity"), mlr3::msr("classif.acc"), mlr3::msr("classif.auc")) terminator <- mlr3tuning::trm("evals", n_evals = 100) tuner <- mlr3tuning::tnr("mbo") ## Create tuning instance instance <- mlr3tuning::ti(task = task, learner = lrn_graph_1, resampling = inner_resampling, measures = performance_measures, terminator = terminator) ## Run the tuning process tuner$optimize(create_tuning_instance)
设想的并行方案(可行性存疑)
- 步骤1:创建学习器列表
learner_list - 步骤2:对每个学习器并行调优
cl <- parallel::makeCluster(4, outfile = "Output.txt") doSNOW::registerDoSNOW(cl) tuner_output_list <- foreach::foreach(learner_ID = 1:9, .errorhandling = "pass") %dopar% { ## Run the function "ti()" for each learner run_tuner <- mlr3tuning::ti(tuner = tuner, learner = learner_list[[learner_ID]], resampling = resampling, measure = measure, terminator = terminator) } parallel::stopCluster(cl)
- 步骤3:获取调优结果
- 步骤4:将调优后的学习器用
mlr_learners_classif.avg组合(未明确实现方式)
问题分析与解决方案
现有代码的核心问题
- 参数调用错误:
tuner$optimize(create_tuning_instance)中的参数应为之前创建的instance对象,参数错误会导致逻辑异常,甚至无意义的计算。 - 调优空间爆炸:直接对整个堆叠图调优,相当于同时优化9个学习器的超参数,搜索空间是所有学习器超参数的笛卡尔积,100次评估远不足以覆盖,这是运行缓慢的核心原因。
- 未启用并行:现有代码未配置mlr3的并行机制,默认单线程运行,进一步拖慢速度。
并行方案的可行性与落地实现
你设想的分层独立调优+并行执行是堆叠调优的合理思路,能大幅降低计算复杂度,具体实现步骤如下:
1. 并行调优每个基础学习器
library(mlr3) library(mlr3tuning) library(foreach) library(doSNOW) library(parallel) # 初始化带超参数搜索空间的基础学习器列表 learner_list <- list( lrn("classif.gausspr", param_set = ps(sigma = p_dbl(lower = 0.01, upper = 10))), lrn("classif.glmnet", param_set = ps(alpha = p_dbl(0,1), lambda = p_dbl(0.001, 1))), lrn("classif.rpart", param_set = ps(cp = p_dbl(0, 0.1))), lrn("classif.kknn", param_set = ps(k = p_int(1, 20))), lrn("classif.svm", param_set = ps(cost = p_dbl(0.1, 10), gamma = p_dbl(0.01, 1))), lrn("classif.gbm", param_set = ps(n.trees = p_int(100, 500), shrinkage = p_dbl(0.01, 0.1))), lrn("classif.xgboost", param_set = ps(eta = p_dbl(0.01, 0.3), max_depth = p_int(3, 10))), lrn("classif.ranger", param_set = ps(mtry = p_int(1, task$ncol-1), num.trees = p_int(100, 500))), lrn("classif.nnet", param_set = ps(size = p_int(1, 10), decay = p_dbl(0.001, 0.1))) ) # 配置并行集群 cl <- makeCluster(4, outfile = "Output.txt") registerDoSNOW(cl) # 并行调优每个学习器,返回调优后的模型 tuner_output_list <- foreach(learner = learner_list, .packages = c("mlr3", "mlr3tuning")) %dopar% { instance <- ti( task = task, learner = learner, resampling = rsmp("cv", folds = 2), measures = msr("classif.acc"), # 优先用核心指标加速调优 terminator = trm("evals", n_evals = 100) ) tnr("mbo")$optimize(instance) # 把最优参数赋值给学习器 instance$learner$param_set$values <- instance$result_learner_param_vals instance$learner } stopCluster(cl)
2. 构建并评估堆叠学习器
用mlr3pipelines将调优后的基础学习器组合成堆叠模型,第1层用平均融合:
library(mlr3pipelines) # 创建基础学习器分支 base_learners <- lapply(tuner_output_list, function(lrn) po("learner", lrn)) # 拼接成堆叠图:分支并行计算 -> 结果平均 graph <- gunion(base_learners) %>>% po("classif.avg") # 转换为可训练的堆叠学习器 stack_learner <- as_learner(graph) # 外部验证堆叠模型性能 outer_resampling <- rsmp("cv", folds = 5) resample(task, stack_learner, outer_resampling, measures = performance_measures)
额外优化建议
- 精简调优指标:调优阶段用核心指标(如
classif.acc),多指标评估放在最终模型验证环节,减少计算量。 - 调整终止条件:若100次评估仍慢,可减少
n_evals或改用时间终止器(trm("time", secs = 3600))。 - 使用mlr3内置并行:通过
future包配置全局并行,更贴合mlr3框架:library(future) plan(multisession, workers = 4) # 开启4线程并行 # 后续调优、重采样会自动并行执行
内容的提问来源于stack exchange,提问作者Marine
相关产品推荐
相关产品推荐

