机器学习中不平衡分类问题的解决方案与实践
·
1. 不平衡分类问题的本质挑战
在真实世界的数据科学项目中,我们经常会遇到类别分布严重不均的数据集。比如信用卡欺诈检测中正常交易占比99.9%,医疗诊断中健康样本远多于患病样本。这类场景下,传统分类算法会陷入"多数类偏好"陷阱——模型会倾向于将所有样本预测为多数类来获得表面上的高准确率。
举个例子,在银行风控系统中,如果欺诈交易仅占0.1%,一个总是预测"正常"的模型准确率就能达到99.9%。这种模型在实际业务中完全无效,而我们需要关注的恰恰是那0.1%的异常案例。这就是典型的不平衡分类(Imbalanced Classification)问题。
2. 系统性解决方案框架
2.1 数据层面的处理策略
2.1.1 重采样技术对比
-
过采样(Over-sampling) :通过复制少数类样本或生成合成样本(SMOTE/ADASYN)来平衡分布
- SMOTE原理:在特征空间中对少数类样本进行线性插值
- 实现代码示例:
from imblearn.over_sampling import SMOTE sm = SMOTE(sampling_strategy='auto', k_neighbors=5) X_res, y_res = sm.fit_resample(X, y) - 注意事项:SMOTE可能导致过拟合,需配合交叉验证使用
-
欠采样(Under-sampling) :随机或基于聚类(Tomek links/ENN)减少多数类样本
- ClusterCentroids实现:
from imblearn.under_sampling import ClusterCentroids cc = ClusterCentroids(sampling_strategy='auto') X_res, y_res = cc.fit_resample(X, y) - 最佳实践:欠采样适合大数据场景,但会丢失信息
- ClusterCentroids实现:
2.1.2 混合采样方案
结合过采样和欠采样,如SMOTE+ENN:
from imblearn.combine import SMOTEENN
sme = SMOTEENN(sampling_strategy='auto')
X_res, y_res = sme.fit_resample(X, y)
2.2 算法层面的改进方法
2.2.1 代价敏感学习
通过class_weight参数调整误分类代价:
from sklearn.svm import SVC
model = SVC(class_weight='balanced') # 自动按类别比例调整权重
2.2.2 集成学习方法
- EasyEnsemble :对多数类多次欠采样后集成
from imblearn.ensemble import EasyEnsembleClassifier eec = EasyEnsembleClassifier(n_estimators=10) eec.fit(X, y) - BalancedRandomForest :每棵树训练时平衡采样
from imblearn.ensemble import BalancedRandomForestClassifier brf = BalancedRandomForestClassifier(n_estimators=100) brf.fit(X, y)
2.3 评估指标的选择艺术
2.3.1 超越准确率的指标
- 混淆矩阵分析:重点关注召回率(Recall)和精确率(Precision)
- Fβ分数:平衡召回和精确率(β=2更重视召回)
from sklearn.metrics import fbeta_score f2_score = fbeta_score(y_test, y_pred, beta=2) - PR曲线:比ROC曲线更适合极度不平衡数据
from sklearn.metrics import precision_recall_curve precision, recall, _ = precision_recall_curve(y_test, y_pred)
2.3.2 业务对齐的指标设计
- 定义自定义损失函数,如:
def business_loss(y_true, y_pred): fp_cost = 100 # 误报成本 fn_cost = 500 # 漏报成本 return np.sum((y_pred > y_true) * fp_cost + (y_true > y_pred) * fn_cost)
3. 实战项目工作流
3.1 数据探索阶段
- 类别分布可视化:
import seaborn as sns sns.countplot(x='target', data=df) - 特征相关性分析:
from sklearn.feature_selection import mutual_info_classif mi_scores = mutual_info_classif(X, y)
3.2 建模阶段最佳实践
- 基准模型建立(不做任何平衡处理)
- 尝试不同采样策略+相同算法
- 测试代价敏感学习
- 验证集成方法效果
- 模型调优(重点关注少数类表现)
3.3 模型部署注意事项
- 监控生产环境中的类别分布变化
- 设置动态阈值调整机制:
from sklearn.calibration import calibration_curve prob_true, prob_pred = calibration_curve(y_test, y_proba, n_bins=10)
4. 典型问题解决方案
4.1 样本量极少的场景
- 使用Few-shot Learning技术
- 数据增强:时间序列可采用窗口切片(Windowing)
4.2 概念漂移问题
- 在线学习机制:
from sklearn.linear_model import SGDClassifier model = SGDClassifier(loss='log_loss', class_weight='balanced') model.partial_fit(X_new, y_new, classes=[0,1])
4.3 多类别不平衡
- 使用One-vs-Rest策略
- 分层抽样确保每个minority类都被充分代表
5. 进阶技巧与经验分享
在实际项目中,我发现这些策略特别有效:
-
分层交叉验证 :确保每折保持原始分布
from sklearn.model_selection import StratifiedKFold skf = StratifiedKFold(n_splits=5) -
概率校准 :提高预测概率的可信度
from sklearn.calibration import CalibratedClassifierCV calibrated = CalibratedClassifierCV(base_estimator=model, cv=3) -
动态阈值优化 :根据业务需求调整决策边界
from sklearn.metrics import precision_recall_curve precisions, recalls, thresholds = precision_recall_curve(y_test, y_proba) optimal_idx = np.argmax(recalls + precisions) optimal_threshold = thresholds[optimal_idx] -
模型解释性 :使用SHAP分析特征贡献
import shap explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X_test)
对于金融风控这类高代价场景,我通常会采用三级防御策略:首层用快速过滤模型(高召回),中层用精确模型(高准确率),最终人工复核。这种级联结构在保持系统效率的同时最大化风险捕获能力。
更多推荐
所有评论(0)