auc计算公式推导与Python代码实现

auc计算公式推导与Python代码实现参考 AUC 计算方法与 Python 实现代码 python 计算 auc 指标代码 defcalAUC prob labels f list zip prob labels rank values2forva values2insor f key lambdax x 0 rankList i 1foriinrange len rank ifrank i 1 posNum 0negNum 0for

参考

  1. AUC的计算方法
  2. AUC计算方法与Python实现代码
  3. 百面机器学习127页

1.使用概率定义计算auc

1.1计算公式推导

  • M为正样本数量,N为负样本数量。
  • r a n k i rank_i ranki为第i条样本序号。将所有样本按照预测得分升序排列,预测分最小的序号为1,预测分最大的序号为T=M+N。式1分子的求和部分,表示将所有正样本的序号求和。
  • 预测得分相同的多条样本,序号要取原始序号的平均值

假设第1大的正样本序号为 r a n k a 1 rank_{a1} ranka1,则预测得分比它小的样本有 r a n k a 1 − 1 rank_{a1}-1 ranka11个,其中包含了M-1个正样本,因此预测得分比它小的负样本个数为 n 1 = r a n k a 1 − M n_1=rank_{a1}-M n1=ranka1M

假设第i大的正样本序号为 r a n k a i rank_{ai} rankai,同理可得预测得分比它小的负样本个数为 n i = r a n k a i − M + i − 1 n_i=rank_{ai}-M+i-1 ni=rankaiM+i1

根据AUC的概率定义 A U C = P ( P 正 样 本 > P 负 样 本 ) = ∑ I ( P 正 样 本 , P 负 样 本 ) / ( M ∗ N ) AUC=P(P_{正样本}>P_{负样本})=\sum I(P_{正样本}, P_{负样本})/ (M*N) AUC=P(P>P)=I(P,P)/(MN),分子可以通过 n i n_i ni来计算, ∑ I ( P 正 样 本 , P 负 样 本 ) = ∑ a i ∈ 正 样 本 n a i = ∑ a i ∈ 正 样 本 r a n k a i − M ( M + 1 ) / 2 \sum I(P_{正样本}, P_{负样本})=\sum_{ai∈正样本} n_{ai}=\sum_{ai∈正样本} rank_{ai} – M(M+1)/2 I(P,P)=ainai=airankaiM(M+1)/2,从而得到最终结果式2。

1.2修复代码bug

根据式2,博文2给出了如下Python实现代码,这个代码有bug,没有处理预测得分相同的情况。

#有bug,没有处理预测得分相同的情况 def calAUC1(prob,labels): f = list(zip(prob,labels)) #(prob, label)列表 rank = [values2 for values1,values2 in sorted(f,key=lambda x:x[0])] #升序排序后的label列表 rankList = [i+1 for i in range(len(rank)) if rank[i]==1] #正样本序号列表,从1开始 posNum = 0 negNum = 0 for i in range(len(labels)): #统计正负样本个数 if(labels[i]==1): posNum+=1 else: negNum+=1 auc = 0 auc = (sum(rankList)- (posNum*(posNum+1))/2)/(posNum*negNum) #计算auc print(auc) return auc 

下面是与sklearn.metrics.roc_auc_score比较的结果,预测得分有重复时,上面的calAUC1代码给出错误结果。

y_true = np.array([1, 1, 0, 0, 1, 1, 0]) #预测得分无重复,结果正确 y_scores = np.array([0.8, 0.7, 0.6, 0.5, 0.4, 0.2, 0.3]) # roc_auc_score is 0.33333 # calAUC1 is 0.33334 #预测得分有重复,结果错误! y_scores = np.array([0.8, 0.7, 0.5, 0.5, 0.5, 0.5, 0.3]) # roc_auc_score is 0.33334 # calAUC1 is 1.0 

增加处理预测得分相同的情况后,修复后的代码如下

#修复bug,处理了预测得分相同的情况 def calAUC(prob, labels): assert len(prob) == len(labels) n = len(prob) f = list(zip(prob, labels)) # (prob, label)列表 f = sorted(f, key=lambda x: x[0]) # 按照预测得分升序排列 tuple = [[f[i][0], f[i][1], i + 1] for i in range(n)] # [prob, lable, rank], rank从1开始。不能用元祖,否则修改不了rank值 # 预测分数相同时,将rank值平均 i = 0 while i < n - 1: j = i while j + 1 < n and tuple[j][0] == tuple[j + 1][0]: # 判断预测分是否相同 j = j + 1 if j > i: # i~j预测得分相同 mean = sum([tuple[k][2] for k in range(i, j + 1)]) / (j + 1 - i) for k in range(i, j + 1): tuple[k][2] = mean # rank值取平均 i = j + 1 posRankList = [x[2] for x in tuple if x[1] == 1] # 正样本序号列表,从1开始 posNum = len([x for x in labels if x == 1]) # 正样本数量 negNum = len([x for x in labels if x == 0]) # 负样本数量 auc = (sum(posRankList) - (posNum * (posNum + 1)) / 2) / (posNum * negNum) # 计算auc return auc 

