【机器学习】ROC 曲线与 PR 曲线
目录
在机器学习中,分类模型的任务是判断一个样本属于哪个类别,比如“这个邮件是垃圾邮件吗?”或“这个病人有癌症吗?”。然而,模型的性能并非总是完美,它可能会犯一些错误。
为了更好地评估和比较不同分类模型的性能,我们需要一些有效的评估指标和可视化工具。
其中,ROC (Receiver Operating Characteristic) 曲线和 PR (Precision-Recall) 曲线 就是两种非常重要的工具,尤其是在处理不平衡数据集时。
本文将深入探讨 ROC 曲线和 PR 曲线的概念、计算方法以及如何使用 Python 中的 scikit-learn 库来绘制它们。
一、混淆矩阵:分类评估的基础
在理解 ROC 和 PR 曲线之前,我们需要先了解混淆矩阵 (Confusion Matrix)。
对于一个二分类问题,混淆矩阵是一个 2x2 的表格,它总结了模型预测结果与真实标签之间的关系:
| 预测为正例 (Positive) | 预测为负例 (Negative) | |
| 真实为正例 (Positive) | 真阳性 (True Positive, TP) | 假阴性 (False Negative, FN) |
| 真实为负例 (Negative) | 假阳性 (False Positive, FP) | 真阴性 (True Negative, TN) |
- 真阳性 (TP):正确预测为正例,比如“模型说这是垃圾邮件,确实是”。
- 假阳性 (FP):错误预测为正例,比如“模型说这是垃圾邮件,但其实不是”。
- 真阴性 (TN):正确预测为负例。
- 假阴性 (FN):漏掉的正例,比如“模型说这不是垃圾邮件,但其实是”。
基于混淆矩阵,我们可以计算出一些基本的评估指标:
- 准确率 (Accuracy):
,表示模型预测正确的样本比例。
- 精确率 (Precision):
,表示在所有预测为正例的样本中,真正例的比例。
- 召回率 (Recall) (也称为灵敏度或真正例率):
,表示在所有真实为正例的样本中,被模型正确预测为正例的比例。
- 假阳性率 (False Positive Rate, FPR):
,表示在所有真实为负例的样本中,被模型错误预测为正例的比例。
- 真阳性率 (True Positive Rate, TPR) (与召回率相同):
。
二、ROC曲线:衡量模型的区分能力
ROC 曲线以 假阳性率 (FPR) 为横轴,真阳性率 (TPR) 为纵轴,展示模型在不同分类阈值下的表现。
什么是分类阈值?
- 模型输出一个概率(比如“80%是正例”)。我们通过设置一个阈值(比如“概率>0.5才算正例”)来决定预测结果。调整阈值会影响TPR和FPR,ROC曲线把所有可能的阈值结果连成一条线。
AUC (Area Under the ROC Curve)
AUC 是 ROC 曲线下的面积,它是一个介于 0 和 1 之间的值。AUC 值越大,表示模型的整体性能越好。
- AUC = 1: 完美分类器。
- AUC = 0.5: 模型的性能与随机猜测相当。
- AUC < 0.5: 模型的性能比随机猜测还要差(通常表示模型学习的方向错误,可以考虑反转预测结果)。
三、 PR曲线:聚焦正例表现
PR 曲线以 召回率 (Recall) 为横轴,精确率 (Precision) 为纵轴,展示模型在正例预测上的表现。
和ROC曲线一样,PR曲线通过调整分类阈值,观察精确率和召回率的变化。
目标是既找到所有正例(高召回率),又确保预测的正例都正确(高精确率)。
Average Precision (AP)
AP 是 PR 曲线下的面积,它衡量了在不同召回率水平上的平均精确率。AP 值越高,表示模型的性能越好。
四、何时使用 ROC 曲线和 PR 曲线?
-
ROC 曲线: 通常在正负样本比例相对平衡的情况下使用。它对类别不平衡问题不太敏感。ROC 曲线关注的是模型区分正负样本的能力。
-
PR 曲线: 更适用于正负样本比例非常不平衡的情况下。当正例非常稀少时,即使模型预测了一些假阳性,其假阳性率 (FPR) 可能仍然很低,导致 ROC 曲线看起来不错。然而,此时的精确率 (Precision) 可能会很低,PR 曲线能够更敏感地反映出这个问题。PR 曲线更关注模型在正例上的预测能力。
五、ROC曲线 vs. PR曲线:如何选择?

示例:在癌症检测中,正例(癌症)很少。如果用ROC曲线,大量真阴性(健康人)可能让曲线看起来很好,但PR曲线能更真实地反映模型对癌症的识别能力。
六、Python 代码实现
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 roc_curve, precision_recall_curve, auc
# 生成样本数据
X, y = make_classification(n_samples=1000, n_classes=2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 训练逻辑回归模型
model = LogisticRegression()
model.fit(X_train, y_train)
# 获取预测概率
y_scores = model.predict_proba(X_test)[:, 1]
# 计算ROC曲线
fpr, tpr, _ = roc_curve(y_test, y_scores)
roc_auc = auc(fpr, tpr)
# 计算PR曲线
precision, recall, _ = precision_recall_curve(y_test, y_scores)
pr_auc = auc(recall, precision)
# 绘制ROC曲线
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot(fpr, tpr, label=f'ROC curve (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--') # 随机猜测线
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend()
plt.grid(True)
# 绘制PR曲线
plt.subplot(1, 2, 2)
plt.plot(recall, precision, label=f'PR curve (AUPRC = {pr_auc:.2f})')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.savefig('roc_pr_curves.png')
实验结果

ROC曲线解读:
- 左下角 (0, 0): 表示模型将所有样本都预测为负例。
- 右上角 (1, 1): 表示模型将所有样本都预测为正例。
- 左上角 (0, 1): 这是理想的情况,表示模型在不产生任何假阳性的情况下,能够识别出所有的真实正例。
- 对角线 (y=x): 表示模型的性能与随机猜测相当。
- 曲线越靠近左上角,模型的性能越好。
PR曲线解读:
- 右上角 (1, 1): 这是理想的情况,表示模型在识别出所有正例的同时,预测的正例都是正确的。
- 靠近右上角的曲线表示模型性能越好。
- 曲线下的面积 (Average Precision, AP) 可以作为衡量 PR 曲线性能的指标。
七、总结
- ROC曲线:展示模型区分正负样本的能力,AUC越高越好,适合平衡数据集。
- PR曲线:聚焦正例的预测能力,AP越高越好,适合不平衡数据集。
- 如何选择:数据平衡用ROC,数据不平衡(正例稀少)用PR。
更多推荐
所有评论(0)