分类评估基础:从任务到底层矩阵
做分类模型这么多年,我最大的体会就是——模型好不好,不能光靠“感觉”。你训练了一个分类器,跑起来效果好像不错,但放到线上就崩了,这种情况我遇到过不止一次。后来才明白,关键不在于模型本身,而在于你怎么衡量它。
这一章,咱们先打好地基。分类任务到底长什么样?混淆矩阵又是个什么东西?搞懂了这两点,后面那些花哨的指标才有意义。
1. 分类任务:你让模型选什么
分类,说白了就是给东西贴标签。
- 垃圾邮件检测:是垃圾,还是正常?
- 医学图像诊断:良性,还是恶性?
- 用户行为预测:点击,还是不点击?
这些都是二分类问题——只有两个类别。但我个人习惯把二分类当作基础中的基础,因为很多多分类问题(比如识别手写数字0-9)也能拆成多个二分类来处理。
每个分类任务,我们都会有一组真实标签(ground truth)和一组模型预测标签。真实标签是客观事实,预测标签是模型的判断。两者一对比,就能看出模型到底瞎猜了多少。
一个小经验:
我在项目中经常发现,新手最喜欢直接看“准确率”——哎呀98%了,模型真棒。但要是正负样本比例是99:1呢?模型全猜负类,准确率也有99%,那这模型其实是个废物。所以,别只看单一指标。
2. 混淆矩阵:最朴素的评估工具
混淆矩阵,名字听着吓人,其实就是一个2×2的表格。它把真实标签和预测标签的四种组合列出来,一目了然。
假设我们关心的是正类(Positive)和负类(Negative):
| 预测为正类 | 预测为负类 | |
|---|---|---|
| 真实为正类 | 真正例 (TP) | 假负例 (FN) |
| 真实为负类 | 假正例 (FP) | 真负例 (TN) |
这四个格子分别对应:
- TP (True Positive):模型说“是”,实际也是“是”。——完美命中。
- FN (False Negative):模型说“不是”,实际却是“是”。——漏检了,这是我最怕的情况,尤其是在医疗场景。
- FP (False Positive):模型说“是”,实际却是“不是”。——误报,虽然烦,但通常比漏检好一点。
- TN (True Negative):模型说“不是”,实际也不是。——正确拒绝。
举个例子,我们检测系统中是否有恶意软件。真实样本中有10个是病毒,90个是正常文件。模型预测结果如下:
预测为正类(病毒) 预测为负类(正常)
真实为正类(病毒) 8(TP) 2(FN)
真实为负类(正常) 1(FP) 89(TN)
可以看到,模型漏掉了2个病毒,误报了1个正常文件。从混淆矩阵,你能直接算出很多指标,比如准确率 = (8+89)/100 = 97%,召回率 = 8/10 = 80%。这比光看准确率更靠谱。
3. 为什么要用混淆矩阵?——我踩过的坑
我曾经参与过一个信贷风控项目,正类(违约用户)只占全场2%。我们用了一个高准确率的模型(98%),结果上线后坏账率暴增。查了混淆矩阵才发现:模型几乎把所有样本都预测为“不违约”,TP=0,FN奇高。虽然准确率好看,但完美错过了所有风险用户。
所以,我现在做分类评估,第一件事就是打印混淆矩阵。它不会骗你。
注意:
混淆矩阵的“正类”定义很关键。比如在医学诊断中,阳性=患病,阴性=健康。如果你把标签搞反了,所有指标都会跟着错。我建议在代码里显式指定正类,比如 table(真实, 预测, dnn = c("真实", "预测")),别依赖默认排序。
4. 从混淆矩阵衍生出的核心指标
有了TP/FP/FN/TN,我们就能玩出很多花来。下面这几个指标,是后续章节的核心基石:
| 指标 | 公式 | 含义 |
|---|---|---|
| 准确率 (Accuracy) | (TP+TN) / (TP+FP+FN+TN) | 整体正确率,但受类别不平衡影响大 |
| 精确率 (Precision) | TP / (TP+FP) | 模型预测为正类中,有多少是真正的正类 |
| 召回率 (Recall) | TP / (TP+FN) | 真正的正类中,模型找出了多少 |
| 特异度 (Specificity) | TN / (TN+FP) | 真正的负类中,模型正确排除了多少 |
我常跟新人说:别死记公式,想想实际场景。比如反欺诈系统,我们宁愿误报(FP高)也不愿漏掉欺诈(FN低),所以召回率比精确率重要。而推荐系统,用户希望看到的都是喜欢的,所以精确率更关键。
5. 学习路线图:这一章的知识框架
下面这张图概括了本章的核心脉络:
6. 实战小练习:用R计算混淆矩阵
虽然我们还没正式讲R包,但你可以用最朴素的方式自己动手。假设你有一个二分类预测结果:
# 真实标签
actual <- c(1, 0, 1, 1, 0, 0, 1, 0, 1, 0)
# 预测标签
predicted <- c(1, 0, 1, 0, 0, 1, 1, 0, 1, 0)
# 生成混淆矩阵
cm <- table(actual, predicted, dnn = c("真实", "预测"))
print(cm)
# 手动计算指标
TP <- sum(actual == 1 & predicted == 1)
FN <- sum(actual == 1 & predicted == 0)
FP <- sum(actual == 0 & predicted == 1)
TN <- sum(actual == 0 & predicted == 0)
accuracy <- (TP + TN) / (TP + FN + FP + TN)
precision <- TP / (TP + FP)
recall <- TP / (TP + FN)
specificity <- TN / (TN + FP)
cat("准确率:", round(accuracy, 3), "\n")
cat("精确率:", round(precision, 3), "\n")
cat("召回率:", round(recall, 3), "\n")
cat("特异度:", round(specificity, 3), "\n")
在R里跑一下这段代码,你会得到一组具体的数字。然后对比上面SVG图的四个格子,是不是一下子就清楚了?
一句话总结:
分类评估的起点,永远是你手里的那个2×2表格。搞懂了TP、FP、FN、TN,后面那些AUC、F1、Kappa全是它们的组合游戏。