Accuracy/Precision/Recall/F1/AUC/PR 的适用场景?
核心概念
分类模型的评估指标用于衡量模型预测结果的优劣。
- Accuracy (准确率): 模型预测正确的样本占总样本的比例,是衡量整体性能最直观的指标。
- Precision (精确率/查准率): 模型预测为正例的样本中,真正是正例的比例。它关注的是预测结果的“准确性”。
- Recall (召回率/查全率): 所有真实正例的样本中,被模型成功预测为正例的比例。它关注的是对正例的“覆盖能力”。
- F1-Score: Precision 和 Recall 的调和平均数,用于在两者之间寻求平衡。
- AUC-ROC: ROC 曲线下的面积,衡量模型在所有可能阈值下区分正负样本的总体“排序能力”。它对类别不平衡不敏感。
- AUC-PR: PR 曲线下的面积,同样衡量模型的排序能力,但在类别极度不平衡时,比 AUC-ROC 更能真实反映模型在稀有正类上的表现。
原理与推导
评估指标的计算都基于混淆矩阵(Confusion Matrix),它总结了模型在每个类别上的预测表现。对于一个二分类问题,混淆矩阵包含四个基本量:
- TP (True Positive): 真正例,真实为正,预测也为正。
- FP (False Positive): 假正例,真实为负,预测为正(Type I Error)。
- TN (True Negative): 真负例,真实为负,预测也为负。
- FN (False Negative): 假负例,真实为正,预测为负(Type II Error)。
1. Accuracy (准确率)
- 数学公式:
- 推导与解释:
- 分子是所有预测正确的样本数(正例预测对 + 负例预测对)。
- 分母是总样本数。
- 直观解释: 模型“猜对”的概率是多少?这个指标在类别均衡的数据集上非常有效。但在类别不平衡时,它会产生误导。例如,99% 的样本是负例,模型即使把所有样本都预测为负例,也能获得 99% 的准确率,但它对正例毫无识别能力。
2. Precision (精确率)
- 数学公式:
- 推导与解释:
- 分子是真正例。
- 分母是所有被模型预测为正例的样本数(预测对的正例 + 预测错的正例)。
- 直观解释: 在所有被你“揪出来”认为是“坏人”的里面,到底有多少是真“坏人”?这个指标衡量的是预测的“纯度”,越高代表模型预测的正例越可信。
3. Recall (召回率)
- 数学公式:
- 推导与解释:
- 分子是真正例。
- 分母是所有真实为正例的样本数(预测对的正例 + 预测漏的正例)。
- 直观解释: 在所有真“坏人”里,你成功“揪出来”了多少?这个指标衡量的是模型的“检出能力”,越高代表模型越不容易漏掉正例。
4. F1-Score
- 数学公式:
- 推导与解释:
- F1-Score 是 Precision 和 Recall 的调和平均数。
- 为什么用调和平均数? 相比算术平均数,调和平均数对较低的值更敏感。如果 Precision 或 Recall 中有一个非常低,F1-Score 也会被拉得很低。这强制模型在两者之间取得较好的平衡,而不是偏袒某一方。例如,P=1.0, R=0.1,算术平均是 0.55,而调和平均(F1)只有约 0.18,更能反映出模型的短板。
5. ROC 曲线与 AUC-ROC
- ROC (Receiver Operating Characteristic) 曲线:
- 横轴:假正例率 (False Positive Rate, FPR) 它表示所有真实负例中,被错误预测为正例的比例。
- 纵轴:真正例率 (True Positive Rate, TPR),它就是 Recall。
- 生成过程:
- 模型的预测结果通常是一个概率值(0到1之间)。
- 通过从高到低(或从低到高)移动分类阈值(threshold),可以得到一系列的 (FPR, TPR) 坐标点。
- 阈值最高时(如1.0),模型非常“苛刻”,几乎不预测正例,(FPR, TPR) 接近 (0, 0)。
- 阈值最低时(如0.0),模型非常“宽松”,把所有样本都预测为正例,(FPR, TPR) 接近 (1, 1)。
- 将这些点连接起来,就构成了 ROC 曲线。
- AUC (Area Under the Curve):
- 几何解释: ROC 曲线下的面积。面积范围在 [0, 1] 之间。
- AUC = 1: 完美分类器。
- AUC = 0.5: 随机猜测分类器(对应图中的对角线)。
- AUC < 0.5: 比随机猜测还差的分类器。
- 概率解释: AUC 值有一个重要的物理意义:随机从正样本集和负样本集中各抽取一个样本,模型将正样本的预测概率排在负样本之前的概率。这个解释使得 AUC 成为衡量模型整体排序能力的黄金标准。
- 几何解释: ROC 曲线下的面积。面积范围在 [0, 1] 之间。
6. PR 曲线与 AUC-PR
- PR (Precision-Recall) 曲线:
- 横轴:Recall (TPR)
- 纵轴:Precision
- 生成过程: 与 ROC 曲线类似,通过移动分类阈值,得到一系列 (Recall, Precision) 坐标点,连接成线。
- AUC-PR:
- 几何解释: PR 曲线下的面积。
- 与 AUC-ROC 的关键区别: 在类别极度不平衡的数据集中,负例数量远大于正例(TN 很大)。
- 在 ROC 曲线中,FPR 的分母是
FP + TN。即使 FP 显著增加,只要 TN 足够大,FPR 的增长也会非常缓慢,导致 ROC 曲线“虚高”,给人一种模型效果很好的错觉。 - PR 曲线的两个轴(Precision 和 Recall)都只关注与正例(TP, FP, FN)相关的部分,不受海量 TN 的影响。当模型在大量负例中将一些样本错误地预测为正例时,FP 会增加,Precision (
TP / (TP + FP)) 会显著下降,PR 曲线会更真实地反映出模型的性能。
- 在 ROC 曲线中,FPR 的分母是
- 基线 (Baseline): 随机猜测模型的 PR 曲线基线是数据集中正例的比例(
P / (P+N)),而 ROC 曲线的基线恒为 0.5。
代码实现
以下代码使用 scikit-learn 演示了如何在一个不平衡数据集上计算和可视化这些指标。
1import numpy as np2from sklearn.metrics import (3 accuracy_score,4 precision_score,5 recall_score,6 f1_score,7 roc_curve,8 auc,9 precision_recall_curve,10 average_precision_score11)12import matplotlib.pyplot as plt1314# --- 1. 准备数据 ---15# 假设这是一个类别极不平衡的场景,例如欺诈检测16# y_true: 真实的标签 (0: 正常, 1: 欺诈)17# y_scores: 模型预测为类别 1 的概率/分数18np.random.seed(42)19y_true = np.array([0] * 950 + [1] * 50) # 95% 是负例, 5% 是正例20# 一个还不错的模型的预测分数21y_scores_good = np.concatenate([22 np.random.rand(950) * 0.4, # 对大部分负例给出低分23 np.random.rand(50) * 0.6 + 0.4 # 对大部分正例给出高分24])25# 一个糟糕的模型(接近随机猜测)的预测分数26y_scores_bad = np.random.rand(1000)2728# 为了计算 Precision/Recall 等,需要一个确定的阈值来得到预测标签29threshold = 0.530y_pred_good = (y_scores_good > threshold).astype(int)3132# --- 2. 计算基础指标 (Accuracy, Precision, Recall, F1) ---33print("--- 基础指标 (基于阈值=0.5) ---")34accuracy = accuracy_score(y_true, y_pred_good)35precision = precision_score(y_true, y_pred_good)36recall = recall_score(y_true, y_pred_good)37f1 = f1_score(y_true, y_pred_good)3839print(f"Accuracy: {accuracy:.4f}")40# 为什么Accuracy会产生误导?41# 如果一个模型把所有样本都预测为0,它的Accuracy也会高达95%,但它毫无用处。42# 我们的模型Accuracy也很高,但这并不能完全说明它对正例的识别能力。43print(f"Precision: {precision:.4f}") # 查准率:预测为1的里面,真1的比例44print(f"Recall: {recall:.4f}") # 查全率:所有真1里面,被找出来的比例45print(f"F1-Score: {f1:.4f}") # P和R的调和平均4647# --- 3. 计算和绘制 ROC 曲线与 AUC ---48print("\n--- AUC-ROC ---")49# 为什么用 y_scores 而不是 y_pred?50# 因为 ROC/PR 曲线是通过改变阈值来评估模型在所有决策点下的表现,所以需要原始的概率分数。51fpr, tpr, thresholds_roc = roc_curve(y_true, y_scores_good)52roc_auc = auc(fpr, tpr)53print(f"AUC-ROC: {roc_auc:.4f}")5455# --- 4. 计算和绘制 PR 曲线与 AUC ---56print("\n--- AUC-PR ---")57prec, rec, thresholds_pr = precision_recall_curve(y_true, y_scores_good)58# scikit-learn 中计算 AUC-PR 通常使用 average_precision_score,它在数值上更稳定59pr_auc = average_precision_score(y_true, y_scores_good)60print(f"AUC-PR (Average Precision): {pr_auc:.4f}")6162# --- 5. 可视化对比 ---63plt.figure(figsize=(14, 6))64plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签65plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号6667# 绘制 ROC 曲线68plt.subplot(1, 2, 1)69plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')70plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') # 随机猜测线71plt.xlim([0.0, 1.0])72plt.ylim([0.0, 1.05])73plt.xlabel('False Positive Rate (FPR)')74plt.ylabel('True Positive Rate (TPR / Recall)')75plt.title('ROC 曲线')76plt.legend(loc="lower right")7778# 绘制 PR 曲线79plt.subplot(1, 2, 2)80# 为什么PR曲线的基线是正样本比例?81# 因为一个随机模型,无论召回率如何变化,其精确率都应该维持在正样本比例附近。82baseline = np.sum(y_true) / len(y_true)83plt.plot(rec, prec, color='darkorange', lw=2, label=f'PR curve (area = {pr_auc:.2f})')84plt.plot([0, 1], [baseline, baseline], color='navy', lw=2, linestyle='--', label=f'Baseline (P={baseline:.2f})')85plt.xlim([0.0, 1.0])86plt.ylim([0.0, 1.05])87plt.xlabel('Recall')88plt.ylabel('Precision')89plt.title('PR 曲线 (类别不平衡时更具信息量)')90plt.legend(loc="lower left")9192plt.tight_layout()93plt.show()
工程实践
| 指标 | 适用场景 | 经验法则与权衡 | | :--- | :--- | :--- | | Accuracy | 类别分布均衡的数据集,且所有类别的预测错误代价相近。例如,CIFAR-10 图像分类。 | - 优点: 直观,易于理解。 <br> - 缺点: 在类别不平衡时极具误导性。一个预测所有样本为多数类的“惰性”模型可以获得很高的准确率。 | | Precision | 对假正例 (FP) 惩罚很高的场景,即“宁可放过,不可杀错”。 | - 场景: 垃圾邮件过滤(将重要邮件误判为垃圾的代价很高)、股票预测(错误预测上涨导致买入的代价很高)。 <br> - 权衡: 提高 Precision 往往以牺牲 Recall 为代价。可以通过提高分类阈值来实现,但这会漏掉更多正例。 | | Recall | 对假负例 (FN) 惩罚很高的场景,即“宁可杀错,不可放过”。 | - 场景: 传染病筛查(漏诊一个病人的社会代价很高)、金融欺诈检测(漏掉一笔欺诈交易的损失很大)。 <br> - 权衡: 提高 Recall 往往以牺牲 Precision 为代价。可以通过降低分类阈值来实现,但这会引入更多误报。 | | F1-Score | 需要在 Precision 和 Recall 之间取得平衡的场景,特别是类别不平衡时。 | - 场景: 大多数需要综合考虑 P 和 R 的业务场景,如产品推荐、文本分类等。 <br> - 变体: F-beta score (),当 时更看重 Recall,当 时更看重 Precision。 | | AUC-ROC | 不关心具体的决策阈值,只关心模型整体的排序能力。适合作为模型对比和调参的主要指标。 | - 优点: 阈值无关,对类别不平衡不敏感(见误区),表现稳定。 <br> - 缺点: 在极度不平衡数据下,其“不敏感”的特性可能掩盖模型在少数类上的表现不佳问题,显得过于乐观。 | | AUC-PR | 类别极度不平衡,且更关注正例(少数类)的识别效果。 | - 场景: 广告点击率预测 (CTR)、搜索引擎查询相关性、基因序列分析。在这些场景,正例非常稀疏,我们更关心模型能否在海量负例中准确找出少数正例。 <br> - 优点: 在类别不平衡时比 AUC-ROC 更具信息量和区分度。 |
选择决策阈值: 在实际应用中,我们不能只交付一个模型,还需要一个决策阈值。这个阈值可以根据 ROC 或 PR 曲线来选择。例如,业务方要求 Recall 必须达到 90% 以上,我们就可以在 PR 曲线上找到满足 Recall > 0.9 的所有点中,Precision 最高的那个点对应的阈值作为最终决策点。
常见误区与边界情况
- Accuracy 陷阱: 这是最常见的误区。在任何不平衡数据集上,都不要孤立地使用 Accuracy 来评估模型。务必结合 Precision, Recall, F1 或 AUC-PR 来综合判断。
- AUC-ROC 对类别不平衡“免疫”的误解: AUC-ROC 对类别不平衡“不敏感”,而不是“免疫”。它的不敏感是因为 FPR 的分母包含海量的 TN,使得 FPR 增长缓慢,导致 AUC 值虚高。这在评估上是“钝感”的,可能掩盖问题,而 AUC-PR 在这种情况下更“敏感”,更能暴露模型在正例上的性能短板。
- AUC 值高不代表模型一定好用: AUC 衡量的是整体排序能力,但在特定应用场景下,我们可能只关心曲线的某个特定部分。例如,在要求高 Precision 的场景,一个模型可能总体 AUC 稍低,但在高 Precision 区间(PR 曲线的左侧部分)表现更好,那么它可能是一个更优的选择。
- 混淆多分类中的 Micro vs. Macro Average:
- Macro-Average (宏平均): 对每个类别独立计算指标,然后取算术平均。它平等对待所有类别,无论类别样本量多少。如果小类别性能很重要,应关注此指标。
- Micro-Average (微平均): 将所有类别的 TP, FP, FN 汇总后,再计算一次指标。它受样本量大的类别主导。在多分类问题中,Micro-Precision, Micro-Recall, Micro-F1 和 Accuracy 的值是完全相等的。
- Weighted-Average (加权平均): 类似宏平均,但在平均时根据每个类别的样本数量进行加权。是 Macro 和 Micro 的折衷。
- PR 曲线的形状: PR 曲线通常不是平滑下降的,可能出现“锯齿”或“波浪”。这是因为随着阈值降低,Recall 增加,但 Precision 可能会因为某个样本的预测翻转而时升时降。这是正常现象。