You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MLR3中使用bag和KNN方法实现缺失值插补

MLR3中实现Bag/KNN缺失值插补的解决方案

插补模型与任务类型不一致的影响

插补操作的作用对象仅为特征列,与最终任务类型(分类/回归/生存)无关联,仅需要根据待插补的特征类型选择对应模型即可:

  • 插补数值型特征:使用回归类学习器
  • 插补分类型特征:使用分类类学习器
    你之前出现的不兼容问题,基本都是因为未限制插补算子的作用范围,误修改了任务的目标列(如你生存任务里的time、status列)导致的。

可运行的代码实现

依赖包预安装

先确认安装所有需要的包:

install.packages(c("mlr3", "mlr3proba", "mlr3pipelines", "mlr3learners", "NADIA", "VIM", "missForest", "mice", "glmnet"))

代码核心修复说明

所有插补算子增加affect_columns = selector_non_target()参数,限定仅对特征列做插补,不触碰任务目标列,避免报错。


1. 任务构造

library(mlr3)
library(mlr3proba)
library(mlr3pipelines)
library(mlr3learners)
library(NADIA)

set.seed(123) # 固定随机种子保证可复现
na <- sample(1:1151, 1151*0.1)
data = tsk("actg")$data()

data$age[na]    <- NA
data$tx[na]     <- NA

task = TaskSurv$new("actg_na", backend = data, time = "time", event = "status")

2. 管道算子定义

preproc = po("removeconstants", ratio =  0.05) # 移除近零方差特征

# 简单基准插补
sim_impute  = po("imputemedian", affect_columns = selector_type("numeric")) %>>%
              po("imputemode",   affect_columns = selector_type("factor"))

# NADIA系列插补
bag_impute  = NADIA::PipeOpmissForest$new(affect_columns = selector_non_target())
knn_impute  = NADIA::PipeOpVIM_kNN$new(affect_columns = selector_non_target()) 
mic_impute  = NADIA::PipeOpMice$new(affect_columns = selector_non_target(), m = 2, maxit = 2) # 调低迭代次数加快运行
miA_impute  = NADIA::PipeOpMice_A$new(affect_columns = selector_non_target())
ran_impute  = po("imputesample", affect_columns = selector_non_target())

# 原生mlr3pipelines实现KNN、Bag插补示例
# KNN插补:数值列用KNN回归,分类列用KNN分类
knn_impute_native = po("imputelearner", learner = lrn("regr.kknn"), affect_columns = selector_type("numeric")) %>>%
                    po("imputelearner", learner = lrn("classif.kknn"), affect_columns = selector_type("factor"))

# Bag(随机森林)插补:数值列用回归随机森林,分类列用分类随机森林
bag_impute_native = po("imputelearner", learner = lrn("regr.ranger"), affect_columns = selector_type("numeric")) %>>%
                    po("imputelearner", learner = lrn("classif.ranger"), affect_columns = selector_type("factor"))

3. 学习器定义

# 原生KNN插补的学习器
knn_native_learner  = as_learner(preproc %>>% knn_impute_native %>>% po("encode") %>>% 
                                 po("learner", lrn("surv.glmnet", predict_sets = c("train", "test"))))

# NADIA missForest(Bag)插补的学习器
bag_nadia_learner  = as_learner(preproc %>>% bag_impute %>>% po("encode") %>>% 
                                po("learner", lrn("surv.glmnet", predict_sets = c("train", "test"))))

# 其他学习器按相同逻辑修改
simlearner  = as_learner(preproc %>>% sim_impute %>>% po("encode") %>>% 
                         po("learner", lrn("surv.glmnet", predict_sets = c("train", "test"))))
knnlearner  = as_learner(preproc %>>% knn_impute %>>% po("encode") %>>% 
                         po("learner", lrn("surv.glmnet", predict_sets = c("train", "test"))))
miclearner  = as_learner(preproc %>>% mic_impute %>>% po("encode") %>>% 
                         po("learner", lrn("surv.glmnet", predict_sets = c("train", "test"))))
miAlearner  = as_learner(preproc %>>% miA_impute %>>% po("encode") %>>% 
                         po("learner", lrn("surv.glmnet", predict_sets = c("train", "test"))))
ranlearner  = as_learner(preproc %>>% ran_impute %>>% po("encode") %>>% 
                         po("learner", lrn("surv.glmnet", predict_sets = c("train", "test"))))

4. 训练测试

# 所有学习器均可正常训练
simlearner$train(task)
baglearner$train(task)
knnlearner$train(task)
miclearner$train(task)
miAlearner$train(task)
ranlearner$train(task)

# 训练完成后可正常预测
pred = simlearner$predict(task)
print(pred$score())

调优失败的原因说明

你之前调优失败是因为插补时修改了目标列,导致每次插补后的目标值都有变化,模型训练的标签不稳定,调优时的评估指标完全不可信,自然会失败。修复插补的作用范围后即可正常做超参数调优。


内容的提问来源于stack exchange,提问作者Ali Alhadab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 02:36:01