3、分类问题评价:准确率、精确率、召回率、F1分数与混淆矩阵
分类模型好不好,不能光看它猜对了几个。说实话,我刚入行那会儿也犯过这毛病——拿个准确率90%的模型就兴冲冲去上线,结果被产品经理追着骂。为什么?因为数据不平衡的时候,准确率会骗人。
这一章,咱们把分类评价的几把尺子掰开揉碎了讲。你搞懂了它们,以后看模型报告就不会被数字忽悠了。
3.1 混淆矩阵:一切评价的起点
所有分类指标,几乎都是从混淆矩阵算出来的。它就是个2×2的表格,记录着模型预测和真实标签的四种组合情况。
| 预测为正类 (Positive) | 预测为负类 (Negative) | |
|---|---|---|
| 真实为正类 | TP (True Positive) 真正例 |
FN (False Negative) 假负例 |
| 真实为负类 | FP (False Positive) 假正例 |
TN (True Negative) 真负例 |
举个例子。你做个垃圾邮件分类器,模型说「这是垃圾邮件」,结果它确实是——这就是TP。模型说「这不是垃圾」,结果它还真是垃圾——这就是FN,漏掉了。模型说「这是垃圾」,结果是一封正常的工作邮件——FP,误报了。
核心记忆法:TP和TN是「猜对了」,FP和FN是「猜错了」。T/F表示预测对不对,P/N表示模型预测的结果是什么。
下面这张图,把混淆矩阵和四个指标的关系画清楚了。
3.2 准确率:最直观,也最容易翻车
准确率的公式很简单:
Accuracy = (TP + TN) / (TP + TN + FP + FN)
说白了,就是「猜对的比例」。听起来很合理对吧?但问题来了——如果正负样本比例是99:1,你闭着眼睛全猜「负类」,准确率也有99%。
我曾经踩过的坑:做一个信用卡欺诈检测模型,欺诈样本只占0.1%。模型准确率99.9%,我差点就提交报告了。幸好多看了一眼混淆矩阵——好家伙,所有欺诈样本全漏了,一个都没抓住。准确率99.9%,召回率0%。
所以我的建议是:准确率只在正负样本均衡的时候用。如果数据不平衡,别拿它当主要指标。
3.3 精确率:宁缺毋滥
精确率问的是:模型说「是」的那些样本里,有多少是真的「是」?
Precision = TP / (TP + FP)
精确率高,意味着模型很少误报。你想想看,搜索引擎搜「苹果」,出来的全是水果苹果,没有苹果手机——这就是精确率高。
什么时候该追求高精确率?误报代价高的场景。比如垃圾邮件分类,把正常邮件误判成垃圾,用户可能错过重要消息。再比如医疗诊断,把健康人误判成病人,后续检查会浪费大量资源。
3.4 召回率:宁可错杀一千,不可放过一个
召回率问的是:所有真正的「是」里面,模型找出来了多少?
Recall = TP / (TP + FN)
召回率高,意味着模型很少漏掉目标。我在做金融风控的时候,对召回率特别敏感。为什么?因为漏掉一个欺诈交易,可能就是几十万的损失。
什么时候该追求高召回率?漏报代价高的场景。比如癌症筛查,宁可让健康人多做一次检查,也不能漏掉一个早期患者。再比如安防监控,宁可误报几次,也不能让可疑人员溜过去。
一个小技巧:精确率和召回率往往是此消彼长的。你把阈值调低,模型更「激进」,召回率上去了,精确率就下来了。反过来,阈值调高,模型更「保守」,精确率高了,召回率就低了。这个关系叫「Precision-Recall Trade-off」。
3.5 F1分数:精确率和召回率的调和平均
既然精确率和召回率经常打架,总得有个指标来综合评估吧?F1分数就是干这个的。
F1 = 2 * (Precision * Recall) / (Precision + Recall)
注意,它用的是调和平均,不是算术平均。调和平均对较小值更敏感。举个例子:
- 精确率0.9,召回率0.1,算术平均是0.5,但F1只有0.18
- 精确率0.5,召回率0.5,算术平均也是0.5,但F1是0.5
你看,F1分数会狠狠惩罚「偏科」的模型。我个人习惯在模型对比时,优先看F1分数。它虽然不是万能的,但至少不会让你被单一指标忽悠。
3.6 多分类场景怎么办?
上面讲的都是二分类。那三分类、十分类呢?
思路其实很简单——把多分类拆成多个「一对多」的二分类。比如三个类别A、B、C,算A的精确率时,把A当正类,B和C当负类。然后有两种聚合方式:
| 聚合方式 | 计算方法 | 适用场景 |
|---|---|---|
| 宏平均 (Macro) | 每个类别分别算指标,再取算术平均 | 各类别同等重要,不考虑样本量 |
| 微平均 (Micro) | 把所有类别的TP、FP、FN加起来,统一算指标 | 样本量差异大,希望大类别主导 |
| 加权平均 (Weighted) | 按每个类别的样本量加权平均 | 兼顾各类别,同时反映样本分布 |
举个例子。类别A有1000个样本,类别B只有10个。宏平均会把A和B的指标一视同仁,B的波动会严重影响结果。微平均则基本被A主导。加权平均介于两者之间。
我的建议:做多分类报告时,把宏平均和加权平均都列出来。如果两者差异很大,说明模型在小类别上表现不好,需要进一步分析。
3.7 实战:用Python算一遍
理论说完了,咱们动手。下面这段代码,用sklearn把今天讲的指标全算一遍。
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score, f1_score
from sklearn.metrics import classification_report
# 假设真实标签和预测结果
y_true = [1, 0, 1, 1, 0, 1, 0, 0, 1, 0]
y_pred = [1, 0, 1, 0, 0, 1, 1, 0, 1, 0]
# 混淆矩阵
cm = confusion_matrix(y_true, y_pred)
print("混淆矩阵:")
print(cm)
# 各项指标
acc = accuracy_score(y_true, y_pred)
prec = precision_score(y_true, y_pred)
rec = recall_score(y_true, y_pred)
f1 = f1_score(y_true, y_pred)
print(f"准确率: {acc:.3f}")
print(f"精确率: {prec:.3f}")
print(f"召回率: {rec:.3f}")
print(f"F1分数: {f1:.3f}")
# 一键生成完整报告
print("\n分类报告:")
print(classification_report(y_true, y_pred))
输出结果:
混淆矩阵:
[[3 1]
[1 5]]
准确率: 0.800
精确率: 0.833
召回率: 0.833
F1分数: 0.833
分类报告:
precision recall f1-score support
0 0.75 0.75 0.75 4
1 0.83 0.83 0.83 6
accuracy 0.80 10
macro avg 0.79 0.79 0.79 10
weighted avg 0.80 0.80 0.80 10
你看,classification_report一行代码,把精确率、召回率、F1、支持度全列出来了,还自动算了宏平均和加权平均。我平时做实验,基本就靠这个函数快速扫一眼模型表现。
3.8 选哪个指标?一张表说清楚
| 场景 | 推荐指标 | 原因 |
|---|---|---|
| 正负样本均衡 | 准确率 | 简单直观,够用 |
| 正负样本严重不均衡 | 精确率 + 召回率 + F1 | 准确率会骗人 |
| 误报代价高(宁缺毋滥) | 精确率 | 减少假正例 |
| 漏报代价高(宁可错杀) | 召回率 | 减少假负例 |
| 需要综合评估 | F1分数 | 平衡精确率和召回率 |
| 多分类,各类别样本量差异大 | 加权平均F1 | 反映真实分布 |
| 多分类,各类别同等重要 | 宏平均F1 | 一视同仁 |
嗯,这一章的内容就到这儿。记住一句话:没有最好的指标,只有最合适的指标。下次拿到一个分类模型,别急着看准确率,先问问自己——这个场景下,漏报和误报,哪个代价更大?想清楚了,指标自然就选对了。