1. 分类评估基础:混淆矩阵的定义与组成(TP、FP、FN、TN)
在做宏基因组分类模型评估时,我遇到最多的问题就是——大伙儿只看准确率。说实话,准确率在样本不平衡时就是个坑。你在写论文或做项目交付时,光报个准确率,甲方或审稿人一眼就能看出你没摸到门道。
真正的评估起点,是混淆矩阵。它把预测结果和真实标签交叉起来,给出四个格子。你把这个四个格子搞明白,后面AUC、PR曲线都是水到渠成的事。
1.1 混淆矩阵长什么样
咱们拿二分类来说。真实标签有两种:正类(Positive)和负类(Negative)。模型预测也有两种:预测为正、预测为负。交叉一下,就出来四个组合:
| 预测为正 | 预测为负 | |
|---|---|---|
| 真实为正 | TP(真正例) | FN(假负例) |
| 真实为负 | FP(假正例) | TN(真负例) |
这四个缩写你必须刻在脑子里。我一开始老搞混FP和FN,后来自己编了个口诀:「FP是模型瞎激动,FN是模型漏了人」。你试试看,管用。
1.2 每个格子到底代表什么
咱们用宏基因组里常见的场景举例——判断一个序列片段是不是来自某致病菌。
- TP(True Positive,真正例):序列确实是致病菌,模型也标成了致病菌。这是你想要的。
- FN(False Negative,假负例):序列是致病菌,但模型说不是。这个最要命——漏检了,临床后果严重。
- FP(False Positive,假正例):序列是正常菌群,但模型误报成致病菌。会导致后续资源浪费,但比漏检好一点。
- TN(True Negative,真负例):序列是正常菌,模型也说正常。这是理想背景。
个人经验:在宏基因组项目里,我见过最坑的一次——FP率只有2%,但因为我们检测的是低丰度耐药基因,那个2%的FP直接把一个阴性样本判成了阳性,导致后续验证多花了两周。所以千万别只看TP,FP在低丰度场景下更要命。
1.3 从混淆矩阵推出来的核心指标
矩阵本身不直接回答“模型好不好”,但你能用它算出三个最基础的指标:
| 指标 | 公式 | 中文名 | 说什么 |
|---|---|---|---|
| 准确率 (Accuracy) | (TP + TN) / (TP + TN + FP + FN) | 总体正确率 | 所有样本中猜对的比例 |
| 精确率 (Precision) | TP / (TP + FP) | 查准率 | 模型说是正类的样本里,到底有多少真是正类 |
| 召回率 (Recall) | TP / (TP + FN) | 查全率 | 所有真正的正类里,模型逮住了多少 |
这三个指标各有侧重。你要是做序列过滤,Precision重要——我宁可少放行几个,也不想放进来一堆垃圾。但你要是做疾病筛查,Recall更关键——漏掉一个病人可能出大事。
一个实用技巧:在Python里快速算混淆矩阵,我一般用 sklearn.metrics.confusion_matrix。你给进去真实标签和预测标签,它直接吐出2×2矩阵。然后你自己算Precision和Recall,代码也就五六行。
举个例子,假设我们跑了一个分类器,结果如下:
from sklearn.metrics import confusion_matrix, precision_score, recall_score
y_true = [1, 0, 1, 1, 0, 0, 1, 0, 0, 1] # 真实标签
y_pred = [1, 0, 1, 0, 0, 1, 1, 0, 0, 1] # 预测标签
cm = confusion_matrix(y_true, y_pred)
print(cm)
# [[3 1]
# [1 5]]
# 手动验证:
# TP = 5(真实1预测1)
# TN = 3(真实0预测0)
# FP = 1(真实0预测1)
# FN = 1(真实1预测0)
precision = precision_score(y_true, y_pred)
recall = recall_score(y_true, y_pred)
print(f"Precision: {precision:.2f}")
print(f"Recall: {recall:.2f}")
你跑一下,Precision是0.83,Recall是0.83。但如果你样本不平衡,比如真实正类只有10%,那准确率可能冲到90%以上,但模型其实是个“只会说负类”的废物。这就是为什么不能只看准确率。
1.4 一个把混淆矩阵串起来的脑图
下面这张图是我自己习惯用的结构,把四个格子、三个指标、以及它们之间的关系画在一起。你对着图理解,比光看文字快得多。
1.5 我的避坑提醒
我曾经踩过的一个坑:刚入行时,有个宏基因组分类任务,正类只占样本的5%。我用随机森林,准确率刷到了95%,高兴得不行。结果一看混淆矩阵——TP只有20,FN却有80,FP才5。说白了模型几乎把所有样本都判成负类,这模型废了。
从那以后,我每次拿到一个新数据集,第一件事就是看正负比例,然后算混淆矩阵。你要是遇到类似情况,试试调分类阈值或者用加权损失。
实用建议:你可以把混淆矩阵的可视化做成热图,用seaborn的heatmap。这样团队评审时一眼就能看出问题。代码也很短:
import seaborn as sns
import matplotlib.pyplot as plt
cm = confusion_matrix(y_true, y_pred)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.show()
1.6 小结一下
混淆矩阵是分类评估的起点,不是终点。四个格子你得闭着眼睛都能说出来。后面咱们讲AUC和ROC曲线,本质上就是在不同的阈值下看TPR(Recall)和FPR的关系,而TPR和FPR都直接来自混淆矩阵。所以今天这个基础,你务必要吃透。