auc 可以理解为:随机抽出一对样本(一个正样本,一个负样本),然后用训练得到的分类器来对这两个样本进行预测,预测得到正样本的概率大于负样本概率的概率。
1 三种求解方法
方法 1
在有 M M M个正样, N N N个负样本的数据集里。一共有 M ∗ N M*N M∗N对样本(一对样本即,一个正样本与一个负样本)。统计这M*N对样本里,正样本的预测概率大于负样本的预测概率的个数。
∑ I ( P r e d p o s , P r e d n e g ) M ∗ N \frac{\sum {I(Pred_{pos}, Pred_{neg})}}{M * N} M∗N∑I(Predpos,Predneg)
如果 P r e d p o s > P r e d n e g Pred_{pos} > Pred_{neg} Predpos>Predneg, I ( P r e d p o s , P r e d n e g ) = 1 I(Pred_{pos}, Pred_{neg}) = 1 I(Predpos,Predneg)=1,如果 P r e d p o s = P r e d n e g Pred_{pos} = Pred_{neg} Predpos=Predneg, I ( P r e d p o s , P r e d n e g ) = 0.5 I(Pred_{pos}, Pred_{neg}) = 0.5 I(Predpos,Predneg)=0.5,否则为0.
- | label | score |
---|---|---|
A | 0 | 0.1 |
B | 0 | 0.4 |
C | 1 | 0.35 |
D | 1 | 0.8 |
2个正样本,2个负样本, M = N = 2 M=N=2 M=N=2,有下面几个组合,(D,B),(D,A),(C,B),(C,A)。 在(D,B)样本对中,正样本D预测的概率大于负样本B预测的概率(也就是D的得分比B高),记为1。同理,对于(C,B)。正样本C预测的概率小于负样本C预测的概率,记为0.
上面AUC可以计算为 1 + 1 + 1 + 0 2 ∗ 2 = 0.75 \frac{1 + 1 + 1 + 0}{2 * 2} = 0.75 2∗21+1+1+0=0.75。
- | label | score |
---|---|---|
A | 0 | 0.1 |
B | 0 | 0.4 |
C | 1 | 0.4 |
D | 1 | 0.8 |
上面AUC可以计算为 1 + 1 + 1 + 0.5 2 ∗ 2 = 0.875 \frac{1 + 1 + 1 + 0.5}{2 * 2} = 0.875 2∗21+1+1+0.5=0.875。
方法 2
- 对预测概率从高到低排序
- 对每一个概率值设一个rank值(最高的概率的rank为n,第二高的为n-1)
- rank实际上代表了该score(预测概率)超过的样本的数目。为了求的组合中正样本的score值大于负样本,如果所有的正样本score值都是大于负样本的,那么第一位与任意的进行组合score值都要大,我们取它的rank值为n,但是n-1中有M-1是正样例和正样例的组合这种是不在统计范围内的(为计算方便我们取n组,相应的不符合的有M个),所以要减掉,那么同理排在第二位的n-1,会有M-1个是不满足的,依次类推,故得到后面的公式M*(M+1)/2,我们可以验证在正样本score都大于负样本的假设下,AUC的值为1
∑ i ∈ p o s i t i v e − c l a s s r a n k i − M ( 1 + M ) 2 M ∗ N \frac{\sum_{i\in positive-class} {rank_i} - \frac{M(1+M)}{2}}{M * N} M∗N∑i∈positive−classranki−2M(1+M)
以它为例
- | label | score |
---|---|---|
A | 0 | 0.1 |
B | 0 | 0.4 |
C | 1 | 0.35 |
D | 1 | 0.8 |
排序后
- | label | score | rank |
---|---|---|---|
D | 1 | 0.8 | 4 |
B | 0 | 0.4 | 3 |
C | 1 | 0.35 | 2 |
A | 0 | 0.1 | 1 |
( 4 + 2 ) − 2 ∗ ( 2 + 1 ) 2 2 ∗ 2 = 0.75 \frac{(4 + 2) - \frac{2*(2 + 1)}{2}}{2 * 2} = 0.75 2∗2(4+2)−22∗(2+1)=0.75
如果出现得分一样的情况:
- | label | score | rank |
---|---|---|---|
A | 1 | 0.8 | 7 |
B | 1 | 0.7 | 6 |
C | 0 | 0.5 | 5 |
D | 0 | 0.5 | 4 |
E | 1 | 0.5 | 3 |
F | 1 | 0.5 | 2 |
G | 0 | 0.3 | 1 |
( 7 + 6 + 5 + 4 + 3 + 2 4 + 5 + 4 + 3 + 2 4 ) − 4 ∗ ( 4 + 1 ) 4 4 ∗ 3 = 0.833 \frac{(7 + 6 + \frac{5 + 4 + 3 + 2}{4} + \frac{5 + 4 + 3 + 2}{4}) - \frac{4*(4 + 1)}{4}}{4 * 3} = 0.833 4∗3(7+6+45+4+3+2+45+4+3+2)−44∗(4+1)=0.833
方法 3
AUC 曲线下的面积
2 python实现
下面code实现了前两种方法
# 方法1
def AUC1(label, pre):
pos = [i for i in range(len(label)) if label[i] == 1]
neg = [i for i in range(len(label)) if label[i] == 0]
auc = 0
for i in pos:
for j in neg:
if pre[i] > pre[j]:
auc += 1
elif pre[i] == pre[j]:
auc += 0.5
if not pos or not neg:
return None
return auc / (len(pos)*len(neg))
# 方法2
def AUC2(label, pre):
new_data = [[p, l] for p, l in zip(pre, label)]
new_data.sort(key = lambda x : x[0])
score_index = {}
for index, i in enumerate(new_data):
if i[0] not in score_index:
score_index[i[0]] = []
score_index[i[0]].append(index + 1)
rank_sum = 0.
for i in new_data:
if i[1] == 1:
rank_sum += sum(score_index[i[0]]) / len(score_index[i[0]]) * 1.0
pos = label.count(1)
neg = label.count(0)
if not pos or not neg:
return None
return (rank_sum - (pos * (pos + 1) * 0.5)) / (pos * neg)
label = [1, 1, 1, 1, 1, 1]
score = [0.1, 0.4, 0.35, 0.8, 0.8, 0.9]
print(AUC1(label, score))
print(AUC2(label, score))
欢迎关注微信公众号(算法工程师面试那些事儿),本公众号聚焦于算法工程师面试,期待和大家一起刷leecode,刷机器学习、深度学习面试题等,共勉~