在金融风控、医疗诊断等实际场景中,二分类模型的评估从来不是简单地看准确率就能解决的。我遇到过太多这样的情况:模型在测试集上准确率高达95%,实际部署后却完全失效。原因往往在于数据分布的特殊性和业务目标的复杂性。
举个例子,在信用卡欺诈检测中,正常交易占比可能高达99.9%,欺诈交易只有0.1%。这时候如果模型无脑预测所有交易都正常,准确率照样能达到99.9%,但这种模型毫无价值。这就是为什么我们需要更精细的评估工具——P-R曲线和ROC曲线。
两类曲线本质上都在回答同一个问题:当模型给出的概率阈值变化时,模型的识别能力如何变化? 但它们的关注点不同:
第一次接触P-R曲线时,我被各种缩写搞得头晕。后来发现只要记住这个混淆矩阵就能理清思路:
| 真实\预测 | 正例 | 反例 |
|---|---|---|
| 正例 | TP | FN |
| 反例 | FP | TN |
精确率(Precision) = TP/(TP+FP)
相当于"宁可放过一千,不可错杀一个"的严格程度。在药物检测中,高精确率意味着尽量避免把健康人误诊为患者。
召回率(Recall) = TP/(TP+FN)
体现"宁可错杀,不可放过"的覆盖范围。在疫情防控中,高召回率意味着尽可能找出所有感染者。
绘制P-R曲线时,我习惯用以下方法快速判断模型质量:
python复制# 快速绘制P-R曲线的sklearn实现
from sklearn.metrics import precision_recall_curve
import matplotlib.pyplot as plt
precision, recall, _ = precision_recall_curve(y_true, y_scores)
plt.plot(recall, precision)
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('P-R Curve (AP=%.2f)' % average_precision)
在以下情况我会优先选择P-R曲线:
最近帮一家电商优化作弊检测系统时,发现当欺诈订单占比<1%时,P-R曲线能清晰反映出模型细微的改进,而ROC曲线几乎看不出差别。
ROC曲线的魅力在于它用两个指标构建坐标系:
这相当于在关注"抓住多少坏人"的同时,也监控"冤枉多少好人"。在信用评分模型中,这能帮我们平衡通过率和坏账率。
AUC值我一般这样解读:
但要注意!AUC高不一定代表模型好。我曾遇到AUC=0.95但实际不可用的模型,原因是:
python复制# ROC曲线绘制最佳实践
from sklearn.metrics import roc_curve, auc
fpr, tpr, _ = roc_curve(y_true, y_scores)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, label='ROC (AUC = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], 'k--') # 随机猜测线
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend(loc="lower right")
ROC曲线在以下情况更适用:
去年设计贷款审批系统时,我们发现当好坏客户比例达到1:3时,ROC曲线就开始失真,这时需要结合P-R曲线一起分析。
选择评估指标时,我通常会问三个问题:
业务最怕什么?
数据长什么样?
模型怎么用?
案例1:金融反欺诈
案例2:疾病筛查
当曲线不理想时,我会尝试:
在最近一个电商推荐项目中,通过调整正样本权重,我们成功将P-R曲线的平衡点从0.6提升到0.8,带来GMV提升12%。
比较多个模型时,单纯看曲线可能产生误导。我的经验是:
很多模型输出的概率并不真实(如SVM),这时需要:
python复制from sklearn.calibration import CalibratedClassifierCV
calibrated = CalibratedClassifierCV(base_estimator=svm, cv=3)
calibrated.fit(X_train, y_train)
这些年我踩过的坑包括:
一个记忆深刻的教训:某次A/B测试显示新模型AUC提升5%,但上线后投诉激增。后来发现是测试集没有包含最新的欺诈模式。