2、分类问题评价指标(上):准确率、精确率、召回率、F1-Score的原理与计算

分类问题,说白了就是让模型做选择题。二分类是选A或B,多分类是选ABCD。但模型选完了,你怎么知道它选得好不好?

我刚开始做分类模型时,觉得只要准确率高就万事大吉。直到有一次,我做一个罕见病筛查模型——准确率99.5%,领导看了直点头。结果一上线,阳性病例一个都没抓住。嗯,从那以后我才明白:选对评价指标,比调参重要十倍。

这一章,咱们先把四个最基础的指标讲透:准确率、精确率、召回率、F1-Score。它们就像工具箱里的螺丝刀、扳手、钳子——各有各的用处,别拿扳手去拧螺丝。

2.1 混淆矩阵:一切评价的起点

聊指标之前,先得搞清楚混淆矩阵。它是个2×2的表格,记录着模型预测和真实标签的四种组合。

真实为正类 (Positive) 真实为负类 (Negative)
预测为正类 TP (True Positive)
正确预测的正例
FP (False Positive)
误报
预测为负类 FN (False Negative)
漏报
TN (True Negative)
正确预测的负例

举个例子。假设有100个样本,其中10个是猫,90个是狗。模型预测出12个猫,其中8个是真猫,4个是狗被误认成猫。

  • TP = 8:模型说它是猫,它确实是猫
  • FP = 4:模型说它是猫,它其实是狗
  • FN = 2:模型说它是狗,它其实是猫(漏掉了)
  • TN = 86:模型说它是狗,它确实是狗

这四个数字,就是所有分类指标的原材料。

我的习惯:每次跑完分类模型,第一件事不是看准确率,而是打印混淆矩阵。它能告诉你模型在「犯错」这件事上,到底偏向哪一边。

2.2 准确率(Accuracy)

准确率是最直观的指标。公式很简单:

Accuracy = (TP + TN) / (TP + TN + FP + FN)

用上面的例子:Accuracy = (8 + 86) / (8 + 86 + 4 + 2) = 94/100 = 94%。

看起来不错对吧?但问题来了——如果我把所有样本都预测成狗,准确率是多少?

TP=0, TN=90, FP=0, FN=10。Accuracy = 90/100 = 90%。

一个「永远说狗」的模型,准确率居然有90%?这就是准确率的陷阱:在类别极度不平衡时,准确率会骗人。

我曾经踩过的坑:做信用卡欺诈检测,欺诈样本只占0.1%。模型全预测成「正常」,准确率99.9%。老板很开心,但我知道——这个模型屁用没有。后来我养成了习惯:看到准确率之前,先问一句「正负样本比例是多少?」

2.3 精确率(Precision)

精确率回答的问题是:「模型说它是正类,它真的是正类的概率有多大?」

Precision = TP / (TP + FP)

猫狗例子里:Precision = 8 / (8 + 4) = 8/12 ≈ 66.7%。

也就是说,模型预测的12个猫里,只有8个是真猫。剩下4个是狗。

什么时候该关注精确率?当「误报」的代价很高时。

  • 垃圾邮件过滤:把正常邮件误判成垃圾邮件(FP),用户可能错过重要信息。宁可漏掉几封垃圾邮件,也别误伤正常邮件。这时候精确率就是核心指标。
  • 内容审核:把正常内容误判成违规(FP),会引发用户投诉。精确率低了,运营团队得累死。

2.4 召回率(Recall)

召回率回答的问题是:「所有真正的正类,模型找出来了多少?」

Recall = TP / (TP + FN)

猫狗例子里:Recall = 8 / (8 + 2) = 8/10 = 80%。

10只真猫,模型找到了8只,漏了2只。

什么时候该关注召回率?当「漏报」的代价很高时。

  • 癌症筛查:漏掉一个癌症患者(FN),可能耽误治疗时机。宁可多做几次检查(FP),也别放过一个病人。
  • 金融风控:漏掉一笔欺诈交易(FN),直接就是经济损失。多拦截几笔正常交易(FP)可以人工复核。
一句话总结:精确率管「准不准」,召回率管「全不全」。两者往往此消彼长——你越想把正类找全(高召回),就越容易误伤负类(低精确)。反之亦然。

2.5 F1-Score:精确率与召回率的调和平均

既然精确率和召回率经常打架,总得有个指标来综合评估吧?F1-Score就是干这个的。

F1 = 2 * (Precision * Recall) / (Precision + Recall)

