第 47 课 - 分类评估指标:精确率、召回率、F1 与 AUC
1. 学习目标
完成本课后,你将能够:
- 理解精确率、召回率、F1分数和AUC的含义与区别。
- 掌握使用
sklearn计算这些评估指标的方法。 - 阐述在不同业务场景下,如何根据需求选择合适的评估指标。
- 对比不同评估指标在衡量模型性能上的优劣。
2. 核心概念
在分类任务中,准确率是一个常见指标,但在数据不平衡时(例如,正样本占1%,负样本占99%),一个永远预测负类的“傻瓜”模型也能获得99%的准确率,但毫无用处。因此,我们需要更精细的指标。
2.1 从混淆矩阵说起
所有指标都源于一个基础:混淆矩阵。它将模型的预测结果与真实标签进行交叉统计,得到四个值:
- 真正例:真实为正,预测为正
- 假正例:真实为负,预测为正(误报)
- 真负例:真实为负,预测为负
- 假负例:真实为正,预测为负(漏报)
2.2 精确率与召回率
- 精确率:
精确率 = 真正例 / (真正例 + 假正例)。它回答的问题是:“在所有预测为正的样本中,有多少是真正的正样本?”高精确率意味着低误报。例如,在垃圾邮件检测中,我们不希望重要的正常邮件被误判为垃圾邮件。 - 召回率:
召回率 = 真正例 / (真正例 + 假负例)。它回答的问题是:“在所有真实为正的样本中,有多少被模型正确找到了?”高召回率意味着低漏报。例如,在疾病诊断中,我们不希望错过任何一个患病者。
精确率和召回率通常是一对矛盾体。 提高阈值(更严格地判定为正)会提高精确率但降低召回率;反之亦然。
2.3 F1分数
为了平衡精确率和召回率,我们引入F1分数,它是两者的调和平均数。
F1 = 2 * (精确率 * 召回率) / (精确率 + 召回率)
F1分数的值域在0到1之间,越接近1越好。当精确率和召回率都很高时,F1也会很高。它更适合评估那些你同时关心误报和漏报的任务。
2.4 AUC-ROC
AUC 是ROC曲线下面积。ROC曲线以假正例率为X轴,**真正例率(即召回率)**为Y轴绘制而成。
- AUC衡量的是模型将正样本排在负样本前面的能力。一个完美的模型AUC=1,一个随机猜测的模型AUC≈0.5。
- AUC的优势:它不受分类阈值选择的影响,能评估模型整体的排序质量。在数据不平衡时,它通常比准确率更稳定。
一句话总结:
- 精确率和召回率:关注“预测为正”的质量和“找到所有正样本”的能力,需要指定阈值。
- F1:精确率和召回率的平衡点。
- AUC:评估模型整体区分正负样本的能力,与阈值无关。
3. 代码示例
# 导入必要的库
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import precision_score, recall_score, f1_score, roc_auc_score
import numpy as np
# 1. 生成一个模拟数据集 (10%的正样本,模拟不平衡数据)
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2,
weights=[0.9, 0.1], random_state=42)
# 2. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 3. 训练一个逻辑回归模型
model = LogisticRegression(random_state=42)
model.fit(X_train, y_train)
# 4. 获取预测概率和预测类别(默认阈值为0.5)
y_pred_proba = model.predict_proba(X_test)[:, 1] # 获取预测为正类的概率
y_pred = model.predict(X_test) # 默认阈值0.5的预测结果
# 5. 计算评估指标
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
auc = roc_auc_score(y_test, y_pred_proba)
print(f"默认阈值(0.5)下的评估结果:")
print(f"精确率 (Precision): {precision:.3f}")
print(f"召回率 (Recall): {recall:.3f}")
print(f"F1分数: {f1:.3f}")
print(f"AUC: {auc:.3f}")
# 6. 演示阈值的影响
# 我们尝试一个更严格的阈值 (0.7),只对更确信的样本预测为正
y_pred_strict = (y_pred_proba >= 0.7).astype(int)
precision_strict = precision_score(y_test, y_pred_strict)
recall_strict = recall_score(y_test, y_pred_strict)
print(f"\n严格阈值(0.7)下的评估结果:")
print(f"精确率: {precision_strict:.3f}")
print(f"召回率: {recall_strict:.3f}")
print("可以看到,提高阈值后,精确率上升,召回率下降。")
4. 实践练习
练习题 1:基础计算
给定一个混淆矩阵如下:
| 预测为正 | 预测为负 | |
|---|---|---|
| 真实为正 | 80 | 20 |
| 真实为负 | 10 | 90 |
| 请手动计算该模型的精确率、召回率和F1分数。 |
要求:写出计算过程。 预期输出:
- 精确率 = 80 / (80 + 10) ≈ 0.889
- 召回率 = 80 / (80 + 20) = 0.800
- F1 ≈ 2 * (0.889 * 0.800) / (0.889 + 0.800) ≈ 0.842
练习题 2:比较不同模型
使用课程代码示例中的数据集和划分方式,再训练一个RandomForestClassifier模型(设置random_state=42)。分别计算逻辑回归和随机森林在测试集上的AUC值。
要求:编写代码完成,并比较哪个模型的AUC更高。
预期输出示例:
逻辑回归 AUC: 0.921
随机森林 AUC: 0.945
随机森林的AUC更高。
练习题 3:业务决策(挑战)
假设你正在为一个电商平台构建“用户购买意向预测”模型。如果一个高意向用户没有被识别出来(假负例),平台损失一次销售机会;如果一个低意向用户被错误推送了优惠券(假正例),平台会浪费营销成本。 问题:在这种场景下,你认为应该更侧重提升模型的精确率还是召回率?请结合指标的定义和业务后果解释你的理由。
5. 常见错误
- 只看准确率:在数据不平衡时,准确率具有极大的欺骗性。务必结合精确率、召回率等指标综合评估。
- 混淆精确率与召回率:记住口诀——“精确率关心预测出的正样本对不对,召回率关心正样本有没有找全”。
- 忽略阈值的影响:
model.predict()使用的是默认阈值0.5,但在很多业务场景中,调整阈值是优化模型的关键步骤(如练习1中所示)。 - 单一指标论:没有哪个指标是“万能”的。要根据业务目标(更怕误报还是更怕漏报)来选择主要优化的指标。例如,医学诊断(漏报代价高)更看重召回率;垃圾邮件过滤(误报代价高)更看重精确率。
6. 小结
- 精确率:预测为正的样本中,真正为正的比例。高精确率 = 低误报。
- 召回率:所有真实正样本中,被模型找到的比例。高召回率 = 低漏报。
- F1分数:精确率与召回率的调和平均数,用于寻求二者的平衡。
- AUC-ROC:评估模型将正样本排在负样本之前的整体排序能力,值越接近1越好,且与分类阈值无关。
- 关键思想:选择评估指标的核心依据是业务目标。理解不同指标的含义和权衡关系,是构建有效机器学习模型的重要一步。
下一课,我们将深入探讨混淆矩阵的可视化,并学习如何绘制ROC曲线和PR曲线,这些工具能帮助我们更直观地理解模型性能。