模型评估指标详解:准确率/召回率/F1/AUC一次全搞懂

所属模块:卷三 · 知识体系篇 · 第三部分 模型训练与调优
考试权重:★★★★★(必考中的必考,每次考试必有计算题)
阅读时长:约28分钟


一、为什么一个"准确率"不够用?

先看一个场景:某癌症筛查模型,在1000名患者中(990名健康,10名患癌),模型直接预测所有人"健康"。

准确率 = 990/1000 = 99% ——看起来很完美?

但这个模型把所有癌症患者都漏诊了,是彻底失败的模型!

这就是为什么需要更丰富的评估指标体系。


二、混淆矩阵(Confusion Matrix):一切指标的基础

2.1 混淆矩阵结构

                    预测值
                 正例(1)  负例(0)
         ┌─────────────────────────┐
真  正例  │   TP      │    FN      │
实  (1)   │ (真正例)  │  (假负例)  │
值  ──────┼───────────┼────────────┤
    负例  │   FP      │    TN      │
    (0)   │ (假正例)  │  (真负例)  │
         └─────────────────────────┘

TP(True Positive):预测正,实际也正 ✅
TN(True Negative):预测负,实际也负 ✅
FP(False Positive):预测正,实际负  ❌(误报/虚警)
FN(False Negative):预测负,实际正  ❌(漏报)

2.2 各象限含义记忆口诀

“T看对不对,P看预测什么”

  • T(True)= 预测对了;F(False)= 预测错了
  • P(Positive)= 预测为正;N(Negative)= 预测为负

三、分类指标四件套

3.1 准确率(Accuracy)

Accuracy=TP+TNTP+TN+FP+FN\text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN}Accuracy=TP+TN+FP+FNTP+TN

  • 含义:整体预测正确的比例
  • 适用:类别均衡时
  • 不适用:类别不平衡(如癌症检测、欺诈检测)

3.2 精确率/查准率(Precision)

Precision=TPTP+FP\text{Precision} = \frac{TP}{TP + FP}Precision=TP+FPTP

  • 含义:预测为正的样本中,实际为正的比例(宁可漏报,不能误报)
  • 适用场景:垃圾邮件过滤(宁可放过垃圾邮件,也不误删正常邮件)

3.3 召回率/查全率(Recall)

Recall=TPTP+FN\text{Recall} = \frac{TP}{TP + FN}Recall=TP+FNTP

  • 含义:实际为正的样本中,被预测为正的比例(宁可误报,不能漏报)
  • 适用场景:癌症检测(宁可误报健康人,也不漏诊癌症患者)

3.4 F1分数(F1 Score)

F1=2×Precision×RecallPrecision+Recall\text{F1} = \frac{2 \times \text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}F1=Precision+Recall2×Precision×Recall

  • 含义:Precision和Recall的调和平均数(比算术平均更严格)
  • 适用:希望Precision和Recall都高的场景

3.5 精确率 vs 召回率的权衡

         精确率 ↑          召回率 ↑
    ┌──────────────────────────────────────┐
    │ 代价:漏报增多    代价:误报增多      │
    │ 适合:垃圾邮件    适合:癌症检测/     │
    │       推荐系统        欺诈识别        │
    └──────────────────────────────────────┘

调节阈值影响二者:
  阈值↑(更严格判正)→ Precision↑,Recall↓
  阈值↓(更宽松判正)→ Precision↓,Recall↑

四、完整指标体系:六大核心指标一览

指标 公式 适用场景
Accuracy (TP+TN)/总数 类别均衡
Precision TP/(TP+FP) 误报代价高
Recall TP/(TP+FN) 漏报代价高
F1 Score 2·P·R/(P+R) 综合评价
F-beta (1+β²)·P·R/(β²·P+R) β>1偏重Recall;β<1偏重Precision
AUC-ROC ROC曲线下面积 阈值无关的综合性能

五、ROC曲线与AUC:阈值无关的评估利器

5.1 ROC曲线原理

ROC曲线坐标轴:
Y轴:TPR(True Positive Rate)= Recall = TP/(TP+FN)
X轴:FPR(False Positive Rate)= FP/(FP+TN)  → 误报率

通过遍历所有分类阈值(0→1),得到一系列(FPR, TPR)点,连成曲线:

TPR
 1 │              *
   │          *
   │      *
   │  *
   │*
 0 └──────────────── FPR
   0                  1

  对角线 = 随机猜测(AUC=0.5)
  曲线越靠左上角越好(AUC越接近1.0)

