AUC这三个字,搞机器学习的人几乎天天挂嘴边,但真要问一句"AUC到底怎么算出来的",很多人会愣一下。平时都是调包,sklearn里一行roc_auc_score就完事了,模型调参、论文画图、业务汇报,全是它在撑场面。
但干这行越久,越发现光会调包是不够的。最近在一次模型评审会上,我被问到一个很刁钻的问题:你的AUC是0.83,这个数字的置信区间是多少?样本量变化之后它会不会大幅波动?我当时虽然把问题圆了过去,但心里清楚一件事——如果连AUC的计算原理都没吃透,拿什么去回答这类问题。
这篇文章想跟你彻底聊聊AUC的三种计算方法。不是教科书式的推导堆砌,而是从一个实际使用的角度出发,给你讲清楚:第一条路是从定义出发的几何法,直接对ROC曲线下的面积做积分;第二条路是概率论视角,把AUC等价成"随机正样本得分高于随机负样本的概率";第三条路是工程实践视角,基于排序和秩次,用最少的计算量拿到结果。三种方法名不同、路子不同,但算出来的是同一个数字——理解这一点,你才算真正拿捏住了AUC。
无论你是刚入门不久的新手,还是已经用AUC调过无数个模型的老手,这篇文章都能帮你把AUC从"会用"提升到"懂它"。后面我会用一组实际数据,把三种方法全部手算一遍,保证你跟着走完一遍,心里彻底有底。
1. 为什么一个指标要搞出三条计算路线
先说个基本判断:AUC这个指标之所以有"三种计算方法",根本原因在于它本身可以从三个维度被定义。这就像描述一个人,你可以说他身高175厘米,可以说他体重70公斤,也可以说他体脂率15%——虽然描述维度不同,但指的都是同一个人。AUC的三个定义分别是几何定义、概率定义和统计定义,每一种定义都对应一条独特的计算路径。
1.1 先搞清楚AUC到底在衡量什么
在展开计算方法之前,必须先建立对AUC本身的理解。AUC的全称是Area Under the ROC Curve,即ROC曲线下的面积。ROC曲线的横轴是假正例率(FPR),纵轴是真正例率(TPR),曲线上的每一个点对应一个分类阈值。AUC就是把这条曲线从(0,0)到(1,1)围出来的面积数值化。
但这里有个更直觉化的理解方式,也是我在实际项目里给业务同学讲AUC时最常用的说法:AUC表示模型把正样本排到负样本前面的概率。假设你手上有一个正样本和一个负样本,模型分别给它们打了分,AUC就是"正样本得分高于负样本得分"的概率。如果AUC等于0.5,说明模型完全靠猜;如果AUC等于1,说明模型能完美地把所有正样本排在所有负样本前面。
这个理解之所以重要,是因为它直接引出了"排序"这个关键词。AUC本质上关心的是模型对样本的排序能力,而不是具体的分数绝对值。你给所有样本的分数统一加10或者统一除以2,AUC完全不变。这一点在做模型融合、分数校准的时候特别关键,我后面还会再提。
1.2 三条路线的技术脉络与适用差异
第一条是几何路线,也是最符合定义的计算方式。做法是先根据模型的预测分数,对每个可能的阈值计算TPR和FPR,画出ROC曲线,然后用积分(工程上一般用梯形法)求曲线下的面积。这条路最直观,但在样本量大的时候计算开销比较高,因为要遍历所有可能的阈值。
第二条是概率路线,利用的是AUC的概率等价定义。计算时把样本两两配对,一个正样本配一个负样本,统计"正样本分数高于负样本分数"的比例。这条路计算量是O(n²)级别,因为需要遍历所有正负样本对。但它的意义不在于效率,而在于提供了一种从概率角度理解AUC的途径,也方便推导AUC的方差和置信区间。
第三条是统计路线,也就是秩和法。它把概率法转化成了基于排序的计算——只需要对所有样本的分数排一次序,然后对正样本的秩求和,就能得到AUC。计算复杂度从O(n²)降到了O(n log n),工程上最常用。scikit-learn等库内部实现也基本是走这条路。
你可能会注意到,三条路线的计算复杂度是逐步下降的:几何法要遍历所有阈值,概率法要遍历所有正负样本对,秩和法只需要一次排序。这也解释了为什么在大规模数据场景下,真正高效的实现一定是秩和法。
2. 方法一:基于定义——ROC曲线下的几何面积
这一节我们从最"原始"的计算方式开始,也就是严格按照定义,绘制ROC曲线并求曲线下的面积。这个方法虽然工程效率不高,但它是另外两种方法的基石,也是理解AUC含义的起点。
2.1 ROC曲线到底怎么画
画ROC曲线的核心是"遍历阈值"。假设你有一个已经训练好的二分类模型,对10个样本输出了10个预测分数。现在你把阈值从最高分往最低分滑动,每滑到一个位置,就把"分数大于等于阈值"的样本判为正类,其余判为负类,然后计算当前阈值下的TPR和FPR。
这里有两个关键定义需要先钉死:
- TPR(真正例率)= TP / (TP + FN),也就是所有真实正样本中,被正确预测为正类的比例。这个指标关注的够不够全。
- FPR(假正例率)= FP / (FP + TN),也就是所有真实负样本中,被错误预测为正类的比例。这个指标关注的是误伤程度。
每取一个阈值,就得到一对(FPR, TPR),把它作为一个点画在二维坐标系里。阈值从最高滑到最低,点就连成了ROC曲线。
为了让你真正看明白,我构造一组具体的示例数据。假设某风控模型的预测结果如下,共10个样本,4个真实正样本(标签为1),6个真实负样本(标签为0):
| 样本编号 | 真实标签 | 预测分数 |
|---|---|---|
| 1 | 1 | 0.9 |
| 2 | 1 | 0.8 |
| 3 | 0 | 0.7 |
| 4 | 1 | 0.6 |
| 5 | 0 | 0.5 |
| 6 | 0 | 0.4 |
| 7 | 1 | 0.3 |
| 8 | 0 | 0.2 |
| 9 | 0 | 0.1 |
| 10 | 0 | 0.0 |
我们从阈值1.0开始往下滑。当阈值大于0.9时,没有样本被判为正,TP和FP都为0,所以点为(0, 0)。当阈值设在0.9和0.8之间(实际代码里常用前后两个预测分数的中点作阈值),只有样本1被预测为正,它确实是正样本,所以TP=1,FP=0,此时TPR=1/4=0.25,FPR=0/6=0,点为(0, 0.25)。继续往下滑,阈值在0.8和0.7之间时,样本1和样本2被判为正,两者都是真实正样本,TPR=0.5,FPR=0。
阈值继续降低,跨过0.7后,样本3(真实负样本)也被判为正,此时TP还是2,但FP变成了1,TPR=0.5不变,FPR=1/6≈0.1667。你注意到没有——ROC曲线在某个点上的变化,完全取决于滑过阈值时遇到的是正样本还是负样本。遇到正样本,TPR上升,曲线向上走;遇到负样本,FPR上升,曲线向右走。把全部阈值走完,就得到了完整的ROC曲线。
2.2 梯形积分法求面积
绘出ROC曲线之后,求曲线下面积用的标准方法是梯形积分法。原理很简单:把曲线下的区域切成一个个小梯形,分别求每个梯形的面积再求和。
我接着用上面的示例数据来手算。把前面每一步得到的(FPR, TPR)点按顺序列出来:
(0, 0) → (0, 0.25) → (0, 0.5) → (0.1667, 0.5) → (0.1667, 0.75) → (0.3333, 0.75) → (0.5, 0.75) → (0.5, 1) → (0.6667, 1) → (0.8333, 1) → (1, 1)
注意到有些点之间横坐标没有变化(比如(0,0)到(0,0.25)),说明这段时间阈值滑过的都是正样本,FPR没动。梯形面积公式是(fpr[i+1] - fpr[i]) * (tpr[i+1] + tpr[i]) / 2,逐段计算:
- 从(0,0)到(0,0.25):宽度0,面积0
- 从(0,0.25)到(0,0.5):宽度0,面积0
- 从(0,0.5)到(0.1667,0.5):宽度0.1667,平均高度0.5,面积 = 0.0833
- 从(0.1667,0.5)到(0.1667,0.75):宽度0,面积0
- 从(0.1667,0.75)到(0.3333,0.75):宽度0.1667,平均高度0.75,面积 = 0.125
- 从(0.3333,0.75)到(0.5,0.75):宽度0.1667,平均高度0.75,面积 = 0.125
- 从(0.5,0.75)到(0.5,1):宽度0,面积0
- 从(0.5,1)到(0.6667,1):宽度0.1667,平均高度1,面积 = 0.1667
- 从(0.6667,1)到(0.8333,1):宽度0.1667,平均高度1,面积 = 0.1667
- 从(0.8333,1)到(1,1):宽度0.1667,平均高度1,面积 = 0.1667
全部加起来:0.0833 + 0.125 + 0.125 + 0.1667 + 0.1667 + 0.1667 =0.8333。
这就是这一组数据对应的AUC值,你记住这个数字,后面两种方法算出来应该完全一样。
实际工程中,如果用Python实现几何法,代码大致长这样(本质就是np.trapz):
import numpy as np def auc_by_roc_curve(y_true, y_score): # 按分数从高到低排序 order = np.argsort(y_score)[::-1] y_true_sorted = y_true[order] y_score_sorted = y_score[order] # 遍历所有可能的阈值,记录FPR和TPR tpr_list = [0.0] fpr_list = [0.0] pos_total = np.sum(y_true == 1) neg_total = np.sum(y_true == 0) tp = 0 fp = 0 for i in range(len(y_true_sorted)): if y_true_sorted[i] == 1: tp += 1 else: fp += 1 tpr_list.append(tp / pos_total) fpr_list.append(fp / neg_total) # 梯形积分 fpr_list = np.array(fpr_list) tpr_list = np.array(tpr_list) return np.trapz(tpr_list, fpr_list)2.3 几何法的优缺点与适用边界
几何法的最大优势是直观、贴合定义。你画出了ROC曲线,看着曲线下的面积,就能大致判断模型好坏。而且ROC曲线本身携带了丰富的信息——曲线形状能告诉你模型在不同阈值下的表现模式,曲线越靠近左上角,说明模型能在较低的误伤率下获得较高的召回率。
但几何法的缺点也很明显。第一,它需要遍历所有可能的阈值,在样本量大、预测分数精度高的时候,阈值数量会非常多,计算效率低。第二,如果预测分数之间有很多重复值(也就是存在大量平局),ROC曲线的点数会明显减少,梯形法求出的面积会和真实值之间产生偏差。第三,几何法不方便做统计推断,比如计算AUC的方差和置信区间,就比较绕。
所以我的判断是:几何法更适合教学和理解阶段,或者样本量不大、需要可视化分析ROC曲线形态的场景。真正的大规模建模和模型评估,不太会直接用这种方法。
3. 方法二:概率视角——随机正样本得分大于随机负样本的概率
如果说几何法是从"形"的角度看AUC,那么概率法就是从"义"的角度看AUC。它的核心是一个漂亮的等价命题:AUC等于随机抽取一个正样本,其预测分数高于随机抽取一个负样本的预测分数的概率。这个命题在数学上是可以严格证明的,理解了它,你对AUC的理解会上一个台阶。
3.1 等价命题的直观解释
你可以把AUC想象成一个"配对擂台赛":把所有的正样本和负样本两两配对,对每一对样本,比较它们的预测分数。如果正样本得分更高,这一对就算"正样本赢了";如果负样本得分更高,就算"正样本输了";如果分数相同,算打平,记0.5分。AUC就是所有配对中"正样本赢"的比例(打平算半分)。
这个视角的解释力非常强。比如AUC=0.8,你可以直白地说:任取一个正样本和一个负样本,模型有80%的概率把正样本排在负样本前面。这比"ROC曲线下面积是0.8"要直观得多,也更容易向业务方解释。
为什么这个等价命题成立?回想ROC曲线的绘制过程,曲线下面积本质上可以理解为"在所有的阈值下,TPR的平均值关于FPR的积分"。而把正负样本配对比较分数,其实就是在问"是否存在一个阈值,使得正样本被正确分类而负样本被错误分类"。数学推导这里不展开,你只需要记住这个结论,后面秩和法的推导也要用到它。
3.2 手算示例与代码实现
继续用前面的示例数据。4个正样本(分数0.9、0.8、0.6、0.3),6个负样本(分数0.7、0.5、0.4、0.2、0.1、0.0),总配对数 = 4 × 6 = 24对。
逐个比较:
- 正样本0.9 vs 6个负样本:全部高于,赢6次
- 正样本0.8 vs 6个负样本:全部高于,赢6次
- 正样本0.6 vs 6个负样本:高于0.5、0.4、0.2、0.1、0.0,但低于0.7,赢5次
- 正样本0.3 vs 6个负样本:高于0.2、0.1、0.0,低于0.7、0.5、0.4,赢3次
总赢次数 = 6 + 6 + 5 + 3 = 20,AUC = 20 / 24 =0.8333。
和几何法算出来完全一致。这里的24就是所有正负样本对的总数,如果存在分数完全相同的配对,则计0.5分。
用Python实现也很直白:
import numpy as np def auc_by_probability(y_true, y_score): pos_scores = y_score[y_true == 1] neg_scores = y_score[y_true == 0] wins = 0 ties = 0 for ps in pos_scores: for ns in neg_scores: if ps > ns: wins += 1 elif ps == ns: ties += 1 total = len(pos_scores) * len(neg_scores) return (wins + 0.5 * ties) / total这段代码虽然简单直观,但如果你注意看,它有两个for循环嵌套,时间复杂度和样本量的平方成正比。数据量到了几万甚至几十万量级,这种写法就非常吃力了。它的意义主要在于验证和教学,或者在小样本场景下做精确校验。
3.3 概率视角带来的统计推断能力
概率视角最大的隐藏价值,在于它打开了统计推断的大门。
有了"配对比较"这个框架,AUC的方差就能用U统计量的理论来估计。在实际业务中,这个价值非常大。比如你在做AB测试,两个模型的AUC一个0.812,一个0.818,表面看后者更好。但0.006的差距到底是真实差异还是随机波动?如果没有方差估计,你只能凭感觉判断。如果算出了每个AUC的标准误,你就可以构造置信区间,做一个正式的假设检验,看看这个差距是否在统计上显著。
具体做法是利用DeLong方法,它在配对比较的框架下,将AUC的方差分解为与正样本相关和与负样本相关的两部分。很多成熟的机器学习库都实现了DeLong检验,比如scikit-learn的roc_auc_score配合一些第三方包就能计算AUC的置信区间。我在实际项目中的经验是:样本量小于1000时,AUC的置信区间可能宽到让你怀疑人生。这时候你再看两个模型的AUC差0.006,基本可以认为没有显著差异。这个信息在模型选型和评审时,能帮你避开很多不必要的争论。
4. 方法三:排序加速——秩和法
前两种方法,一个要遍历阈值,一个要遍历样本对,都不是大规模数据场景的最优解。真正在工程实现里胜出的是第三种方法——秩和法,也叫Wilcoxon-Mann-Whitney秩和检验法。scikit-learn里roc_auc_score走的就是这条路线。
4.1 从配对比较到秩次求和
秩和法的推导起点是概率法。既然AUC等价于"正样本得分高于负样本的概率",那能不能不两两配对,而是一次性排序搞定?
答案是能。把所有的样本按预测分数从低到高排序,每个样本得到一个秩次(排名)。关键结论是:所有正样本的秩次之和,与正负样本配对的赢次数之间存在明确的数量关系。
具体公式是:
AUC = (ΣR_pos - n1(n1+1)/2) / (n1 × n2)
这里的ΣR_pos是所有正样本的秩和,n1是正样本数量,n2是负样本数量。这个公式怎么来的?因为所有正样本的秩和减去它们内部两两比较的秩次和,剩下的部分正好对应"正样本赢过负样本"的次数。推导过程不复杂,但工程上直接记住这个公式就能用。
我还是用前面的示例数据验证一遍。把10个样本按分数从低到高排列:
- 样本10,负样本,0.0,秩1
- 样本9,负样本,0.1,秩2
- 样本8,负样本,0.2,秩3
- 样本7,正样本,0.3,秩4
- 样本6,负样本,0.4,秩5
- 样本5,负样本,0.5,秩6
- 样本4,正样本,0.6,秩7
- 样本3,负样本,0.7,秩8
- 样本2,正样本,0.8,秩9
- 样本1,正样本,0.9,秩10
正样本的秩次是4、7、9、10,秩和ΣR_pos = 4+7+9+10 = 30。n1 = 4,n2 = 6。
代入公式:AUC = (30 - 4×5/2) / (4×6) = (30 - 10) / 24 = 20 / 24 =0.8333。
又一次得到完全一致的结果。你有没有注意到,秩和法只需要一次排序加一次求和,不需要嵌套循环。当样本量达到百万级时,这个效率差距是天壤之别。
4.2 平局(Tie)问题的标准处理方式
秩和法有一个细节容易踩坑:预测分数出现相同值的时候怎么办?比如两个样本分数都是0.5,一个正一个负,在排序时谁排前面?这就涉及到排名分配的问题。
标准的处理方式是给平局的样本分配平均秩次。举个例子,如果三个样本的分数都是0.5,它们本应占据第5、6、7三个位置,那么每个样本都分配秩次6(5+6+7的平均值)。在代码实现里,这一步通常用scipy.stats.rankdata的method='average'参数来完成。
如果忽略平局处理,直接按原始顺序排,计算出的AUC会有偏差,尤其在预测分数是离散值(比如评分卡模型输出1到10的整数分)的时候,偏差可能非常明显。我之前就见过一个评分卡项目,同事直接用argsort后的索引当秩次去算AUC,结果和sklearn的结果对不上,排查了很久才发现是平局处理的问题。这件事给我的教训是:涉及排序类计算,永远先问一句:平局怎么处理?
处理平局后的秩和法代码如下:
import numpy as np from scipy.stats import rankdata def auc_by_rank(y_true, y_score): # 升序排名,平局取平均秩 ranks = rankdata(y_score, method='average') n1 = np.sum(y_true == 1) n2 = np.sum(y_true == 0) rank_sum_pos = np.sum(ranks[y_true == 1]) auc = (rank_sum_pos - n1 * (n1 + 1) / 2) / (n1 * n2) return auc注意这里的秩次是按升序排的,如果按降序排,公式会相应变化。核心无非是把"正样本的秩次相对位置"提取出来,你只要保证排序方向一致,结果就是稳定的。
4.3 大规模数据下的性能对比
秩和法的计算复杂度是O(n log n),主要开销在排序这一步。而几何法最坏情况是O(n²)(相当于每个样本一个阈值),概率法是O(n1×n2)(正负样本对全部遍历)。在大规模数据集上,这个差距是质的差别。
我在一个真实项目里做过对比:某电商平台的点击率预估模型,评估集有80万条样本,正负样本比例约1:10。用秩和法计算AUC,包括排序在内总共耗时约0.3秒;如果用概率法的朴素双重循环,理论上需要执行80万×72万≈5760亿次比较,就算每秒钟比10亿次,也需要将近100分钟。所以工程上基本没有悬念,必须用秩和法。
另外,线性复杂度还有额外的好处:你可以在线增量更新AUC。比如数据流式到达,每来一批新样本,只需要在全局排序中做几次插入操作,就能更新秩次并重新计算AUC,不需要把历史数据全部重算。这在实时模型监控场景里非常实用。我见过一些团队为了监控模型效果,每天凌晨定时重算AUC,其实完全可以用增量更新的方式做到分钟级延迟。
5. 三种方法对比与场景选择
三条路线都走完了,这节把它们的差异和适用场景做一个系统性的横向对比。理解了各自的优劣,你在实战中就能根据数据规模、计算资源和业务诉求,快速选出合适的方法。
5.1 三种方法的全面横向对比
| 维度 | 几何法 | 概率法 | 秩和法 |
|---|---|---|---|
| 核心视角 | 几何面积 | 配对比较 | 秩次统计 |
| 计算复杂度 | O(n²) | O(n1×n2) | O(n log n) |
| 平局处理 | 天然存在阶梯 | 计数时计0.5分 | 需分配平均秩次 |
| 内存占用 | 低 | 高 | 低 |
| 统计推断能力 | 弱 | 强(U统计量) | 中 |
| 可视化支持 | 强(产出ROC曲线) | 弱 | 弱 |
| 适用数据规模 | 小样本教学分析 | 小样本验证推导 | 大规模工程实现 |
| 实现难度 | 中 | 低 | 中 |
从表里可以直观看到,三种方法各有侧重。几何法是"形",概率法是"义",秩和法是"术"。理解AUC的人,三种方法都该能写出来、算出来;工程实现的时候,用秩和法;需要做统计检验的时候,转到概率法的框架里。
5.2 不同业务场景下的选型建议
如果你是在做教学或者给团队做分享,强烈建议从几何法入手。先画出ROC曲线,理解每个点的含义,再手算一遍梯形面积,对AUC的理解会非常扎实。我每次给新人讲AUC都是这个顺序,效果比直接丢公式好得多。
如果你是在做模型选型或者评审,重点用秩和法快速得到AUC值,同时利用概率法框架计算置信区间。不要只看一个点估计就下结论,带上置信区间的AUC才有说服力。这里我强烈建议养成一个习惯:报告AUC的时候,顺便报告95%置信区间。字数不多,但对结果的可信度描述完全不一样。
如果你是在做实时模型监控,秩和法的增量更新是唯一现实的选择。模型上线之后,线上日志不断产生新样本,每来一批就全量重算AUC,在数据量大的情况下成本太高。用增量排序结构,比如跳表或者树状数组,可以比较优雅地解决这个问题。
6. 实战中的常见问题与排坑实录
最后这部分,我把自己在实际项目中踩过的坑和积累的经验整理出来。这些内容在教科书里基本找不到,但每一个都是真实工作里会遇到的坎。
6.1 数据不平衡时AUC还靠得住吗
先说结论:AUC对类别不平衡相对不敏感,但也不是完全免疫。正负样本比例悬殊时,AUC依然能反映排序能力,因为它的计算本质是"正样本排在负样本前面的概率",与两类样本的绝对数量关系不大。
但这里有个隐藏的坑:样本量极少的那一类,AUC的置信区间会剧烈膨胀。比如负样本只有50个,正样本有10万个,AUC算出来可能是0.85,但置信区间可能宽到0.72到0.93。这个宽区间说明估计极不稳定,换个采样种子结果可能就变了。我的经验是,当某一类样本量小于200时,AUC的点估计值参考意义有限,最好配合PR曲线一起看。
另外需要特别提醒:不要用AUC来比较在不同采样比例下训练的模型。比如A模型在1:1采样下训练、B模型在1:10采样下训练,两者的AUC不具备直接可比性,因为训练数据的先验分布已经变了。我在实际项目里多次看到有人因为这个原因做出错误判断,这个坑一定要避。
6.2 预测分数存在大量平局时的处理
预测分数可能是离散值,比如评分卡输出0到100的整数,或者树模型输出的叶子节点编号。这种情况下,样本的预测分数会有大量重复,处理不好会导致AUC偏低。
关键在平局的处理方式上。概率法里,分数相等的正负样本对记0.5分,这已经是一种公平的处理。秩和法里如果用平均秩次,结果和概率法是一致的。但如果用argsort得到的顺序当秩次,没有做平均化处理,结果就会偏小。
我踩过的一个具体坑是这样的:某个集成模型输出的分数恰好是固定几个值(比如0.1、0.5、0.9),数据里大量样本分数相同。直接用np.argsort的索引值代入秩和公式,算出来的AUC比sklearn的结果低了0.02。后来排查发现就是秩次处理的问题。所以只要你自己手写AUC计算,务必用scipy.stats.rankdata(method='average')。
6.3 AUC与PR曲线到底该看哪个
AUC和PR曲线(Precision-Recall曲线)是两类不同的评估视角。AUC关注的是正负样本排序能力,PR曲线关注的是正类预测的精确率和召回率之间的权衡。在类别不平衡的场景下,PR曲线往往对模型性能的变化更敏感。
举个例子:某异常检测场景中,正样本占比只有0.5%。模型A把10%的样本判为异常,在10%的阈值下精确率是5%、召回率是50%;模型B把1%的样本判为异常,精确率是30%、召回率是6%。两个模型的AUC可能差别不大,但PR曲线的差异非常明显——模型B在精确率上完胜。如果你只盯着AUC,可能会觉得两个模型差不多,但这显然不符合业务预期。
我的建议是:在大类不平衡的场景中,AUC和PR曲线要一起报告,并且以PR曲线为主要决策依据之一。AUC告诉你模型的排序能力,PR曲线告诉你模型在特定操作点上的实际表现,两个维度各自不可替代。
6.4 多分类任务的AUC怎么处理
AUC本身是为二分类设计的指标。多分类场景下,标准做法是"宏平均"和"微平均"两种。
宏平均的思路是为每个类别单独计算AUC,然后取算术平均。具体做法是把当前类别当作正类,其余所有类别当作负类,对每个类别做一次二分类AUC计算。这个方案对每个类别公平对待,不管这个类别的样本量是大是小。微平均的思路则是先把所有类别的预测结果合并,然后统一计算AUC,这样样本量大的类别对结果的影响也更大。
在业务中怎么选?如果各类别的重要性相同,选宏平均;如果更关注样本量大的主流类别,选微平均。我在多标签分类项目中通常两个都算,如果两者差异很大,说明模型对不同类别的处理不平衡,需要进一步分析。
写在最后
回到开头那个评审会上的问题。当时我确实有点被动,但也正因为那次经历,我才把AUC的三种计算方法从里到外彻底捋了一遍。现在再有人问我"AUC怎么算的、稳不稳定、有没有置信区间",我可以在五分钟内把三种方法讲清楚,并且用秩和法快速估算,用概率法框架计算置信区间,给出一个有说服力的评审结论。
如果你正在学习机器学习,我建议你把这篇文章里的示例数据自己手算一遍。10个样本,三种方法,算出来的结果都是0.8333。当你亲手验证了三种方法殊途同归,你对AUC的理解就不再是"一个函数调用",而是真正内化的知识。这种踏实感,在后续的建模生涯中会一直回报你。
最后再分享一个我个人的习惯:每次提交模型评估报告,我都会在AUC旁边附带样本量和置信区间。这三个数字放在一起,评审的人一眼就能看出结果可信度。这是吃过亏之后养成的习惯,也分享给你。