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)
      
    • 最佳实践:欠采样适合大数据场景,但会丢失信息
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 建模阶段最佳实践

  1. 基准模型建立(不做任何平衡处理)
  2. 尝试不同采样策略+相同算法
  3. 测试代价敏感学习
  4. 验证集成方法效果
  5. 模型调优(重点关注少数类表现)

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. 进阶技巧与经验分享

在实际项目中,我发现这些策略特别有效:

  1. 分层交叉验证 :确保每折保持原始分布

    from sklearn.model_selection import StratifiedKFold
    skf = StratifiedKFold(n_splits=5)
    
  2. 概率校准 :提高预测概率的可信度

    from sklearn.calibration import CalibratedClassifierCV
    calibrated = CalibratedClassifierCV(base_estimator=model, cv=3)
    
  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]
    
  4. 模型解释性 :使用SHAP分析特征贡献

    import shap
    explainer = shap.TreeExplainer(model)
    shap_values = explainer.shap_values(X_test)
    

对于金融风控这类高代价场景,我通常会采用三级防御策略:首层用快速过滤模型(高召回),中层用精确模型(高准确率),最终人工复核。这种级联结构在保持系统效率的同时最大化风险捕获能力。

更多推荐