48·监督学习-分类进阶

混淆矩阵与 ROC/PR 曲线

evaluationvisualization

第48课:混淆矩阵与 ROC/PR 曲线

学习目标

完成本课后,你将能够:

  1. 理解并解释混淆矩阵的结构及其每个元素的含义。
  2. 掌握 ROC 曲线与 AUC 值的计算原理和可视化方法。
  3. 了解 PR 曲线的特点及其与 ROC 曲线的适用场景区别。
  4. 使用 Python 和 scikit-learnmatplotlib 等库,完整实现分类模型的评估与可视化。

核心概念

1. 混淆矩阵:模型的“成绩单”

混淆矩阵(Confusion Matrix)是分类模型最基础、最全面的评估工具。它像一个2x2的表格(针对二分类),清晰展示了模型预测结果与真实标签之间的关系。

想象一下,模型是一个学生,真实答案是“标准答案”。

  • 真正例(TP):模型预测“是”,答案也是“是”。(答对了)
  • 假正例(FP):模型预测“是”,但答案其实是“否”。(答错了,误报)
  • 假负例(FN):模型预测“否”,但答案其实是“是”。(答错了,漏报)
  • 真负例(TN):模型预测“否”,答案也是“否”。(答对了)

直观理解

  • 左上到右下的对角线(TP, TN)代表预测正确的样本。
  • 右上到左下的对角线(FP, FN)代表预测错误的样本。

基于这个矩阵,我们可以计算出精确率、召回率、准确率等所有指标。

2. ROC 曲线:权衡“抓准”与“抓全”

ROC(Receiver Operating Characteristic)曲线用于评估模型在不同阈值下,区分正负样本的能力。它的两个坐标轴是:

  • 真正例率(TPR,也叫召回率):在所有真实为正的样本中,模型找对了多少。(抓全的能力)
  • 假正例率(FPR):在所有真实为负的样本中,模型错认了多少。(误报的代价)

绘制过程:将模型输出的概率值从高到低排序,依次将每个概率值作为阈值,计算出对应的(TPR, FPR)点,连接成线。

  • 理想情况:曲线尽可能靠近左上角(TPR=1, FPR=0)。
  • 随机猜测模型:曲线为对角线(TPR = FPR)。

AUC(Area Under the Curve):ROC曲线下的面积,取值范围[0.5, 1]。AUC越大,说明模型性能越好。AUC的直观意义:随机抽取一个正样本和一个负样本,模型将正样本预测为正的概率高于负样本的概率。

3. PR 曲线:关注“查准”与“查全”的平衡

PR(Precision-Recall)曲线在正样本非常稀少的场景下(如欺诈检测、罕见病诊断)更有参考价值。它的两个坐标轴是:

  • 精确率(Precision):在所有模型预测为正的样本中,有多少是真正的正样本。(预测为正的可靠性)
  • 召回率(Recall):在所有真实为正的样本中,模型找对了多少。(抓全的能力)

特点:当正样本极少时,FPR 的分母(真实负样本数)很大,导致即使 FP 很多,FPR 也可能很小,从而可能高估 ROC 曲线的性能。而 PR 曲线直接关注正样本的识别能力,对此更为敏感。

代码示例

下面,我们将使用 scikit-learn 生成数据、训练模型,并用 matplotlib 绘制混淆矩阵、ROC曲线和PR曲线。

# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (confusion_matrix, ConfusionMatrixDisplay,
                             roc_curve, auc,
                             precision_recall_curve, average_precision_score,
                             classification_report)

# 1. 生成模拟的二分类数据(设置一些样本不平衡)
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2,
                           weights=[0.9, 0.1], # 10%的正样本,模拟不平衡
                           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, max_iter=1000)
model.fit(X_train, y_train)

# 4. 获取测试集上的预测概率(用于绘制曲线)
y_prob = model.predict_proba(X_test)[:, 1] # 获取正类的概率
y_pred = model.predict(X_test)

# ========== 5. 绘制混淆矩阵 ==========
cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=model.classes_)
disp.plot(cmap='Blues')
plt.title('Confusion Matrix')
plt.show()

# 打印详细的分类报告
print("分类报告:\n", classification_report(y_test, y_pred))

