分类器各种各样,如何评价这些分类器的性能呢?(这里只考虑二元分类器,分类器的输出为概率值)

方法一:概率定义法

从正样本中随机选取元素记为x,从负样本中随机选取元素记为y,x的置信度大于y的概率

计算方法可以描述为

s=0
for x in 正例:
s+=1/正例总数×置信度小于x的负例所占比例
return s

概率是用来定义问题的利器,如基尼系数。

方法二:正样本排名法

对全部样本按照置信度从高到低进行排序,排名依次记做1,2,3......全部正例的排名之和记为R,R越小表明分类器越准。

方法三:复杂定义法

我提出一种评判指标:点评测法。

给定一个阈值,就可以将分类器的概率值确定化为0、1值。现在只考虑你认为值为1的样本,这些样本占“实际假”样本的比例越小越好,这些样本占“实际为真”的样本的比例越大越好,于是可以得到二元组(这些样本占“实际假”的比例,这些样本占“实际真”的比例)。把这个二元组画在平面直角坐标系中,得到一个点,这个点离(0,1)越近越好!

上面说的是给定了一个阈值,大多数时候,阈值是不好确定的,那就采用“动态阈值”,让阈值从0到1变化就会得到一个点序列,也就是一条曲线。这条曲线就是传说中的ROC。

ROC是一种折线,它是一种评价二值分类器的性能指标

AUC是求折线下面的面积,折线不一定是ROC折线

00:我说0,实际也为0

01:我说0,实际为1

10:我说1,实际为0

11:我说1,实际为1

那么,x坐标可以表示为10/(00+10),y坐标可以表示为11/(01+11)

也就是说,x坐标可以表示为10/x0,y坐标表示为11/x1

也就是说,只看“我说1”的那一部分,该部分在全部“实际0”的部分所占比例为x轴,该部分在“实际1”部分所占比例为y轴。

描述起来多么复杂!但是上面三种方法得到的结果是一模一样的,虽然定义上差很多,但最终说的是一回事!

AUC的直观认识

  • AUC对于置信度不敏感,它只关注名次而不关注具体置信度
  • 从AUC角度看,好的分类器就是一个好的排序器。分类器在某种程度上就是排序器。
  • AUC对于样本正负样本不均衡的现象完全不敏感,从方法一定义上可以看出来。
import sklearn.metrics as metrics
import numpy as np def roc(y_true, y_mine):
a = [(y_mine[i], y_true[i]) for i in range(len(y_true))]
a = sorted(a, key=lambda x: -x[0])
thresh = sorted(list(set([0, 1] + [i[0] for i in a])), key=lambda x: -x)
cnt = [np.count_nonzero(y_true == 0), np.count_nonzero(y_true == 1), 0, 0]
x = []
y = []
j = 0
for i in thresh:
while j < len(a) and a[j][0] >= i:
if a[j][1]:
cnt[0b11] += 1
cnt[0b01] -= 1
else:
cnt[0b10] += 1
cnt[0b00] -= 1
j += 1
x.append(cnt[0b10] / (cnt[0b00] + cnt[0b10]))
y.append(cnt[0b11] / (cnt[0b11] + cnt[0b01]))
return x, y, thresh def auc(x, y):
a = sorted([(x[i], y[i]) for i in range(len(x))], key=lambda x: x[0])
area = 0
for i in range(1, len(a)):
area += (a[i - 1][1] + a[i][1]) * (a[i][0] - a[i - 1][0]) / 2
return area def auc2(y_mine, y_true):
"""
auc的物理意义在于:随机正样本比随机负样本得分高的概率
基于这种直观的思路可以更快速的计算auc
:param y_mine:
:param y_true:
:return:
"""
a = sorted([(y_mine[i], y_true[i]) for i in range(len(y_mine))], key=lambda x: -x[0])
s = 0
true_count = len([1 for i in y_true if i])
false_count = len(y_true) - true_count
total_false = false_count
for i in a:
if i[1]:
s += 1 / true_count * false_count / total_false
else:
false_count -= 1
return s y_mine = np.random.rand(10)
y_true = np.random.randint(0, 2, 10)
x, y, t = roc(y_true, y_mine)
print(auc(x, y))
print(metrics.auc(x, y))
print(auc2(y_mine, y_true))

