类别不平衡时采样需按目标选择策略:保分布、保测试可信度或保业务指标;采样必须在交叉验证每折内仅对训练集进行,验证/测试集保持原分布;smote适用于连续特征且样本充足场景,否则用randomoversampler。

直接上结论:类别不平衡时,采样不是“选个库调个函数”就能解决的,关键看你是想保训练集分布、保测试集可信度,还是保业务指标——不同目标对应完全不同的采样策略和位置。
采样必须放在交叉验证的每一折里,不能在划分前全局做
常见错误是先用 imblearn.over_sampling.SMOTE 对整个数据集重采样,再切训练/验证/测试集。这会导致验证集和测试集“偷看到”训练样本的合成特征,严重高估模型性能,尤其在小样本或高维场景下,ValueError: Found array with 0 sample(s) 或 AUC 虚高 0.15+ 都很常见。
- 正确做法:在每轮
sklearn.model_selection.StratifiedKFold的训练索引上单独做采样,验证索引保持原样 - 验证集和测试集绝对不参与任何采样——它们必须反映真实分布
- 如果用
imblearn.pipeline.Pipeline,确保SMOTE步骤只作用于训练路径,且fit仅在训练折上调用
过采样选 SMOTE 还是 RandomOverSampler?看特征类型和噪声容忍度
SMOTE 在数值型特征上能生成合理插值点,但对类别型特征(如 one-hot 编码后的字段)或含大量离群点的数据,容易生成无效样本,导致决策边界模糊;RandomOverSampler 简单复制少数类样本,稳定但可能加剧过拟合。
- 连续特征为主 + 样本量 ≥ 500 → 优先试
SMOTE(k_neighbors=3),k 太大会引入噪声 - 含大量类别特征 / 样本量 RandomOverSampler(random_state=42)
- 混合类型特征 → 用
imblearn.over_sampling.SMOTENC,显式指定类别列索引,否则报错ValueError: Expected numerical data
欠采样慎用,除非你明确接受信息损失
RandomUnderSampler 直接丢弃多数类样本,在多数类本身样本有限(比如总样本
- 仅当多数类样本充足(≥ 10× 少数类)且训练速度是瓶颈时才考虑
- 优先用
EditedNearestNeighbours或OneSidedSelection,它们基于 KNN 删除边界混乱样本,比随机丢弃更保留分布形态 - 永远检查欠采样后多数类的标签分布是否仍覆盖所有业务子类——比如删完后“iOS 用户”全没了,模型上线就崩
采样后必须重新校准概率输出
过采样会让模型输出的概率值系统性偏高(比如预测“欺诈”的概率普遍虚高 0.2),直接阈值截断会大幅降低召回;欠采样则让概率整体偏低。不校准就上生产,F1 和业务指标会严重失真。
- 用
sklearn.calibration.CalibratedClassifierCV包裹你的分类器,method='isotonic'对小样本更鲁棒 - 校准必须在采样后的训练集上做,且验证集用于评估校准效果(画 reliability curve)
- 避免用
predict_proba前没调calibrated_clf.fit(X_train_res, y_train_res)—— 这步漏掉,概率就是废的
最常被跳过的环节是:采样后没重跑特征重要性分析。原来排第 3 的特征,采样后可能掉到第 12,说明它依赖原始分布;这类变化不检查,后续特征工程和解释性报告全是错的。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











