mlr3高基数因子编码col_roles报错求助(更新包后仍存在)
mlr3空间任务中使用Impact编码训练glmnet模型的列角色错误解决
问题描述
尝试用mlr3包训练glmnet模型,针对27水平的高基数分类变量采用Impact编码,运行时出现如下错误:
Error in .__Task__col_roles(self = self, private = private, super = super, : Assertion on 'names of col_roles' failed: Names must be a permutation of set {'feature','target','name','order','stratum','group','weight','coordinate','space','time'}, but has extra elements {'always_included'}. This happened PipeOp high_cardinality_encoding's $train()
核心代码如下:
data <- read.csv("C:/Users/test.csv") data$presence <- as.factor(data$presence) data$habitat <- as.factor(data$habitat) classif_task_sp <- mlr3spatial::as_task_classif_st(id = "A1", x = data[, which(!(names(data) %in% c("ID", "year")))], target = "presence", positive = "1", coordinate_names = c("x", "y"), crs = "EPSG:4326", coords_as_features = FALSE) classif_task_sp$set_col_roles("presence", roles = c("target", "stratum")) partition_classif_task_sp <- mlr3::partition(classif_task_sp, ratio = 0.67) factor_encoding <- mlr3pipelines::po("removeconstants") %>% mlr3pipelines::po("encodeimpact", affect_columns = selector_cardinality_greater_than(10), id = "high_cardinality_encoding") %>% mlr3pipelines::po("encode", method = "one-hot", affect_columns = selector_cardinality_greater_than(3), id = "low_cardinality_encoding") %>% mlr3pipelines::po("encode", method = "treatment", affect_columns = selector_type("factor"), id = "binary_encoding") learner_glmnet <- mlr3tuningspaces::lts(mlr3::lrn("classif.glmnet", predict_type = "prob", standardize = FALSE)) learner_glmnet_factor_encoding <- mlr3::as_learner(factor_encoding %>% learner_glmnet) tuning <- mlr3tuning::auto_tuner(tuner = mlr3tuning::tnr("grid_search", resolution = 5, batch_size = 10), learner = learner_glmnet_factor_encoding, resampling = mlr3::rsmp("spcv_coords", folds = 2), measure = mlr3::msr("classif.prauc"), terminator = mlr3tuning::trm("evals", n_evals = 2, k = 0)) run_resampling <- mlr3::resample(classif_task_sp, learner = tuning, resampling = mlr3::rsmp("spcv_coords", folds = 2), store_models = TRUE) run_training <- tuning$train(classif_task_sp, row_ids = partition_classif_task_sp$train)
已更新mlr3至0.21.1、mlr3fselect至1.2.1,错误仍存在。
问题分析
错误根源是mlr3spatial的空间分类任务(TaskClassifST)仅支持固定的标准列角色列表,而流程中引入了mlr3fselect模块的always_included非标准角色,导致角色校验失败。该角色可能来自编码管道的重复变量处理、调优组件的隐式配置冲突。
解决方案
1. 修复编码管道的选择器,避免重复处理
当前编码管道的选择器存在重叠(比如高基数变量可能被后续one-hot/treatment编码再次处理),调整选择器明确划分处理范围:
factor_encoding <- mlr3pipelines::po("removeconstants") %>% # 处理基数>10的高基数变量 mlr3pipelines::po("encodeimpact", affect_columns = selector_cardinality_greater_than(10), id = "high_cardinality_encoding") %>% # 处理基数4-10的中基数变量 mlr3pipelines::po("encode", method = "one-hot", affect_columns = selector_cardinality_between(4, 10), id = "low_cardinality_encoding") %>% # 处理基数≤3的低基数变量 mlr3pipelines::po("encode", method = "treatment", affect_columns = selector_cardinality_less_than_or_equal_to(3), id = "binary_encoding")
2. 移除非标准列角色
在任务传入管道前,手动清理不被支持的列角色:
# 定义空间任务允许的标准列角色 allowed_roles <- c("feature","target","name","order","stratum","group","weight","coordinate","space","time") # 过滤掉非标准角色 classif_task_sp$col_roles <- classif_task_sp$col_roles[names(classif_task_sp$col_roles) %in% allowed_roles]
3. 调整调优学习器的创建方式
mlr3tuningspaces::lts()可能隐式添加特征选择相关配置,改用基础学习器手动绑定调优空间:
# 创建基础glmnet学习器 learner_glmnet <- mlr3::lrn("classif.glmnet", predict_type = "prob", standardize = FALSE) # 绑定glmnet的默认调优空间 learner_glmnet$param_set <- mlr3tuningspaces::ts("classif.glmnet.default")$param_set
4. 逐步排查验证
先跳过调优流程,测试编码管道+学习器的基础训练,确认编码逻辑无问题:
# 测试基础训练流程 test_learner <- mlr3::as_learner(factor_encoding %>% learner_glmnet) test_train <- test_learner$train(classif_task_sp, row_ids = partition_classif_task_sp$train)
若基础训练正常,再逐步添加调优组件排查冲突点。
内容的提问来源于stack exchange,提问作者Marine
相关产品推荐
相关产品推荐

