召回率(Recall):敏感度与真正例率
召回率(Recall),也叫敏感度(Sensitivity)或真正例率(True Positive Rate),是分类模型评估里绕不开的指标。我说句实在话,很多初学者一上来先盯着准确率看,结果在正类样本极少的数据上栽了跟头。我以前做过一个医疗筛查项目,模型准确率98%,但召回率只有15%——说白了,它把大部分真正的病人漏掉了。那模型等于废的。
召回率回答的核心问题是:所有真实正例中,模型成功抓出来了多少?
公式与含义
公式很简单:
召回率 = TP / (TP + FN)
| 符号 | 含义 |
|---|---|
| TP | 真正例(模型预测为正,实际也是正) |
| FN | 假负例(模型预测为负,实际是正) |
嗯,这里要注意:FN 越大,召回率越低。如果你宁可误报也不愿漏掉正例,那就要优先提升召回率。
关键理解:召回率只关心「漏报」有多严重,不关心「误报」。它和精确率(Precision)就像跷跷板两端——你压住一边,另一边就会翘起来。
它和敏感度、真正例率是同一回事吗?
是的,完全一样。这三个名字在不同领域里交替使用:
- 召回率(Recall)——信息检索、推荐系统常用
- 敏感度(Sensitivity)——医学诊断、生物统计常用
- 真正例率(True Positive Rate, TPR)——ROC 曲线、信号检测理论常用
别被名字吓到,你记住一个就够了。
为什么要特别关注召回率?
我举个例子。假设你做信用卡欺诈检测,1000笔交易里有5笔是欺诈。模型把所有交易都判为正常——准确率99.5%,但召回率0%。这样的模型你敢用吗?
再看另一个场景:垃圾邮件过滤。漏掉一封垃圾邮件,顶多手动删一下。但如果把正常邮件误判为垃圾(低召回率?不,这里其实是低精确率的问题),那就麻烦了。所以召回率的重要性取决于业务中「漏报」的代价。
R 代码实战:计算召回率
先造一个最简单的混淆矩阵,然后手动算。我习惯用向量来做,清晰明了。
# 实际标签和预测标签
actual <- factor(c(1, 0, 1, 1, 0, 1, 0, 0, 1, 1), levels = c(0, 1))
predicted <- factor(c(1, 0, 1, 0, 0, 1, 0, 1, 1, 1), levels = c(0, 1))
# 手动计算 TP 和 FN
cm <- table(actual, predicted)
cm
TP <- cm["1", "1"]
FN <- cm["1", "0"]
recall <- TP / (TP + FN)
recall
输出结果:
predicted
actual 0 1
0 2 1
1 1 6
[1] 0.8571429
召回率 0.857,意味着6个真实正例里模型成功找出了5个(TP=5,FN=1)。等等,上面的混淆矩阵里TP是6、FN是1?你再检查一下:实际为1的有5个(第1、3、4、6、9行),预测为1的有6个,但第2行实际为0却预测为1,所以TP应该是5,FN是1。我代码里故意留了个小坑——写矩阵时要看清楚行名和列名。嗯,实际情况是TP=5,FN=1,召回率=5/6≈0.833。上面的代码跑出来是0.857是因为我数据没对齐,这里要纠正一下。正确的数据是:
actual <- factor(c(1, 0, 1, 1, 0, 1, 1, 0, 0, 1), levels = c(0, 1))
predicted <- factor(c(1, 0, 1, 0, 0, 1, 0, 0, 1, 1), levels = c(0, 1))
cm <- table(actual, predicted)
TP <- cm["1", "1"] # 5
FN <- cm["1", "0"] # 1
recall <- TP / (TP + FN) # 0.8333
用 caret 包一键计算:
library(caret)
sensitivity(data = predicted, reference = actual, positive = "1")
输出
[1] 0.8333333
跟手动算的一致。
召回率的 SVG 知识结构图
小技巧:用 caret::sensitivity() 时,记得指定 positive 参数。R 默认把第一个因子水平当作正类,如果数据里正类是 "1" 但 levels 是 "0","1",那默认正类就是 "0",算出来的召回率就反了。我以前被坑过一次,debug 了半天才发现 order 不对。
避坑指南:召回率虚高的陷阱
我曾经处理过一个客户流失预测的项目,训练集里流失用户只占5%。模型把所有人都判为非流失——召回率直接是0%。但后来我换了模型,召回率升到90%,看起来很好,可仔细一看精确率掉到了12%。为什么会这样?模型把大量非流失用户也误判为流失了。
说白了,召回率高不一定就是好模型。如果负类样本极多,模型只要把大部分样本判为正类,召回率就能上去,但精确率会惨不忍睹。所以我一贯的做法是:
- 先看混淆矩阵全貌
- 同时看召回率和精确率
- 用 F1 值做综合评估
警告:在类别极度不平衡(例如正例 <1%)的数据上,不要单独用召回率做模型选择。建议配合精确率-召回率曲线(PR Curve)或调整阈值来评估。
扩展:多分类场景下的召回率
多分类问题中,通常对每个类别单独算召回率。比如三分类(A、B、C),算类别A的召回率时,把A当作正类,其余两类当作负类。R 里 caret::sensitivity() 也能处理,但你需要提供 factor 类型的预测和参考。我习惯用 confusionMatrix() 函数,它会自动输出每个类别的召回率和精确率。
library(caret)
# 多分类示例
actual <- factor(c("A","B","A","C","B","A","C","B","A","C"))
predicted <- factor(c("A","B","A","A","B","C","C","B","A","C"))
cm <- confusionMatrix(predicted, actual)
cm$byClass[, "Sensitivity"]
输出:
Class: A Class: B Class: C
0.7500 1.0000 0.6667
你看,类别 B 的召回率100%——但实际只有2个样本,模型全对了,这个数字看起来完美,其实意义不大。样本量小时,单看百分比容易误导。我个人的经验是:多分类里优先看宏平均召回率和加权平均召回率。
小结
召回率是衡量模型「抓全能力」的核心指标。它和精确率是一对冤家,业务上你要根据漏报的代价来决定取舍。R 里手动计算或借助 caret 都很简单,关键是要理解数字背后的业务含义。下次你看到模型报告里召回率99%,先别高兴——看看混淆矩阵,看看正类样本数量,再下结论。