深度学习auc_机器学习入门之AUC理解和Python实现

本文介绍了AUC作为二分类问题评价指标的重要性,并通过一个垃圾邮件分类的例子阐述了AUC无需预先设定阈值的优势。文章详细解释了ROC曲线的生成过程,以及AUC的直观理解——正样本概率高于负样本的概率比例。最后,提供了AUC的Python计算代码,展示了如何利用排列组合思想求解AUC。
摘要由CSDN通过智能技术生成

稍微了解机器学习或深度学习的同学,应该对AUC不陌生,它算是二分类问题中最为常用的评价指标之一。之所以专门写文章来解释其含义,是因为上次面试时被问到如何自己用代码实现AUC时没有答上来,才发现自己一直是似懂非懂的状态。痛定思痛,决定写一篇文章来解释AUC的含义以及给出详细的Python代码实现

除了AUC之外,二分类场景里用得更多的一个评价指标是accuracy,也就是准确率。比方说经典的用朴素贝叶斯模型去预测邮件是否是垃圾邮件的场景,我们先假设在现实生活中正常邮件和垃圾邮件出现的比例是接近1:1。在模型训练好之后,每来一个样本,我们会用已训练好的模型去预测这个样本是垃圾邮件的概率,所以每个样本都会有一个对应的预测结果prob(概率):当prob > 0.5时,认为对应的样本(邮件)是垃圾邮件,此时令该样本的label为1

当prob < 0.5时,认为对应的样本(邮件)不是垃圾邮件,此时令该样本的label为0

然后我们就根据预测出来的label和样本真实的label是否相等来计算准确率,准确率越高,我们认为模型的效果越好

也就是说,计算准确率我们需要知道每个样本对应的预测label,而为了获得label,我们需要人为指定一个阈值来对prob进行划分对吧,那为什么上面的例子里阈值是0.5呢?为啥不能设置成0.6、0.7,甚至0.9?

答案当然是可以!!!这个值是人为给定的。但是你会发现,当阈值设定为0.5的时,最终计算出的accuracy会不错,比方说80%;但是如果你随便设定阈值为一个其他值,比方说0.9,你会发现accuracy会很低,也是说即使是相同的模型,选择不同的阈值,最终从准确率上看模型的性能会差别很大

究竟阈值设置成多少会比较合适呢?一般情况下应该设置成先验概率:在上面垃圾邮件分类的例子里,这个先验概率是样本里所有垃圾邮件的个数/总邮件的个数,前面提到假设在现实生活中正常邮件和垃圾邮件出现的比例是接近1:1,那么这个先验概率值就是0.5。但是不幸的是,现实中往往会因为可获得的样本过少等原因,导致在这些样本上统计得到的先验概率是有偏的,从而得到一个不是那么合理的阈值,无法反映模型的真实性能

有没有什么评价指标不需要给定阈值呢?AUC就是,它是基于对样本的预测概率进行排序后计算得到的,所以并不需要知道阈值,具体怎么排序怎么计算,稍后会结合代码详细解释,这里先说说怎么理解auc

AUC(Area Under Curve)被定义为ROC曲线下的面积。其中,ROC曲线全称为受试者工作特征曲线 (receiver operating characteristic curve),它是根据一系列不同的二分类方式(分界值或决定阈),以真阳性率(敏感性)为纵坐标,假阳性率(1-特异性)为横坐标绘制的曲线,我从百度上截取了一段关于ROC曲线的示例:

这个应该我们最常见到的关于auc的解释。TPR和FPR的计算公式我就不写了,网上很多。这里简单解释下这个图是怎么画出来的:

假设你的数据有两部分,一部分是预测值probs,例如:probs = [0.9, 0.8, 0.6, 0.7, 0.95];另外一部分是对应的labels,例如:labels = [1, 1, 0, 1, 0]。注意,以下思路或者伪代码都是以Python的形式给出先将probs和labels组成一个tuple(暂且命名为t)

以probs为key对t从大到小进行排序,例如排序后 t = [(0.95, 0), (0.9,1), (0.8,1), (0.7,1), (0.6,0)]

