AUC面试

2021-07-20  本文已影响0人  Jarkata

目录

  1. 混淆矩阵
  2. ROC曲线
  3. AUC定义
  4. AUC计算
  5. AUC 优点和缺点
  6. AUC的python实现代码

1. 混淆矩阵

混淆矩阵是了解AUC的必要前提。它是一个总结分类器所得结果的矩阵,一般为k行k列(k为分类的类别数)。以二分类为例,混淆矩阵如下图所示。

首先牢记这2个公式:

2. ROC曲线

ROC曲线是Receiver Operating Characteristic Curve的简称,中文名是受试者工作特征曲线。
这一节主要来学如何绘制ROC曲线
(1) 首先,ROC曲线的横坐标是假阳性率FPR,纵坐标是真阳性率TPR。怎么计算上一节已详述。
(2) 其次,明确计算AUC的时候,预测值y_pred一般都是[0, 1]的小数(代表预测为正样本的概率),真实值y_true为0或1。如果计算FPR和TPR,我们就需要知道预测的正负样本情况,但给的预测值是小数,如何划分预测的正负样本呢?答案是选取截断点
(3) 截断点是指区分正负预测结果的阈值。比如截断点=0.1,那就表示y_pred<0.1的为预测为负样本,y_pred>=0.1预测正样本。所以绘制AUC曲线需要不断移动“截断点”来得到所有的(FPR,TPR)点,然后把这些点用线段连起来就是ROC曲线了。
(4) 截断点取值为\{ +\infty , -\infty}就够了。+ \infty表示所有都预测为负样本,(fpr,tpr)=(0,0)。
-\infty表示所有都预测为正样本,(fpr,tpr)=(1,1)。也就是这两个坐标点固定有,所以一般截断点默认取值就是预测值的所有唯一值。
如何绘制,如下图所示:

ROC曲线,横坐标FPR,纵坐标TPR

3. AUC定义

AUC(Area Under ROC Curve),顾名思义,即ROC曲线下的面积
AUC越大,说明分类器越可能把正样本排在前面,衡量的是一种排序的性能
那么问题来了,ROC曲线下的面积怎么就能衡量分类器的排序能力?且听慢慢道来。

如果ROC面积越大,说明曲线越往左上角靠过去。那么对于任意截断点,(FPR,TPR)坐标点越往左上角(0,1)靠,说明FPR较小趋于0(根据定义得知,就是在所有真实负样本中,基本没有预测为正的样本),TRP较大趋于1(根据定义得知,也就是在所有真实正样本中,基本全都是预测为正的样本)。并且上述是对于任意截断点来说的,很明显,那就是分类器对正样本的打分基本要大于负样本的打分(一般预测值也叫打分),衡量的不就是排序能力嘛!

So,现在可以给一个比较常用的AUC的定义
即:随机从正样本和负样本中各选一个,分类器对于该正样本打分大于该负样本打分的概率

4. AUC计算

AUC如果按照原始定义ROC曲线下的面积来计算,非常之麻烦。

可以转换一下思路,按照上述给出的常用的AUC定义,即随机选出一对正负样本,分类器对于正样本打分大于负样本打分的概率。咱们就来算算这个概率到底是多少,那么也就算出AUC是多少了。

假设数据集一共有M个正样本,N个负样本,预测值也就是M+N个。我们将所有样本按照预测值进行从小到大排序,并且排序编号由1到M+N。

那么在所有情况下,正样本打分大于负样本的个数=
rank_1+rank_2+...+rank_M -(1+2+...+M)
所以,AUC的正式计算公式也就有了,如下:

rank(i)表示正样本i的编号,MXN表示随机从正负样本各取一个的情况数。一般考代码题,比如用python写个AUC计算,也是用上述公式原理。

但是,还没有完,有一个小问题,可能大家没注意到。那就是如果有预测值是一样的,那么怎么进行排序编号呢?

其实很简单,对于预测值一样的样本,我们将这些样本原先的排号平均一下,作为新的排序编号就完事啦。仔细理解可看下图:

上图中,正样本个数M=5,负样本个数N=3,预测值相同有4个。我们将预测值pred相等的情况(上图红色字体),对其进行新的排序编号,变成4.5。

那么根据公式就可以算出上图中的AUC=


用sklearn的auc计算验证一下,一样。

所以,你掌握了吗?
掌握了的话,可看看这里给出的笔者经历的腾讯面试题。

有一堆样本,其中2000个负样本,8000个正样本,其中负样本的预测值为均匀分布U(0.4, 0.6),正样本的预测值为均匀分布U(0.5, 0.7)。求AUC。需要给出详细解答过程。(答案可翻到最后)

5. AUC的有点和缺点(八股)

优点:

缺点:

  1. AUC的Python实现代码
    AUC的具体计算公式都给了,理解了其中逻辑,实现起来就比较容易了。代码如下,核心代码也就10行左右:
import numpy as np
import pandas as pd

# 正例
y_pred = list(np.random.uniform(0.4,0.6,2000))+list(np.random.uniform(0.5,0.7,8000))
# 负例
y_true = [0] * 2000 + [1]*8000

def calc_auc(y_true, y_pred):
    pair = list(zip(y_true,y_pred))
    pair = sorted(pair, key = lambda x:x[1]) # 进行排序
    df = pd.DataFrame([[x[0],x[1],i+1] for i,x in enumerate(pair)],
    columns=['y_true','y_pred','rank'])
    # 下面需要将预测值为一样的进行重新编号
    for k,v in df.y_pred.value_counts().items():
        if v==1: # 说明该预测值k只出现了一次,没有重复,不考虑
            continue
        rank_mean = df[df.y_pred==k]['rank'].mean()
        df.loc[df.y_pred==k, 'rank'] = rank_mean
    
    pos_df = df[df.y_true==1] # 正样本的表
    m = pos_df.shape[0] # 正样本数
    n = df.shape[0]-m # 负样本数
    return (pos_df['rank'].sum()-m*(m+1)/2)/(m*n)

print(calc_auc(y_true,y_pred))

from sklearn.metrics import roc_auc_score
print(roc_auc_score(y_true,y_pred))

看完上述结果,你应该知道了上面的腾讯面试题结果是什么了(7/8,几何概率模型)


上一篇下一篇

猜你喜欢

热点阅读