前言
上一篇谈到準确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1 Score,它们适用在不同的场景,接着我们再来讨论『ROC/AUC 曲线』,它是一个更全面评估效能的指标。
远在1941年『ROC/AUC 曲线』就被用来侦测敌军飞机及船舰,美军利用雷达信号判断飞机、船舰的所在位置,之后也被广泛应用在无线电、生物学、犯罪心理学、医学领域,接下来我们就来领略它的强大威力。
定义
ROC(Receiver operator characteristic):有人翻译为『接收操作特徵图』,其实没甚么帮助,它的定义是在各种『决策门槛』(decision threshold)下,比较『真阳率』(True Positive Rate;TPR)与『假阳率』(False Positive Rate;FPR)间的变化。
图. 『真阳率』与『假阳率』公式
ROC曲线可以绘製成一条曲线,如下图,有多条ROC曲线,相互比较效能,AUC(Area Under the Curve)就比较容易理解,即ROC曲线之下所覆盖的面积,除以总面积的比率。
图. ROC曲线比较,X轴为假阳率,Y轴为真阳率。
以雷达侦测为例,信号要大于某个决策门槛(decision threshold),飞机才会出现在雷达萤幕上,假设雷达萤幕旁有一旋钮,可以调整门槛值,如果调高一点,则雷达萤幕侦测敌机的能力变差,有些信号弱的飞机就不会显示,反之,门槛调低一点,则雷达萤幕侦测敌机的能力变强,但是我们可能把天空中的大鸟误认为飞机(假阳率)。因此,可以在各种门槛下计算真阳率及假阳率,作为样本点,将所有样本点连成一线,即ROC曲线,因此,这条线越接近上方,表示真阳率越高,即判断正确的比率越高,换句话说,ROC曲线下方覆盖的面积(AUC)越大,表示效能越好。以上就是ROC/AUC 曲线的精髓。
图解决策门槛对『真阳率』与『假阳率』的影响
我们从二分类的分配(分布)角度来看,如果调整决策门槛,则TP(真阳)、FP(假阳)会随之变化。
图. TP、TN、FT、FN 的示意图,资料来源:Finding Donors: Classification Project With PySpark
二分类的分配差异越显着,AUC的分数就越高,见下图。
图. AUC,资料来源:Finding Donors: Classification Project With PySpark
ROC曲线绘图
接下来我们就要了解如何绘製ROC曲线,範例如下:
资料内容如下,第一栏为预测为真的机率,第二栏为实际值。
绘製ROC曲线步骤:
画一个空白图如下。


图. ROC(红线)
绘製原理很直觉,实际值为1(真),表示真阳(预测超过门槛),故Y轴加1格,反之,为假阳(预测超过门槛,但实际为假),故X轴加1格。
程式开发
依照上述步骤,撰写程式如下:
import numpy as npimport matplotlib.pyplot as pltfrom sklearn.metrics import roc_curve, roc_auc_score, auc# 读取资料import pandas as pddf=pd.read_csv('./data.csv')# 计算第二栏的真(1)与假(0)的个数,假设分别为P及NP= df[df['actual']==1].shape[0]N= df[df['actual']==0].shape[0]print(P,N)y_unit=1/PX_unit=1/N# 以第一栏降幂排序,从大排到小。df2=df.sort_values(by='predict', ascending=False)# 依序扫描第二栏,计算每一座标点# 若是1,Y加一单位,反之,若是0,X加一单位X=[]y=[]current_X=0current_y=0for row in df2.itertuples(): # row[0] is index #print(row[2]) if row[2] == 1: current_y+=y_unit else: current_X+=X_unit X.append(current_X) y.append(current_y)X=np.array(X) y=np.array(y) print(X, y)# 绘图。 plt.title('Receiver Operating Characteristic')plt.plot(X, y, color = 'orange')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()
直接使用 Scikit-Learn套件更简单,程式如下:
import numpy as npimport matplotlib.pyplot as pltfrom sklearn.metrics import roc_curve, roc_auc_score, auc# 读取资料import pandas as pddf=pd.read_csv('./data.csv')# 在各种『决策门槛』(decision threshold)下,计算 『真阳率』(True Positive Rate;TPR)与『假阳率』(False Positive Rate;FPR)fpr, tpr, threshold = roc_curve(df['actual'], df['predict'])print(fpr, tpr, threshold)auc1 = auc(fpr, tpr)## Plot the resultplt.title('Receiver Operating Characteristic')plt.plot(fpr, tpr, color = 'orange', label = 'AUC = %0.2f' % auc1)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()
执行结果如下:
相关程式码放在这里的 ROC_AUC_sample 目录。
结论
以上说明希望能有助于观念的釐清,如有失当,还请各位先进不吝指正。