二分类问题中的评价指标

一些定义

  • 阳性(Positive, P),指样本中阳性的个数, P = T P + F N P=TP+FN P=TP+FN
  • 阴性( Negtive,N),指样本中阴性的个数, N = T N + F P N=TN+FP N=TN+FP
  • 假阳性(False Positive, FP),指预测中将阴性预测为阳性的个数
  • 假阴性(False Negtive, FN),指预测中将阳性预测为阴性的个数
  • 假阳性率(False Positive Rate, FPR),又叫误诊率,相当于假设检验中的取伪概率, F P R = F P / N FPR=FP/N FPR=FP/N.
  • 真阳性率(True Positive Rate, TPR)又叫敏感性(sensitivity),召回率, T P R = T P / P . TPR=TP/P. TPR=TP/P.
  • 查准率 P*(有些地方定义也是用P,为了避免和阳性P重复,这里加了个*号), P ∗ = T P / ( T P + F P ) P*=TP/(TP+FP) P=TP/(TP+FP) 。判断正确的阳性占全部判断为阳性的比例。
  • 查全率R,和真阳性率TPR一个意思,又称为精确性(specificity) R = T P / ( T P + F N ) = T P / P R=TP/(TP+FN)=TP/P R=TP/(TP+FN)=TP/P.判断正确的阳性占全部真实阳性的比例。

通常我们用一个混淆矩阵直观表示上述概念:
在这里插入图片描述

ROC曲线

定义与解释

ROC曲线起源于第二次世界大战时期雷达兵对雷达的信号判断。ROC的全称是Receiver Operating Characteristic Curve,中文名字叫“受试者工作特征曲线”,顾名思义,其主要的分析方法就是画这条特征曲线.

在这里插入图片描述
上图的横轴代表假阳率(FPR),纵轴代表灵敏度(真阳率,TPR)。理想状态我们希望,FPR=0,TPR=1,也就是希望曲线能够尽可能接近(0,1)这一点。如果曲线在对角线之上,表明真阳率>假阳率,这是分类器才是有效的。反之,如果曲线在对角线或对角线之下,表明真阳率《假阳率,这时分类器是无效的。而曲线上的每一点对应一次调参的结果,所以最接近(0,1)点的值所对应的参数就是分类器的最优参数。

下面两幅图中两条ROC曲线相交于一点,AUC值几乎一样:当需要高Sensitivity时,模型A比B好;当需要高Speciticity时,模型B比A好;
在这里插入图片描述在这里插入图片描述

ROC曲线的实现方法

画法一

ROC曲线上的每一个点都对应一次参数的调整,我们可以通过改变参数来逐步描绘出ROC曲线。可以举个例子来说明,譬如下表中的flag是样本的类别(1:Positive; 0:negtive),score是分类器(例如:logist regression)预测的该样本为阳性的概率, 我们需要调整的参数是threshold(如果score>threshold则判定为阳性,否则判定为阴性)。
在这里插入图片描述
这里我们可以设置参数的调整范围为0,0.1,0.2,…,0.9,1。于是可以做出ROC曲线为:
在这里插入图片描述

R语言实现

#用R语言实现
x=c(1,1,0,1,1,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0)
score=c(0.9,0.8,0.7,0.6,0.55,0.54,0.53,0.52,0.51,0.505,0.4,0.39,0.38,0.37,0.36,0.35,0.34,0.33,0.30,0.1)
df=data.frame(flag=x,score=score)
index_P=df$flag==1

res=data.frame(TPR=NA,FPR=NA,threshold=NA)
res=res[-1,]
for(threshold in seq(0,1,0.001)){
  pre_P=df$score>threshold

  TPR=sum(pre_P[index_P]==1)/length(index_P)
  FPR=sum(pre_P[!index_P]==1)/(nrow(df)-sum(index_P))
  res=rbind(res,data.frame(TPR,FPR,threshold))
}
plot(res$FPR,res$TPR,type='b',xlab = "FPR",ylab='TPR',main = "ROC曲线")

效果 如下:
在这里插入图片描述

python语言实现

#python实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
x=[1,1,0,1,1,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0]
score=[0.9,0.8,0.7,0.6,0.55,0.54,0.53,0.52,0.51,0.505,0.4,0.39,0.38,0.37,0.36,0.35,0.34,0.33,0.30,0.1]