下面是测试结果,不管预测得分有无重复,修改后的calAUC与sklearn.metrics.roc_auc_score结果一致。

y_true = np.array([1, 1, 0, 0, 1, 1, 0]) #预测得分无重复,结果正确 y_scores = np.array([0.8, 0.7, 0.6, 0.5, 0.4, 0.2, 0.3]) # roc_auc_score is 0.33333 # calAUC is 0.33334 #预测得分有重复,结果正确! y_scores = np.array([0.8, 0.7, 0.5, 0.5, 0.5, 0.5, 0.3]) # roc_auc_score is 0.33334 # calAUC is 0.33334 

2.使用面积定义计算auc

代码如下,暂未处理预测得分相同的情况。

# 使用面积定义计算auc def aucArea(prob, labels): f = list(zip(prob, labels)) lableSort = [label for p, label in sorted(f, key=lambda x: x[0], reverse=True)] # 降序排列 posNum = len([x for x in labels if x == 1]) # 正样本数量 negNum = len([x for x in labels if x == 0]) # 负样本数量 area = 0 h = 0 for label in lableSort: if label == 1: h += 1 else: area += h # 向右移动时,更新面积 area = area / (posNum * negNum) return area 
y_true = np.array([1, 1, 0, 0, 1, 1, 0]) #预测得分无重复,结果正确 y_scores = np.array([0.8, 0.7, 0.6, 0.5, 0.4, 0.2, 0.3]) # roc_auc_score is 0.33333 # aucArea is 0.33334 #预测得分有重复,结果错误! y_scores = np.array([0.8, 0.7, 0.5, 0.5, 0.5, 0.5, 0.3]) # roc_auc_score is 0.33334 # aucArea is 0.66666 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176296.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午10:16
下一篇 2026年3月26日 下午10:17


相关推荐

  • 【22】进大厂必须掌握的面试题-30个Informatica面试

    点击上方“全栈程序员社区”,星标公众号 重磅干货,第一时间送达 在大数据时代,任何公司的成功都取决于数据驱动的决策和业务流程。在这种情况下,数据集成对于任何业务的成功秘诀都是至关重…

    2021年6月24日
    114
  • media type的类型汇总

    media type的类型汇总用的比较多的是screen和print:区分打印和屏幕显示(Android,iPhone都不是手持设备handheld,都是screen设备)转载于:https://www.cnblogs.com/hulaoxi/p/6140054.html

    2022年5月25日
    88
  • 51单片机入门教程(2)——实现流水灯

    51单片机入门教程(2)——实现流水灯51单片机入门教程(2)——实现流水灯一、搭建流水灯电路二、流水灯程序2.1延时程序2.2延时函数2.3按字节寻址2.4逻辑移位2.5条件判断一、搭建流水灯电路在Proteus中搭建流水灯电路如图二、流水灯程序我们可以把流水灯看作依次点亮若干个灯。程序如下:#include&amp;amp;amp;lt;reg52.h&amp;amp;amp;gt;sbitled1=P2^0;sbitled2=P2^1…

    2022年6月10日
    34
  • android编程入门[通俗易懂]

    android编程入门[通俗易懂]作者:邓鸿链接:https://www.zhihu.com/question/26417244/answer/110074475来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。一、基础篇需要掌握的技能如下:1、熟练掌握基本控件以及容器控件的使用;常用的基本控件有:Button、TextView、EditText、ListView

    2022年6月17日
    38
  • Eclipse代码的自动补全

    Eclipse代码的自动补全打开eclipse依次点击Window–>Perferences–>Java–>Editor–>ContentAssist在【AutoactivationtriggersforJava:】选项后的文本框中会看到一个”.”。eclipse默认只有在你输入”.”之后才会有代码提示和自动补全。我们需要在”.”之后加上”qwertyuiopasdfghjklzxcvbnm”,其实就是从左至右,从上至下顺序按你的键盘。…

    2022年5月31日
    44
  • 科技爱好者周刊(第 383 期):你是第几级 AI 编程

    科技爱好者周刊(第 383 期):你是第几级 AI 编程

    2026年3月15日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号