如何将XGBoost调优元数据转为tidymodels的tune对象用于tune_bayes?
问题:将已有XGBoost调优元数据转换为tidymodels兼容格式用于
tune_bayes 问题背景
多次运行XGBoost调优后,仅保存了包含模型参数与性能的文本元数据,结构如下:
str(p) 'data.frame': 130 obs. of 10 variables: $ mtry : int 922 1046 512 1317 675 1303 518 1029 1345 1180 ... $ min_n : int 34 36 73 89 91 32 73 52 75 93 ... $ tree_depth : int 44 33 43 37 34 48 25 19 38 41 ... $ learn_rate : num 0.0236 0.0257 0.0292 0.0254 0.0271 0.023 0.025 0.0226 0.0281 0.0641 ... $ loss_reduction: num 0.0268 0.745 0.148 0.171 0.0275 ... $ sample_size : num 0.967 0.947 0.789 0.825 0.973 0.521 0.798 0.813 0.993 0.959 ... $ .metric : chr "mn_log_loss" "mn_log_loss" "mn_log_loss" "mn_log_loss" ... $ .estimator : chr "binary" "binary" "binary" "binary" ... $ mean : num 0.423 0.424 0.424 0.424 0.424 0.425 0.425 0.426 0.427 0.427 ... $ std_err : num 0.000382 0.000439 0.000408 0.000344 0.000368 0.000407 0.000386 0.000398 0.000392 0.000441 ...
尝试将该元数据作为tune_bayes的初始输入时,触发报错:
Error in check_initial(): ! initial should be a positive integer or the results of [tune_grid()] Run rlang::last_trace() to see where the error occurred.
可复现代码示例(param为已有元数据):
library(tidyverse) library(tidymodels) data(cells) set.seed(123) df_split <- initial_split(cells %>% select(-case)) df_train <- training(df_split) df_test <- testing(df_split) set.seed(123) df_train_folds <- vfold_cv(df_train, v = 5) # 预处理配方 recipe_df <- recipe(class ~ ., data=df_train) %>% step_zv(all_predictors()) %>% step_normalize(all_numeric_predictors()) xgb_prep<- prep(recipe_df,verbose=T) # 定义XGBoost模型 xgb_spec <- boost_tree( trees = 100, tree_depth = tune(), min_n = tune(), mtry = tune(), loss_reduction = tune(), sample_size = tune(), learn_rate = tune(), ) %>% set_engine('xgboost') %>% set_mode('classification') # 构建工作流 xgb_wf <- workflow() %>% add_model(xgb_spec) %>% add_recipe(xgb_prep) # 设置参数范围 xgb_params <- parameters(xgb_wf) %>% update(learn_rate = learn_rate(c(0.01, 0.3), trans=NULL), tree_depth = tree_depth(c(3, 100)), min_n = min_n(c(1, 10)), loss_reduction = loss_reduction(c(1, 5),trans=NULL), sample_size= sample_prop(c(0.5,1)), mtry = finalize(mtry(), df_train)) # 已有元数据 param <- tibble(mtry = c(36,27), min_n = c(8,25), tree_depth = c(4,6), learn_rate = c(0.116,0.000000111), loss_reduction = c(11.5406445593368101,0.0000001105066459), sample_size = c(0.306 ,0.984 ), metric = "mn_log_loss", estimator = "binary", mean = c(0.404,0.420), std_err = c(0.0137,0.0171)) # 尝试运行tune_bayes options(tidymodels.dark = TRUE) set.seed(123) xgb_res <- tune_bayes( xgb_wf, resamples = df_train_folds, param_info = xgb_params, initial = param, iter =5, metrics = metric_set(mn_log_loss), control = control_bayes(verbose = TRUE, parallel_over = "everything", no_improve = 10) )
解决方案
tune_bayes要求initial参数为tune_grid的输出格式(带tune_results类的交叉验证结果表),需按以下步骤转换已有元数据:
1. 修正列名与结构
确保元数据列名与tidymodels输出一致,并补充交叉验证所需的关键列:
# 修正列名,匹配tidymodels规范 param_fixed <- param %>% rename(.metric = metric, .estimator = estimator) # 生成每个参数组合对应所有交叉验证折的行 initial_results <- param_fixed %>% # 关联所有 Fold ID crossing(id = df_train_folds$id) %>% mutate( .iter = 0, # 初始迭代标记为0 .config = paste0("Pre-set", row_number()), # 每个参数组合的唯一标识 .estimate = mean # 用已有平均性能作为单折性能(若有单折数据可替换) ) %>% # 按tidymodels结果格式排序列 select(id, .iter, .config, mtry, min_n, tree_depth, learn_rate, loss_reduction, sample_size, .metric, .estimator, .estimate) # 标记为tune_results类 class(initial_results) <- c("tune_results", "tbl_df", "tbl", "data.frame")
2. 重新运行tune_bayes
将转换后的initial_results传入initial参数:
set.seed(123) xgb_res <- tune_bayes( xgb_wf, resamples = df_train_folds, param_info = xgb_params, initial = initial_results, iter =5, metrics = metric_set(mn_log_loss), control = control_bayes(verbose = TRUE, parallel_over = "everything", no_improve = 10) )
关键说明
- 必须为每个参数组合补充所有交叉验证折的行,
tune_bayes依赖完整的折级性能数据 - 若原始元数据有单折的详细性能值,替换
.estimate为对应数值可提升结果准确性 - 确保参数列名与模型定义的调优参数完全一致,避免识别失败
内容的提问来源于stack exchange,提问作者arne maa
相关产品推荐
相关产品推荐

