话不多说,先上代码,看看是怎么求的,再来分析原理。
# -*- coding:utf-8 -*-
# Peoject:004_MyScripts
# File:AUROC_test
# User:csu.pan-||
# Time:2023/6/15 10:46
# IDE: PyCharm
# Func: AUROC的测试
# 导入sklearn算法库中的包
from sklearn.metrics import roc_curve, auc
import numpy as np
def AUC(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
return auc / (len(pos) * len(neg))
if __name__ == '__main__':
label = [1, 1, 1, 1, 0, 0, 0, 0]
pre = [0.65, 0.65, 0.50, 0.51, 0.41, 0.48, 0.42, 0.42]
print('mycompu_AUROC: ', AUC(label, pre))
'''
label是列表形式,对应方法1中的label形式
pre是列表形式,对应方法1中的pre形式
'''
fpr, tpr, thresholds = roc_curve(label, pre, pos_label=1)
optimal_idx = np.argmax(tpr - fpr)
optimal_threshold = thresholds[optimal_idx] # 求出最佳阈值
print('sklearn_AUROC: ', auc(fpr, tpr))
print('optimal_thres: ', optimal_threshold)
结果1:
mycompu_AUROC: 1.0
sklearn_AUROC: 1.0
optimal_thres: 0.5
现在换一个输入,看看情况咋样。
label = [1, 1, 1, 1, 0, 0, 0, 0]
pre = [0.45, 0.45, 0.40, 0.41, 0.31, 0.38, 0.32, 0.32]
结果2:
mycompu_AUROC: 1.0
sklearn_AUROC: 1.0
optimal_thres: 0.4
看到没有,代码中使用了sklearn的求AUROC函数和自定义的函数,从结果和代码来看,AUROC只是在排序,只要正样本的预测值比负样本大,就能得分,并没有说所有阈值下都能有效。
当我们使用MVTecAD数据集上那些算法的时候,一定要注意了,虽然AUROC指标看上去都很高,达到了99%以上,但是不同的验证集求出来的最佳阈值,可能就具有很大的差异。
所以,目前这些无监督的工业检测算法,都号称不需要负样本,实际上却需要验证集的正负样本来求取最佳阈值,但不同的验证集最佳阈值差异很大,比如结果1和结果2中的,你要是拿0.5的阈值去套,那结果2预测的就全是负例了,虽然AUROC都是1。这在工业部署的时候并不具有实用性,我们真正需要的是召回率和误检率这些指标。
参考:
https://www.jianshu.com/p/2253bde32823
https://blog.youkuaiyun.com/didi_ya/article/details/125141195