不平衡数据分类需先诊断失衡程度与类型,再组合采样、阈值调整与评估;应计算各类占比及min/max样本比,重点关注recall、precision、f1-score,慎用accuracy和AUC。

直接上结论:不平衡数据分类不能只靠改 class_weight 或换算法,得先诊断失衡程度和类型,再组合采样、阈值调整与评估手段——否则模型在测试集上 accuracy 很高,但 recall 接近 0,根本没法用。
怎么看你的数据到底有多不平衡?
别凭感觉。用 collections.Counter(y) 或 y.value_counts(normalize=True) 算出各类占比,重点关注少数类是否低于 5%;更关键的是看 min_samples / max_samples 比值(比如 1:100 是严重失衡,1:5 属轻度)。若少数类样本数
常见错误:直接跑 classification_report 却忽略 support 列——support 小于 30 的类别,F1 值波动极大,不可信。
SMOTE 和 RandomOverSampler 到底该选哪个?
SMOTE 在特征空间中对少数类样本做线性插值生成新样本,适合数值型特征多、边界较连续的场景;但它会放大噪声,且对高维稀疏数据(如 TF-IDF 文本)效果差,甚至导致过拟合。
立即学习“Python免费学习笔记(深入)”;
RandomOverSampler 简单重复采样,不引入新特征组合,适合类别边界不规则、或含大量离散/分类特征的数据(比如用户行为日志中的 device_type、country),但可能让模型记住重复样本。
- 用
imblearn.over_sampling.SMOTE(k_neighbors=3)时,若报ValueError: Expected n_neighbors <= n_samples,说明某类样本数 ≤ k_neighbors,必须先设k_neighbors=min(3, len(minority_class)-1) - 文本分类任务中,优先试
RandomOverSampler+ 特征哈希(HashingVectorizer)而非 SMOTE,后者在稀疏向量上插值得到的“新样本”常是全零向量
为什么调了 class_weight='balanced' 还是没用?
class_weight='balanced' 实际是按 n_samples / (n_classes * n_samples_of_class) 自动加权,它只影响损失函数梯度更新方向,并不改变预测阈值——模型输出仍是默认 0.5 分界,而失衡下最优阈值往往在 0.1~0.3 区间。
必须配合后处理:
- 用
model.predict_proba(X)[:, 1]获取正类概率,再用precision_recall_curve找f1_score最高点对应的阈值 - LightGBM/XGBoost 可直接设
scale_pos_weight = len(negative) / len(positive),比class_weight更稳定 - sklearn 的
CalibratedClassifierCV能校准概率输出,让阈值调整更可靠
评估指标选错等于白干
Accuracy 和 AUC 在极端不平衡下完全失效:一个把所有样本都判为多数类的模型,accuracy 可能 >99%,AUC 仍接近 0.5(因 AUC 关注排序能力,但多数类内部排序无意义)。
必须盯住以下三个指标:
-
recall(查全率):少数类里被找出来的比例,医疗/风控场景首要目标 -
precision(查准率):预测为少数类的样本里,真少数类占多少,推荐系统关注这个 -
f1-score(宏平均或加权平均):precision 和 recall 的调和平均,比 accuracy 更敏感
注意:average='macro' 对各类等权重,适合各类重要性相同时;若少数类代价极高(如癌症漏诊),应单独看其 recall,并用 confusion_matrix 检查误判分布——比如模型总把某子类(如 stage-2 肿瘤)判成 stage-1,说明特征表达不足,不是采样能解决的。


















