1. 不平衡数据问题概述
在机器学习实践中,我们经常会遇到类别分布严重不均衡的数据集。比如在信用卡欺诈检测中,正常交易可能占99.9%,而欺诈交易只有0.1%。这种数据不平衡会导致模型倾向于预测多数类,而对少数类的识别率极低。
我最近在一个医疗诊断项目中就遇到了这个问题:健康样本与患病样本的比例达到了20:1。初始模型对患病样本的召回率只有15%,完全达不到临床使用要求。这促使我系统研究了不平衡数据的处理方法。
2. 不平衡数据的评估指标
2.1 为什么准确率会误导
当数据不平衡时,准确率(Accuracy)是最不可靠的指标。假设我们有一个99%负样本的数据集,即使模型全部预测为负,也能获得99%的准确率,但这完全没有意义。
2.2 更合适的评估指标
在实践中,我主要关注以下指标:
- 召回率(Recall):对少数类样本的识别能力
- 精确率(Precision):预测为少数类的样本中实际为少数类的比例
- F1-score:精确率和召回率的调和平均
- PR曲线:比ROC曲线更能反映不平衡数据的真实表现
- Kappa系数:考虑类别不平衡的模型一致性指标
3. 数据层面的处理方法
3.1 过采样技术
SMOTE算法是我最常用的过采样方法。它通过在少数类样本的特征空间中进行插值来生成新样本,而不是简单复制。
from imblearn.over_sampling import SMOTE smote = SMOTE(sampling_strategy='minority') X_res, y_res = smote.fit_resample(X, y)注意:SMOTE可能导致过拟合,建议配合交叉验证使用。我在实践中发现,对高维数据效果会下降。
3.2 欠采样技术
随机欠采样虽然简单,但会丢失大量信息。我更喜欢使用以下方法:
- NearMiss:保留与少数类最接近的多数类样本
- Tomek Links:移除边界上的多数类样本
- Cluster Centroids:对多数类进行聚类后采样
from imblearn.under_sampling import TomekLinks tl = TomekLinks() X_res, y_res = tl.fit_resample(X, y)3.3 混合采样策略
在实际项目中,我经常组合使用过采样和欠采样。比如先使用SMOTE增加少数类样本,再用Tomek Links清理边界样本。
4. 算法层面的处理方法
4.1 类别权重调整
大多数算法都支持类别权重参数。以逻辑回归为例:
from sklearn.linear_model import LogisticRegression model = LogisticRegression(class_weight='balanced')我在实践中发现,设置class_weight='balanced'通常比手动指定权重效果更好。
4.2 代价敏感学习
通过代价矩阵明确指定不同误分类的代价。比如在医疗诊断中,将假阴性的代价设得比假阳性高很多。
4.3 集成学习方法
我特别推荐以下两种集成方法:
- EasyEnsemble:多次对多数类欠采样并集成
- BalanceCascade:逐步移除被正确分类的多数类样本
from imblearn.ensemble import EasyEnsembleClassifier eec = EasyEnsembleClassifier(n_estimators=10) eec.fit(X_train, y_train)5. 模型选择与调优
5.1 适合不平衡数据的算法
根据我的经验,以下算法处理不平衡数据表现较好:
- 决策树类算法(随机森林、XGBoost等)
- 支持向量机(使用类别权重)
- 神经网络(配合合适的损失函数)
5.2 阈值调整技巧
默认的0.5分类阈值通常不是最优的。我通常这样做:
- 在验证集上预测概率
- 绘制PR曲线
- 选择使F1-score最大的阈值
from sklearn.metrics import precision_recall_curve precisions, recalls, thresholds = precision_recall_curve(y_val, y_proba) f1_scores = 2*(precisions*recalls)/(precisions+recalls) best_threshold = thresholds[np.argmax(f1_scores)]6. 实际项目经验分享
6.1 医疗诊断项目案例
在这个数据集中,正负样本比例为1:20。我尝试了以下方案:
- 基线模型:准确率98%,但召回率只有12%
- 使用SMOTE过采样:召回率提升到45%,但精确率下降到30%
- 组合SMOTE和Tomek Links:召回率65%,精确率55%
- 最终采用XGBoost+类别权重:召回率78%,精确率68%
6.2 常见陷阱与解决方案
- 数据泄露:在过采样前一定要先划分训练测试集
- 过拟合:使用交叉验证评估,避免在测试集上调整阈值
- 计算成本:SMOTE对大数据集很耗时,可以考虑随机过采样
6.3 我的最佳实践建议
- 首先尝试简单的类别权重调整
- 对中小型数据集,SMOTE+欠采样组合效果很好
- 对大型数据集,直接使用带权重的树模型更高效
- 一定要使用PR曲线而非ROC曲线评估
- 最终模型要在独立的测试集上验证
不平衡数据问题没有银弹解决方案。在我的实践中,通常需要尝试多种方法的组合,并通过严格的交叉验证来评估真实效果。记住,业务需求(如对召回率或精确率的侧重)应该指导我们选择最终的解决方案。