关于AUC的理解和计算方式
一日某大佬给了我出了个题,给了我一个表格,让我去手算一下AUC是多少,日常我都是模型直接输出(如下),真要手算一时半会还想不起来,所以今天咱深入了解下。
print(roc_auc_score(y_true,y_scores))
这里我把大佬所述绘制成表格
| prob | 正例 | 负例 |
|---|---|---|
| 0.8 | 5 | 4 |
| 0.5 | 1 | 2 |
| 0.3 | 2 | 2 |
下面分别从模型输出和手算两方面计算一下AUC
1 模型输出AUC的值
首先将表格翻译成我们训练时候数据的模样,正例是1,负例为0,
那么表格对应的数据为[1,1,1,1,1,0,0,0,0,1,0,0,1,1,0,0]
对应的概率为[0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.5,0.5,0.5,0.3,0.3,0.3,0.3]
先用我经常输出模型评价指标的代码跑一下结果:
from sklearn.metrics import roc_auc_score,accuracy_score,f1_score,precision_score,recall_score
import numpy as np
y_true=np.array([1,1,1,1,1,0,0,0,0,1,0,0,1,1,0,0])
y_scores=np.array([0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.5,0.5,0.5,0.3,0.3,0.3,0.3])
print("y_true is",y_true)
print("y_scores is",y_scores)
print("AUC is",roc_auc_score(y_true,y_scores))
y_pred = [int(item >= 0.5) for item in y_scores]
print (y_pred)
print (confusion_matrix(y_true, y_pred))
print (classification_report(y_true, y_pred))
print ("Accuracy : %.4f" % accuracy_score(y_true, y_pred))
print ('Recall: %.4f' % recall_score(y_true,y_pred))
print ('F1-score: %.4f' % f1_score(y_true,y_pred))
print ('Precesion: %.4f' % precision_score(y_true,y_pred))
输出结果如下
y_true is [1 1 1 1 1 0 0 0 0 1 0 0 1 1 0 0]
y_scores is [0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.5 0.5 0.5 0.3 0.3 0.3 0.3]
AUC is 0.546875
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
[[2 6]
[2 6]]
precision recall f1-score support
0 0.50 0.25 0.33 8
1 0.50 0.75 0.60 8
accuracy 0.50 16
macro avg 0.50 0.50 0.47 16
weighted avg 0.50 0.50 0.47 16
Accuracy : 0.5000
Recall: 0.7500
F1-score: 0.6000
Precesion: 0.5000
哦这个AUC=0.546875,且为啥用y_scores不用y_pred去算AUC呢,下面我们一一解答
首先:我们看一下本案例的混淆矩阵是多少
| True_1 | True_0 | |
|---|---|---|
| pre_1 | 6 (TP) | 6 (FP) |
| pre_0 | 2 (FN) | 2 (TN) |
TPR(真阳率)=TP/(TP+FN)=6/(6+2)=3/4
FPR(假阳率)=FP/(FP+TN)=6/(6+2)=3/4
2 概率学定义计算AUC
其次,我们从概率学的那个定义去计算AUC:随机给定一个正例或者负例,判定正例为正比判定负例为正要高的概率,证明见链接2,有如下公式:
依据这个公式,结合正负例和得分,我们把顺序从新排列下
[1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0]
[0.8,0.8,0.8,0.8,0.8,0.5,0.3,0.3,0.8,0.8,0.8,0.8,0.5,0.5,0.3,0.3]
我们这里仔细回想下AUC概率上怎么算:随机给定一个正例或者负例,判定正例为正比判定负例为正要高的概率
敲黑板:随机给一个正例和负例:
->有8个正例和负例,两两组和,所以M*N=64
对于第1个正例来说,它的得分是0.8,9-16都是负例,有4个0.8,2个0.5,2个0.3
所以是4*0.5(相同0.5)+2*1+2*1=6
同理第2,3,4,5正例也是如此;
对于第6个正例,它的得分是0.5,9-16都是负例,有4个0.8,2个0.5,2个0.3
所以是0*4+2*0.5+2*1=3
同理求得第7,8对应的I分别是1和1
所以按照公式
AUC=(6*5+3+1+1)/64=35/64=0.546875
3 按照得分排序rank计算
随机给定一个正例或者负例,判定正例为正比判定负例为正要高的概率
我们按照概率值由低到高排序,相同的概率正样本在前负样本在后进行排名(递增的序列)
那么,如果有M个正样本和N个负样本,
如果rank最大的正样本为rank_1,那么他前面就有M-1个正样本,
他前面就会有rank_1-1-(M-1)=rank_1-M个负样本
rank第二大的正样本为rank_2,那么他前面就有M-2个正样本,
就会有rank_2-1-(M-2)=rank_2-(M-1)个负样本
...
直到最小的正样本rank_M,他前面0个正样本,有rank_M-1个负样本
把这些加起来
rank_1+rank+2+..rank_M-(M+M-1+M-2+...1)--等差数列
将此公式运用到本例:
| lable | prob | rank |
|---|---|---|
| 1 | 0.3 | 1 |
| 1 | 0.3 | 2 |
| 0 | 0.3 | 3 |
| 0 | 0.3 | 4 |
| 1 | 0.5 | 5 |
| 0 | 0.5 | 6 |
| 0 | 0.5 | 7 |
| 1 | 0.8 | 8 |
| 1 | 0.8 | 9 |
| 1 | 0.8 | 10 |
| 1 | 0.8 | 11 |
| 1 | 0.8 | 12 |
| 0 | 0.8 | 13 |
| 0 | 0.8 | 14 |
| 0 | 0.8 | 15 |
| 0 | 0.8 | 16 |
同分数要算均值且只算正例,相同的prob正例都要计算
🎉