如何处理数据集的类别不平衡
欺诈检测 99 笔正常对 1 笔欺诈、故障预测千分之一正例——类别不平衡是工业数据集的常态而非例外。它的陷阱在于:模型全预测多数类就有 99% 准确率,而这一文不值。本文按”换指标 → 数据层 → 算法层 → 业务层”四步给出完整处理路径。
第一步:先换指标,否则一切免谈
准确率在不平衡数据上是误导指标。改用:
- Precision / Recall / F1:关注少数类的查准与查全
- PR-AUC(Precision-Recall 曲线下面积):比 ROC-AUC 对不平衡更敏感——负例海量时 ROC-AUC 会虚高
- 混淆矩阵 + 业务成本:漏报一笔欺诈的损失 vs 误报一笔的客服成本,成本矩阵决定最优工作点
指标换对之后,”优化”才有意义。
第二步:数据层手段
- 过采样少数类:简单复制易过拟合;SMOTE 在少数类样本间插值合成新样本,缓解复制的记忆效应;边界样本重点合成(Borderline-SMOTE)
- 欠采样多数类:随机删多数类会丢信息;Tomek links / 编辑最近邻只删边界冗余样本,保留分布骨架
- 数据增强:图像旋转裁剪、文本回译改写——用变换扩少数类,比合成更保真
- 组合拳:多数类欠采样+少数类过采样(如 SMOTE+Tomek)常优于单用
数据层手段的风险:合成样本可能引入不存在的模式,验证集必须保持原始分布(只在训练折内采样,防泄漏)。
第三步:算法层手段
- 类权重(class_weight):损失函数中少数类错误乘以高权重(sklearn 的 class_weight=’balanced’、深度学习的 WeightedLoss)——不改数据改代价,最常用且无合成风险
- Focal Loss:在交叉熵上压低易分样本的权重,让模型聚焦难分样本(目标检测应对不平衡的成名作)
- 树模型天然稍好:GBDT 对不平衡鲁棒性优于线性模型,但极端比例仍需加权
- 集成视角:BalanceCascade / EasyEnsemble——每轮用全部少数类+抽样多数类训一个基学习器,集成投票
第四步:业务层手段(常被忽略却最有效)
- 阈值移动:模型输出概率,默认 0.5 切分未必最优;按成本矩阵在验证集上扫阈值选最优工作点(漏报代价高→阈值调低换召回)
- 换问题 framing:极端不平衡(1:10000)时分类框架本身勉强,改异常检测/排序问题(学正常模式、按异常分排序)往往更自然
- 两级漏斗:粗筛(高召回轻量模型)+ 精判(高精确重模型/人工),成本与效果兼得
评估与验证规范
- 分层 K 折(stratified K-fold):保证每折少数类比例一致,否则折间指标剧烈波动
- 验证/测试集永不采样:保持真实分布,指标才反映线上表现
- 报告带置信区间或多次种子均值:不平衡下单次跑分方差大
决策速查
| 不平衡程度 | 首选组合 |
|---|---|
| 轻度(<1:10) | class_weight + PR-AUC 监控 |
| 中度(1:10–1:100) | 类权重/SMOTE + 阈值移动 |
| 重度(>1:100) | 异常检测 framing 或两级漏斗 + focal loss |
类别不平衡的处理顺序永远是:指标 → 代价 → 数据 → 算法 → 业务。多数人直奔 SMOTE,而老手先问”漏报和误报各值多少钱”——因为不平衡问题的最优解往往不在模型里,而在成本矩阵与阈值的交点上。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 非鱼小站!
评论
WalineDisqus