# ========== 6. 绘制 ROC 曲线并计算 AUC ==========
fpr, tpr, thresholds_roc = roc_curve(y_test, y_prob)
roc_auc = auc(fpr, tpr)

plt.figure(figsize=(10, 5))

# ROC 曲线
plt.subplot(1, 2, 1)
plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--', label='Random Guess')
plt.xlabel('False Positive Rate (FPR)')
plt.ylabel('True Positive Rate (TPR)')
plt.title('Receiver Operating Characteristic (ROC) Curve')
plt.legend(loc='lower right')
plt.grid(True)

# ========== 7. 绘制 PR 曲线并计算平均精度 ==========
precision, recall, thresholds_pr = precision_recall_curve(y_test, y_prob)
avg_precision = average_precision_score(y_test, y_prob)

# PR 曲线
plt.subplot(1, 2, 2)
plt.plot(recall, precision, color='blue', lw=2, label=f'PR curve (AP = {avg_precision:.2f})')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve')
plt.legend(loc='upper right')
plt.grid(True)

plt.tight_layout()
plt.show()

# 输出关键阈值信息示例
print(f"AUC (ROC): {roc_auc:.4f}")
print(f"Average Precision (PR): {avg_precision:.4f}")

代码输出说明

  1. 混淆矩阵图:深色对角线数值高表示预测准确。
  2. 分类报告:展示了精确率、召回率、F1-score等详细数值。
  3. ROC曲线图:橙色曲线离左上角越近越好,蓝色虚线是随机猜测的基准线。
  4. PR曲线图:蓝色曲线,面积(AP)越大,模型在正样本上的综合表现越好。

实践练习

练习1:基础理解

假设一个模型的混淆矩阵如下:

[[95, 5],
 [10, 90]]

请手动计算该模型的准确率、精确率、召回率

  • 预期输出:准确率=0.925,精确率=0.947,召回率=0.9。

练习2:模型比较

在上述代码的基础上,增加一个 RandomForestClassifier 模型。分别绘制两个模型的 ROC 曲线在同一张图上进行比较,并标注各自的 AUC 值。

  • 要求:使用不同颜色区分曲线,图例清晰。
  • 预期输出:一张包含两条ROC曲线的对比图。

练习3:业务场景分析

在欺诈检测场景中(正样本“欺诈”极少),你认为应该更关注 ROC-AUC 还是 PR-AUC?为什么?

  • 要求:从两类错误的代价(FP和FN)角度进行简短分析。
  • 预期输出:一段文字说明你的选择和理由。

常见错误

  1. 混淆矩阵的正负类定义错误:在绘图时,确保 ConfusionMatrixDisplaydisplay_labels 参数与你的类别顺序一致。通常,model.classes_ 的第一个元素对应矩阵左上角的类别。
  2. 在样本严重不平衡时只看 ROC 曲线:当负样本远多于正样本时,ROC-AUC 可能会给出过于乐观的评价。此时应结合 PR 曲线和平均精度(AP)进行综合判断。
  3. 误读 AUC 值:AUC=0.5 意味着模型与随机猜测无异,但 AUC=0.8 并不直接等同于“80%的准确率”。它是一个排序能力的度量。
  4. 曲线绘制不平滑:当测试集样本较少时,ROC/PR 曲线可能会出现锯齿状。这是正常现象,不影响AUC/AP的计算和模型整体性能的判断。

小结

  • 混淆矩阵是分类评估的基石,它提供了关于预测结果(TP, FP, FN, TN)的全景视图,所有其他指标都源于此。
  • ROC-AUC 衡量模型整体区分正负样本的排序能力,对类别不平衡相对不敏感,是通用性很强的评估指标。
  • PR-AUC(平均精度) 更聚焦于正样本的识别能力,在正样本稀少、或“误报”(FP)代价远高于“漏报”(FN)的业务场景下(如推荐系统、欺诈检测)更具参考价值。
  • 在实际项目中,应结合使用这些工具:先看混淆矩阵了解错误类型,再通过 ROC 和 PR 曲线评估模型在不同操作点(阈值)下的表现,并根据业务目标选择合适的评估指标。

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「K-Means 聚类算法」 以巩固所学知识。