df=pd.DataFrame({'flag':x,'score':score})
index_P=df['flag']==1

res=pd.DataFrame(columns=['TPR','FPR','threshold'])

for threshold in np.arange(0,1,0.001):
    pre_P=df['score']>threshold
    TPR=sum(pre_P[index_P]==1)/len(index_P)
    FPR=sum(pre_P[~index_P]==1)/(df.shape[0]-sum(index_P))
    res=res.append({'TPR':TPR,'FPR':FPR,"threshold":threshold},ignore_index=True)

res.plot(x='FPR',y='TPR',title="ROC curve",marker='o')
plt.show()

效果如下:
在这里插入图片描述

画法二

相比与画法一,这里的画法更加简单,不用每次重复计算TPR和FPR。
给定 P 个正例和N 个反例,根据学习器预测结果对样例进行排序,然后把分类阈值值设为最大,即把所有样例均预测为反例,此时真正例率TPR和假正例率FPR均为 0 , 在坐标 (0, 0) 处标记一个点然后,将分类阈值依次设为每个样例的预测值,即依次将每个样例划分为正例。设前一个标记点坐标为 ( x , y ) (x, y) (xy) , 当前若为真正例,则对应标记点的坐标为 ( x , y + 1 P ) (x,y+\frac{1}{P}) (x,y+P1);当前若为假正例,则对应标记点的坐标为 ( x + 1 N , y ) (x +\frac{1}{N},y) (x+N1,y) ,然后用线段连接相邻点即得.

AUC

AUC(Area under roc Curve)面积就是ROC曲线下面的面积,真实场景中ROC曲线一般都会在这条直线的上方,所以AUC的取值一般在0.5~1之间。AUC的值越大,说明该模型的性能越好。 常用来比较两个分类器的性能。

A U C = 1 2 ∑ i = 1 m − 1 ( x i + 1 − x i ) ( y i + y i + 1 ) . AUC=\frac{1}{2}\sum_{i=1}^{m-1}(x_{i+1}-x_i)(y_i+y_{i+1}). AUC=21i=1m1(xi+1xi)(yi+yi+1).

P-R曲线

与ROC曲线相比较,P-R曲线刻画的是查全率(TPR)与查准率的关系(P*)的关系,如下图所示:
在这里插入图片描述
由于我们希望TP的比例在真阳中假阳样本中的比例都尽可能大,也就是既希望查准率(P*)很大,也希望查全率(R,TPR)很大,那么该曲线越接近(1,1)越好。

上图中A曲线和B曲线有交叉地方,表明这两个分类器各有优劣,要具体情况比较。如果非要分个高下,可以利用**平衡点(Break-Event Point, BEP)**来比较,也即在查准率=查全率的时候,比较他们P-R曲线上点的大小。同样地,我们也可以利用曲线下的面积大小来进行比较。

但BEP还是过于简单了些,更常用的是F1度量:
F 1 = 2 × P ∗ × R P ∗ + R = 2 × T P P + N + T P − T N F1=\frac{2\times P^*\times R}{P^*+R}=\frac{2\times TP}{P+N+TP-TN} F1=P+R2×P×R=P+N+TPTN2×TP
等价于:
1 F 1 = 1 2 ( 1 P + 1 R ) . \frac{1}{F1}=\frac{1}{2}\left(\frac{1}{P}+\frac{1}{R}\right). F11=21(P1+R1).

进一步,由于对查准率和查全率的重视程度不同,我们还可以利用 F β F_\beta Fβ度量:
F β = ( 1 + β 2 ) × P ∗ × R ( β 2 × P ∗ ) + R , F_\beta=\frac{(1+\beta^2)\times P^*\times R}{(\beta^2\times P^*)+R}, Fβ=(β2×P)+R(1+β2)×P×R,
等价于
1 F β = 1 β 2 ( 1 P + β 2 R ) . \frac{1}{F_\beta}=\frac{1}{\beta^2}\left(\frac{1}{P}+\frac{\beta^2}{R}\right). Fβ1=β21(P1+Rβ2).

