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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 01:23:41