Optuna调优LightGBM时固定feature_fraction被自动搜索问题排查
问题根因
Optuna不会修改任何你没通过trial.suggest_*声明的参数,你看到feature_fraction取值波动,完全是代码错误加LightGBM参数逻辑导致的,核心问题有三个:
- 多处LightGBM参数名拼写错误,你写的固定值根本没被框架读到:
- 叶子数参数写成了
numleaves,正确名称是num_leaves,中间漏了下划线 - 最小海森和参数写成了
min_sum_hessianin_leaf,正确名称是min_sum_hessian_in_leaf,hessian和in之间漏了下划线
这些拼错的参数会被LightGBM直接忽略,回退到默认参数校验逻辑,甚至会触发隐式的参数自动适配,让你以为自己设对的参数没生效。
- 叶子数参数写成了
- 错把日志控制参数
verbose当成超参数搜索。这个参数合法值只有三个:-1(静默)、0(仅输出警告)、1(输出训练信息),你给的搜索范围是1-5,当取值大于1时LightGBM会输出调试级别的日志,把每个节点分裂时的临时特征采样占比打出来,你看到的变化的feature_fraction其实是节点级的临时统计值,根本不是全局参数的实际取值。 - 开了
extra_trees=True但没固定专属随机种子extra_seed。Extra Trees模式本身会在每个节点分裂时做随机特征采样、随机阈值选择,没固定这个种子的话,每次节点采样的比例都会随机波动,日志里自然会看到数值变化,但你全局设的feature_fraction=1其实是生效的。
另外你代码里训练集、验证集的变量名也写错了,1gbtrain、1gb_val是非法变量名(Python不允许变量名以数字开头),应该是手滑把小写的l打成了数字1,运行时会直接报错。
修复方法
- 修正所有参数拼写错误,补全缺失的固定随机种子,不要把日志控制参数放进搜索空间,高版本Optuna直接用
suggest_float加log=True替代已经弃用的suggest_loguniform/suggest_uniform,修正后的参数字典如下:
param = { 'objective': 'binary', 'boosting': 'gbdt', 'metric': 'auc', 'max_depth':4, 'seed': 100, 'feature_fraction': 1.0, # 明确传浮点型,避免类型解析歧义 'feature_fraction_seed': 100, 'extra_seed': 100, # 固定extra_trees的随机种子 'bagging_seed': 100, # 固定bagging采样的随机种子 'is_unbalance': True, 'is_provide_training_metric': True, 'extra_trees': True, 'force_col_wise': True, 'verbose': -1, # 固定为静默模式,避免输出冗余调试日志 # 以下为待搜索参数,全部修正参数名拼写 'num_leaves': trial.suggest_int('num_leaves', 10, 16), # max_depth=4时最大叶子数为2^4=16,设30的上限完全无效 'learning_rate': trial.suggest_float('learning_rate', 1e-4, 1e-2), 'min_data_in_leaf': trial.suggest_int('min_data_in_leaf', 10, 80), 'min_sum_hessian_in_leaf':trial.suggest_float('min_sum_hessian_in_leaf', 1e-8, 10.0, log=True), 'max_bin': trial.suggest_int('max_bin', 80, 300), 'lambda_l1': trial.suggest_float('lambda_l1', 1e-5, 1e-1, log=True), 'path_smooth':trial.suggest_float('path_smooth', 0.4, 1.5) }
- 修正训练接口的参数错误,调整不合理的训练配置:
gbm=lgb.train(param, train_set=lgb_train, # 修正变量名 valid_sets=[lgb_val,lgb_train], # 修正变量名 valid_names = ['eval', 'train'], verbose_eval=20, # 日志输出间隔通过这个参数控制,不要改param里的verbose early_stopping_rounds=50, # 原来的5轮太早,很容易欠拟合 num_boost_round=1000) # 原来的10轮迭代严重不足,设大值靠早停自动控制
- 改完之后重启Python内核,清空内存里残留的旧变量、旧study实例再运行,就不会再出现
feature_fraction被乱改的问题,搜索效率也会提升很多。
内容的提问来源于stack exchange,提问作者Amelia
相关产品推荐
相关产品推荐

