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

Sklearn/imblearn管道交叉验证:是否仅重采样训练集,验证集保持不平衡?

不平衡数据集K折交叉验证+SMOTE重采样的实现说明

imblearn的Pipeline完全可以实现你的需求,且只会在交叉验证的训练折上执行SMOTE重采样,验证折将保持原始的不平衡状态。

核心机制说明

Sklearn(包括imblearn扩展)的交叉验证逻辑严格遵循"训练集单独处理"的原则:

  • 在每一折交叉验证中,先将数据集划分为训练折和验证折
  • 管道中的所有预处理/重采样步骤(比如SMOTE)仅会对训练折执行拟合和转换操作
  • 验证折始终保持原始的不平衡状态,仅用于模型评估,不会被任何重采样操作修改

这样做的目的是避免数据泄露——在真实场景中,你无法对未见过的测试数据做重采样,因此交叉验证必须模拟这种情况,才能得到真实可信的模型评估结果。

代码示例

以下是完整的实现代码,包含数据集生成、管道构建、交叉验证及验证集分布验证:

# 导入依赖库
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score, KFold
from sklearn.svm import SVC
from imblearn.pipeline import Pipeline
from imblearn.over_sampling import SMOTE

# 生成不平衡数据集(类别0占90%,类别1占10%)
X, y = make_classification(
    n_samples=1000, n_features=10, n_informative=2,
    n_redundant=0, n_clusters_per_class=1, weights=[0.9], random_state=42
)

# 构建imblearn管道:先SMOTE重采样,再训练SVM分类器
pipe = Pipeline([
    ('smote', SMOTE(random_state=42)),
    ('classifier', SVC())
])

# 定义5折交叉验证(开启洗牌保证数据分布均匀)
kf = KFold(n_splits=5, shuffle=True, random_state=42)

# 执行交叉验证,计算平均准确率
scores = cross_val_score(pipe, X, y, cv=kf, scoring='accuracy')
print(f"5折交叉验证平均准确率: {scores.mean():.4f} ± {scores.std():.4f}")

# 验证每一折中验证集的原始不平衡状态
for fold_num, (train_idx, val_idx) in enumerate(kf.split(X), 1):
    val_class_counts = np.bincount(y[val_idx])
    print(f"\n第{fold_num}折验证集类别分布:")
    print(f"类别0: {val_class_counts[0]}个,类别1: {val_class_counts[1]}个")
    print(f"类别比例: {val_class_counts[0]/val_class_counts[1]:.2f}:1")

关键细节解释

  • 管道中的SMOTE组件仅在fit阶段对训练集执行重采样,transform阶段不会修改输入数据(直接返回原数据)
  • cross_val_score在每一折中会自动拆分数据,对训练子集调用pipe.fit(),对验证子集仅调用pipe.predict(),因此验证集不会被SMOTE处理
  • 运行代码后可看到,每一折验证集的类别比例始终接近9:1,和原始数据集一致,证明验证集未被重采样

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:26:04