在分类问题中,预测观测值属于每个类别的概率比直接预测类别更为灵活。
这种灵活性来自于概率可以通过不同的阈值来解释,这使得模型的操作者能够权衡模型所犯错误的关注点,例如假阳性数量与假阴性数量的权衡。当使用模型中一种错误的成本大于另一种错误成本时,就需要这样做。
在二元(两类)分类预测建模问题中,有两个诊断工具可以帮助解释概率预测:**ROC 曲线**和**精确率-召回率曲线**。
在本教程中,您将了解 ROC 曲线、精确率-召回率曲线以及何时使用它们来解释二元分类问题的概率预测。
完成本教程后,您将了解:
- ROC 曲线总结了预测模型在使用不同概率阈值时的真阳性率与假阳性率之间的权衡。
- 精确率-召回率曲线总结了预测模型在使用不同概率阈值时的真阳性率与阳性预测值之间的权衡。
- ROC 曲线适用于类别之间观测值平衡的情况,而精确率-召回率曲线适用于不平衡数据集。
开始您的项目,阅读我的新书《机器学习概率》,其中包含分步教程和所有示例的Python 源代码文件。
让我们开始吧。
- 更新于 2018 年 8 月:修复了精确率-召回率图中“无技能线”的表示错误。还修复了将 ROC 误称为“相对”而不是“接收者”(感谢拼写检查)的笔误。
- 更新于 2018 年 11 月:修正了对每个轴上值大小的解释的描述,感谢 Karl Humphries。
- 更新于 2019 年 6 月:修复了对不平衡结果解释时的笔误。
- 更新于 2019 年 10 月:更新了 ROC 曲线和精确率-召回率曲线图,添加了标签,使用了逻辑回归模型,并实际计算了无技能分类器的性能。
- 更新于 2019 年 11 月:改进了对精确率-召回率曲线无技能分类器的描述。
- 更新于 2023 年 10 月:对代码进行了小幅更新,使其更符合 Pythonic 风格

如何在 Python 中使用 ROC 曲线和精确率-召回率曲线进行分类
照片由 Giuseppe Milo 拍摄,保留部分权利。
教程概述
本教程分为6个部分;它们是
- 预测概率
- 什么是 ROC 曲线?
- ROC 曲线和 Python 中的 AUC
- 什么是精确率-召回率曲线?
- 精确率-召回率曲线和 Python 中的 AUC
- 何时使用 ROC 与精确率-召回率曲线?
预测概率
在分类问题中,我们可以直接预测类别值。
或者,预测每个类别的概率会更灵活。原因是为了提供选择甚至校准如何解释预测概率的阈值的功能。
例如,默认值可能是使用 0.5 的阈值,这意味着 [0.0, 0.49] 中的概率是负面结果 (0),而 [0.5, 1.0] 中的概率是正面结果 (1)。
可以调整此阈值以针对特定问题调整模型的行为。一个例子是减少一种或另一种类型的错误。
在进行二元或两类分类问题的预测时,我们可能会犯两种错误。
- 假阳性。在没有事件发生时预测事件。
- 假阴性。在事件实际发生时预测没有事件。
通过预测概率并校准阈值,模型操作者可以选择这两种关注点的平衡。
例如,在雾霾预测系统中,我们可能比假阳性更担心低假阴性。假阴性意味着在实际是高雾霾日的情况下没有警告雾霾日,导致公众健康出现问题,无法采取预防措施。假阳性意味着公众在不需要时会采取预防措施。
比较预测两类问题概率的模型的一种常用方法是使用 ROC 曲线。
什么是 ROC 曲线?
在预测二元结果概率时的一个有用工具是接收者操作特征曲线,或 ROC 曲线。
它是在 0.0 和 1.0 之间多个不同候选阈值下,假阳性率(x 轴)与真阳性率(y 轴)的图。换句话说,它绘制了虚警率与命中率。
真阳性率计算为真阳性数除以真阳性数和假阴性数之和。它描述了模型在实际结果为阳性时预测阳性类别的能力。
1 |
真阳性率 = 真阳性 / (真阳性 + 假阴性) |
真阳性率也称为灵敏度。
1 |
灵敏度 = 真阳性 / (真阳性 + 假阴性) |
假阳性率计算为假阳性数除以假阳性数和真阴性数之和。
它也称为虚警率,因为它总结了在实际结果为阴性时预测为阳性类别的频率。
1 |
假阳性率 = 假阳性 / (假阳性 + 真阴性) |
假阳性率也称为反特异度,其中特异度是真阴性数除以真阴性数和假阳性数之和。
1 |
特异度 = 真阴性 / (真阴性 + 假阳性) |
其中
1 |
假阳性率 = 1 - 特异度 |
ROC 曲线在几个方面是一个有用的工具
- 不同模型的曲线可以进行总体或不同阈值的直接比较。
- 曲线下面积 (AUC) 可用作模型技能的摘要。
曲线的形状包含大量信息,包括对于问题最重要的信息,即预期的假阳性率和假阴性率。
为了清楚说明
- 图中 x 轴上的较小值表示较低的假阳性率和较高的真阴性率。
- 图上 y 轴上的较大值表示较高的真阳性率和较低的假阴性率。
如果您感到困惑,请记住,当我们预测二元结果时,它要么是正确的预测(真阳性),要么不是(假阳性)。这些选项之间存在张力,真阴性和假阴性也是如此。
一个有技能的模型平均会将随机选择的真实阳性事件分配比阴性事件更高的概率。这就是我们所说的模型具有技能。通常,有技能的模型由向图的左上角弯曲的曲线表示。
无技能分类器是无法区分类别并会随机预测类别或在所有情况下都预测恒定类别的分类器。无技能模型在点 (0.5, 0.5) 处表示。每个阈值上无技能的模型由从图的左下角到右上角的一条对角线表示,其 AUC 为 0.5。
具有完美技能的模型表示为点 (0,1)。具有完美技能的模型由一条从图的左下角到左上角,然后沿着顶部到右上角的一条线表示。
操作员可以为最终模型绘制 ROC 曲线,并选择一个阈值,该阈值可在假阳性和假阴性之间实现理想的平衡。
想学习机器学习概率吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
ROC 曲线和 Python 中的 AUC
我们可以使用 scikit-learn 的 roc_curve() 函数在 Python 中绘制模型的 ROC 曲线。
该函数同时接受测试集中的真实结果 (0,1) 和正类的预测概率。该函数为每个阈值返回假阳性率、真阳性率和阈值。
1 2 3 |
... # 计算 roc 曲线 fpr, tpr, thresholds = roc_curve(y, probs) |
ROC 的 AUC 可以使用 roc_auc_score() 函数计算。
与 roc_curve() 函数一样,AUC 函数也同时接受测试集中的真实结果 (0,1) 和正类的预测概率。它返回介于 0.0 和 1.0 之间的 AUC 分数,分别代表无技能和完美技能。
1 2 3 4 |
... # 计算 AUC auc = roc_auc_score(y, probs) print('AUC: %.3f' % auc) |
下面列出了在小型测试问题上计算逻辑回归模型的 ROC 曲线和 ROC AUC 的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import matplotlib.pyplot as plt # roc 曲线和 auc from sklearn.datasets import make_classification from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import roc_curve from sklearn.metrics import roc_auc_score # 生成 2 类数据集 X, y = make_classification(n_samples=1000, n_classes=2, random_state=1) # 划分为训练/测试集 trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.5, random_state=2) # 生成无技能预测(多数类别) ns_probs = [0 for _ in range(len(testy))] # 拟合模型 model = LogisticRegression(solver='lbfgs') model.fit(trainX, trainy) # 预测概率 lr_probs = model.predict_proba(testX) # 只保留正向结果的概率 lr_probs = lr_probs[:, 1] # 计算分数 ns_auc = roc_auc_score(testy, ns_probs) lr_auc = roc_auc_score(testy, lr_probs) # 总结得分 print('No Skill: ROC AUC=%.3f' % (ns_auc)) print('Logistic: ROC AUC=%.3f' % (lr_auc)) # 计算 roc 曲线 ns_fpr, ns_tpr, _ = roc_curve(testy, ns_probs) lr_fpr, lr_tpr, _ = roc_curve(testy, lr_probs) # 绘制模型的 ROC 曲线 plt.plot(ns_fpr, ns_tpr, linestyle='--', label='No Skill') plt.plot(lr_fpr, lr_tpr, marker='.', label='Logistic') # 轴标签 plt.xlabel('假阳性率') plt.ylabel('真阳性率') # 显示图例 plt.legend() # 显示绘图 plt.show() |
运行示例后,它会打印逻辑回归模型和仅预测所有示例为 0 的无技能分类器的 ROC AUC。
1 2 |
无技能:ROC AUC=0.500 逻辑回归:ROC AUC=0.903 |
同时还会创建模型 ROC 曲线图,显示模型具有技能。
注意:鉴于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。考虑运行示例几次并比较平均结果。

