python机器学习 不平衡黑白数据(Binary Imbalanced Data)


先搞清楚:不平衡到什么程度?

y.value_counts(normalize=True)

常见等级

正类比例 严重程度
40–60% 正常
20–40% 轻度不平衡
5–20% 中度不平衡
<5% 极度不平衡(风控 / 欺诈 / 交易信号)

<10% 一定要处理


二、第一原则(非常重要)

不要只看 Accuracy 看这些指标:

指标 用途
Recall 抓到多少正类
Precision 抓到的是不是真
F1 平衡指标
ROC-AUC 排序能力
PR-AUC 极不平衡时首选
from sklearn.metrics import classification_report
print(classification_report(y_true, y_pred))

三、处理方法总览(实战优先级)

方法 1:调整模型权重(首选

Logistic / SVM / Tree 都支持

from sklearn.linear_model import LogisticRegression

model = LogisticRegression(class_weight="balanced")

优点

  • 不破坏数据分布
  • 回测稳定
  • 金融/风控首选

方法 2:阈值移动(金融非常重要)

默认:

y_pred = (proba > 0.5).astype(int)

调整为:

y_pred = (proba > 0.2).astype(int)

这一步比 SMOTE 更重要


方法 3:下采样(负类太多)

from imblearn.under_sampling import RandomUnderSampler

rus = RandomUnderSampler()
X_res, y_res = rus.fit_resample(X, y)

适合

  • 样本极多(百万级)
  • 负类冗余

方法 4:上采样 / SMOTE(慎用)

from imblearn.over_sampling import SMOTE
X_res, y_res = SMOTE().fit_resample(X, y)

为什么慎用?

破坏时间序列 金融数据「造假」风险 回测很漂亮,实盘崩

时间序列 / 量化 不建议


方法 5:换模型(树模型天然抗不平衡)

推荐

  • XGBoost
  • LightGBM
  • CatBoost

XGBoost 设置

scale_pos_weight = len(y[y==0]) / len(y[y==1])

xgb.XGBClassifier(
    scale_pos_weight=scale_pos_weight,
    eval_metric="auc"
)

四、不同场景的最佳实践(你直接抄)

金融 / 量化信号(1 = 进场)

推荐组合

✔ class_weight
✔ 阈值调节
✔ PR-AUC
❌ SMOTE

风控 / 违约 / 欺诈

✔ Recall 优先
✔ PR-AUC
✔ XGBoost + scale_pos_weight
✔ 下采样

医疗 / 事件预测

✔ Recall > Precision
✔ 阈值降低
✔ 成本敏感学习

五、一个完整「标准模板」(强烈推荐)

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, precision_recall_curve

X_train, X_test, y_train, y_test = train_test_split(
    X, y, stratify=y, test_size=0.2
)

model = LogisticRegression(class_weight="balanced")
model.fit(X_train, y_train)

proba = model.predict_proba(X_test)[:,1]
auc = roc_auc_score(y_test, proba)

# 阈值调优
precision, recall, thresholds = precision_recall_curve(y_test, proba)