如何用K折交叉验证训练可预测的XGBoost二分类模型?
问题描述
我需要训练一个XGBoost二分类器,带标签的训练数据存储在libsvm格式的txt文件中。当前数据集极度不平衡,一类约200个样本,另一类约66000个样本。导师建议不要使用标准的训练测试拆分,而是采用K折交叉验证(K-fold CV)。但我之前仅用K折交叉验证做模型性能评估,不清楚如何用它替代训练测试拆分来得到可用于预测新样本的模型。我尝试过xgb.cv和cross_val_score,但这些方法仅输出模型分数,无法得到可用于预测新样本标签的模型。我是否需要手动进行K折训练?希望能得到相关代码示例。另外,我还被告知不能对该分类器数据做类别平衡,因为需要先得到基线模型。
当前代码仅输出准确率分数,无法得到可用于预测的模型:
from numpy import mean from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from xgboost import XGBClassifier # generate dataset X, y = load_svmlight_file(file_path) # define model model = XGBClassifier() # define evaluation procedure cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1) # evaluate model scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1) mean_accuracy = scores.mean() print(f'Mean Accuracy: {mean_accuracy}')
解决方案
核心结论
是的,你需要手动实现K折训练流程——因为cross_val_score这类工具仅负责性能评估,不会保留训练好的可预测模型。针对不平衡数据集的基线模型需求,推荐两种实用方案:
方案1:K折评估+全量数据训练基线模型
这是基线模型的标准做法:先用K折验证得到可靠的性能指标,再用全部数据训练一个可直接用于预测的最终模型。
import numpy as np from sklearn.model_selection import cross_val_score, RepeatedStratifiedKFold from sklearn.datasets import load_svmlight_file from xgboost import XGBClassifier # 加载libsvm格式数据 file_path = "your_data.txt" X, y = load_svmlight_file(file_path) # 1. 用重复分层K折做性能评估(适配不平衡数据,符合导师要求) cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1) base_model = XGBClassifier() # 建议针对不平衡数据,同时关注F1/Recall,而不只是准确率 scores = cross_val_score(base_model, X, y, scoring='f1', cv=cv, n_jobs=-1) print(f"Mean CV F1 Score: {np.mean(scores):.4f}") # 2. 用全部数据训练最终基线模型(不做类别平衡) final_model = XGBClassifier() final_model.fit(X, y) # 预测新样本示例 # new_X = load_svmlight_file("new_samples.txt")[0] # preds = final_model.predict(new_X)
方案2:手动K折训练+集成模型预测
如果担心全量训练过拟合,可以保留每个折训练的模型,预测时综合所有模型的结果(比如多数投票):
import numpy as np from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.datasets import load_svmlight_file from xgboost import XGBClassifier file_path = "your_data.txt" X, y = load_svmlight_file(file_path) cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1) trained_models = [] cv_scores = [] # 手动遍历每个交叉验证折 for train_idx, val_idx in cv.split(X, y): X_train, X_val = X[train_idx], X[val_idx] y_train, y_val = y[train_idx], y[val_idx] # 训练基线模型(不设置类别平衡参数) model = XGBClassifier() model.fit(X_train, y_train) # 记录分数并保存模型 score = model.score(X_val, y_val) cv_scores.append(score) trained_models.append(model) print(f"Mean CV Accuracy: {np.mean(cv_scores):.4f}") # 集成模型预测函数(多数投票逻辑) def ensemble_predict(models, new_X): all_preds = [model.predict(new_X) for model in models] # 对每个样本的所有模型预测取均值后四舍五入,实现多数投票 return np.round(np.mean(all_preds, axis=0)).astype(int) # 预测新样本示例 # new_X = load_svmlight_file("new_samples.txt")[0] # ensemble_preds = ensemble_predict(trained_models, new_X)
关键注意事项
- 针对极度不平衡数据集,准确率不是最优评估指标,建议将
cross_val_score的scoring参数改为'f1'、'recall'或'precision',更能反映模型对少数类的识别能力 - 基线模型要求不做类别平衡,因此不要设置
XGBClassifier的scale_pos_weight参数,保持默认即可
内容的提问来源于stack exchange,提问作者sshen
相关产品推荐
相关产品推荐