无技能分类器和逻辑回归模型的 ROC 曲线图
什么是精确率-召回率曲线?
有许多方法可以评估预测模型的技能。
在相关领域信息检索(根据查询查找文档)中的一种方法是衡量精确率和召回率。
这些度量在应用机器学习中评估二元分类模型时也很有用。
精确率是真阳性数除以真阳性数和假阳性数之和的比率。它描述了模型预测阳性类别的能力。精确率也称为阳性预测值。
1 |
阳性预测能力 = 真阳性 / (真阳性 + 假阳性) |
或者
1 |
精确率 = 真阳性 / (真阳性 + 假阳性) |
召回率计算为真阳性数除以真阳性数和假阴性数之和的比率。召回率与灵敏度相同。
1 |
召回率 = 真阳性 / (真阳性 + 假阴性) |
或者
1 |
灵敏度 = 真阳性 / (真阳性 + 假阴性) |
1 |
召回率 == 灵敏度 |
在两个类别之间观察值不平衡的情况下,回顾精确率和召回率很有用。具体来说,有很多无事件(类别 0)的例子,而只有少数事件(类别 1)的例子。
原因是通常大量的类别 0 示例意味着我们不太关心模型正确预测类别 0 的能力,例如高真阴性。
计算精确率和召回率的关键在于,这些计算不使用真阴性。它只关注少数类别 1 的正确预测。
精确率-召回率曲线是精确率(y 轴)和召回率(x 轴)随不同阈值变化的图,类似于 ROC 曲线。
无技能分类器是无法区分类别并会随机预测类别或在所有情况下都预测恒定类别的分类器。无技能线根据正类与负类分布而变化。它是一条水平线,其值为数据集中正例的比例。对于平衡数据集,这是 0.5。
虽然 ROC 的基线是固定的,但[精确率-召回率曲线]的基线由正例 (P) 和负例 (N) 的比例决定,即 y = P / (P + N)。例如,对于平衡的类别分布,我们有 y = 0.5…
— 在不平衡数据集上评估二元分类器时,精确率-召回率图比 ROC 图更具信息量,2015。
具有完美技能的模型表示为点 (1,1)。有技能的模型由一条弯曲到无技能平线以上 (1,1) 的曲线表示。
还有一些复合分数试图总结精确率和召回率;两个例子包括
在模型选择方面,F-Measure 总结了特定概率阈值(例如 0.5)下的模型技能,而曲线下面积则总结了跨阈值的模型技能,类似于 ROC AUC。
这使得精确率-召回率以及精确率与召回率的图表和汇总度量成为具有类别观测值不平衡的二元分类问题的有用工具。
Python 中的精确率-召回率曲线
精确率和召回率可以在 scikit-learn 中计算。
精确率和召回率可以通过 precision_recall_curve() 函数针对阈值进行计算,该函数以真实输出值和正类概率作为输入,并返回精确率、召回率和阈值。
1 2 3 |
... # 计算精确率-召回率曲线 precision, recall, thresholds = precision_recall_curve(testy, probs) |
F-Measure 可以通过调用 f1_score() 函数来计算,该函数以真实类别值和预测类别值作为参数。
1 2 3 |
... # 计算 F1 分数 f1 = f1_score(testy, yhat) |
精确率-召回率曲线的面积可以通过调用 auc() 函数并传入每个阈值计算出的召回率 (x) 和精确率 (y) 值来近似。
1 2 3 |
... # 计算精确率-召回率 AUC auc = auc(recall, precision) |
在为每个阈值绘制精确率和召回率曲线时,重要的是将召回率作为 x 轴,将精确率作为 y 轴。
下面列出了为逻辑回归模型计算精确率-召回率曲线的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
import matplotlib.pyplot as plt # 精确率-召回率曲线和 f1 from sklearn.datasets import make_classification from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import precision_recall_curve from sklearn.metrics import f1_score from sklearn.metrics import auc # 生成 2 类数据集 X, y = make_classification(n_samples=1000, n_classes=2, random_state=1) # 划分为训练/测试集 trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.5, random_state=2) # 拟合模型 model = LogisticRegression(solver='lbfgs') model.fit(trainX, trainy) # 预测概率 lr_probs = model.predict_proba(testX) # 只保留正向结果的概率 lr_probs = lr_probs[:, 1] # 预测类别值 yhat = model.predict(testX) lr_precision, lr_recall, _ = precision_recall_curve(testy, lr_probs) lr_f1, lr_auc = f1_score(testy, yhat), auc(lr_recall, lr_precision) # 总结得分 print('Logistic: f1=%.3f auc=%.3f' % (lr_f1, lr_auc)) # 绘制精确率-召回率曲线 no_skill = len(testy[testy==1]) / len(testy) plt.plot([0, 1], [no_skill, no_skill], linestyle='--', label='No Skill') plt.plot(lr_recall, lr_precision, marker='.', label='Logistic') # 轴标签 plt.xlabel('Recall') plt.ylabel('Precision') # 显示图例 plt.legend() # 显示绘图 plt.show() |
运行示例首先打印逻辑回归模型的 F1 分数和曲线下面积 (AUC)。
注意:鉴于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。考虑运行示例几次并比较平均结果。
1 |
逻辑回归:f1=0.841 auc=0.898 |
然后创建精确率-召回率曲线图,显示逻辑回归模型(橙色)与无技能模型(蓝色)的每个阈值的精确率/召回率。

无技能分类器和逻辑回归模型的精确率-召回率图
何时使用 ROC 与精确率-召回率曲线?
通常,ROC 曲线和精确率-召回率曲线的使用如下:
- ROC 曲线应在每个类别观测值大致相等时使用。
- 精确率-召回率曲线应在中度至高度类别不平衡时使用。
推荐此原因是因为 ROC 曲线在类别不平衡的数据集上对模型呈现乐观的图景。
然而,当类别分布存在很大偏差时,ROC 曲线可能会对算法性能产生过于乐观的看法。[…] 精确率-召回率 (PR) 曲线,通常用于信息检索,已被引用为对于类别分布偏差很大的任务的 ROC 曲线的替代方案。
— 精确率-召回率和 ROC 曲线之间的关系,2006。
有些人甚至认为,在不平衡的数据集上使用 ROC 曲线可能会产生误导,导致对模型技能的错误解读。
……由于对特异度的直观但错误的理解,ROC 图在不平衡数据集的背景下具有视觉可解释性,但就分类性能的可靠性而言可能是具有欺骗性的。另一方面,[精确率-召回率曲线]图由于评估了正面预测中真正例的比例,因此可以为观察者提供对未来分类性能的准确预测。
— 在评估不平衡数据集上的二元分类器时,精确率-召回率图比 ROC 图更具信息量,2015。
这种乐观图景的主要原因是 ROC 曲线中误报率使用了真负例,而精确率-召回率曲线仔细避免了该比率。
如果测试集中正面和负面实例的比例发生变化,ROC 曲线将保持不变。准确率、精确率、提升和 F 分数等指标使用混淆矩阵两列的值。随着类别分布的变化,即使分类器性能的根本原因没有改变,这些度量也会随之改变。ROC 图基于 TP 率和 FP 率,其中每个维度都是严格的列比,因此不依赖于类别分布。
— ROC 图:数据挖掘研究人员的注意事项和实践考量,2003。
我们可以用一个简短的例子来具体说明这一点。
下面是相同的 ROC 曲线示例,但问题已修改,类别 0 与类别 1 的观察比例约为 100:1(具体为 Class0=985,Class1=15)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import matplotlib.pyplot as plt # 不平衡数据集上的 ROC 曲线和 AUC from sklearn.datasets import make_classification from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import roc_curve from sklearn.metrics import roc_auc_score # 生成 2 类数据集 X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.99,0.01], random_state=1) # 划分为训练/测试集 trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.5, random_state=2) # 生成无技能预测(多数类别) ns_probs = [0 for _ in range(len(testy))] # 拟合模型 model = LogisticRegression(solver='lbfgs') model.fit(trainX, trainy) # 预测概率 lr_probs = model.predict_proba(testX) # 只保留正向结果的概率 lr_probs = lr_probs[:, 1] # 计算分数 ns_auc = roc_auc_score(testy, ns_probs) lr_auc = roc_auc_score(testy, lr_probs) # 总结得分 print('No Skill: ROC AUC=%.3f' % (ns_auc)) print('Logistic: ROC AUC=%.3f' % (lr_auc)) # 计算 roc 曲线 ns_fpr, ns_tpr, _ = roc_curve(testy, ns_probs) lr_fpr, lr_tpr, _ = roc_curve(testy, lr_probs) # 绘制模型的 ROC 曲线 plt.plot(ns_fpr, ns_tpr, linestyle='--', label='No Skill') plt.plot(lr_fpr, lr_tpr, marker='.', label='Logistic') # 轴标签 plt.xlabel('假阳性率') plt.ylabel('真阳性率') # 显示图例 plt.legend() # 显示绘图 plt.show() |
运行示例表明该模型具有技能。
注意:鉴于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。考虑运行示例几次并比较平均结果。
1 2 |
无技能:ROC AUC=0.500 逻辑回归:ROC AUC=0.716 |
确实,它有技能,但所有这些技能都被衡量为做出了正确的真负例预测,而且有很多负例预测。
如果您查看预测,您会发现模型在测试集中的所有情况下都预测了多数类(类别 0)。该分数非常具有误导性。
ROC 曲线图证实了对于大多数概率阈值,该模型都具有技能。