以上两个度量都是基于调和平均的,之所以这样做是因为与算数平均和几何平均相比,调和平均更重视较小值.

代价敏感错误率与代价曲线

在实际中阳性识别为阴性和阴性识别为阳性的错误代价不同,由此可以构造一个代价矩阵:
在这里插入图片描述
一般情况下,重要的是代价比值而非绝对值,例如 c o s t 01 : c o s t 10 = 5 : 2 cost_{01}:cost_{10}=5:2 cost01:cost10=5:2与50:10所起的效果相当。

D + D^+ D+ D − D^- D分别代表样例集 D D D的正例和反例集, m m m为总样本量,则**代价敏感(cost-sensitive)**错误率为
E ( f ; D ; c o s t ) = 1 m ( ∑ x i ∈ D + 1 ( f ( x i ) ≠ y i ) × c o s t 01 + ∑ x i ∈ D − 1 ( f ( x i ) ≠ y i ) × c o s t 10 ) . E(f;D;cost)=\frac{1}{m}\left(\sum_{x_i\in D^+}1(f(x_i)\neq y_i)\times cost_{01}+\sum_{x_i\in D^-}1(f(x_i)\neq y_i)\times cost_{10}\right). E(f;D;cost)=m1(xiD+1(f(xi)=yi)×cost01+xiD1(f(xi)=yi)×cost10).

在非均匀等代价下,ROC曲线不能直接反映出学习器的期望总体代价,而代价曲线(cost curve)则可达到该目的。代价曲线图的横轴是取值为 [ 0 , 1 ] [0,1] [0,1]的正例概率代价
P ( + ) c o s t = p × c o s t 01 p × c o s t 01 + ( 1 − p ) × c o s t 10 , P(+)cost=\frac{p\times cost_{01}}{p\times cost_{01}+(1-p)\times cost_{10}}, P(+)cost=p×cost01+(1p)×cost10p×cost01,
其中 p p p是样例为正例的概率;纵轴是取值为[0,1]的归一化代价
c o s t n o r m = F N R × p × c o s t 01 + F P R × ( 1 − p ) × c o s t 10 p × c o s t 01 + ( 1 − p ) × c o s t 10 cost_{norm}=\frac{FNR\times p\times cost_{01}+FPR\times (1-p)\times cost_{10}}{p\times cost_{01}+(1-p)\times cost_{10}} costnorm=p×cost01+(1p)×cost10FNR×p×cost01+FPR×(1p)×cost10
其中 F N R = 1 − T P R FNR=1-TPR FNR=1TPR是假反例率.

代价曲线的绘制方法:
ROC 由线上每一点对应了代价平面上的一条线段 , 设 ROC 曲线上点的坐标为 (TPR, FPR) ,则可相应计算出 FNR,然后在代价平面上绘制
一条从 (0 , FPR) 到 (1 , FNR) 的线段,线段下的面积即表示了该条件下的期望总体代价;如此将 ROC 曲线土的每个点转化为代价平面上的一条线段,然后取所有线段的下界,围成的自积即为在所有条件下学习器的期望总体代价,如图:
在这里插入图片描述

相关程序包

R语言中可以利用pROC包来绘制ROC曲线,使用roc函数的格式大致如下,
ci=T代表计算95%的置信区间,auc=T则会返回auc值,例如利用数据集aSAH来进行测试:

#R语言
library(pROC)
data(aSAH)
tmp=roc(aSAH$outcome, aSAH$s100b, smooth=TRUE,ci=T,auc = T)
plot(tmp)
#或者ggroc(tmp)
#python语言
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt
x=[1,1,0,1,1,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0]
score=[0.9,0.8,0.7,0.6,0.55,0.54,0.53,0.52,0.51,0.505,0.4,0.39,0.38,0.37,0.36,0.35,0.34,0.33,0.30,0.1]

fpr, tpr, thresholds = roc_curve(x, score)
#计算AUC值
roc_auc = auc(fpr, tpr)
#绘制ROC图
plt.plot(fpr,tpr)
plt.show()

可以参考:
https://www.freesion.com/article/2560277921/

参考

https://www.jianshu.com/p/2ca96fce7e81
https://www.plob.org/article/12476.html
《机器学习》周志华

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值