You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Optuna回调结合sklearn cross_validate优化XGBoost时回调失效求助

问题原因分析
  1. cross_validate无法传递验证集给XGBoost:sklearn.cross_validate在训练模型时,不会将交叉验证的验证集传递给XGBoost的训练过程,导致XGBoost没有计算你指定的pre指标,回调函数找不到test-pre这个监控目标,触发警告且无法执行剪枝。
  2. 回调指标名称错误:你设置的回调监控指标是"test-pre",但XGBoost在没有指定eval_set的情况下根本不会生成这个指标;即使指定了eval_set,默认的指标前缀是validation_0而非test。
  3. 回调未关联到训练过程:XGBClassifier的callback参数需要在训练时配合eval_set才能生效,而cross_validate内部的fit调用没有传入eval_set,等于回调没有被激活。
解决方案

替换cross_validate为手动交叉验证循环,在每个fold中明确传入eval_set,确保回调能监控到验证集指标:

import optuna
import xgboost as xgb
from sklearn.model_selection import KFold
from sklearn.metrics import precision_score

def optuna_objective_xgb(trial):
    params = {
        'n_estimators': trial.suggest_categorical('n_estimators', [20, 50, 100, 200]),
        'max_depth': trial.suggest_categorical('max_depth', [14, 18, 22, 26, 30, 34, 38, 42, 46, 50]),
        'learning_rate': trial.suggest_categorical('learning_rate', [0.01, 0.1, 0.3]),
        'gamma': trial.suggest_categorical('gamma', [0, 0.25, 0.5, 1]),
        'reg_lambda': trial.suggest_float('reg_lambda', 0, 1, step=0.1),
        'subsample': trial.suggest_float('subsample', 0.1, 1, step=0.1),
        'colsample_bytree': trial.suggest_float('colsample_bytree', 0.1, 1, step=0.1),
        'min_child_weight': 0,
        'eval_metric': 'pre',
        'random_state': 10,
        'n_jobs': -1
    }

    kf = KFold(n_splits=4, shuffle=True, random_state=10)
    precision_scores = []

    for train_idx, val_idx in kf.split(X_train, y_train):
        X_fold_train, X_fold_val = X_train.iloc[train_idx], X_train.iloc[val_idx]
        y_fold_train, y_fold_val = y_train.iloc[train_idx], y_train.iloc[val_idx]

        # 初始化回调,监控validation_0-pre指标(对应eval_set的第一个验证集)
        pruning_callback = optuna.integration.XGBoostPruningCallback(trial, "validation_0-pre")
        
        model = xgb.XGBClassifier(**params)
        # 训练时传入eval_set和回调,verbose=1可以看到中间输出
        model.fit(
            X_fold_train, y_fold_train,
            eval_set=[(X_fold_val, y_fold_val)],
            callbacks=[pruning_callback],
            verbose=1
        )
        
        y_pred = model.predict(X_fold_val)
        precision = precision_score(y_fold_val, y_pred)
        precision_scores.append(precision)

    return sum(precision_scores) / len(precision_scores)
关键修改点说明
  • 手动交叉验证:用KFold拆分数据,在每个fold中单独训练,确保eval_set被传入fit方法,让XGBoost计算验证集指标。
  • 修正回调指标名:XGBoost对第一个eval_set的指标命名格式是validation_0-<eval_metric>,所以回调监控目标改为"validation_0-pre"。
  • 显式传入回调:在fit时通过callbacks参数传入剪枝回调,同时开启verbose=1查看中间训练输出。
  • 计算指标:手动计算每个fold的precision,最后返回均值,和原代码逻辑一致。
额外注意事项
  • 如果你的数据集是numpy数组而非pandas DataFrame,把iloc换成普通索引即可。
  • 确保Optuna和XGBoost版本兼容,建议使用最新稳定版:pip install --upgrade optuna xgboost scikit-learn

内容的提问来源于stack exchange,提问作者aurfa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 22:09:54