我们通常使用ROC和AUC来衡量分类算法在二分类问题上表现的好坏。
在二分类问题上,可将样例根据其真实类别和分类模型预测的类别分为如下四种(1表示类别为真,0表示类别为假):
假如我们有100个正例,其中85个被预测为正例,15个被预测为反例;
80
个反例,其中70
个被预测成为反例,10
个被预测成为正例。那么:
TP | 85 |
---|---|
FN | 15 |
TN | 70 |
FP | 10 |
很多学习器是为测试样本产生一个实值或概率预测,然后将这个预测值与一个分类阈值进行比较,若大于阈值则分为正类,否则为反类。例如,神经网络在一般情形下是对每个测试样本预测出一个[0.0,1.0]
之间的实值,然后将这个值与阈值(比如0.5)进行比较,大于阈值(比如0.5)则判为正例,否则为反例。这个阈值设置的好坏,直接决定了学习器的泛化能力。
在不同的应用任务中,我们可根据任务需求来采用不同的阈值。例如,若我们更重视“查准率”,则可以把阈值设置的大一些,让分类器的预测结果更有把握;若我们更重视“查全率”,则可以把阈值设置的小一些,让分类器预测出更多的正例。因此,阈值设置的好坏,体现了综合考虑学习器在不同任务下的泛化性能的好坏。
ROC全称是“受试者工作特征”(Receiver OperatingCharacteristic)曲线。我们根据学习器的预测结果,把阈值从0变到最大,即刚开始是把每个样本作为正例进行预测,随着阈值的增大,学习器预测正样例数越来越少,直到最后没有一个样本是正样例。在这一过程中,每次计算出两个重要量的值,分别以它们为横、纵坐标作图,就得到了“ROC曲线”。
设计一个指标来判断分类器的好坏,这里我们使用
真正例率TPR
和假正例率FPR
来判断,它们的定义如下:
T P R = T P / ( T P + F N ) F P R = F P / ( F P + T N ) \begin{array}{l} T P R=T P /(T P+F N) \\ F P R=F P /(F P+T N) \end{array} TPR=TP/(TP+FN)FPR=FP/(FP+TN)
上面的例子中:
T P R = T P T P + F N = 85 85 + 15 = 85 100 F P R = F P F P + T N = 10 10 + 70 = 10 80 \begin{array}{l} T P R=\dfrac{TP}{TP+FN}=\dfrac{85}{85+15}=\dfrac{85}{100}\\ F P R=\dfrac{FP}{FP+TN}=\dfrac{10}{10+70}=\dfrac{10}{80} \end{array} TPR=TP+FNTP=85+1585=10085FPR=FP+TNFP=10+7010=8010
TPR越高,FPR越低,则可以证明分类器分类效果越好
但是两者又是相互矛盾的,我们为了降低假正例率FP,让样本被分为正例的要求变得更高,这样反例被误判为正例的个数FP(假正例)就会减少,那么FPR的值就会降低;
但与此同时,有一部分不是很像正例的正例会被我们错误的归为反例,FN(假反例)的个数就会升高,TPR的值也会降低。反之,TPR的值增大,FPR的值也会增大。
所以单单凭TPR和FPR的两个值是没有办法比较两个分类器的好坏。这里就提出了ROC曲线。我们使用TPR作为纵轴,FPR作为横轴作图,就可以得到ROC曲线。
对角线对应于“随机猜测”模型
,而点(0,1)则对应于将所有正例预测为真正例、所有反例预测为真反例的“理想模型”。
绘图过程如下:给定 m + m^+ m+个正例, m − m^- m−个反例,根据学习器预测结果对样例进行排序,然后把分类器阈值设为最大,此时所有的样例均预测为反例,此时真正例率和假正例率均为 0,在坐标 (0,0) 处标一个点。然后,将分类阈值依次设为每个样例的预测值(预测概率),即依次将每个样例划分为正例。
TPR
),则对应标记点的坐标为 ( x , y + 1 m + ) (x,y+\dfrac{1}{m^+}) (x,y+m+1),FPR
),则对应标记点的坐标为 ( x + 1 m − , y ) (x+\dfrac{1}{m^-},y) (x+m−1,y)。然后用线段连接相邻点即得ROC曲线。该方法简单、直观、通过图示可观察分析方法的准确性,并可用肉眼作出判断。ROC曲线将真正例率和假正例率以图示方法结合在一起,可准确反映某种学习器真正例率和假正例率的关系,是检测准确性的综合代表;
在生物信息学上的优点:ROC曲线不固定阈值,允许中间状态的存在,利于使用者结合专业知识,权衡漏诊与误诊的影响,选择一个更加的阈值作为诊断参考值。
假如我们已经得到了所有样本的概率输出(属于正样本的概率),现在的问题是如何改变这个阈值(概率输出)?
我们根据每个测试样本属于正样本的概率值从大到小排序。
下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p
表示正样本,n
表示负样本),“Score”表示每个测试样本属于正样本的概率。
1,2,3,4
都会被认为是正样本,因为它们的“Score”值都大于等于
0.6,而其他样本则都认为是负样本。1
和0
时,分别可以得到ROC曲线上的(0,0)
和(1,1)
两个点。将这些(FPR,TPR)
对连接起来,就得到了ROC曲线。当阈值取值越多,ROC曲线越平滑。举例帮助理解,使用逻辑回归对数据进行分类,可以得到如下的表格
这个逻辑回归分类器很好的预测了类别,这个样本有4个正例,3个反例
。
我们可以按照如下方式绘制ROC曲线图,
TPR=0.5
而假正例率FPR=0
;如上图,我们就可以说分类器1的分类效果好于分类器2。
因为在相同的FPR的条件下,分类器1的TPR要高于分类器2的TPR。
但是如果出现了下面的情况:
我们此时没有办法直观的说明两个分类器那个更好一些,
这种情况我们一般使用AUC
的值来进行判断。
AUC(Area Under ROC Curve)也就是直ROC曲线下面的面积
通常我们认为AUC值大的分类器性能较好
def anotherPlotROC(predStrengths, classLabels): #0--->1
import matplotlib.pyplot as plt
cur = (0.0, 0.0)
ySum = 0.0
numPosClas = sum(np.array(classLabels) == 1.0)
yStep = 1/float(numPosClas); xStep = 1/float(len(classLabels) - numPosClas)
sortedIndicies = predStrengths.argsort()
fig = plt.figure()
fig.clf()
ax = plt.subplot(111)
for index in sortedIndicies.tolist()[0][::-1]:
if classLabels[index] == 1.0: #TP真正例
delX = 0; delY = yStep
else:
delX = xStep; delY = 0 #FP假正例
ySum += cur[1]
ax.plot([cur[0], cur[0] + delX], [cur[1], cur[1]+delY], c='b')
cur = (cur[0]+delX, cur[1]+delY)
ax.plot([0,1], [0,1], 'b--')
plt.xlabel("False positive rate"); plt.ylabel("True positive rate")
plt.title('ROC')
ax.axis([0,1,0,1])
print("the Area Under the Curve is", ySum*xStep)
plt.show()
使用《机器学习实战》中第五章的病马预测数据使用第八章adaboost分类算法进行分类可得到的ROC曲线如下 :
接下来就是利用python实现ROC曲线,sklearn.metrics
有roc_curve, auc
两个函数
fpr, tpr, thresholds = roc_curve(y_test, scores)
其中y_test
为测试集的结果,scores
为模型预测的测试集得分(注意:通过decision_function(x_test)
计算scores
的值);fpr,tpr,thresholds
分别为假正率、真正率和阈值。(应该是不同阈值下的真正率和假正率)。
roc_auc =auc(fpr, tpr)
其中roc_auc
为计算的acu
的值。
解释:
sklearn.metrics.roc_curve函数提供了很好的解决方案。
首先看一下这个函数的用法:
fpr, tpr, thresholds=sklearn.metrics.roc_curve(y_true,y_score,pos_label=None,sample_weight=None,drop_intermediate=True)
参数解析(来源sklearn官网):
y_true: array, shape = [n_samples]
#True binary labels in range {0, 1} or {-1, 1}. If labels are not binary, pos_label should be explicitly given.
即真实标签矩阵。
y_score : array, shape = [n_samples]
#
Target scores, can either be probability estimates of the positive class, confidence values, or non-thresholded measure of decisions (as returned by “decision_function” on some classifiers).
即模型的预测结果矩阵。
pos_label : int or str, default=None
#Label considered as positive and others are considered negative.
即标签中认定为正的label个数。
例如:
label= [1,2,3,4]
,如果设置pos_label = 2
,则认为3,4为positive,其他均为negtivesample_weight: array-like of shape = [n_samples]
#optional Sample weights.
即采样权重,可选择取其中的一部分进行计算。
drop_intermediate: boolean, optional (default=True)
#Whether to drop some suboptimal thresholds which would not appear on a plotted ROC curve. This is useful in order to create lighter ROC curves.
即可选择去掉一些对于ROC性能不利的阈值,使得得到的曲线有更好的表现性能。
返回值Returns
:
thresholds: array, shape = [n_thresholds]
Decreasing thresholds on the decision function used to compute fpr and tpr. thresholds[0] represents no instances being predicted and is arbitrarily set to max(y_score) + 1.
即所选择不同的阈值,按照降序排列。
fpr : array, shape = [>2]
#Increasing false positive rates such that element i is the false positive rate of predictions with score >= thresholds[i].
根据不同阈值求出的fpr。
tpr: array, shape = [>2]
#Increasing true positive rates such that element i is the true positive rate of predictions with score >= thresholds[i].
根据不同阈值求出来的tpr上述方法可得到一组tpr和fpr,在此基础上即可作出roc曲线。求AUC可通过函数auc(fpr,tpr)
,其返回值即为AUC的值。
实例分析如下:
import numpy as np
from sklearn import metrics
import matplotlib.pyplot as plt
from sklearn.metrics import auc
y = np.array([1,1,2,3]) #y为数据的真实标签
scores = np.array([0.1, 0.2, 0.35, 0.8]) #scores为分类其预测的得分
fpr, tpr, thresholds = metrics.roc_curve(y, scores, pos_label=2) #得到fpr,tpr, thresholds
返回值对应如下:
得到一组fpr和tpr之后即可画出该次测试对应的roc曲线
plt.plot(fpr,tpr,marker = 'o')
plt.show()
from sklearn.metrics import auc
AUC = auc(fpr, tpr)
最终得到AUC=0.67
参考:1、https://zhuanlan.zhihu.com/p/46438528;
2、https://blog.csdn.net/ice110956/article/details/20288239?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control
3、https://blog.csdn.net/Mr_HHH/article/details/79667677?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control
4、https://blog.csdn.net/xyz1584172808/article/details/81839230
5、https://www.jianshu.com/p/1da84ac7ff03