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

方法一:概率定义法

从正样本中随机选取元素记为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. NLP十大里程碑

    NLP十大里程碑 2.1 里程碑一:1985复杂特征集 复杂特征集(complex feature set)又叫做多重属性(multiple features)描写.语言学里,这种描写方法最早出现在语 ...

  2. Maven中<dependencies>节点和<dependencyManagement>节点的区别

    dependencyManagement只是插件管理,并不是真正的插件依赖,所以里面包含的插件在没有子项目使用的时候,并不会真正下载 1 .使用项目继承 利用项目继承可以将结构信息,部署信息,共同的依 ...

  3. 为apache安装mod_wsgi的时候出现-fpic的问题

    1.为了在apache里跑python项目,需要安装模块mod_wsgi 2.但是由于yum只支持python2.6,所以通过yum install mod_wsgi方式安装的mod_wsgi是pyt ...

  4. 【BZOJ】【2850】【Violet 0】巧克力王国

    KD-Tree 问平面内在某条直线下方的点的权值和 我一开始yy的是:直接判这个矩形最高的两个点(y坐标的最大值)是否在这条直线下方就可以了~即判$A*x+B*y<C$... 然而这并不对啊…… ...

  5. " 初窥 " nginx

    1. 无题 第一次听到Nginx这个词,还是两年前的事儿了,最近常逛CSDN,越来越频繁的接触到这个词汇,今天看了些资料,简单的总结下,作为入门. 2. 背景介绍: Nginx (发音同 engine ...

  6. COM中的几个基本概念

    类厂 组件结构示例 DllGetClassObject COM库与类厂的交互

  7. [Algorithm] Largest sum of non-adjacent numbers

    Given a list of integers, write a function that returns the largest sum of non-adjacent numbers. Num ...

  8. Pinger2

    import java.io.IOException;import java.io.InputStreamReader;import java.io.LineNumberReader;import j ...

  9. (算法)判断字符串中是否包含HelloWorld

    题目: 给定某字符串,判断该字符串中是否包含HelloWorld,出现HelloWorld不一定要连续,但顺序不变,如“HeByello,ByeWorByeld”就包含“HelloWorld”. 思路 ...

  10. Android 之 AndroidManifest.xml 详解(一)

    当Android启动一个应用程序组件之前,它必须知道哪些个组件是存在的,所以开发人员在开发过程中,必须将应用程序中出现的组件一一在AndroidManifest.xml文件中" 声明 &qu ...