其实,auc还可以推导一下得到更简单一点的公式:

def auc2(y_mine, y_true):
"""
auc的物理意义在于:随机正样本比随机负样本得分高的概率
基于这种直观的思路可以更快速的计算auc
本函数只适用于计算得分各不相同的样本,如果存在并列情况,此函数结果错误
:param y_mine:
:param y_true:
:return:
"""
a = sorted(zip(y_mine, y_true), key=lambda x: -x[0])
T = np.count_nonzero(y_true)
F = len(y_true) - T
R = sum(i + 1 for i in range(len(a)) if a[i][1] == 1)
return 1 + (T + 1) / (2 * F) - R / (T * F)

知乎上大神的答案,很高级。

从AUC到真实类别(label)?
最开始思考这个问题是做一个网上的比赛,二分类问题,每次提交一组预测系统会计算出一个AUC值,因为这个比赛只有5000样本,并且系统显示的AUC值有小数点后面7、8位,所以我想是否可以通过可能通过AUC值计算出样本的真实label来。也许并没有实际价值,但是问题本身是很有趣的,像是在破解密码。
一个naive但是可行但是效率很低的办法, 就是每次生成一组预测值,里面只有一个样本预测为1,其余都是0,然后提交预测计算AUC,然后根据这个AUC来判断此样本的label,但是这样效率太低了,5000个样本,需要5000次提交。
思考了很久,最后发现可以通过AUC的另一个计算公式入手。也就是第一部分说的U statistic。 3.1 根据一个AUC值计算样本中0,1的数目
根据AUC与U statistic的联系,我们可以用下面的代码计算AUC:
auc=(sum(rank(c(p(label==1),p(label==0)))[1:n1])-n1*(n1+1)/2)/n0/n1
上面label表示样本的真实类别,p表示预测为1的概率,rank是R的内置函数,n0表示真实数据中0的数目,n1表示1的数目,n0+n1=n表示数据所有样本数目,根据这个简单的一行代码,我们可以不用任何包来计算AUC。
上面公式很有趣,n0,n1还有label都是固定的,p不同导致auc不一致,观察sum里面,可以发现这个sum本质是什么?就是计算pred里面对应的真实label为1的那些预测值的rank的和。
继续使用第一部分的例子,5个样本的预测值的rank:
rank(c(0.5,0.6,0.55,0.4,0.7))[1] 2 4 3 1 5
其中真实为1的样本(1,2,5)的对应rank是2,4,5,这三个rank值的和2+4+5=11,n0=2,n1=3,于是根据上面的AUC公式:(11-3*(3+1)/2)/2/3=5/6=0.83333,这个结果与我们在第一部分用AUC定义算的值完全一样。
所以说,真正影响auc的,就是预测值里面对本来是1的样本的预测的rank的和。
要破解真实label,第一部要做的是找到样本里面0和1的数目,也就是n0和n1等于多少。这个问题不复杂。要知道相同预测值的rank也一致,就是说如果所有样本的预测只取0或者1,那对应的rank只有两个unique数值。
再观察AUC公式里面的sum:
sum(rank(c(pred(label==1),pred(label==0)))[1:n1])
这个sum是n1个数值的和,这n1个数值,当我们的pred只有两个不同取值的时候,仅包括两个unique的数值。继续用上面例子,一共有5个样本,我们生成第一组预测p如下:
> p=c(1,1,1,0,0)> rank(p)[1] 4.0 4.0 4.0 1.5 1.5 可见p的rank只有两个不同取值,1.5和4,这是因为预测概率p也只有两个不同取值。
然后我们还知道sum是n1个数的sum,我们不知道的是这n1个数,里面有几个1.5,几个4,假设其中有k1个1.5,k2个4,可以列出一个方程:
k1+k2=n1
k1*1.5+k2*4=sum(rank(c(p(label==1),p(label==0)))[1:n1])=auc*n0*n1+n1*(1+n1)/2
所以最终得到下面的方程组:
k1+k2=n1
k1*1.5+k2*4=0.833333*n0*n1+n1*(1+n1)/2
n0+n1=5
其中k1,k2和n1未知,两个方程,3个未知数,属于不定方程组,但是要知道k1,k2,和n1都是整数,并且有取值范围,要借出来很简单,写一个for 循环,1秒中就可以找到一组满足3个方程多k1,k2以及n1。
如果我们变更p,比如p=c(rep(1,m),rep(0,5-m)),通过一样的算法,可以计算出来前m个样本中1的数量。
通过这个算法,我可以算出来这个贷款预测比赛测试数据中有509个1和4491个0。
做到这里,差点就放弃了,但是后来突然又有了灵感,找到了下面的算法:
3.2 根据AUC破解样本的真实label
这里就省略思考过程了, 直接来破解算法:
对于一组总数为n的测试样本,我们先来计算
m=floor(log(n,base=2))+1
这个m表示我们通过两次auc计算可以计算出至少多少个样本的真实label,比如n=5000,那么m=13
也就是说通过我们两次提交,可以最少得到13个样本的label。这13个样本是可以自己随便指定的,比如我们对前13个样本感兴趣,那么具体做法如下:
fix1=2^c(0:12)fix2=c(fix1[-1],fix1[1])unfixed=setdiff(1:5000,fix1)p1=c(fix1,unfixed)#第1组预测p2=c(fix2,unfixed)#第2组预测
使用上面的两组预测p1和p2分别计算AUC,得到auc1和auc2,根据上面给出的auc算法:
sum(rank(c(p1(label==1),p1(label==0)))[1:n1])-n1*(1+n1)/2=auc1*n0*n1sum(rank(c(p2(label==1),p2(label==0)))[1:n1])-n1*(1+n1)/2=auc2*n0*n1
两个公式相减:
sum(rank(c(p1(label==1),p1(label==0)))[1:n1])-sum(rank(c(p2(label==1),p2(label==0)))[1:n1])-n1*(1+n1)/2=(auc1-auc2)*n0*n1
得到的这个等式里,我们已经通过上面的方法找到了n0和n1,auc1和auc2是已知,所以等式右面值可以算出,那么等式左面呢,因为我们两个预测结果p1和p2只有前三个点的预测之不一样,其余点的预测值一样,rank也一样,那么等式左面的两个sum的差,其实只由前13个样本的真实label决定,具体来说:
sum1-sum2=y1*(fix1[1]-fix2[1])+y2*(fix1[2]-fix2[2])+...+y13*(fix1[13]-fix2[13])=y1*(-1)+y2*(-2)+...+y12*(-2048)+y13*(4095) 上面的方程里面yi代表样本i的真实label,有且只有唯一解,以为这个方程本质上就是10进制数用2进制表达。所以通过两次auc计算,我们可以找到13个点的真实标签。比如对上面提到的贷款预测比赛,选定前13个label,auc1=0.50220853,auc2= 0.5017588,然后就可以算出来前13个test样本只有第三个样本是0,其余都是1。
但是13并不是上限,我有一些更好的结果,比较复杂,在这就不展开说了。