按probs从高到低计算阈值,过程如下:第一个阈值为1(其实这个阈值只要大于0.95即可),大于该阈值的视为正例,小于该阈值为负例,然后按公式计算TPR和FPR,得到ROC图上的一个坐标,此时TPR和FPR都为0

第二个阈值为(0.95+0.9)/2, 大于该阈值的视为正例,小于该阈值为负例(实际这个阈值只要是小于0.95且大于0.9即可,不一定要是均值),然后按公式计算TPR和FPR,得到ROC图上的第二个坐标

第三个阈值为(0.9+0.8)/2, 大于该阈值的视为正例,小于该阈值为负例,然后按公式计算TPR和FPR,得到ROC图上的第三个坐标

重复上述过程,最后一个阈值为0(其实这个阈值只要比probs的最小值小即可),依然是大于该阈值的视为正例,小于该阈值为负例,此时所有样本都被判定为正例,按公式计算TPR和FPR可知,TPR=FPR=1,得到ROC图上的最后一个坐标

也就是说,ROC曲线肯定是从坐标(0,0)到坐标(1,1)的一条曲线,而曲线越靠近左上角,说明正样本中混入的负样本越少,模型对正负样本的区分能力越强,此时ROC曲线下方的面积越大;当给定某一个阈值时,正负样本刚好被隔开,即预测值大于该阈值的刚好都是正样本,预测值小于该阈值的刚好都是负样本,这个模型就可以认为是一个完美的模型,此时ROC曲线下方的面积就是1。至于这个完美的阈值是多少,我们并不需要知道,只需要存在这样一个阈值就行了

看完上面的解释是不是对AUC有一些理解了?但是如果现在要你自己写一个函数去实现AUC的计算,该怎么写?你该不会去计算曲线下方的面积吧?

别慌,我们先从概率的角度再去理解下AUC:假设有M个正样本和N个负样本

从M个正样本中随机抽取一个样本a,其prob为p_a, 然后从N个负样本中随机抽取一个样本b,其prob为p_b,这样一共有

个抽取结果,每个抽取结果是一个pair (p_a, p_b)

假设所有抽取结果中有K个结果满足p_a > p_b,那么

这么理解的话,AUC的计算就变成一个比较简单的排列组合问题了。通过上面这种方式,我们很容易就能计算AUC:

import numpy as np

from collections import Counter

class Metrics(object):

@classmethod

def auc(cls, labels, probs):

c = Counter(labels)

pos_cnt, neg_cnt = c[1], c[0]

t = sorted(zip(probs, labels), key=lambda x: (x[0], x[1]), reverse=True)

pos_than_neg, find_neg = 0, 0

tmp_set = set()

for i in range(len(t)):

"""处理多个样本的预测概率值相同的情况"""

if i + 1 < len(t) and t[i][0] == t[i + 1][0]:

tmp_set.add(i)

tmp_set.add(i + 1)

continue

if len(tmp_set) > 1:

c = Counter([t[i][1] for i in tmp_set])

pos, neg = c[1], c[0]

find_neg = find_neg + neg

pos_than_neg += pos * (neg_cnt - find_neg + neg / 2)

tmp_set.clear()

continue

if t[i][1] == 1:

pos_than_neg += (neg_cnt - find_neg)

else:

find_neg += 1

return 1.0 * pos_than_neg / (pos_cnt * neg_cnt)

通过抽样的方式来解释AUC,其实跟上面通过ROC曲线下的面积来理解AUC是异曲同工的:假设所有正样本的预测概率值都是分布在0.6-1.0这个区别,那么0.6-1.0这个区间里混入的负样本越少,表明模型对正负样本的区分能力越强,ROC曲线越靠近左上角,满足p_a > p_b的K越大,AUC越大;相反,0.6-1.0这个区间里混入的负样本越多,表明模型对正负样本的区分能力越差,ROC曲线越靠近对角线,满足p_a > p_b的K越少,AUC越小

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值