不熟练分类器和逻辑回归模型在不平衡数据集上的 ROC 曲线图
我们也可以在同一数据集上重复相同的模型测试,并计算精确率-召回率曲线和统计数据。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
import matplotlib.pyplot as plt # 不平衡数据集上的精确率-召回率曲线和 F1 分数 from sklearn.datasets import make_classification from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import precision_recall_curve from sklearn.metrics import f1_score from sklearn.metrics import auc # 生成 2 类数据集 X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.99,0.01], random_state=1) # 划分为训练/测试集 trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.5, random_state=2) # 拟合模型 model = LogisticRegression(solver='lbfgs') model.fit(trainX, trainy) # 预测概率 lr_probs = model.predict_proba(testX) # 只保留正向结果的概率 lr_probs = lr_probs[:, 1] # 预测类别值 yhat = model.predict(testX) # 计算每个阈值的精确率和召回率 lr_precision, lr_recall, _ = precision_recall_curve(testy, lr_probs) # 计算分数 lr_f1, lr_auc = f1_score(testy, yhat), auc(lr_recall, lr_precision) # 总结得分 print('Logistic: f1=%.3f auc=%.3f' % (lr_f1, lr_auc)) # 绘制精确率-召回率曲线 no_skill = len(testy[testy==1]) / len(testy) plt.plot([0, 1], [no_skill, no_skill], linestyle='--', label='No Skill') plt.plot(lr_recall, lr_precision, marker='.', label='Logistic') # 轴标签 plt.xlabel('Recall') plt.ylabel('Precision') # 显示图例 plt.legend() # 显示绘图 plt.show() |
运行示例首先会打印 F1 分数和 AUC 分数。
注意:鉴于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。考虑运行示例几次并比较平均结果。
我们可以看到,模型因为在所有情况下都预测了多数类而受到惩罚。分数表明,根据 ROC 曲线看起来不错的模型,实际上在使用关注正类的精确率和召回率进行考虑时,几乎没有技能。
1 |
逻辑回归:f1=0.000 auc=0.054 |
精确率-召回率曲线图强调,对于大多数阈值,该模型仅略高于不熟练线。
这是可能的,因为模型会预测概率,并且对某些案例不确定。这些通过在曲线构建中评估的不同阈值而暴露出来,将一些类别 0 翻转为类别 1,提供了一些精确率,但召回率非常低。

