3. 真正率、假正率、召回率、精确率的关系与计算
这一章,咱们把分类评估里最绕的几个指标彻底理顺。
真正率、假正率、召回率、精确率——名字这么多,到底什么关系?
我刚开始入行时也被这些术语搞得头大。后来带项目多了才发现,它们其实围绕着同一个核心:混淆矩阵。
把混淆矩阵搞明白,剩下的事就是加减乘除。
3.1 先从混淆矩阵说起
无论你用什么模型,二分类的结果都可以塞进一个 2×2 的表格里。
| 预测为正 | 预测为负 | |
|---|---|---|
| 真实为正 | TP(真正例) | FN(假负例) |
| 真实为负 | FP(假正例) | TN(真负例) |
四个格子,记住就行。
TP 是你猜对了的正例;FP 是你错当成正例的负例;FN 是你漏掉的正例;TN 是你猜对的负例。
我习惯在做任何指标计算前,先把这四类数清楚。不然算出来的数字自己都不信。
3.2 真正率(TPR)与召回率(Recall)
先说第一个结论:TPR 和 Recall 是同一个东西。
公式一模一样:
TPR = TP / (TP + FN)
Recall = TP / (TP + FN)
说白了,它们都在问:所有真实的正例里,你找回来了多少?
只不过在不同场景叫法不同。医学诊断里常叫灵敏度,信息检索里常叫召回率。我见过不少新人把这两个名字混着用,结果汇报时把领导搞晕了。嗯,这个坑我踩过。
核心理解: TPR 越高,代表模型越不“漏判”。但代价往往是……你看下去就知道了。
3.3 假正率(FPR)
FPR 是另一个方向:
FPR = FP / (FP + TN)
它衡量的是误报有多严重。
所有真实的负例里,有多少被你错误地标成了正例?
我曾经帮一家电商做风控模型,老板特别强调:宁可放过一千,不可误杀一个。因为误判一个正常用户,可能意味着永久流失。那会儿我把 FPR 压得极低,哪怕 TPR 只有 60% 也能接受。
所以你看,指标本身没有好坏,关键看业务场景想要什么。
3.4 精确率(Precision)
Precision = TP / (TP + FP)
精确率关注的是:你预测为正的那些样本里,到底有多少是真货?
举个例子:你发了 100 条推广短信,真正点开的只有 30 个。Precision 就是 30%。剩下的 70 条都是打扰用户,甚至可能被投诉。
我做过一个广告点击率预估项目,Precision 每提升 5 个点,运营团队的投诉量直接减半。效果立竿见影。
3.5 这四个指标到底什么关系?
到这里公式都记住了。但关系呢?
我画张图帮你看清。
从上往下看,逻辑很清楚:
- 混淆矩阵是源头。没有它,算什么都白搭。
- TPR/召回率、FPR、Precision 是三个最常用的派生指标。
- Precision 和 Recall 是一对“冤家”——你想尽可能找全正例(高 Recall),就得接受误报(低 Precision);反过来也一样。
- TPR 和 FPR 则手拉手形成了 ROC 曲线,用来判断模型整体的排序能力。
3.6 一个例子让你全明白
假设我们有 20 个样本,10 个正例,10 个负例。模型预测结果如下:
真实值: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
预测值: [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
来,我们一起手算:
- TP = 4(前 10 个里有 4 个猜对了正例)
- FN = 6(漏掉的 6 个正例)
- FP = 2(负例里被错判成正例的 2 个)
- TN = 8(负例里猜对了 8 个)
TPR = 4 / (4 + 6) = 0.4
FPR = 2 / (2 + 8) = 0.2
Precision = 4 / (4 + 2) = 0.666
Recall = TPR = 0.4
你看,Precision 66.7%,Recall 只有 40%。
如果我把阈值调低,让模型更“大胆”地预测正例,Recall 可能升到 70%,但 FP 一多,Precision 就会掉到 50% 以下。
这就是权衡。你想想看,业务更在乎哪个?
3.7 代码跑一遍,体会更深
我习惯做实验时先把这四个指标全部打印出来,再看看不同阈值下它们怎么变。
import numpy as np
from sklearn.metrics import confusion_matrix
y_true = np.array([1,1,1,1,1,0,0,0,0,0])
y_scores = np.array([0.9, 0.8, 0.7, 0.4, 0.3, 0.6, 0.5, 0.2, 0.1, 0.05])
for thresh in [0.6, 0.5, 0.4, 0.3]:
y_pred = (y_scores >= thresh).astype(int)
tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
tpr = tp / (tp + fn)
fpr = fp / (fp + tn)
precision = tp / (tp + fp) if (tp + fp) > 0 else 0
recall = tpr
print(f"阈值={thresh:.1f} | TPR(Recall)={tpr:.2f} | FPR={fpr:.2f} | Precision={precision:.2f}")
输出会清晰展示:阈值越低,Recall 越高,Precision 越低。FPR 也会跟着涨。
实用建议: 我一般在项目初期先盯住 TPR 和 Precision 两个指标,用 PR 曲线找到双方都能接受的平衡点。等模型排序能力基本定型,再看 ROC AUC 做最终评判。
避坑提醒: 我曾经在一个样本极度不平衡的项目里,光看 Accuracy 觉得模型很好,结果 Precision 只有 5%,根本没法上线。后来养成了习惯:四个指标一起看,缺一不可。
3.8 一张表总结
| 指标 | 公式 | 关注点 | 受阈值影响 |
|---|---|---|---|
| TPR / Recall | TP / (TP + FN) | 覆盖了多少正类 | 阈值↑ → TPR↓ |
| FPR | FP / (FP + TN) | 误报了多少负类 | 阈值↑ → FPR↓ |
| Precision | TP / (TP + FP) | 预测为正的准确率 | 阈值↑ → Precision↑ |
记住这个框架,以后无论遇到什么评估指标,你都能从混淆矩阵推导出来。项目管理、算法选型、业务沟通,一套逻辑全搞定。