tidymodels贝叶斯优化调优xgboost触发grid_latin_hypercube报错
报错成因
tune_bayes()的param_info入参要求接收dials包构造的超参数规则集合,不支持直接传入expand.grid()生成的候选组合数据框。你把全量组合数据框传给param_info后,函数内部调用拉丁超立方采样生成初始搜索点时,无法识别data.frame类的输入,直接触发了grid_latin_hypercube方法不匹配的报错。- 控制台提示的「1728个调优参数」是传错参数后的连带bug:函数把你传入的1728行组合数据框误识别为1728个独立待调参数,不是你真的设置了上千个待优化参数。
- 原始代码里还有一处参数名不匹配问题:超参数表中写的
sample_prop和boost_tree()定义里的sample_size = tune()命名不一致,就算解决了类型问题,这处错误也会导致后续运行失败。 - 另外mtcars仅32条样本,10折分层抽样触发了样本量不足的警告,小样本场景不需要强制做分层抽样。
修复步骤
- 构造符合dials规范的超参数规则,用
value_set()限定每个超参数只能取你预设的候选值,保证贝叶斯优化搜索时不会超出你给定的取值范围:
params <- parameters( trees = trees(range = c(500, 1000)) %>% value_set(c(500, 700, 900, 1000)), min_n = min_n(range = c(10, 40)) %>% value_set(seq(10, 40, by = 10)), tree_depth = tree_depth(range = c(6, 10)) %>% value_set(seq(6L, 10L, by = 2L)), learn_rate = learn_rate(range = c(0.1, 1)) %>% value_set(c(0.1, 0.6, 1)), loss_reduction = loss_reduction(range = c(0.1, 1)) %>% value_set(c(0.1, 0.6, 1)), sample_size = sample_prop(range = c(0.1, 1)) %>% value_set(c(0.1, 0.6, 1)), mtry = mtry(range = c(2, 7)) %>% value_set(seq(2, 7, by = 1)) )
- 修正
expand.grid()的列名,把sample_prop改成和模型一致的sample_size,这个表作为贝叶斯优化的初始搜索网格传入,而不是传给param_info:
initial_grid <- expand.grid( trees = seq(500, 1000, by = 200), min_n = seq(10, 40, by = 10), tree_depth = seq(6L, 10L, by = 2L), learn_rate = seq(0.1, 1, by = 0.5), loss_reduction = seq(0.1, 1, by = 0.5), sample_size = seq(0.1, 1, by = 0.5), mtry = seq(2, 7, by = 1) )
- 调整重抽样和调参函数调用,去掉小样本下不适用的分层抽样参数,把超参数规则和初始网格传给对应入参:
set.seed(123) # 32个样本无需分层抽样 resampling <- vfold_cv(data = data.training, v = 10) doParallel::registerDoParallel() set.seed(456) res <- tune_bayes( xgboost_workflow, iter = 6, resamples = resampling, param_info = params, # 传入dials格式的超参数取值规则 initial = initial_grid, # 传入你预先生成的固定候选组合作为初始搜索点 metrics = metric_set(mae), control = control_bayes( verbose = TRUE, save_pred = TRUE ) )
注意:贝叶斯优化是序列迭代式搜索算法,不需要提前枚举所有可能的超参数组合,只要通过
value_set()限定每个参数的合法候选值,算法每轮迭代选点时就只会从你给定的候选值里生成组合,不会超出预设范围。
内容的提问来源于stack exchange,提问作者Patric
相关产品推荐
相关产品推荐