不熟练分类器和逻辑回归模型在不平衡数据集上的精确率-召回率图
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
论文
- 对召回率和精确率作为检索系统性能度量的批判性研究, 1989.
- 精确率-召回率和 ROC 曲线之间的关系, 2006.
- 在评估不平衡数据集上的二元分类器时,精确率-召回率图比 ROC 图更具信息量, 2015.
- ROC 图:数据挖掘研究人员的注意事项和实践考量, 2003.
API
- sklearn.metrics.roc_curve API
- sklearn.metrics.roc_auc_score API
- sklearn.metrics.precision_recall_curve API
- sklearn.metrics.auc API
- sklearn.metrics.average_precision_score API
- 精确率-召回率,scikit-learn
- 精确率、召回率和 F 度量,scikit-learn
文章
总结
在本教程中,您了解了 ROC 曲线、精确率-召回率曲线以及何时使用它们来解释二元分类问题的概率预测。
具体来说,你学到了:
- ROC 曲线总结了预测模型在使用不同概率阈值时的真阳性率与假阳性率之间的权衡。
- 精确率-召回率曲线总结了预测模型在使用不同概率阈值时的真阳性率与阳性预测值之间的权衡。
- ROC 曲线适用于类别之间观测值平衡的情况,而精确率-召回率曲线适用于不平衡数据集。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
我认为对 P/R 曲线来说,对角线不是正确的基线。基线“愚蠢”的分类器应该是一条精确率=正例%的直线。
你说得对,谢谢!
已修复。
感谢您对该主题的介绍
以下一行引起了疑问
>>> 分数看起来并不令人鼓舞,因为有技能的模型通常在 0.5 以上。
随机模型的基线是 n_positive/(n_positive+n_negative)。或者只是正例的比例,因此将精确率-召回率曲线的 AUC 与该值进行比较是有意义的。
抱歉,我不明白你的问题。你能详细说明一下吗?
很抱歉我上面说得不够清楚。
我的意思是
对于 ROC,随机模型的 AUC 是 0.5。
对于 PR 曲线,随机模型的 AUC 是 n_positive/(n_positive+n_negative)。
也许将 PR AUC 与 n_positive/(n_positive+n_negative) 进行比较是有意义的?
第一次阅读时,这句话
>>> 分数看起来并不令人鼓舞,因为有技能的模型通常在 0.5 以上。
在 PR 曲线 AUC 的背景下显得含糊不清。
谢谢!
谢谢。
我同意 Alexander 的观点。
PR 曲线中的随机分类器给出 AUPR 为 0.1。
AUPR 对不平衡数据集更好,因为它表明仍有改进的空间,而 AUROC 似乎已饱和。
关于您 10/2019 编辑中的精确率-召回率图的几点评论
在您当前的精确率-召回率图中,基线是一条对角线,表示不熟练,这似乎不正确:不熟练模型要么只预测负例(精确率=0 (!),召回率=0),要么只预测正例(精确率=数据集中正例的比例,召回率=1)。
函数 precision_recall_curve() 返回点 (precision=1, recall=0),但在这个情况下不应该返回,因为没有进行正例预测。
此外,我认为对角线具有误导性,因为 precision_recall_curve() 实际上只返回两个点,然后将它们连接起来。对角线上的点不能由不熟练模型实现。
此外,在我看来,与随机模型相比,正确的精确率-召回率基线是精确率等于数据集中正例比例的水平线。
谢谢 Theresa,我会调查的。
你好,你有没有弄清楚为什么 precision_recall_curve 返回点 (precision=1, recall=0)?谢谢。
你好 Yakun……以下资源可能对您感兴趣
https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc
很棒的教程。
谢谢!
马修斯相关系数怎么样?
我没用过,有参考资料吗?
这是一个很好的简单解释
https://lettier.github.io/posts/2016-08-05-matthews-correlation-coefficient.html
我被告知,在赛马评分领域,使用 ML 产生的评分,如果您已经有了概率输出,那么直接对概率本身使用度量(例如 McFadden 的伪 R^2、Brier 分数等)会更有意义。
谢谢。
您难道不认为一个没有技能的模型(我假设是指随机抛硬币)应该有 0.5 的 AUC 而不是 0.0 吗?
0.0 的 ROC AUC 意味着模型完全不正确。
0.5 的 ROC AUC 将是一个朴素的模型。
我不知道你说的朴素模型是什么意思。根据你用来描述没有技能的模型,它的 AUC 应该是 0.5,而一个完美错误分类每个点的模型 AUC 将是 0。
完美错误分类每个点和完美正确分类每个点一样难。
朴素模型有时也是正确的。最常见的朴素模型总是预测最常见的类别,这样的模型的最小 AUC 为 0.5。
你说得对,谢谢!
感谢用更简单的方式解释了区别。
我很高兴它能帮到你。
这里有一个拼写错误,应该是“is”
“比较预测二分类问题概率的模型的一种常见方法是使用
ROC 曲线。”
好文章 🙂 感谢分享!
谢谢,已修复!
平均精确率实际上就是精确率-召回率曲线下的面积。您“比较它们”具有很强的误导性。差异是由于 scikit-learn 中的不同实现。Auc 对精确率-召回率曲线进行线性插值,而平均精确率使用分段常数离散化。
谢谢 Tony。
我不认为我们是在比较它们,它们是不同的度量。
“为了说清楚
图中 x 轴上的值越大表示真阳性越高,假阴性越低。
图中 y 轴上的值越小表示假阳性越低,真阴性越高。”
在描述 ROC 曲线时,是否应该交换 x 和 y?
你说得对,已修复。谢谢!
你好,感谢精彩的教程 🙂
不过我有一个评论。
你写道:“在每个阈值下,没有技能的模型由图的左下角到右上角的对角线表示,其 AUC 为 0.0。”
我认为 AUC 是 ROC 曲线下的面积。根据您的解释(从左下角到右上角的对角线),对角线穿过 (0.5, 0.5) 的面积是 0.5 而不是 0。因此在这种情况下 AUC = 0.5(?)
也许我有什么误解。
你说得对,已修复。
你好,Jason。
我再次回顾了您的精彩教程,一个问题浮现在我的脑海中。
在 sklearn 中,我们是否可以使用平均精确率分数来评估模型技能(应用于高度不平衡的数据集)并执行交叉验证。对于像 Lightgbm 这样的某些机器学习算法,我们不能为此类交叉验证使用这样的度量,而是有其他度量,如二元 logloss。
问题是,对于这种不平衡问题,binary logloss 是否是像 average precision score 一样的好度量?
是的,log loss(交叉熵)可以作为不平衡类别的好度量。它捕捉了预测概率和实际概率分布之间的差异。
嗨,Jason,
感谢您的总结。
您的陈述
“通常,ROC 曲线和精确率-召回率曲线的使用如下:
* ROC 曲线应在类别观测数大致相等时使用。
* 精确率-召回率曲线应在存在中度至高度类别不平衡时使用。”
……具有误导性,如果不是错误的话。即使您引用的文章也没有这样说。
通常建议对高度不平衡的数据集(即正例与负例比例小于 1:100 或类似比例)同时使用 PRC 和 ROC。此外,PRC 的高思想旨在在分数高值时没有负例,只有正例。这可能不是研究和分类器的目标。此外,正如您引用的一篇文章中所述,即使对于平衡数据集,AUROC 也可能具有误导性,因为它“同等”地加权了真阳性和真阴性。我还想提到,AUROC 是“分类器将随机选择的正实例排在随机选择的负实例之上的概率”的估计值,并且它与 Mann–Whitney U 检验有关。
总而言之,我总是建议
1)使用 AUROC、AUPRC、准确率以及其他与研究目标相关的指标
2)绘制正例和负例的分布并进行分析
请告诉我您的想法。
谢谢您的留言。
嗨,Jason,
在这些示例中,您始终使用 API,因此所有示例都具有计算函数。但我不明白如何使用这些方程,例如
真阳性率 = 真阳性 / (真阳性 + 假阴性)
“真阳性”都是单个浮点数,那么我们如何得到用于绘图的数组呢?
(真阳性 + 假阴性):是测试数据最终预测的总和吗?
我手动计算时非常困惑。
它们是计数,例如,真阳性的示例数量,依此类推。
您能否解释一下如何为多标签分类绘制 ROC 曲线?
据我所知,ROC 曲线通常不用于多标签分类。
嗨,Jason,
我绘制了 ROC,您可以在以下链接中看到,但我不知道为什么它不像真正的 ROC。
您能否检查一下并告诉我我可能犯了什么错误?
https://imgur.com/a/WWq0bl2
hist = model.fit(x_train, y_train, batch_size= 10, epochs= 10, verbose= 2)
y_predic = model.predict(x_test)
y_predic = (y_predic> 0.5)
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_predic)
plt.figure()
plt.plot([0, 1], [0, 1], ‘k–‘)
plt.plot(fpr, tpr)
plt.xlabel(‘False positive rate’, fontsize = 16)
plt.ylabel(‘True positive rate’, fontsize = 16)
plt.title(‘ROC curve’, fontsize = 16)
plt.legend(loc=’best’, fontsize = 14)
plt.show()
我很乐意回答问题,但恐怕我没有能力调试您的代码。
非常感谢您的回复。
不,我的意思是如果可能的话,请检查一下图,然后告诉我您的想法。
嗨,Jason,
抱歉,这里有点令人困惑,
我们生成了 2 个类的数据集,为什么使用 n_neighbors=3?
感谢您的帮助。
Alex
是的,2 个类别与 kNN 中使用的样本数(k=3)无关。
数据集由许多示例或数据行组成,有些属于类别 0,有些属于类别 1。我们将查看 kNN 中的 3 个样本来选择新示例的类别。
你好 Jason,在代码的这部分顶部,您提到“计算逻辑回归模型在小型测试问题上的 ROC 曲线和 AUC 的完整示例列于下文”。KNN 是“逻辑回归”吗?我有点困惑。
看起来是个笔误。已修复。谢谢!
你好 Jason,感谢您出色的教程!
判断模型的好坏,PR-AUC 与 F1 分数是否完全相同?因为这两个度量都只依赖于精确率和召回率?还是我遗漏了什么?
谢谢!
我不太确定,凭经验来说。
好帖子 — 我们能从 PR 曲线的某个特定片段(即随着召回率增加,精确率也增加)与另一个片段(即随着召回率增加,精确率降低)中做出什么推断?
在 PR 曲线中,它应该是递减的,从不递增——它总是具有相同的向下形状。
如果不是这样,那可能是由于预测/模型的校准不佳或数据高度不平衡(例如,在本教程中)导致精确率/召回率关系出现人为痕迹。
我一直在思考同样的问题,https://stats.stackexchange.com/questions/183504/are-precision-and-recall-supposed-to-be-monotonic-to-classification-threshold 这里第一个回答简单演示了为什么y轴(精度)不是单调递减的,而x轴(召回率)是单调递增的,因为在每个阈值步骤中,精度可能增长或减少其分子或分母,而召回率仅可能增长其分子。
感谢分享。
我觉得这完全错了。🙁
嗨,Jason,
一如既往的精彩。只是一个小地方,但可能会引起轻微的混淆,在所有精确率-召回率曲线的代码中,注释都指向了ROC曲线。
# 绘制模型的 ROC 曲线
pyplot.plot(recall, precision, marker=’.’)
此致
Gerry
谢谢,已修复!
嗨,Jason,
感谢这篇文章!您总是写一些我在其他地方找不到答案的文章。这是一个很棒的总结!一个快速的问题——当您使用“smog system”作为例子来描述FP与FN成本时,您是指我们更关注高FN而不是高FP吗?如果我没理解您的意思,请纠正我。
此致,
Sunny
谢谢。
是的,这可能会令人困惑。我当时的意思是,我们想要(关心)低假阴性,而不是假阳性。
高假阴性是一个问题,高假阳性则不是问题。
嗨,Jason,
我们如何确定精度百分比和召回率百分比的一个好的操作点?我知道这取决于用例,但您能否就如何处理这个问题给出您的想法?
谢谢!
是的,用一个朴素的方法建立一个基线分数,并将更复杂的方法与基线进行比较。
好帖子。谢谢 Jason。
一个问题。PR曲线下面积和平均精度得分有什么区别?我认为两者定义相似。
另外,您建议如何从精度-召回率曲线中选择阈值,就像我们为ROC曲线使用Youden指数一样?
我建议查看您模型的曲线,并选择一个权衡对您的领域/利益相关者有意义的点。
好问题。它们很相似。
我一时半会儿给不出一个好的答案,我需要写一篇关于它的文章,并去研究一些实际例子。
我猜平均精度得分和精度召回率曲线下面积是相同的。区别在于计算这些指标的方式。根据AUC的文档页面,它说
“使用梯形法则计算曲线下面积(AUC)
这是一个通用函数,给定曲线上的点。要计算ROC曲线下面积,请参阅roc_auc_score。要总结精度-召回率曲线的另一种方法,请参阅average_precision_score。”
所以我想,它用梯形法则计算任何曲线下面积,而average_precision_score则不然。
感谢您这篇优秀且清晰的文章!
在以下这句话中,不应该是“假阴性”而不是“假阳性”
“这些选项之间存在一种权衡,真阴性和假阳性也是如此。”
我想你是对的。已修复。
感谢您这篇优秀且清晰的文章。
我使用了GaussianNB模型,得到了阈值[2.00000e+000, 1.00000e+000, 1.00000e+000, 9.59632e-018 ]。
阈值的值非常小是否正常??
提前感谢
“确实,它有技能,但其中很大一部分技能被衡量为做出了正确的假阴性预测”——这句话我一点也看不懂。
什么叫“正确的假阴性”?根据我目前的理解,“正确”包括TP和TN,而不是FP或FN。如果是正确的,为什么是假的?如果是假的,怎么会是正确的?
您能解释一下“正确”是根据什么来判断的吗?y_true 还是别的什么?
这看起来像个笔误,我认为我想说的是真阴性,例如,占多数的类别。
已修复。谢谢。
好帖子,我觉得它非常直观。
但为什么在精确率-召回率曲线中只保留正类别的概率呢?
我尝试了负类别的概率,结果图很奇怪。请解释一下使用正类别概率而不是负类别概率的直观原因好吗?
实际上,scikit learn 的 “predict_proba()” 会为每行中的每个类别预测概率,它们加起来等于 1。在二元分类的情况下,它预测一个样本为负类和正类的概率,第二列显示了一个样本属于正类的概率有多大。
当我们只传入正类别概率时,ROC 会在不同的阈值下进行评估,并检查给定的概率是否大于阈值(例如 0.5),则属于正类,否则属于负类。同样,它也会在不同的阈值下进行评估,并给出 roc_auc 分数。
感谢解释ROC曲线,我想问一下如何比较许多算法的ROC曲线,例如SVM、KNN、RandomForest等。
通常它们都会一起绘制。
您还可以比较每个算法的ROC曲线下面积。
谁能解释一下平均精度得分的意义?
是的,请看这个
https://en.wikipedia.org/wiki/Evaluation_measures_(information_retrieval)#Mean_average_precision
非常感谢这个教程。确实没有多少这样的资源。
谢谢,很高兴它帮到了你!
嗨,Jason,
谢谢您的教程!
我有一个关于F1分数的问题,因为我知道最好的值是1(完美的精度和召回率),最坏的值是0,但我不知道是否有最低的标准值。
我得到了一个F分数0.44,因为我有很多假阳性,但假阴性很少。但我不知道0.44是否足以说明我的模型是好的。您知道文献中是否有标准?例如,在ROC中,0.75是一个好的分数。
谢谢
是的,一个朴素分类模型返回的F1分数
https://machinelearning.org.cn/how-to-develop-and-evaluate-naive-classifier-strategies-using-probability/
嗨,Jason,
感谢您用简单的语言解释这些概念!
我有点困惑。您提到ROC是处理平衡数据集的最佳选择,而精确率-召回率是处理不平衡数据集的最佳选择。但是,如果我们得到一个不平衡的数据集,我们难道不应该先对其进行平衡,然后再开始构建模型吗?
此致,
Bishal Mandal
我们可能会决定平衡训练集,但不会平衡用于进行预测的测试集。
我一整天都在想这个问题🙂。谢谢
你好。您能告诉我我是否可以用这种方式创建ROC曲线吗?
y_test=我的测试数据真实标签(6500,1)
x_test=我的测试数据(6500,3001)
prediction=model.predict(x_test)
fpr,tpr,thresholds=roc_curve(y_test,prediction)
plt.plot(fpr,tpr)
plt.show()
auc = roc_auc_score(y_test, prediction)
抱歉,我无法调试您的示例。
或许可以试试?
谢谢,解决了。
很高兴听到这个消息。
抱歉,我还有另一个问题。当我看到阈值数组的元素时,我注意到它的第一个元素大约是1.996。这怎么可能?阈值应该在0到1之间,不是吗?
再次感谢
我还在您的代码中检查了它,情况也是如此,您的阈值第一个元素是2!
您能告诉我阈值元素的数量是如何得出的吗?例如,在您的代码中,阈值有5个元素,但在我的问题中,它有1842个元素。
也许可以仔细检查一下这个值?
我建议您仔细重读 Aleks 的帖子,并考虑重新措辞您关于 ROC 仅用于平衡数据的说法,事实并非如此。PlosONE 论文的标题具有误导性。确实,在 N >> P 的情况下,ROC 可以给出高 AUC,但假阳性很多,而 PR 曲线对此更敏感。但这取决于您的目标,我建议您阅读 David Powers 的论文,了解 ROC 相对于 PROC 的许多有利统计特性。 https://stats.stackexchange.com/questions/7207/roc-vs-precision-and-recall-curves,他在这里写了一篇优秀的直接总结,可以用来改进这篇博文。
顺便说一句,博文很棒。
谢谢 Chris,我会再看一遍这篇论文。
我的精度和召回率曲线一直到最后都在上升,但在最后崩溃了。您知道为什么吗?这是正常的吗?谢谢。
很抱歉听到它崩溃了,它给出了什么错误?
非常感谢 Jason 的教程
我想问一下深度多标签分类的 ROC 曲线和精确率-召回率曲线。
我已经能够使用 sklearn.metrics (multilabel_confusion_matrix) 绘制所有标签的混淆矩阵。我的问题是,如何为所有标签绘制 ROC 曲线和精确率-召回率曲线?
我感谢任何帮助。
非常感谢。
通常,PR 曲线和 ROC 曲线仅用于二分类问题。
非常感谢 Jason 的回复。
那么,多标签分类的评估指标是什么?
只有准确率和损失吗?
这取决于您的问题什么最重要。
Log loss 是多类别分类的一个不错的起点。对于多标签(完全是另一回事),平均精度或 F1 是不错的选择。
我的最佳建议是回顾利益相关者或领域专家,找出模型最关键的方面,然后选择一个能够捕捉到这一点的指标。您可以通过采用一些标准度量并运行模拟预测来获得良好的感觉,看看它给出了什么分数,以及它是否能为您/利益相关者讲述一个好故事。
太棒了!
非常感谢 Jason。
不客气。
您好,感谢您提供出色的教程!
我遇到了一个问题,每当我显示 ROC 曲线时,都会收到以下错误:
File “C:\Program Files\Python37\lib\site-packages\sklearn\metrics\base.py”, line 73, in _average_binary_score raise ValueError(“{0} format is not supported”.format(y_type))
ValueError: multiclass format is not supported
先生,请帮助我解决这个问题。谢谢
ROC 曲线只能用于二分类(2类)分类问题。
这非常有帮助。感谢您为我们这些初学者提供恰当的解释。
很高兴听到这个消息。
嗨,Jason,
我正在处理一个医学数据库,用于预测极端罕见事件(发生概率为0.6%)。我有10个不同的特征,来自类别0的样本有28,597个,来自类别1的样本有186个。
我已经开发了几个模型。此外,我还尝试对训练集进行下采样以创建一个平衡的训练集,并在不平衡的测试集上进行测试。
不幸的是,无论我使用什么模型,PR曲线都与本帖中“不熟练分类器和逻辑回归模型在不平衡数据集上的精确率-召回率图”的图相似。
有什么方法可以处理这个数据库吗?我将非常感谢任何建议!
是的,有一些想法
– 尝试使用各种数据缩放的标准模型
– 尝试使用类别加权的模型的版本,如逻辑回归、SVM 等。
– 尝试欠采样方法
– 尝试过采样方法
– 尝试在同一训练集上使用过采样和欠采样的组合
– 尝试单类别分类器
– 尝试为不平衡数据设计的集成方法
– 尝试替代性能指标
– 尝试 k 折交叉验证来估计 pr auc
希望这些能作为一个开始有所帮助。
非常感谢。我已经开始使用您的建议了。祝我好运和耐心😀
祝你好运!
我正在处理的数据也存在同样的问题(发生率约为0.3%)。
我假设您对特征与事件之间的生物学联系有一些专业知识,但可以尝试计算每个特征与目标之间的 Pearson(点双列)相关性,这应该能给您一些关于您的特征与您要预测的事件之间是否存在任何联系的线索。
您也可以尝试无监督学习(聚类),看看事件是否只存在于某些簇中。
在正例事件没有足够进入验证数据集的情况下,使用 ROC 进行验证可能会有点棘手。
尽管这有点作弊,因为您会提前对验证数据做出假设,但您可以单独分割负例和正例,以便在训练和验证数据中得到相同的流行度。
很棒的建议。
LOOCV(留一法交叉验证)评估是在数据有限的情况下的一种好方法。
谢谢您的建议。我正在考虑中。
你好 Jason,
很棒的文章。
我偶然发现了 PLoS One 的论文(Saito and Rehmsmeier 2015),我有一个关于 PRC 评估的问题。
作者们提到:
“尽管如此,在进行点之间的插值时必须小心,因为 PRC 和 ROC 曲线的插值方法不同——ROC 分析使用线性插值,而 PRC 分析使用非线性插值。PRC 空间中两个点 A 和 B 之间的插值可以表示为函数 y = (TPA + x) / {TPA + x + FPA + ((FPB – FPA) * x) / (TPB – TPA)},其中 x 可以是 TPA 和 TPB 之间的任意值 [26]。”
在您的文章中,您使用 sklearn 的 auc(recall, precision) 计算了 AUC(PRC)。
这是否与您引用的说法相冲突,因为我也会使用 auc(FPR, TPR) 来计算 ROC AUC?
我认为在我自己的实验中比较模型时,这关系不大,但是与其他论文比较 AUC 时呢?
嗯。是的,您可能是对的。
以下是我的一番感慨。
总的来说,重复一个实验并在本地进行比较。
将结果与论文中的结果进行比较几乎是无用的,因为几乎总是描述不足——这反过来又基本上是欺诈。我对计算科学并不 impressed。
如何计算我需要传递给下面函数的概率
roc_curve(y, probs)
您可以调用 model.predict_proba() 来预测概率。
您为什么说在精确率-召回率的情况下,我们不太关注高真阴性?是因为您将类别 0 视为优势类别吗?但是,将类别 0 视为优势类别难道不只是一个例子吗?那么,在类别 1 是优势类别的情况下,这意味着模型将不太关注真阳性。在这种情况下,您关于真阴性不包含在精确率和召回率公式中的观点就不相关了。
在二元分类中,类别 0 是负类/多数类,类别 1 总是正类/少数类。这是约定俗成。
你好,
是否有任何公式可以从 ROC 曲线确定最佳阈值?
谢谢
Surajit
是的,我有一篇关于该主题的帖子。
您可以使用 J 统计量
https://en.wikipedia.org/wiki/Youden%27s_J_statistic
感谢您的回复。如何得知您的帖子关于此主题?
您可以通过电子邮件/RSS/Twitter/Facebook/LinkedIn 关注本网站。
请查看每页底部的链接。
此外,如何从 PR 曲线确定最佳阈值?是 F 分数还是其他什么?
很好的问题!
您可以使用 f-measure 测试每个阈值。
我将在即将发布的帖子中也涵盖这一点。
为什么选择 F 分数而不是其他指标
好问题,请看这个关于选择指标的框架
https://machinelearning.org.cn/tour-of-evaluation-metrics-for-imbalanced-classification/
嘿!
您通过调用“lr_precision, lr_recall, _ = precision_recall_curve(testy, lr_probs)”获得了“_”作为阈值——但您在绘制曲线时没有使用它们,我说得对吗?您是如何使用阈值的?我的意思是,您一定以某种方式使用了它们来进行绘图?
没错,我们不直接使用阈值,而是使用召回率与精确率的线性图。
那么,对于大致平衡的数据集,我可以放心地忽略精确率-召回率曲线得分,而对于中度(或大幅度)不平衡的数据集,我可以放心地忽略 AUC ROC 曲线得分吗?
不,您必须选择最适合您任务的指标,然后使用它来评估和选择模型。
先选指标。
谢谢,我是在谈论特定的二元分类任务。我有两个数据集。一个是失衡的(1:2.7),第二个几乎是完美的平衡。我应该为这两个数据集选择什么指标?再次感谢,祝您好运!
我建议选择最能体现您和利益相关者项目需求的指标。
一个好的开始是思考分类和误分类错误的重要性。错误是可对称的吗?两个类别都很重要吗,等等。
一些可以考虑的指标包括 roc auc、pr auc、gmean、f-measure 等。
你真棒,谢谢
不客气。
嗨,感谢您这篇精彩的文章。
我的问题是,如果我重新采样我的不平衡数据集,我可以在这种情况下使用 AUC 来评估模型吗?
是的。
抱歉,我的意思是,在这种情况下我是否可以使用 ROC 曲线来评估模型?
是的。您想要的任何指标。
采样只影响训练集,不影响用于评估的测试集。
嗨,Jasono,您的解释方式让我总是在查询的末尾加上“machinelearningmastery”。谢谢
我的问题是:我的不平衡数据集的比例是(22:1,正类:负类),我使用“sigmoid”作为最后一个(输出)层的激活函数来训练神经网络模型。训练后,我调用函数“model.predict”,如下所示:
y_prediction = model.predict(X_test)
当我打印 y_prediction 时,它显示的值是介于 1 和 0 之间的浮点数(我认为这些是每个 X_test 样本的类别 1(正类)的概率)。
之后,我将 y_prediction 通过阈值 0.5 转换为 1 和 0,如下所示:
y_pred = np.zeros_like(y_prediction)
y_idx = [y_prediction >= 0.5]
y_pred[y_idx] = 1
之后,我绘制了精确率-召回率曲线(PR 曲线),该曲线向 (1,1) 弯曲。
现在我有以下问题
Q1:我如何从我的 PR 曲线中获得最佳阈值,将其应用于 y_prediction(如上所述),从而获得良好的召回率和精确率?
Q2:我如何确信这些精确率、召回率或 F1 分数是好的,并且模型表现良好?
谢谢
谢谢!
您可以使用 F 分数测试所有阈值,并使用具有最高 F 分数的阈值。我有一个关于此的教程已安排。
不确定是否理解第二个问题。使用大量数据和重复评估以确保分数稳健?
当我有预测输出作为重建图像(例如,自编码器)时,如何绘制 ROC?假设我计算了重建的某个分数并将其视为二元分类。我尝试使用 scikit-learn 包,结果与我的训练实验几乎相同。
我的模型结构
图像序列作为输入 -> 编码器 -> ConvLSTM -> 解码器 -> 输出重建的图像序列
不确定那是否可能。
先生,我如何使用 PROMISE DATASET KC1 绘制 ROC 曲线,请帮忙。
ROC 曲线是为预测绘制的,而不是为数据集绘制的。
首先对数据集进行建模,然后在测试集上进行预测,然后使用上面的代码从预测中绘制 ROC 曲线。
很棒
谢谢!
嗨,Jason Brownlee,
首先,我为这个超长的问题道歉。说到这里……;o)
……我无法忽视这样一个事实:您代表了数据科学领域的重要能力,并且您展现了与他人分享宝贵知识的令人印象深刻的意愿。鉴于此,我希望您能提供一些建议。我有两个问题。
我目前正在定义一个基于 KNN 的分类,用于处理一个相对不平衡,有些人认为高度不平衡的数据集,该数据集包含 2K+ 篇各种科学内容的文章。算法的目的是弄清楚哪些文章需要被抓取,更有趣的是,哪些文章需要继续处理。这些文章的数量远远少于那些不感兴趣的文章。我已经设法使算法运行起来,并且它做得相当不错。我认为是的。这就是我想让您告诉我,在对文本进行预处理、向量化之后,我该如何评估 KNN 模型的性能。阅读您的文章,我似乎理解在处理(高度?)不平衡数据集时,精确率-召回率曲线更能显示结果。
因此,首先
我是否需要在精确率-召回率曲线之前进行混淆矩阵,并且这两者是否作为 scikit-learn 模块的标准组件存在?
其次,我在执行算法的 KNN 分类部分时似乎遇到了一个问题。我正在导入一个 csv 文件,为每一行/文本表示添加一个唯一的 id,然后在测试新观测值的关系时,我添加了我在其中添加的唯一 id 列表中的一个数字。然后——在呈现结果时——我将它们连接到 df 并概述例如 20 个最近邻。可能是 10 个或其他数字。这效果很好。它指向一个列表,我可以在其中看到我喜欢的文章被突出显示,精确率通常在 75% 到 80% 之间。我的问题实际上是我希望能够输入文本/搜索词而不是数字。根据我“继承”的教程,它说“巴拉克·奥巴马的邻居是这个和那个,但这只是因为应用的数据结构是‘姓名’和‘文本’特征。我的文章不能这样分割。虽然整体上涵盖了相同的科学领域,但它们是不同的,非常不同。所以我的问题是:是否可以添加一个新特征/列,按该新列索引,然后使用文本作为搜索标准来尝试添加输入的‘get_closest_neighs’结果?
谢谢。
首先要清楚什么对项目很重要,然后找到匹配的指标。
这将大有帮助,特别是最后一部分
https://machinelearning.org.cn/tour-of-evaluation-metrics-for-imbalanced-classification/
抱歉,我不确定您第二问题的意思。这可能更多是工程问题而不是建模问题。
嗨,这是我使用的教程,关于问题 2—— http://andrewgaidus.com/Finding_Related_Wikipedia_Articles/
您提到“这之所以可能,是因为模型预测了概率,并且对某些情况不确定。这些情况通过曲线构建中评估的不同阈值暴露出来,将一些类别 0 翻转为类别 1,提供了一些精确度但召回率很低。”
正如图中所示,这不应该提供一些召回率但精确度很低吗?
非常有启发性!
谢谢!
尊敬的先生,
我正在使用基于蚁群优化算法的 Ant Miner 用于我的数据集。我不知道如何获取阈值和 predict_value。它不像这里使用的分类器。你能指导我如何使用该值来绘制 ROC 曲线吗?如果您需要代码,我可以发送给您,以便您查看。
抱歉,我没有能力调试您的代码。
我不熟悉您使用的软件,也许直接联系作者?
嘿,也许您或其他人可以帮助我理解 ROC AUC。在什么情况下,我应该使用它来评估模型性能而不是准确率?我特别问的是,您说在不平衡数据的情况下不应使用 ROC。您说 ROC 曲线显示了对大多数阈值都有用的模型,但您的模型只预测了大的类别。您所说的预测是指阈值 0.5 吗?以及您所说的“可能会产生误导并导致对模型技能的错误解释”中的模型技能,您是指模型在所有样本都相等加权的情况下预测得有多好?但是,如果我们使用阈值 0.5 并对所有样本进行相等加权,我们不就回到了简单的准确率衡量了吗?ROC AUC 不是用来检查模型是否能够区分两个类别的吗?这与类别分布无关,不是吗?
这可以帮助您选择要使用的指标
https://machinelearning.org.cn/tour-of-evaluation-metrics-for-imbalanced-classification/
嗨,Jason,
假设我们使用逻辑回归构建了一个分类模型,并且数据存在巨大的不平衡(用于找出信用违约)。现在模型给出了混淆矩阵(敏感性/召回率/TP/TN 等)。由于模型的阈值默认为 0.5,TP 率较低。
现在我的理解。
1)我们只看 ROC AUC 曲线来找到阈值概率
2)回到最初建立的模型,根据新阈值进行分类(通过获取预测概率并根据阈值进行相应分类)
如果上述理解是正确的,那么 AUC 意味着什么?它如何成为精确率/召回率的替代指标?毕竟,我仍然需要回到最初建立的模型并更改阈值,对吗?然后再次绘制混淆矩阵,对吗?
请提供建议。
差不多。
我们可以使用 ROC 曲线找到一个阈值来调整指标。
我们可以直接使用 ROC AUC 指标来评估模型,这与阈值或混淆矩阵无关。
ROC AUC 是曲线下的面积。
嗨,Jason,
感谢这篇帖子。
一个问题。您得到了阈值,但如何使用它?我的意思是,您是否会再次拟合模型并在“Earlystopping”函数中设置阈值,例如?
我之所以这样问,是因为我找不到在哪里使用阈值。我的意思是,当您要保存调整后的改进模型时,您会怎么做?
谢谢。
不客气。
好问题,请参阅此关于选择阈值并使用它将概率转换为清晰标签的内容。
https://machinelearning.org.cn/threshold-moving-for-imbalanced-classification/
你好,
如何比较 Python 中 AUROC 和 AUPRC 曲线给出的两个 AUC?也就是说,两个不同但相关的模型产生的两个 AUC 之间是否存在统计学上的差异?
让我稍微澄清一下……
我有以下“值”
模型 1(49 个项目)
逻辑回归 AUROC
逻辑回归 AUPRC
随机森林 AUROC
随机森林 AUPRC
梯度提升 AUROC
梯度提升 AUPRC
模型 1(51 个项目)
逻辑回归 AUROC
逻辑回归 AUPRC
随机森林 AUROC
随机森林 AUPRC
梯度提升 AUROC
梯度提升 AUPRC
我想在 Python 中比较模型 1 和模型 2 之间相应的 AUROC/AUPRC 值,以查看模型预测有效性之间是否存在显着差异,但我不确定如何进行此测试,您是否知道 Python 中允许我这样做的任何包?
如果两种处理都应用于同一数据,您可以使用配对检验。
您可以为每种方法计算 ROC AUC 并直接进行比较。
嗨,Jason,
非常感谢您出色的教程!
我在一个研究实验室工作,我需要开始使用 Python 来计算 ELISA 测定数据表的 EC50 和 AUC(串行稀释样品的剂量反应曲线),我想问您是否在 Python 中进行类似操作的经验或是否能帮助我找到有用的资源。当然 EC50 和 AUC 可以很容易地用 Prism 计算,但我也想知道如何在 Python 中完成。我知道如何在 Python 中绘制数据表,但在进行转换、归一化和线性回归,然后计算 ELISA 测定的最终 AUC 方面我感到很茫然。
任何帮助将不胜感激。
谢谢,
Alex
不客气!
上面的教程将向您展示如何绘制 ROC 曲线和计算 ROC AUC。
有关数据归一化的帮助,请参阅此
https://machinelearning.org.cn/standardscaler-and-minmaxscaler-transforms-in-python/
有关线性回归的帮助,请参阅此
https://machinelearning.org.cn/spot-check-regression-machine-learning-algorithms-python-scikit-learn/
我不知道 EC50 是什么,抱歉。
我希望这能作为起点有所帮助。
亲爱的 Jason,
您能否简短回答以下问题?
当敏感性 = 1.0,特异性 = 0.556,PPV = 0.818,NPV = 1.0 时,是否可能得到 AUC = 1?
谢谢你,
我建议是否定的。
“无技能分类器,只为所有示例预测 0”的结果不应该是 ROC 曲线上的一个点(0, 0),而不是 AUC 为 0.5 吗?为了得到 AUC 为 0.5,您不应该查看所有预测类别 1 概率为 p 的模型,其中 p 在 [0, 1] 之间,从而得到一组点 {(p, p)},这些点共同形成对角线吗?
该示例绘制了这种情况,它是一条对角线,如果您不确定,可以自己查看。
谢谢您的回复。我确实看到了对角线,但我认为整条线并不对应于预测所有示例为 0,这就是文本中所写的。预测所有示例为 0 只是线上的一个点(点 (0, 0))。无技能线是由一组预测类别 1 的概率在 0 到 1 之间的分类器创建的。例如,点 (0.25, 0.25) 是通过 25% 的时间预测类别 1 创建的。无论类别如何不平衡,这都成立。这有意义吗?
同意。
您可以预测随机标签以获得更合适的线。
你好 Jason,
我总是遇到这个问题,假设我正在处理的模型要求高召回率,我调整了一个模型,使其达到了非常高的召回率,符合我的目标,但精确率非常低,比如 0.12,模型仍然可以被认为是好的吗?我该如何估计此类模型的泛化能力?
我使用 gridsearch+ cv 达到了召回率 1。
谢谢你,
仅选择召回率或精确率不是一个好主意,它们需要平衡。改用 fbeta
https://machinelearning.org.cn/fbeta-measure-for-machine-learning/
谢谢,抱歉,我不小心又发布了同样的问题。我会阅读您发送的文章。
谢谢你,
Karthik
不客气。
你好,文章做得很好!
如果我正在创建一个我更关注高召回率的模型,我该如何调整我的模型来实现这一点?对于 KNN 分类器,我可以更改哪些参数来影响召回率?
非常感谢!
好问题,选择一个像“召回率”或“f1”这样的指标,然后测试一系列模型和模型配置,看看哪一个能达到你选定指标的最佳结果。
这将帮助你选择一个指标
https://machinelearning.org.cn/tour-of-evaluation-metrics-for-imbalanced-classification/
你好 Jason,
我总是遇到这个问题,假设我正在处理的模型要求高召回率,我调整了一个模型,使其达到了非常高的召回率,符合我的目标,但精确率非常低,比如 0.12,模型仍然可以被认为是好的吗?我该如何估计此类模型的泛化能力?
我使用 gridsearch+ cv 达到了召回率 1。
谢谢你,
好是相对于你项目的目标或你项目利益相关者的要求而言的。没有客观上的“好”模型。
我建议优化 F-beta 指标,而不是仅仅优化召回率,因为你想要的是最好的召回率和精确率,而不仅仅是召回率。
https://machinelearning.org.cn/fbeta-measure-for-machine-learning/
模型性能是使用重复的k折交叉验证来估计的。
https://machinelearning.org.cn/repeated-k-fold-cross-validation-with-python/
多么棒的文章——非常感谢,Jason!我确实终于明白了,多亏了你,AUC 在模型比随机猜测好多少方面可能具有误导性(当数据集不平衡时),但这在你从几个模型中选择时重要吗?AUC 仍然会选出最好的那个吗?
再次感谢——你引用论文并真正解释了它们如何为你的文章增加背景,这真是太棒了!
谢谢!
好问题。是的,选择 AUC 更好的模型,按照定义,它本身会有一个相对好的“AUC”分数,只是在考虑其他指标时它可能并不好。
哈哈,我意识到我没有很好地表达!我猜我的意思是,模型的排名是否与我使用 AUPR 的情况相同?感谢您快速回复——我非常欣赏您的工作。
可能,但可能不会,选择一个合适的指标至关重要,更多请看这里
https://machinelearning.org.cn/tour-of-evaluation-metrics-for-imbalanced-classification/
谢谢您的文章。
Jason,有没有什么方法(在 Python 中)可以使用 ROC AUC 来调查我们数据集中每个特征的预测能力?
ROC AUC 是二元分类的一个分数。不确定它与特征重要性确切的关系。
也许从这里开始
https://machinelearning.org.cn/calculate-feature-importance-with-python/
嘿 Jason,感谢你的精彩教程。
我只想报告你文本中一个可能的错别字。在句子
“……使用 precision_recall_curve() 函数的阈值,该函数以真实输出值和正类别的概率作为输出并返回……”
不应该是“输入”(input)而不是“输出”(output)吗?
谢谢
Dário
不客气。
谢谢,已修复!
你好,请问括号里的这两个数字代表什么?
概率在 [0.0, 0.49] 之间为负面结果 (0)
概率在 [0.5, 1.0] 之间为正面结果 (1)。
你可以直接使用 if 语句。
你好 Jason…
我在 Weka 中使用随机树进行了分类,并导出了测试数据集的预测实例,请问“Prediction”列中的数字代表什么?因为它是随机树,而不是产生概率的逻辑回归。
inst# actual, predicted ,error , prediction
1 2 2 0.933
2 1 2 + 0.58
3 2 2 0.828
4 2 2 0.667
我猜预测是 class=1 的概率。
非常感谢
大家好。感谢您的精彩解释。我想问一下关于创建 ROC 的
Weka 中的决策树。
选择一个截止点来选择最佳阈值点是否有意义?
因为对于决策树,我们无法更改分配,而且也没有
决策树中的阈值。或者我们只能在没有截止点的情况下计算决策树的 AUC?
抱歉,我没有选择 Weka 中阈值的例子。
我这里有一个 Python 的例子
https://machinelearning.org.cn/threshold-moving-for-imbalanced-classification/
非常感谢 (: ,非常有用..
不客气。
你好 Jason
我的数据集包含攻击和正常数据。我该如何使用逻辑回归来实现呢?我是否必须押注于攻击数据?
这个过程将帮助你完成你的项目。
https://machinelearning.org.cn/start-here/#process
我有一个多类别(5 类)高度不平衡的数据集。我可以使用 ROC 曲线作为评估指标吗?
通常,ROC 曲线用于二分类,而不是多分类。
Jason,一如既往地感谢你的精彩教程。
我有一个不平衡的数据集,其中测试集的正类是占主导地位的。PR 曲线应该在负类占主导时使用,对吗?那么,在这种情况下我应该使用什么?
Class=1 应该是少数类,如果不是,你可能需要向指标指定哪个是正类,哪个是负类。
请问如何为多类别分类问题绘制 ROC?
它不能。
嗨,感谢您这篇精彩的文章。
我只是想知道如何在精确率-召回率曲线中选择阈值,尽管它是在所有可能的阈值上绘制的,以及我如何为曲线上的特定点定义确切的阈值?
提前感谢。
不客气。
好问题,请看本教程
https://machinelearning.org.cn/threshold-moving-for-imbalanced-classification/
是否有 Python 代码可以从多类别(超过 2 个类别)分类的 ANNs 中获得精确率-召回率曲线?谢谢。
据我所知,没有。
使用 predict_prob,我们只绘制第二列的正类概率。但如果某些示例的 column2 值小于 column1 值,则意味着这些示例属于类别 0 而不是 1。但我们仍然绘制了它们从未属于类别 1 的 column 2。这些将不属于 TPR?
嗨,Jason,
非常感谢您精彩的文章和博客。确实很有信息量。我仍在为 PR 曲线的无技能模型而苦恼,以及为什么它是一条直线。请看下面
1- 一个随机模型,抛硬币,只会预测等于数据集中正类比例的精确率,召回率=0.5(虚线水平线的中间/无技能分类器)。
2- 一个预测所有数据点都为 1 的模型,只会预测等于数据集中正类比例的精确率,召回率=1(虚线水平线的末端)。
3- 一个预测所有数据点都为 0(负类)的模型,将预测一个未定义的精确率(分母=0)和召回率 0。(这不在虚线水平线上……?)
另外,我真的不明白,一个无技能模型怎么能预测召回率例如 0.75,精确率等于 TP 比例。对我来说,无技能模型的所有点都无法达到,无技能模型应该限制在有限数量的点,而不是整条水平线……?
3-
在 ROC 曲线中,无技能并不真正是一条线,它是一个点或两个点,我们构建一条线作为参考。
Jason,Kamyar 指的是 PR 曲线而不是 ROC 曲线。我也非常努力地理解这一点。你能具体说明这两个点是什么并解释其原理吗?提前非常感谢。
嗨,Jason先生,
请,我有两个问题
1- 为什么 ROC AUC 的结果会随着归一化而降低?
2- 你能解释一下这种情况吗:即使 SVM 或 GNB 的模型准确率很高(约 90%),但 AUC 值却很低(约 50%),即使没有归一化?
致敬
抱歉,第二个问题仅针对 SVM。
输入数据的归一化有助于使用对输入进行加权或使用距离度量的模型。
我建议不要比较不同类型的指标,而是选择一个指标并进行优化。
是的,这是正确的,但 GNB 没有可以调整的参数,只有归一化可能会影响结果。而且,如果 ACC 很高,那就意味着所有其他指标都很高,那么 AUC 如何降低呢,因为它取决于召回率和 FPR。我无法想象这个想法。
嗨,Jason,
对于 roc_curve 函数,将分数作为概率密度还是概率传递是正确的吗?
是的,只要该值是决策的度量。
嗨
我正在尝试绘制 ROC 曲线来评估我在 Python 中使用 AdaBoostclassifier 包开发的预测模型的准确性。
probs = model.predict_proba(X_test)
preds = probs[:,1]
fpr, tpr, threshold = metrics.roc_curve(y_test, preds)
roc_auc = metrics.auc(fpr, tpr)
# method I: plt
import matplotlib.pyplot as plt
plt.title(‘Receiver Operating Characteristic’)
plt.plot(fpr, tpr, ‘b’, label = ‘AUC = %0.2f’ % roc_auc)
plt.legend(loc = ‘lower right’)
plt.plot([0, 1], [0, 1],’r–‘)
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel(‘True Positive Rate’)
plt.xlabel(‘False Positive Rate’)
plt.show()
我运行了这段代码,但遇到了这个“ValueError: multiclass format is not supported”。
错误已经说明了一切。ROC 曲线用于预测准确性,即二分类。该公式不能应用于非二分类情况。
你好,
我正在努力为多类别(类别数=4)分类问题找出 PRC 曲线及其 AUC。
from sklearn.multiclass import OneVsRestClassifier
from xgboost import XGBClassifier
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import average_precision_score
clf = OneVsRestClassifier(XGBClassifier(n_estimators=50, max_depth=3, random_state=0))
clf.fit(X_train, Y_train)
Y_score = clf.predict_proba(X_test)
# precision recall curve
n_classes=4
precision = dict()
recall = dict()
for i in range(n_classes)
precision[i], recall[i], _ = precision_recall_curve(Y_test[:, i], Y_score[:, i])
plt.plot(recall[i], precision[i], lw=2, label=’class {}’.format(i))
plt.xlabel(“recall”)
plt.ylabel(“precision”)
plt.legend(loc=”best”)
plt.title(“precision vs. recall curve”)
plt.show()
它给了我一个错误,说
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed
你能否分享一段可运行的多类别代码,以便我能理解我的错误?
嗨,Jason,
感谢您的教程!非常具有启发性!
在最后一句话中
“这些通过曲线构建中评估的不同阈值得到暴露,将一些类别 0 翻转为类别 1,提供了一些精确率但召回率很低。”
难道不应该是反过来:“提供了一些召回率但精确率很低”吗?
谢谢,
Abel
精确率和召回率都与阳性预测有关。哪个类别被视为阳性是这个问题如何表述的问题。
你好,我有两个版本的不平衡数据集。它们是相同的数据集,但其中一个是通过从另一个数据集中删除一些行构建的。因此不平衡性发生了变化。一个有 0.11 的基线,另一个有 0.13 的基线。我可以比较它们的 aupr 分数吗?有没有办法实现这种比较?谢谢
我不明白那是什么
从 sklearn.datasets 导入 make_classification
那是什么?
你好。
如果我们使用了权重或成本矩阵来补偿不平衡怎么办?
是否仍然偏向于使用 AUC PR 指标?
或者使用权重或成本矩阵就足够了,然后我们就可以使用 AUC ROC 曲线甚至准确率作为优化模型的指标?
反之亦然,如果你使用 AUC PR 作为我们的指标……你是否也需要使用权重或成本矩阵?
“0.0 和 1.0 分别代表无技能和完美技能。”
这可能需要一点澄清。无技能正如你所说,应该是 0.5,而不是 0。小于 0.5 不仅仅是无技能,而是几乎是故意糟糕的模型 :)
你好 Mohamad…以下资源可能对您有帮助
https://machinelearning.org.cn/evaluate-skill-deep-learning-models/
你好,很棒的来源。sklearn 中对应的无技能是什么?有对应的虚拟模型吗?我找不到。如果没有,我该如何拟合一个无技能模型并获得预测,以便我可以手动计算每个概率的精确率和召回率?只是为了更好地理解,这对我来说并不清楚。非常感谢。
你好 Vicky…以下资源可能对您有帮助
https://scikit-learn.cn/stable/modules/generated/sklearn.dummy.DummyClassifier.html
你好,James,那么无技能模型在精确率-召回率曲线中的平均精确率分数呢?你如何计算它?
你好 James,无技能在精确率-召回率曲线中的原理是什么?
你好,谢谢你提供这么棒的内容。
我使用这些内容(图片和代码)进行机器学习相关的个人学习。
再次感谢您提供如此精彩的内容。
非常欢迎你,Lee Jun!感谢您的支持!