AUC计算及为何不受样例不均衡的影响

本文详细介绍了AUC(Area Under Curve)和ROC曲线的概念,强调AUC作为衡量分类器性能的指标,优于ROC曲线的直观性。AUC计算包括直接计算pair对和求ROC曲线下的面积两种方法。此外,文章探讨了AUC为何在正负样本不均衡的数据集中仍能有效评估模型,并通过实例说明AUC不受样本比例影响。最后,分析了负样本增多可能提高AUC的原因,并提及数据增强和采样的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

脚注:以下内容仅是闲暇时遇到问题的总结,便于日后查看。如有不对地方,还请及时指正。

1. AUC定义

定义

AUC(Area Under Curve)主要作用是衡量学习器优劣的一种性能指标,其被定义为ROC曲线下与坐标轴围成的面积。
那这里为什么不用ROC曲线直接作为衡量学习器优劣的指标呢?其实是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好(因为它只是个曲线,不易拿来对比),而AUC作为一个数值,数值越大代表分类器效果越好,易量化。

ROC曲线

ROC曲线全称为受试者工作特征曲线 (receiver operating characteristic curve),它是根据一系列不同的二分类方式(分界值或决定阈),以真阳性率(TPR)为纵坐标,假阳性率(FPR)为横坐标绘制的曲线。

(1)名词定义
  • 真阳性率[TPR]: 正确预测为正例个数/所有正例个数
    TPR=TPTP+FNTPR = \frac{TP}{TP+FN}TPR=TP+FNTP
  • 假阳性率[FPR] : 错误预测为正例个数/所有负例个数
    TPR=FPTN+FPTPR = \frac{FP}{TN+FP}TPR=TN+FPFP
(2)几何解释

ROC
ROC曲线的形成,就是将确定正负样例标签的阈值α\alphaα从0->1按照一定步长取一遍,分别在每个阈值点上计算出(TPR, FPR),进而可形成一条曲线。这里其实就暗示了后面计算AUC的一种方式,几何方式求曲线下的面积。
如上图可以看到,我们的理想点(0,1)。如果这条曲线往理想点靠近,即曲线弯曲成都是要往左上角靠近的,它的曲线下面积越大。

思考: 理想状态点出现,即意味着我们学习器中所有正样本预测分 > 负样本预测分,当阈值α∈(max(负样本得分),min(正样本得分))\alpha \in (max(负样本得分), min(正样本得分))α(max(),min()),曲线必然可以抵达理想点;换句话说,只要当我们预测出来
merit=#{samplePair:satisfy(正样本得分>负样本得分)}merit = \#\{samplePair: satisfy(正样本得分>负样本得分)\}merit=#{samplePair:satisfy(>)}merit数值越大,越是表明当前获得的学习器效果好.

2. AUC计算

因为AUC计算方法目前主要看到有三种,下面主要是摘抄常用的两种方法:

(1) 方法一 :直接计算pair对

首先用学习器预测出每个样本的分类预测分pi^\hat{p_i}pi^, 对{pi^,i=1,2,3,…,n}\{\hat{p_i}, i=1,2,3,\dots,n\}{pi^,i=1,2,3,,n}升序排列,获得其对应排序分为:{ri,i=1,2,3,…,n}\{r_i, i=1,2,3,\dots,n\}{ri,i=1,2,3,,n}备注:n=M+N,其中M为正样本个数,N为负样本个数.n = M + N, 其中M为正样本个数,N为负样本个数.n=M+N,MN.

则:AUC=Σsamplei∈positiveSampleri−M∗(M+1)2M∗NAUC = \frac{\Sigma_{sample_i \in positiveSample}r_i - \frac{M*(M+1)}{2}}{M*N}AUC=MNΣsampleipositiveSampleri2M(M+1)备注:这里的计算方法其实就是在计算上述所说的merit数值大小.

(2) 方法二 :求ROC曲线下的面积

计算脚本见下方(借鉴同事脚本),当时这里我还真想了下,具体是如何计算的梯形面积的?下面提出几个注意的点:

首先,这段代码较好的是减少了一次排序,试想如果数据量非常大的时候,排序是非常耗时的方式,这是个比较精妙的地方。

其次,这里的bucket_size可以设计的足够大,回想大学学积分那会,我们总希望梯形分割越多越好,越是能逼近真实曲线下的面积(上限为样本数,再大无意)。

最后,为什么计算梯形面积是从bucket号从大到小?其实这样才能使得我们计算的梯形面积是从横轴的左向右。回头看一下上面手稿图,我们的(0,0)点实际上是threadhold=1threadhold=1threadhold=1, 也即阈值是非常大的,而编码序号大的bucket意味着高threashold。

附上脚本如下:

def cal_auc(label_list, p_list, bucket_size):
    bucket_list = {}
    for idx, pi in enumerate(p_list):
        if bucket_list.get(int(pi*bucket_size), {}) == {}:
            bucket_list[int(pi*bucket_size)] = {}
            bucket_list[int(pi*bucket_size)][0] = 1-label_list[idx]
            bucket_list[int(pi*bucket_size)][1] = label_list[idx]
        else:
            bucket_list[int(pi*bucket_size)][label_list[idx]] += 1
    
    area = 0
    fp = 0
    tp = 0
    for i in range(bucket_size , -1, -1):
        if bucket_list.get(i,{})=={}:
            continue
        newfp = fp + bucket_list[i][0]
        newtp = tp + bucket_list[i][1]
        area += (newfp -fp) * (tp + newtp) / 2.0
        fp = newfp
        tp = newtp
    
    auc = area / ( fp * tp )
    
    return " ".join(["%s"%auc, "%s"%( tp + fp) ])

