在R的mlr3中使用Bootstrap重采样集成学习器时遇重复row_ids错误
Bootstrap重采样在mlr3集成模型中因重复row_ids报错的问题解决
问题描述
使用mlr3构建集成学习器时,执行Bootstrap重采样出现报错,提示row_ids存在重复值,但单学习器执行相同重采样逻辑可正常运行。报错信息如下:
Error in as_data_backend.data.frame(data, primary_key = row_ids):
Assertion on 'data[[primary_key]]' failed: Contains duplicated
values, position 8.
This happened PipeOp regr.lm's $train()
可复现代码:
library(mlr3) library(mlr3learners) library(mlr3pipelines) library(progressr) lgr::get_logger("mlr3")$set_threshold("warn") ens.lrnr <- gunion(list( po("learner_cv",lrn("regr.lm")), po("learner_cv",lrn("regr.rpart")))) %>>% po("featureunion") %>>% lrn("regr.lm", id="master") |> as_learner() task <- tsk("boston_housing") task$select(task$feature_names[! task$feature_names %in% "town"]) boot_res <- function(.lrnr) { progressr::with_progress(expr = { mlr3::resample( task = task, learner = .lrnr, resampling = rsmp("bootstrap", repeats = 100, ratio = 1), store_models = FALSE ) }) } # 单学习器可正常运行 rpart_boot <- boot_res(lrn("regr.rpart")) # 集成学习器运行失败 ens_boot <- boot_res(ens.lrnr)
原因分析
Bootstrap重采样是有放回抽样,出现重复row_ids属于正常现象。但集成学习器中的po("learner_cv")会将交叉验证得到的预测值作为新特征,与原任务数据合并。此时原任务的row_ids因Bootstrap抽样重复,合并后的数据无法生成合法的数据后端(mlr3要求数据后端的主键必须唯一),因此触发报错。而单学习器无需合并交叉验证预测值与原数据,所以不会出现该问题。
解决方案
在集成学习器的特征合并步骤后,添加一个重置row_ids的操作,确保数据主键唯一。可以自定义PipeOp来完成这个操作,也可以在每个learner_cv输出后处理数据的row_ids。
方法1:自定义重置row_ids的PipeOp
# 定义重置row_ids的PipeOp po_reset_rowids <- po("rowapply", applicator = function(task) { task$set_row_ids(seq_len(task$nrow)) task }) # 重构集成学习器 ens.lrnr <- gunion(list( po("learner_cv", lrn("regr.lm")), po("learner_cv", lrn("regr.rpart")) )) %>>% po("featureunion") %>>% po_reset_rowids %>>% lrn("regr.lm", id="master") |> as_learner()
方法2:在learner_cv后清除rownames
ens.lrnr <- gunion(list( po("learner_cv", lrn("regr.lm")) %>>% po("colapply", applicator = function(x) { rownames(x) <- NULL x }), po("learner_cv", lrn("regr.rpart")) %>>% po("colapply", applicator = function(x) { rownames(x) <- NULL x }) )) %>>% po("featureunion") %>>% lrn("regr.lm", id="master") |> as_learner()
修改后执行ens_boot <- boot_res(ens.lrnr)即可正常完成Bootstrap重采样。
内容的提问来源于stack exchange,提问作者Hugh Graham
相关产品推荐
相关产品推荐

