为何cross_validate不支持XGBClassifier的eval_set参数?
解决cross_validate识别XGBClassifier的eval_set参数问题
问题原因
eval_set是XGBoost模型拟合阶段的参数,而非模型初始化参数。直接把eval_set写在XGBClassifier()的初始化参数中,会被sklearn的cross_validate流程忽略——因为交叉验证会为每个折重新调用fit(),初始化时传入的eval_set不会被传递到fit()方法中,因此触发参数未使用的警告。
方案1:通过fit_params传递eval_set
将eval_set作为fit()方法的参数,通过cross_validate的fit_params参数传入,即可让cross_validate识别该参数。
注意:此方案使用全局的X_train/X_test作为评估集,并非交叉验证折内的验证集,适合你只想跟踪模型在固定数据集上的学习进程场景。
修改后的代码:
from sklearn.model_selection import cross_validate from xgboost import XGBClassifier # 初始化模型时不传入eval_set xgb_clf = XGBClassifier(n_estimators=30, max_depth=3, min_child_weight=4, random_state=42) scores = cross_validate( estimator=xgb_clf, X=data.drop('Y', axis=1), y=data['Y'], # 将eval_set和verbose(可选,用于打印迭代分数)传入fit_params fit_params={ 'eval_set': [(X_train, y_train), (X_test, y_test)], 'verbose': 1 # 启用后会打印每个迭代的评估分数 }, cv=5, error_score='raise', return_train_score=True, return_estimator=True )
方案2:手动实现交叉验证,跟踪折内学习曲线
如果需要严格遵循交叉验证逻辑,跟踪每个折的模型在自身验证集上的学习进程,建议手动实现交叉验证循环,这样可以为每个折的模型传入对应的折内验证集作为eval_set,并保存每个模型的评估结果。
示例代码:
from sklearn.model_selection import KFold from xgboost import XGBClassifier import pandas as pd import matplotlib.pyplot as plt # 初始化交叉验证拆分器 kf = KFold(n_splits=5, shuffle=True, random_state=42) X = data.drop('Y', axis=1) y = data['Y'] # 存储每个折的学习曲线数据 all_evals = [] for fold_idx, (train_idx, val_idx) in enumerate(kf.split(X)): X_fold_train, X_fold_val = X.iloc[train_idx], X.iloc[val_idx] y_fold_train, y_fold_val = y.iloc[train_idx], y.iloc[val_idx] # 初始化模型 xgb_clf = XGBClassifier(n_estimators=30, max_depth=3, min_child_weight=4, random_state=42) # 拟合模型,传入折内的训练集和验证集作为eval_set evals_result = {} xgb_clf.fit( X_fold_train, y_fold_train, eval_set=[(X_fold_train, y_fold_train), (X_fold_val, y_fold_val)], eval_metric='logloss', # 根据你的任务选择合适的评估指标 verbose=1, evals_result=evals_result # 保存评估结果 ) # 将当前折的评估结果整理并存储 fold_evals = pd.DataFrame({ 'fold': fold_idx + 1, 'iteration': range(len(evals_result['validation_0']['logloss'])), 'train_logloss': evals_result['validation_0']['logloss'], 'val_logloss': evals_result['validation_1']['logloss'] }) all_evals.append(fold_evals) # 合并所有折的学习曲线数据 all_evals_df = pd.concat(all_evals) # 绘制学习曲线 plt.figure(figsize=(10,6)) for fold in all_evals_df['fold'].unique(): fold_data = all_evals_df[all_evals_df['fold'] == fold] plt.plot(fold_data['iteration'], fold_data['train_logloss'], label=f'Fold {fold} Train') plt.plot(fold_data['iteration'], fold_data['val_logloss'], label=f'Fold {fold} Val') plt.xlabel('Estimator Iteration') plt.ylabel('Log Loss') plt.title('XGBoost Learning Curves Across Cross-Validation Folds') plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

