mlr3中搜索空间参数依赖配置、调优特征查询及filter.nfeat调参与特征选择的对比咨询
问题1:如何设置依赖于K的D值,保证D≤K且为指定比例
你之前用.extra_trafo的思路方向对,但用法不对。在mlr3里要实现参数值的动态依赖,我们有两种靠谱的方式:
方式一:用trafo函数过滤不合法配置
通过转换函数,让网格搜索自动排除不符合D∈{10%,25%,50%,100%}*K且D≤K的组合:
searchspace = ps( importance.filter.nfeat = p_int(lower = 1, upper = length(task$feature_names), id = "K"), classif.ranger.max.depth = p_int(lower = 1, upper = length(task$feature_names), id = "D") ) # 添加转换规则,过滤不合法的(K,D)对 searchspace$trafo = function(x, param_set) { k = x$K # 计算当前K对应的合法D候选值,取整数且≥1 valid_d = round(k * c(0.1, 0.25, 0.5, 1)) valid_d = unique(valid_d[valid_d >= 1 & valid_d <= k]) # 如果当前D不在合法列表里,就排除这个配置 if (!(x$D %in% valid_d)) { return(NULL) } x }
方式二:手动生成所有合法配置(更直观)
直接提前生成所有符合要求的(K,D)组合,让网格搜索只遍历这些合法项,避免过滤逻辑:
# 生成所有K的可能值 all_K = seq(1, length(task$feature_names)) # 对每个K生成对应的合法D值 valid_configs = lapply(all_K, function(k) { d_options = round(k * c(0.1, 0.25, 0.5, 1)) d_options = unique(d_options[d_options >= 1 & d_options <= k]) # 把每个(K,D)对转成配置列表 lapply(d_options, function(d) { list( importance.filter.nfeat = k, classif.ranger.max.depth = d ) }) }) valid_configs = unlist(valid_configs, recursive = FALSE) # 直接把合法配置传给调优实例 inst1 = TuningInstanceMultiCrit$new( task = task, learner = graph_learner, resampling = rsmp("cv"), measures = msrs(c("classif.ce","classif.bacc","classif.mcc")), terminator = trm("evals", n_evals = 50), search_space = valid_configs )
问题2:调优后怎么看实际用的特征?是不是按重要性选的?
查看实际使用的特征
有两种简单的方法可以提取调优后模型用到的特征:
方法一:从最优配置训练的模型中提取
# 获取最优参数配置 best_config = inst1$result_learner_param_vals # 用最优配置训练完整的图学习器 graph_learner$param_set$values = best_config graph_learner$train(task) # 提取filter步骤的筛选结果 filter_step = graph_learner$graph$ops$filter selected_features = filter_step$state$selected_features print(selected_features)
方法二:从调优存档中提取(需提前保存模型)
如果创建调优实例时加了store_models = TRUE,可以直接从存档里拿:
# 创建实例时开启模型保存 inst1 = TuningInstanceMultiCrit$new( task = task, learner = graph_learner, resampling = rsmp("cv"), measures = msrs(c("classif.ce","classif.bacc","classif.mcc")), terminator = trm("evals", n_evals = 50), search_space = valid_configs, store_models = TRUE ) # 找到性能最优的模型索引(这里以分类错误率最低为例) best_idx = which.min(inst1$archive$data$classif.ce) # 提取对应模型的筛选特征 best_model = inst1$archive$learners[[best_idx]] selected_features = best_model$graph$ops$filter$state$selected_features print(selected_features)
是否按重要性排序筛选?
是的!你用的flt("importance")会基于ranger的impurity重要性分数,把特征从高到低排序,然后取前importance.filter.nfeat个。可以用下面的代码验证:
# 单独训练ranger获取特征重要性 ranger_lrn = lrn("classif.ranger", importance = "impurity", predict_type = "prob") ranger_lrn$train(task) importance_scores = ranger_lrn$importance() # 按重要性降序排列特征 sorted_features = names(sort(importance_scores, decreasing = TRUE)) # 对比筛选后的特征,应该是前K个 print(all.equal(selected_features, sorted_features[1:best_config$importance.filter.nfeat]))
问题3:调参
importance.filter.nfeat与特征选择的关系,实践中优先选哪个 核心区别
importance.filter.nfeat调参- 本质是固定逻辑的Top-K筛选:先按特征重要性排序,再调选多少个(K)作为参数。
- 优点:速度极快,不需要遍历所有特征子集,适合高维度数据快速缩小范围;逻辑清晰,解释性强。
- 缺点:只能选连续的Top-K特征,无法发现“非Top-K但组合起来效果更好”的特征子集。
特征选择(比如你用的RFE)
- 本质是搜索最优特征子集:可以是任意组合的特征,不一定是Top-K。
- 优点:能找到更灵活的特征组合,可能挖掘到重要性低但互补的特征,最终性能可能更优。
- 缺点:计算成本极高,特征数量多的时候搜索空间呈指数级增长,耗时很长。
实践选择建议
优先用
importance.filter.nfeat调参的场景:- 数据维度极高(上千个特征),特征选择的计算成本无法承受;
- 更关注模型解释性,需要清晰的特征筛选逻辑;
- 作为特征选择的前置步骤:先通过Top-K调参把特征从几百降到几十,再做特征选择,平衡效率和性能。
优先用特征选择的场景:
- 数据维度适中(几百个以内),计算资源充足;
- 追求最优预测性能,愿意花费时间搜索;
- 业务场景需要特定特征子集(比如排除某些无关特征,而非只按重要性筛选)。
推荐结合使用:
大部分场景下,先通过Top-K调参缩小特征范围,再用RFE等方法在子集中搜索最优组合,既能节省时间,又能得到不错的性能。
内容的提问来源于stack exchange,提问作者LengJH
相关产品推荐
相关产品推荐