5.2 AUC值解读标准

AUC值范围 模型性能
1.0 完美(通常意味着数据泄露)
0.9 ~ 1.0 优秀
0.8 ~ 0.9 良好
0.7 ~ 0.8 一般,需改进
0.5 ~ 0.7 较差,接近随机
< 0.5 比随机还差(标签可能反了)

5.3 PR曲线 vs ROC曲线

比较点 ROC曲线 PR曲线
X轴 FPR(误报率) Recall(召回率)
Y轴 TPR(召回率) Precision(精确率)
适用数据 类别均衡 类别严重不平衡
反映问题 整体分类能力 正例识别能力
基线 对角线(AUC=0.5) 随正例比例变化

记忆规则:类别不平衡时,优先看PR曲线,ROC可能虚高。


六、多分类评估:宏平均 vs 微平均

当类别数>2时,F1等指标需要聚合各类别结果:

示例:3分类(类A/B/C)各自的Precision和Recall

        类A    类B    类C
P:     0.9    0.7    0.5
R:     0.8    0.6    0.4
F1:    0.85   0.65   0.44
样本数:200    50     50
聚合方式 计算方法 特点
macro avg 各类别F1的算术平均 对每个类别一视同仁,小类别影响大
weighted avg 各类别F1按样本量加权 反映整体性能,适合不均衡
micro avg 全局TP/FP/FN汇总后计算 等同于accuracy(无权重差异时)
macro F1  = (0.85 + 0.65 + 0.44) / 3 = 0.647
weighted F1 = (0.85×200 + 0.65×50 + 0.44×50) / 300 = 0.748

七、回归任务评估指标

指标 公式 特点
MAE (1/n)Σ|ŷ-y| 绝对误差,单位同原始
MSE (1/n)Σ(ŷ-y)² 放大大误差,对异常值敏感
RMSE √MSE 单位同原始,综合常用
R²(决定系数) 1 - SS_res/SS_tot 越接近1越好,可为负数
MAPE (1/n)Σ|ŷ-y|/y × 100% 相对误差,跨量纲比较
R² = 1 表示完美拟合
R² = 0 表示模型等同于用均值预测
R² < 0 表示模型比均值预测还差

八、代码示例:完整评估指标计算

import numpy as np
from sklearn.metrics import (
    accuracy_score, precision_score, recall_score, f1_score,
    roc_auc_score, roc_curve, precision_recall_curve,
    confusion_matrix, classification_report,
    mean_absolute_error, mean_squared_error, r2_score
)
import matplotlib.pyplot as plt

# ──────────────────────────────────────────
# 一、分类指标完整计算
# ──────────────────────────────────────────
# 模拟预测结果
y_true  = np.array([1,1,1,0,0,0,1,0,1,0])
y_pred  = np.array([1,0,1,0,1,0,1,0,0,0])
y_score = np.array([0.9,0.4,0.8,0.2,0.7,0.1,0.95,0.3,0.45,0.15])

# 混淆矩阵
cm = confusion_matrix(y_true, y_pred)
TP, FP, FN, TN = cm[1,1], cm[0,1], cm[1,0], cm[0,0]
print("=== 混淆矩阵 ===")
print(f"TP={TP}, FP={FP}, FN={FN}, TN={TN}")

# 各项指标
accuracy  = accuracy_score(y_true, y_pred)
precision = precision_score(y_true, y_pred)
recall    = recall_score(y_true, y_pred)
f1        = f1_score(y_true, y_pred)
auc       = roc_auc_score(y_true, y_score)

print(f"\n=== 核心指标 ===")
print(f"Accuracy : {accuracy:.4f}  ({TP+TN}/{len(y_true)})")
print(f"Precision: {precision:.4f}  (TP/(TP+FP) = {TP}/{TP+FP})")
print(f"Recall   : {recall:.4f}  (TP/(TP+FN) = {TP}/{TP+FN})")
print(f"F1 Score : {f1:.4f}")
print(f"AUC-ROC  : {auc:.4f}")

# 完整分类报告
print("\n=== 分类报告(sklearn标准格式)===")
print(classification_report(y_true, y_pred, target_names=['负例', '正例']))

# ──────────────────────────────────────────
# 二、ROC曲线绘制
# ──────────────────────────────────────────
fpr, tpr, thresholds = roc_curve(y_true, y_score)
plt.figure(figsize=(10, 4))

