评论
作者:Zolzaya Luvsandorj,iSelect 数据科学家
ROC 曲线下面积是评估监督分类模型的最有用的指标之一。这个指标通常被称为 ROC-AUC。这里,ROC 代表接收者操作特征,AUC 代表曲线下面积。在我看来,AUROCC 是一个更准确的缩写,但可能听起来不如 ROC-AUC 那样悦耳。在正确的语境中,AUC 也可以暗示 ROC-AUC,尽管它也可以指代任何曲线下的面积。
图片由Joel Filipe在Unsplash提供
在这篇文章中,我们将深入了解 ROC 曲线的概念构建,并在 Python 中以静态和交互式格式可视化该曲线。
ROC 曲线展示了在不同阈值下*假阳性率(FPR)与真正阳性率(TPR)*之间的关系。让我们理解这三个术语的含义。
首先,让我们回顾一下混淆矩阵的样子:
作者提供的图像
复习一下混淆矩阵,让我们来看一下这些术语。
我们可以使用下面的简单公式来计算 FPR:
FPR 告诉我们错误预测的负记录的百分比。
作者提供的图像
我们可以使用下面的简单公式来计算 TPR:
TPR 告诉我们正确预测的正记录的百分比。这也被称为召回率或灵敏度。
作者提供的图像
一般来说,分类模型可以预测给定记录属于某一类别的概率。通过将概率值与我们设定的阈值进行比较,我们可以将记录分类到一个类别中。换句话说,你需要定义一个类似于以下的规则:
如果为正的概率大于或等于阈值,则记录被分类为正预测;否则为负预测。
在下面的小例子中,我们可以看到三个记录的概率分数。使用两个不同的阈值(0.5 和 0.6),我们将每个记录分类到一个类别中。如你所见,预测的类别根据我们选择的阈值不同而有所变化。
作者提供的图像
在构建混淆矩阵并计算如 FPR 和 TPR 等比率时,我们需要预测的类别而不是概率分数。
现在我们知道了 FPR、TPR 和阈值是什么,理解 ROC 曲线的展示就很简单了。在构造曲线时,我们首先计算许多阈值下的 FPR 和 TPR。一旦我们得到这些阈值的 FPR 和 TPR,我们就将 FPR 绘制在 x 轴上,将 TPR 绘制在 y 轴上,从而得到 ROC 曲线。就是这样!✨
作者提供的图像
ROC 曲线下的面积范围从 0 到 1。一个完全随机的模型其 AUROCC 为 0.5,由下方虚线蓝色三角形对角线表示。ROC 曲线距离该线越远,模型的预测能力越强。
作者提供的图像
现在,到了查看一些代码示例来巩固我们的知识的时候了。
首先,让我们导入在本帖其余部分中需要的库:
import numpy as np
import pandas as pd
pd.options.display.float_format = "{:.4f}".formatfrom sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, plot_roc_curveimport matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
sns.set(palette='rainbow', context='talk')
现在,我们将构建一个函数,根据正确类别、预测为正类的概率和阈值,来找出假阳性和真阳性的数量:
def get_fp_tp(y, proba, threshold):
"""Return the number of false positives and true positives."""
# Classify into classes
pred = pd.Series(np.where(proba>=threshold, 1, 0),
dtype='category')
pred.cat.set_categories([0,1], inplace=True)
# Create confusion matrix
confusion_matrix = pred.groupby([y, pred]).size().unstack()\
.rename(columns={0: 'pred_0',
1: 'pred_1'},
index={0: 'actual_0',
1: 'actual_1'})
false_positives = confusion_matrix.loc['actual_0', 'pred_1']
true_positives = confusion_matrix.loc['actual_1', 'pred_1']
return false_positives, true_positives
请注意,实际上你将使用分割的数据集(例如训练集、测试集)。但为了简单起见,我们在这篇文章中不会对数据进行分割。
我们将在一个玩具数据集上构建一个简单的模型,并获取记录的正类概率(用值 1 表示):
# Load sample data
X = load_breast_cancer()['data'][:,:2] # first two columns only
y = load_breast_cancer()['target']# Train a model
log = LogisticRegression()
log.fit(X, y)# Predict probability
proba = log.predict_proba(X)[:,1]
我们将使用 1001 个不同的阈值,范围从 0 到 1,每次增加 0.001。换句话说,阈值将类似于 0、0.001、0.002、…、0.998、0.999、1。让我们找出这些阈值的 FPR 和 TPR。
# Find fpr & tpr for thresholds
negatives = np.sum(y==0)
positives = np.sum(y==1)columns = ['threshold', 'false_positive_rate', 'true_positive_rate']
inputs = pd.DataFrame(columns=columns, dtype=np.number)
thresholds = np.linspace(0, 1, 1001)for i, threshold in enumerate(thresholds):
inputs.loc[i, 'threshold'] = threshold
false_positives, true_positives = get_fp_tp(y, proba, threshold)
inputs.loc[i, 'false_positive_rate'] = false_positives/negatives
inputs.loc[i, 'true_positive_rate'] = true_positives/positives
inputs
绘图数据已准备好。让我们来绘制它:
def plot_static_roc_curve(fpr, tpr):
plt.figure(figsize=[7,7])
plt.fill_between(fpr, tpr, alpha=.5)
# Add dashed line with a slope of 1
plt.plot([0,1], [0,1], linestyle=(0, (5, 5)), linewidth=2)
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.title("ROC curve");
plot_static_roc_curve(inputs['false_positive_rate'],
inputs['true_positive_rate'])
虽然构建自定义函数有助于我们理解曲线及其输入,并更好地控制它们,但我们也可以利用sklearn的优化能力。例如,我们可以使用roc_curve()
函数获取 FPR、TPR 和阈值。我们可以使用自定义绘图函数以相同的方式绘制数据:
fpr, tpr, thresholds = roc_curve(y, proba)
plot_static_roc_curve(fpr, tpr)
Sklearn还提供了一个plot_roc_curve()
函数,自动完成所有工作。你只需一行代码(添加标题是可选的):
plot_roc_curve(log, X, y)
plt.title("ROC curve"); # Add a title for clarity
使用静态图时,很难看到曲线上不同点对应的阈值。一个选项是检查我们创建的inputs
数据框。另一个选项是创建图的交互式版本,这样当我们悬停在图表上时,可以看到 FPR 和 TPR 以及对应的阈值:
def plot_interactive_roc_curve(df, fpr, tpr, thresholds):
fig = px.area(
data_frame=df,
x=fpr,
y=tpr,
hover_data=thresholds,
title='ROC Curve'
)
fig.update_layout(
autosize=False,
width=500,
height=500,
margin=dict(l=30, r=30, b=30, t=30, pad=4),
title_x=.5, # Centre title
hovermode = 'closest',
xaxis=dict(hoverformat='.4f'),
yaxis=dict(hoverformat='.4f')
)
hovertemplate = 'False Positive Rate=%{x}<br>True Positive Rate=%{y}<br>Threshold=%{customdata[0]:.4f}<extra></extra>'
fig.update_traces(hovertemplate=hovertemplate)
# Add dashed line with a slope of 1
fig.add_shape(type='line', line=dict(dash='dash'), x0=0, x1=1, y0=0, y1=1)
fig.show()plot_interactive_roc_curve(df=inputs,
fpr='false_positive_rate',
tpr='true_positive_rate',
thresholds=['threshold'])
交互性非常有用,不是吗?
希望你喜欢学习如何构建和可视化 ROC 曲线。一旦你理解了这条曲线,就很容易理解另一条相关曲线:精确度-召回率曲线。
感谢阅读这篇文章。如果你感兴趣,这里有一些我其他文章的链接:
再见了 ????????
个人简介: Zolzaya Luvsandorj 在 iSelect 担任数据科学家。在以优异的成绩获得多个荣誉奖项完成 BCom 学位后,Zolzaya 曾在一家咨询公司担任数据分析师三年,然后转到现在的职位。她热衷于扩展数据科学、计算机科学和统计学知识,并在博客中用简单的语言解释数据科学概念。
原文。已获许可转载。
相关:
-
直接使用 Pandas 获取互动图表
-
如何创建一个互动的 3D 图表并轻松与任何人分享
-
指标的重要性,第一部分:评估分类模型
1. 谷歌网络安全证书 - 快速进入网络安全职业生涯。
2. 谷歌数据分析专业证书 - 提升你的数据分析技能
3. 谷歌 IT 支持专业证书 - 支持你的组织 IT 部门