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

XGBRegressor结合EarlyStopping在cross_val_predict中报错的问题咨询

问题解答

一、validation_0与eval_set的关联逻辑

在XGBoost的fit方法中,当你传入eval_set=[(X, y)]时,XGBoost会自动为每个传入的验证集分配默认命名:第一个验证集叫validation_0,第二个叫validation_1,以此类推。

官方示例里的EarlyStopping设置data_name="validation_0",就是明确指定要监控第一个验证集的指标(这里是mlogloss),当该指标在连续rounds=2轮迭代中没有达到min_delta的提升时,触发早停逻辑。两者的关联完全依赖这个默认命名规则。

二、交叉验证中EarlyStopping报错的问题分析与解决

错误原因

你使用cross_val_predict时,这个函数默认只会把当前折的训练数据传给模型fit,不会自动将折内的测试集作为验证集传入eval_set。而EarlyStopping必须依赖至少一个验证集来监控指标,因此抛出ValueError: Must have at least 1 validation dataset for early stopping。

解决方法

放弃使用cross_val_predict,手动实现交叉验证循环,在每个折内明确拆分训练集和验证集,并将验证集传入模型的fit方法的eval_set参数中。

修改后的代码示例:

import xgboost as xgb
from sklearn.model_selection import KFold
import numpy as np

class CustomEarlyStopping(xgb.callback.EarlyStopping):
    def __init__(self, rounds=2, min_delta=1e-3, save_best=True, maximize=False, data_name="validation_0", metric_name="rmse"):
        super().__init__(rounds=rounds, min_delta=min_delta, save_best=save_best, maximize=maximize, data_name=data_name, metric_name=metric_name)

# 10次10折交叉验证
cvx = KFold(n_splits=10, shuffle=True, random_state=239)
es = CustomEarlyStopping()

model_base = xgb.XGBRegressor(colsample_bytree=0.3, learning_rate=0.1, max_depth=10, alpha=10, 
                              n_estimators=500, n_jobs=-1, random_state=239, callbacks=[es])
model_base.set_params(tree_method='approx', device="cpu")

cv_preds = []

# 外层10次循环
for _ in range(10):
    fold_preds = []
    # 内层10折拆分
    for train_idx, val_idx in cvx.split(X_train, y_train):
        X_tr, y_tr = np.asarray(X_train)[train_idx], np.asarray(y_train)[train_idx]
        X_val, y_val = np.asarray(X_train)[val_idx], np.asarray(y_train)[val_idx]
        
        # 初始化新模型(避免跨折的状态污染)
        model = xgb.XGBRegressor(**model_base.get_params())
        # 传入验证集,让EarlyStopping生效
        model.fit(X_tr, y_tr, eval_set=[(X_val, y_val)], verbose=False)
        
        # 预测当前折的验证集
        fold_preds.append(model.predict(X_val))
    
    # 将当前10折的预测结果合并为一个数组
    cv_preds.append(np.concatenate(fold_preds))

关键注意点

  • 每次折训练都要初始化新的模型实例,避免上一轮折的早停状态影响当前折。
  • 必须在fit时传入eval_set,确保EarlyStopping能拿到验证集指标。
  • 最后将每个折的预测结果拼接成完整的数组,和cross_val_predict的输出格式一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 23:21:27