使用mlr3的auto_tuner()调用Hyperband/MBO调参报错,tune()正常
mlr3 auto_tuner调XGBoost参数报错解决
问题描述
使用mlr3分析含100个特征的数据集,通过Pipeline串联预处理步骤与XGBoost学习器,调用auto_tuner()搭配Hyperband或MBO调参时触发参数缺失错误,但直接使用tune()函数无此问题。
相关代码
learner <- po("encode", method = "treatment", affect_columns = selector_type("factor")) %>>% po("scale") %>>% po("learner", lrn("classif.xgboost", predict_type = "prob", nrounds = to_tune(p_int(1, 5000, tags="budget")), eta = to_tune(1e-4, 1, logscale = TRUE), max_depth = to_tune(1, 20), colsample_bytree = to_tune(1e-1, 1), colsample_bylevel = to_tune(1e-1, 1), lambda = to_tune(1e-3, 1e3, logscale = TRUE), alpha = to_tune(1e-3, 1e3, logscale = TRUE), subsample = to_tune(1e-1, 1))) at <- auto_tuner( tuner = tnr("hyperband", eta = 2), learner = learner, resampling = rsmp("cv", folds=2), measure = msr("classif.auc"), terminator = trm("none"), store_models = TRUE, evaluate_default = TRUE) at$train(task_US)
报错信息
Error in .__OptimInstance__eval_batch(self = self, private = private, : Assertion on 'colnames(xdt)' failed: Names must include the elements {'classif.xgboost.nrounds','classif.xgboost.eta','classif.xgboost.max_depth','classif.xgboost.colsample_bytree','classif.xgboost.colsample_bylevel','classif.xgboost.lambda','classif.xgboost.alpha','classif.xgboost.subsample'}, but is missing elements {'classif.xgboost.nrounds'}.
问题原因
当在Pipeline的po("learner")中为XGBoost的nrounds参数设置to_tune(p_int(..., tags="budget"))时,auto_tuner会将带budget标签的参数识别为Hyperband专属的预算参数,不会将其纳入普通调参参数列表,导致优化实例调用时缺失该参数。而tune()函数不会做这种特殊识别,会正常处理所有标记为to_tune的参数,因此无报错。
解决方案
方案1:移除nrounds的budget标签
如果不需要将nrounds作为Hyperband的预算参数,直接去掉tags="budget",让它作为普通调参参数参与优化:
learner <- po("encode", method = "treatment", affect_columns = selector_type("factor")) %>>% po("scale") %>>% po("learner", lrn("classif.xgboost", predict_type = "prob", nrounds = to_tune(p_int(1, 5000)), # 移除budget标签 eta = to_tune(1e-4, 1, logscale = TRUE), max_depth = to_tune(1, 20), colsample_bytree = to_tune(1e-1, 1), colsample_bylevel = to_tune(1e-1, 1), lambda = to_tune(1e-3, 1e3, logscale = TRUE), alpha = to_tune(1e-3, 1e3, logscale = TRUE), subsample = to_tune(1e-1, 1)))
方案2:明确指定Hyperband的预算参数
如果需要保留nrounds作为Hyperband的预算参数,在auto_tuner中通过budget_variable参数明确指定该参数的完整名称,确保调参器正确识别:
at <- auto_tuner( tuner = tnr("hyperband", eta = 2), learner = learner, resampling = rsmp("cv", folds=2), measure = msr("classif.auc"), terminator = trm("none"), store_models = TRUE, evaluate_default = TRUE, budget_variable = "classif.xgboost.nrounds" # 明确指定预算参数 )
方案3:用GraphLearner包装Pipeline
将Pipeline转换为GraphLearner对象后再传入auto_tuner,避免参数识别异常:
# 定义Pipeline图 learner_graph <- po("encode", method = "treatment", affect_columns = selector_type("factor")) %>>% po("scale") %>>% po("learner", lrn("classif.xgboost", predict_type = "prob", nrounds = to_tune(p_int(1, 5000, tags="budget")), eta = to_tune(1e-4, 1, logscale = TRUE), max_depth = to_tune(1, 20), colsample_bytree = to_tune(1e-1, 1), colsample_bylevel = to_tune(1e-1, 1), lambda = to_tune(1e-3, 1e3, logscale = TRUE), alpha = to_tune(1e-3, 1e3, logscale = TRUE), subsample = to_tune(1e-1, 1))) # 转换为GraphLearner learner <- GraphLearner$new(learner_graph) # 创建auto_tuner at <- auto_tuner( tuner = tnr("hyperband", eta = 2), learner = learner, resampling = rsmp("cv", folds=2), measure = msr("classif.auc"), terminator = trm("none"), store_models = TRUE, evaluate_default = TRUE)
内容的提问来源于stack exchange,提问作者Jemay
相关产品推荐
相关产品推荐