3. AUC为何对正负样例不均衡的数据集评价有效?

在很多排序场景下,尤其是当前许多数据集正负样例都不太均衡;或者说因训练集过大,可能会对数据进行负采样等操作。这擦操作的前提是建立在AUC值不会受到正负样本比例的影响。看过很多博客也都在讨论:为什么AUC不会受正负样例不平衡的影响?为什么排序喜欢选择AUC作为评判指标。

一方面,从AUC定义来解释,它是比较“正样本预测分 & 负样本预分”数值相对大小关系。如若数据比例不同,模型预测分预测值绝对大小会因此而改变,但是相同分类器对于正负样本的区分能力是一定的。

另一方面,有人拿出实践证明:不采样数据集( 不对负样本采样),对比进行负采样数据集。计算出来的AUC不同,发现负样本越多(即不采样)的数据集AUC数值越高。

下面我们对一个Random分类器,从AUC计算公式角度推导下:AUC是否受样本不均衡影响。

AUC推导
从上面的推导来看的话,貌似不管是正负样本比例是多少,确实好像不会影响到AUC的变化。那么讨论区童鞋说到的为什么负样本增多,AUC还变好了呢?

我之前实践过这个事情,现象也如其所说。思考了下:
首先,在图像分类中,都会采用各种花式数据增强。包括现在一些APP排序也开始这么做,主要是去解决一些debias的问题。这么做的背景是:增加样本的丰富性,让模型见更多的“世面”,以便学习的更好。
其次,我们对数据集进行采样的时候,本身就是比较高难度的事情,采样如何做到公平是非常trick的。现在也有很多文章也在讨论这个话题。

### AUC、ACC、F1、准确率、召回率的应用场景及计算方式 #### 一、AUC (Area Under the Curve) AUC表示ROC曲线下方的面积,其取值范围通常在0.5到1之间。这一指标用于评估二元分类器的整体性能,在不同阈值下综合考虑真正率(True Positive Rate, TPR)和假正率(False Positive Rate, FPR)[^2]。 对于实战应用而言,当面对数据集不平衡的情况时,即某一类别样本显著多于另一类别,此时使用AUC作为评价标准更为合理。因为即使模型预测大多数为多数类也能获得较高的准确度,但这并不代表模型具有良好的泛化能力。而通过观察整个ROC曲线及其下方区域大小(AUC),可以更全面地理解模型区分两类的能力。 Python代码实现: ```python from sklearn.metrics import roc_auc_score import numpy as np # 假设y_true是真实标签,y_scores是概率估计或决策函数得分 auc_value = roc_auc_score(y_true, y_scores) print(f"AUC Value: {auc_value}") ``` #### 二、ACC (Accuracy) 准确性指的是被正确分类的数据点所占比。尽管简单易懂,但在处理不均衡数据集时可能会给出误导性的高分。因此,在某些情况下可能不是最佳的选择。 计算公式: \[ \text{Accuracy}=\frac{\text{TP+TN}}{\text{P+N}}\] 其中 TP 表示 True Positives(真阳性),TN 表示 True Negatives (真阴性), P 和 N 分别指代总共有多少个正和反。 Python代码实现: ```python from sklearn.metrics import accuracy_score accuracy = accuracy_score(y_true, y_pred) print(f"Accuracy Score: {accuracy:.4f}") ``` #### 三、F1-Score F1值是对Precision(精度)与Recall(召回率)的一种加权调和平均数,能够平衡两者之间的关系并提供更加稳健的结果。特别是在存在类别失衡的情况下,F1分数往往比单独依赖 Precision 或 Recall 更具代表性[^1]。 计算公式: \[ F_1=2\times(\frac{{Precision}\times{Recall}}{{Precision}+{Recall}})\] Python代码实现: ```python from sklearn.metrics import f1_score f1 = f1_score(y_true, y_pred, average='binary') print(f"F1 Score: {f1:.4f}") ``` #### 四、Recall (召回率) 召回率反映了模型识别所有实际存在的正向实的能力。具体来说就是从所有真实的正中找出的比有多少被成功检测出来了。这对于那些误报成本较低但是漏检代价高昂的任务非常重要,比如医疗诊断领域中的疾病筛查等[^3]。 计算公式: \[ \text{Recall}= \frac{\text{TP}}{\text{TP + FN}}\] 这里FN代表False Negatives(假阴性) Python代码实现: ```python recall = recall_score(y_true, y_pred, average='binary') print(f"Recall Score: {recall:.4f}") ``` #### 五、Precision (精确率) 精确率关注的是在所有被判定为正向的子中有多少确实是真正的正向案。它适用于希望减少错误肯定情况发生的场合,如垃圾邮件过滤系统里尽可能避免把正常邮件错判成垃圾邮件[^4]。 计算公式: \[ \text{Precision}=\frac{\text{TP}}{\text{TP + FP}}\] FP表示False Positives(假阳性) Python代码实现: ```python from sklearn.metrics import precision_score precision = precision_score(y_true, y_pred, average='binary') print(f"Precision Score: {precision:.4f}") ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值