知识体系篇-数据标注与处理(03)模型训练与调优:模型评估指标详解:准确率/召回率/F1/AUC一次全搞懂
模型评估指标详解:准确率/召回率/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、数据增强等手段对症下药?
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)