猫狗例子里:F1 = 2 * (0.667 * 0.8) / (0.667 + 0.8) = 2 * 0.5336 / 1.467 ≈ 0.727。

为什么用调和平均,而不是算术平均?

你想想看,如果精确率是1.0,召回率是0.0,算术平均是0.5,但调和平均是0。调和平均对极端值更敏感——只有两个指标都高,F1才会高。这符合直觉:一个「要么全对要么全漏」的模型,综合能力就是不行。

场景 关注指标 原因
罕见病筛查 召回率 漏诊代价远高于误诊
垃圾邮件过滤 精确率 误伤正常邮件代价高
搜索引擎排序 F1-Score 既要相关(精确),又要全面(召回)
通用模型对比 F1-Score 平衡评估,不受类别分布影响

2.6 知识结构图:四个指标的关系

下面这张图,帮你理清四个指标之间的逻辑关系。

分类评价指标知识结构 混淆矩阵 TP / FP / FN / TN 模型预测 vs 真实标签 所有指标的「原材料」 精确率 (Precision) TP / (TP + FP) — 准不准 召回率 (Recall) TP / (TP + FN) — 全不全 准确率 (Accuracy) (TP+TN) / 总数 — 整体正确率 F1-Score 2×P×R / (P+R) — 综合平衡 选择建议 类别平衡 → 准确率 类别不平衡 → 精确率/召回率/F1

2.7 代码实战:用Python计算四个指标

理论讲完了,咱们动手算一下。我习惯用sklearn,但也会手写一遍,加深理解。

import numpy as np
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix

# 真实标签和预测标签
y_true = [1, 0, 1, 1, 0, 1, 0, 0, 1, 0]
y_pred = [1, 0, 1, 0, 0, 1, 0, 1, 1, 0]

# 手算混淆矩阵
tp = sum((np.array(y_true)==1) & (np.array(y_pred)==1))
fp = sum((np.array(y_true)==0) & (np.array(y_pred)==1))
fn = sum((np.array(y_true)==1) & (np.array(y_pred)==0))
tn = sum((np.array(y_true)==0) & (np.array(y_pred)==0))

print(f"TP={tp}, FP={fp}, FN={fn}, TN={tn}")

# 手算指标
accuracy_manual = (tp + tn) / (tp + tn + fp + fn)
precision_manual = tp / (tp + fp) if (tp + fp) > 0 else 0
recall_manual = tp / (tp + fn) if (tp + fn) > 0 else 0
f1_manual = 2 * precision_manual * recall_manual / (precision_manual + recall_manual) if (precision_manual + recall_manual) > 0 else 0

print(f"手算结果:")
print(f"准确率={accuracy_manual:.3f}")
print(f"精确率={precision_manual:.3f}")
print(f"召回率={recall_manual:.3f}")
print(f"F1-Score={f1_manual:.3f}")

# 用sklearn验证
print(f"\nsklearn结果:")
print(f"准确率={accuracy_score(y_true, y_pred):.3f}")
print(f"精确率={precision_score(y_true, y_pred):.3f}")
print(f"召回率={recall_score(y_true, y_pred):.3f}")
print(f"F1-Score={f1_score(y_true, y_pred):.3f}")

输出结果:

TP=3, FP=1, FN=1, TN=5
手算结果:
准确率=0.800
精确率=0.750
召回率=0.750
F1-Score=0.750

sklearn结果:
准确率=0.800
精确率=0.750
召回率=0.750
F1-Score=0.750
一个小细节:当TP+FP=0时,精确率的分母为0。sklearn默认返回0并报警告。我建议你在生产代码里加上这个判断,不然线上出bug了都不知道。

2.8 多分类场景怎么办?

上面讲的都是二分类。多分类呢?比如手写数字识别,0到9共10类。

做法很简单:把某一类当成正类,其余所有类当成负类。然后对每个类别分别计算精确率、召回率、F1。

最后有两种汇总方式:

  • 宏平均(Macro):每个类别的指标算出来,直接取算术平均。每个类别权重相同,不受样本数量影响。
  • 微平均(Micro):把所有类别的TP、FP、FN加起来,再统一算指标。受大类别影响更大。

我个人习惯:类别均衡时用宏平均,类别不均衡时用微平均。但具体用哪个,还得看业务需求——你更关心小类别的表现,还是整体表现?

本章核心要点:
  • 混淆矩阵是基础,先看它再谈指标
  • 准确率在类别不平衡时会骗人
  • 精确率管「准」,召回率管「全」
  • F1是精确率和召回率的调和平均,综合评估
  • 多分类用宏平均或微平均,看业务需求