plt.subplot(1, 2, 1)
plt.plot(fpr, tpr, 'b-', linewidth=2, label=f'ROC (AUC={auc:.3f})')
plt.plot([0,1], [0,1], 'k--', label='随机猜测 (AUC=0.5)')
plt.xlabel('FPR(误报率)')
plt.ylabel('TPR(召回率)')
plt.title('ROC曲线')
plt.legend()

# PR曲线
precision_curve, recall_curve, _ = precision_recall_curve(y_true, y_score)
plt.subplot(1, 2, 2)
plt.plot(recall_curve, precision_curve, 'r-', linewidth=2)
plt.xlabel('Recall(召回率)')
plt.ylabel('Precision(精确率)')
plt.title('PR曲线')
plt.tight_layout()
# plt.savefig('evaluation_curves.png', dpi=150)

# ──────────────────────────────────────────
# 三、多分类评估
# ──────────────────────────────────────────
print("\n=== 多分类评估 ===")
y_true_multi = np.array([0,1,2,0,1,2,0,1,2,0])
y_pred_multi = np.array([0,1,1,0,2,2,0,1,2,1])

print(classification_report(y_true_multi, y_pred_multi,
                              target_names=['类A','类B','类C']))

# ──────────────────────────────────────────
# 四、回归指标
# ──────────────────────────────────────────
print("=== 回归指标 ===")
y_reg_true = np.array([3.0, 5.0, 2.5, 7.0, 4.5])
y_reg_pred = np.array([2.8, 5.2, 2.0, 7.5, 4.2])

mae  = mean_absolute_error(y_reg_true, y_reg_pred)
mse  = mean_squared_error(y_reg_true, y_reg_pred)
rmse = np.sqrt(mse)
r2   = r2_score(y_reg_true, y_reg_pred)

print(f"MAE  = {mae:.4f}")
print(f"MSE  = {mse:.4f}")
print(f"RMSE = {rmse:.4f}")
print(f"R²   = {r2:.4f}")

# ──────────────────────────────────────────
# 五、手动计算F-beta(β≠1时)
# ──────────────────────────────────────────
def f_beta(precision, recall, beta):
    """
    beta > 1: 更看重Recall(漏报代价高,如医疗)
    beta < 1: 更看重Precision(误报代价高,如垃圾邮件)
    beta = 1: 标准F1
    """
    if precision + recall == 0:
        return 0
    return (1 + beta**2) * precision * recall / (beta**2 * precision + recall)

print(f"\n=== F-beta ===")
p, r = 0.8, 0.6
print(f"F0.5(偏Precision)= {f_beta(p, r, 0.5):.4f}")
print(f"F1  (均衡)        = {f_beta(p, r, 1.0):.4f}")
print(f"F2  (偏Recall)    = {f_beta(p, r, 2.0):.4f}")

九、指标选择决策树

你的任务类型是?
│
├── 分类
│    │
│    ├── 类别均衡?
│    │    ├── 是 → Accuracy + F1
│    │    └── 否 → F1(weighted) + AUC-PR
│    │
│    ├── 漏报代价 >> 误报代价?
│    │    └── 重点看 Recall(如:癌症检测、欺诈识别)
│    │
│    ├── 误报代价 >> 漏报代价?
│    │    └── 重点看 Precision(如:垃圾邮件、推荐系统)
│    │
│    └── 需要与阈值无关的综合评估?
│         └── AUC-ROC(均衡)或 AUC-PR(不均衡)
│
└── 回归
     ├── 关注绝对误差量级? → MAE / RMSE
     ├── 关注相对比例?     → MAPE
     └── 关注解释方差比例? → R²

十、考试必背:计算题模板

给定混淆矩阵:TP=80, FP=20, FN=40, TN=160,求各指标。

总数N  = 80+20+40+160 = 300
Accuracy   = (80+160)/300 = 80.0%
Precision  = 80/(80+20)   = 80.0%
Recall     = 80/(80+40)   = 66.7%
F1         = 2×0.8×0.667/(0.8+0.667) = 72.7%
FPR        = 20/(20+160)  = 11.1%
Specificity= TN/(TN+FP)   = 160/180 = 88.9%


下一篇预告:《过拟合与欠拟合的识别与处理》——如何通过训练曲线诊断模型状态,并用正则化、Dropout、数据增强等手段对症下药?

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