OULU数据集用于anti-spoofing的测试,里面包含了打印攻击、回放攻击等一些攻击类型,想要具体了解OULU的数据概况的学者们,请读下OULU的原文,本人就不在这里详述了。OULU原文链接如下:OULU数据集 PDF版原文
在用OULU对你设计的模型进行指标测试时,需要注意的一点是:你需要在OULU提供的四个协议上分别进行测试,OULU的前两个协议文件分别只有一个训练txt文件,而后两个协议则分别包含了6个训练文件,dev,test文件在这四个协议中也是如此!这四个协议是作者分别针对不同的攻击环境来进行设置的,具体如下:
协议名 | 含义 |
---|---|
P1 | 评估在背景与光照上的泛化能力(未知的光照与背景变化的泛化能力) |
P2 | 对不同类型的打印和视频攻击进行训练和测试,来评估泛化能力(未知的攻击介质的泛化能力) |
P3 | 对图像捕获设备的类型进行泛化评估 |
P4 | 结合P1-P3上的所有变化,来评估泛化能力 |
借此机会,我把SIW数据集的三个测试协议也放上,感兴趣的学者们可以了解下:
协议名 | 含义 |
---|---|
P1 | 评估对姿势和表情变化的泛化能力 |
P2 | 评估在不同回放攻击设备上的泛化能力 |
P3 | 通过在专门包含重放攻击或打印攻击视频的数据集上进行 |
一些研究者在OULU数据集上的测试结果:
上图第一列代表的是测试协议名,第二列代表模型名字,其中协议3与协议4中值代表“均值±方差”;
在用OULU的四个协议对你的模型测试时,切记,千万不要直接用求出来的TN,TP,FN,FP来直接求APCER,BPCER,ACER,这样的测试方式是不对的,本人一开始就是用这样的方式来求APCER这些指标的,结果发现测出来的指标出奇的好,后来是通过读OULU那篇原论文才发现,这样得测试方式是不对的!害,白白地让我瞎折腾了将近2个月,泪奔!
对于正确的测试方法,原文是这样写的:
它的大致意思就是:APCER与BPCER依赖于一个决策阈值,development集(可以理解为一个验证集)作为一个分离的验证集运行,用于调节模型的参数,并预测阈值以供测试集使用;也就是说:由验证集development set得到一个阈值threshold,而测试集利用验证集得到的这个threshold进行APCER,BPCER的指标测试!
用代码的表示上述的测试方式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#创建一个用于验证集测试的类变量 pad_meter_val = PADMeter() #图像送入模型 output,_ = model(img) #预测概率 class_output = nn.functional.softmax(output, dim=1) #测量TP,TN,FP,FN pad_meter_val.update(target.cpu().data.numpy(),class_output.cpu().data.numpy()) #求eer,阈值thr pad_meter_val.get_eer_and_thr() #用阈值thr求hter,apcer,bpcer pad_meter_val.get_hter_apcer_etal_at_thr(pad_meter_val.threshold) #用阈值thr求acc pad_meter_val.get_accuracy(pad_meter_val.threshold) #################################################### #创建一个用于测试集测试的类变量 pad_meter_test = PADMeter() #图像送入模型 output,_ = model(img) #预测概率 class_output1 = nn.functional.softmax(output, dim=1) #得到TP,TN,FP,FN pad_meter_test.update(target.cpu().data.numpy(),class_output1.cpu().data.numpy()) #在验证集得到的阈值下,测量测试集的hter,apcer等指标 pad_meter_test.get_hter_apcer_etal_at_thr(pad_meter_val.threshold) #验证集得到的阈值下,测量测试集的acc指标 pad_meter_test.get_accuracy(pad_meter_val.threshold)
PADMeter()类封装的一些具体实现细节如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119import math import numpy as np from sklearn.metrics import roc_curve, accuracy_score from sklearn.metrics import roc_auc_score from torch import nn class PADMeter(object): """Presentation Attack Detection Meter""" def __init__(self): self.reset() def reset(self): self.label = np.ones(0) self.output = np.ones(0) self.threshold = None self.grid_density = 10000 def update(self, label, output): #一般取softmax之后,第1维度上的第1列数据 if len(output.shape) > 1 and output.shape[1] > 1: output = output[:, 1] elif len(output.shape) > 1 and output.shape[1] == 1: output = output[:, 0] #拼接,将新的数据拼接到已有的后方 self.label = np.hstack([self.label, label]) self.output = np.hstack([self.output, output]) def get_tpr(self, fixed_fpr): fpr, tpr, thr = roc_curve(self.label, self.output) tpr_filtered = tpr[fpr <= fixed_fpr] if len(tpr_filtered) == 0: self.tpr = 0.0 self.tpr = tpr_filtered[-1] def eval_stat(self, thr): pred = self.output >= thr TN = np.sum((self.label == 0) & (pred == False)) FN = np.sum((self.label == 1) & (pred == False)) FP = np.sum((self.label == 0) & (pred == True)) TP = np.sum((self.label == 1) & (pred == True)) if TN + FP == 0: TN += 0.0001 if TP + FN == 0: TP += 0.0001 return TN, FN, FP, TP def get_eer_and_thr(self): thresholds = [] Min, Max = min(self.output), max(self.output) for i in range(self.grid_density + 1): thresholds.append(Min + i * (Max - Min) / float(self.grid_density)) min_dist = 1.0 min_dist_stats = [] for thr in thresholds: TN, FN, FP, TP = self.eval_stat(thr) far = FP / float(TN + FP) frr = FN / float(TP + FN) dist = math.fabs(far - frr) if dist < min_dist: min_dist = dist min_dist_stats = [far, frr, thr] # for exception if len(min_dist_stats) >= 2: self.eer = (min_dist_stats[0] + min_dist_stats[1]) / 2.0 self.threshold = min_dist_stats[2] else: self.eer = 0.5 self.threshold = 0.5 def get_hter_apcer_etal_at_thr(self, thr=None): if thr is None: self.get_eer_and_thr() thr = self.threshold TN, FN, FP, TP = self.eval_stat(thr) far = FP / float(TN + FP) frr = FN / float(TP + FN) fpr = FP / float(FP + TN) tpr = TP / float(TP + FN) fpr1, tpr1, _ = roc_curve(self.label, self.output, pos_label=1) # print(type(fpr),fpr.shape,fpr.size()) # TPR@FPR=e-2 # tpr1 = np.array(tpr) # fpr1 = np.array(fpr) # print(type(fpr1), fpr1.shape,len(fpr1)) # print(fpr1) score_1 = tpr1[np.where(fpr1 >= 0.01)[0][0]] # TPR@FPR=e-3 score_2 = tpr1[np.where(fpr1 >= 0.001)[0][0]] # TPR@FPR=e-4 score_3 = tpr1[np.where(fpr1 >= 0.0001)[0][0]] self.TN = TN self.FN = FN self.FP = FP self.TP = TP self.apcer = far self.bpcer = frr self.acer = (self.apcer + self.bpcer) / 2.0 self.hter = (far + frr) / 2.0 self.fpr = fpr self.tpr = tpr self.score1 = score_1 self.score2 = score_2 self.score3 = score_3 try: self.auc = roc_auc_score(self.label, self.output) except ValueError: pass def get_accuracy(self, thr=None): if thr == None: self.get_eer_and_thr() thr = self.threshold TN, FN, FP, TP = self.eval_stat(thr) self.accuracy = accuracy = float(TP + TN) / len(self.output)
到此就结束了,在此祝各位学者科研顺利!
最后
以上就是精明月光最近收集整理的关于在anti-spoofing中,在OULU数据集上求APCER,BPCER,ACER上的一个注意事项的全部内容,更多相关在anti-spoofing中,在OULU数据集上求APCER,BPCER,ACER上内容请搜索靠谱客的其他文章。
发表评论 取消回复