参考资料

https://www.zhihu.com/question/39840928

理解ROC和AUC的更多相关文章

  1. ROC和AUC理解

    一. ROC曲线概念 二分类问题在机器学习中是一个很常见的问题,经常会用到.ROC (Receiver Operating Characteristic) 曲线和 AUC (Area Under th ...

  2. 机器学习性能指标之ROC和AUC理解与曲线绘制

    一. ROC曲线 1.roc曲线:接收者操作特征(receiveroperating characteristic),roc曲线上每个点反映着对同一信号刺激的感受性. 横轴:负正类率(false po ...

  3. ROC和AUC介绍以及如何计算AUC ---好!!!!

    from:https://www.douban.com/note/284051363/?type=like 原帖发表在我的博客:http://alexkong.net/2013/06/introduc ...

  4. 【转】ROC和AUC介绍以及如何计算AUC

    转自:https://www.douban.com/note/284051363/ ROC(Receiver Operating Characteristic)曲线和AUC常被用来评价一个二值分类器( ...

  5. 评估分类器性能的度量,像混淆矩阵、ROC、AUC等

    评估分类器性能的度量,像混淆矩阵.ROC.AUC等 内容概要¶ 模型评估的目的及一般评估流程 分类准确率的用处及其限制 混淆矩阵(confusion matrix)是如何表示一个分类器的性能 混淆矩阵 ...

  6. ROC与AUC学习

    全文转自:https://www.cnblogs.com/gatherstars/p/6084696.html#commentform 这篇真的讲的清楚明白!要多复习!加深记忆! 1.概述 AUC(A ...

  7. 机器学习-Confusion Matrix混淆矩阵、ROC、AUC

    本文整理了关于机器学习分类问题的评价指标——Confusion Matrix.ROC.AUC的概念以及理解. 混淆矩阵 在机器学习领域中,混淆矩阵(confusion matrix)是一种评价分类模型 ...

  8. 【分类问题中模型的性能度量(二)】超强整理,超详细解析,一文彻底搞懂ROC、AUC

    文章目录 1.背景 2.ROC曲线 2.1 ROC名称溯源(选看) 2.2 ROC曲线的绘制 3.AUC(Area Under ROC Curve) 3.1 AUC来历 3.2 AUC几何意义 3.3 ...

  9. ROC and AUC

    目录 概 TPR, FPR ROC and AUC 代码 ROC-wiki 概 AUC常常在文章中作为评价一个分类器优劣的指标, 却总是忘记其原由, 索性记上一笔. TPR, FPR 首先理解TP, ...

随机推荐

  1. select点击option获取文本输入框的焦点事件

    HTML文件: <select id="secOrderNum" style="margin-bottom:10px;width:90px;" data- ...

  2. [JQuery] jQuery选择器ID、CLASS、标签获取对象值、属性、设置css样式

    reference : http://www.suyunyou.com/aid1657.html jQuery是继prototype之后又一个优秀的Javascrīpt框架.它是轻量级的js库(压缩后 ...

  3. Glusterfs初试

    Gluster的模式及介绍在此不表,这里只记录安装及配置过程. 1.整体环境 server1 : gfs1.cluster.com server2 : gfs2.cluster.com Client: ...

  4. go语言基础之copy的使用

    1.copy的使用 示例: package main //必须有个main包 import "fmt" func main() { srcSlice := []int{1, 2} ...

  5. (转)U3D DrawCall优化手记

    自:http://www.cnblogs.com/ybgame/p/3588795.html 在最近,使用U3D开发的游戏核心部分功能即将完成,中间由于各种历史原因,导致项目存在比较大的问题,这些问题 ...

  6. PREEMPT_RT的未来

    因为开发资金的问题,Thomas Gleixner宣布他已经不想干了. 商业公司往往用了PREEMPT_RT的功能去不愿意去回报社区,那就自己弄吧. http://lwn.net/Articles/6 ...

  7. socketio server推送

    假设面试官问你:要把server端的数据时时显示在浏览器上怎么实现?我想有非常多人会回答使用Ajax技术定时去訪问一个资源,没错,使用Ajax的确能实现.但面试官要的绝对不是这个答案. 由于使用Aja ...

  8. 控制系统音量,自己定义MPVolumeView

    近期有一个需求,就是控制系统的音量,我们都知道原理在mediaPlayer.framework框架下,有方法 <span style="font-size:18px;"> ...

  9. 在Foreda8中整合Apche httpd2.4.6和Tomcat7.0.42(使用tomcat-connectors-1.2.37)

    本地Apche httpd2.4.6(http://pan.baidu.com/share/link?shareid=4003375081&uk=34256769)和Tomcat7.0.42是 ...

  10. 【已解决】Python脚本运行出现语法错误:IndentationError: unindent does not match any outer indentation level

    转自:http://www.crifan.com/python_syntax_error_indentationerror/comment-page-1/ [问题] 一个python脚本,本来都运行好 ...