Bob 2.0 standard metrics for biometric system evaluation. Scores use strings for template ids.
Forked from pkorshunov/spoof-score-fusion/4
Algorithms have at least one input and one output. All algorithm endpoints are organized in groups. Groups are used by the platform to indicate which inputs and outputs are synchronized together. The first group is automatically synchronized with the channel defined by the block in which the algorithm is deployed.
Endpoint Name | Data Format | Nature |
---|---|---|
test_fusion_scores | pkorshunov/fusion_scores/1 | Input |
Endpoint Name | Data Format | Nature |
---|---|---|
dev_fusion_scores | pkorshunov/fusion_scores/1 | Input |
Analyzers may produce any number of results. Once experiments using this analyzer are done, you may display the results or filter experiments using criteria based on them.
Name | Type |
---|---|
number_of_positives_dev_spoof | int32 |
number_of_negatives_dev_spoof | int32 |
number_of_positives_test_spoof | int32 |
HTER_licit | float32 |
FRR_test_spoof | float32 |
roc_test | plot/isoroc/1 |
number_of_negatives_test_licit | int32 |
FAR_dev_spoof | float32 |
number_of_negatives_dev_licit | int32 |
FAR_dev_licit | float32 |
dev_histograms | plot/bar/1 |
number_of_positives_dev_licit | int32 |
EER_spoof | float32 |
test_histograms | plot/bar/1 |
HTER_spoof | float32 |
FAR_test_spoof | float32 |
number_of_positives_test_licit | int32 |
FRR_dev_licit | float32 |
number_of_negatives_test_spoof | int32 |
FRR_test_licit | float32 |
threshold_licit | float32 |
roc_dev | plot/isoroc/1 |
threshold_spoof | float32 |
FAR_test_licit | float32 |
FRR_dev_spoof | float32 |
EER_licit | float32 |
Parameters allow users to change the configuration of an algorithm when scheduling an experiment
Name | Description | Type | Default | Range/Choices |
---|---|---|---|---|
n_bins_real | Number of histogram bins for real scores | uint32 | 20 | |
n_bins_attack | Number of histogram bins for attack scores | uint32 | 80 | |
n_bins_zimp | Number of histogram bins for zero-impostors scores | uint32 | 100 |
xxxxxxxxxx
import bob.measure
import numpy
class Algorithm:
def __init__(self):
self.positives_dev_licit = []
self.negatives_dev_licit = []
self.positives_test_licit = []
self.negatives_test_licit = []
self.positives_dev_spoof = []
self.negatives_dev_spoof = []
self.positives_test_spoof = []
self.negatives_test_spoof = []
self.dev_scores_real = None
self.n_bins_real = 20
self.n_bins_zimp = 100
self.n_bins_attack = 80
def setup(self, parameters):
self.n_bins_real = float(parameters.get('n_bins_real', self.n_bins_real))
self.n_bins_zimp = float(parameters.get('n_bins_zimp', self.n_bins_zimp))
self.n_bins_attack = float(parameters.get('n_bins_attack', self.n_bins_attack))
return True
def process(self, inputs, output):
dev_scores_zimp = []
dev_scores_attack = []
test_scores_real = []
test_scores_zimp = []
test_scores_attack = []
# accumulate the dev scores
if self.dev_scores_real is None:
self.dev_scores_real = []
while inputs['dev_fusion_scores'].hasMoreData():
inputs['dev_fusion_scores'].next()
dev_fusion_scores = inputs['dev_fusion_scores'].data
self.dev_scores_real.extend(dev_fusion_scores.real_scores)
dev_scores_zimp.extend(dev_fusion_scores.zimp_scores)
dev_scores_attack.extend(dev_fusion_scores.attack_scores)
test_fusion_scores = inputs['test_fusion_scores'].data
test_scores_real.extend(test_fusion_scores.real_scores)
test_scores_zimp.extend(test_fusion_scores.zimp_scores)
test_scores_attack.extend(test_fusion_scores.attack_scores)
# once all values are received, evaluate the scores
if not(inputs.hasMoreData()):
# first, compute everything for licit scenario (no attacks)
self.positives_dev_licit = self.dev_scores_real
self.negatives_dev_licit = dev_scores_zimp
self.positives_test_licit = test_scores_real
self.negatives_test_licit = test_scores_zimp
eer_threshold_licit = bob.measure.eer_threshold(self.negatives_dev_licit, self.positives_dev_licit)
far_dev_licit, frr_dev_licit = bob.measure.farfrr(self.negatives_dev_licit, self.positives_dev_licit, eer_threshold_licit)
far_test_licit, frr_test_licit = bob.measure.farfrr(self.negatives_test_licit, self.positives_test_licit, eer_threshold_licit)
roc_points_dev_licit = bob.measure.roc(self.negatives_dev_licit, self.positives_dev_licit, 100)
roc_points_test_licit = bob.measure.roc(self.negatives_test_licit, self.positives_test_licit, 100)
dev_hist_pos_licit, dev_bin_pos_licit = numpy.histogram(self.positives_dev_licit, self.n_bins_real)
dev_hist_neg_licit, dev_bin_neg_licit = numpy.histogram(self.negatives_dev_licit, self.n_bins_zimp)
test_hist_pos_licit, test_bin_pos_licit = numpy.histogram(self.positives_test_licit, self.n_bins_real)
test_hist_neg_licit, test_bin_neg_licit = numpy.histogram(self.negatives_test_licit, self.n_bins_zimp)
# then, compute everything for spoof scenario (no zero-impostor)
self.positives_dev_spoof = self.dev_scores_real
self.negatives_dev_spoof = dev_scores_attack
self.positives_test_spoof = test_scores_real
self.negatives_test_spoof = test_scores_attack
eer_threshold_spoof = bob.measure.eer_threshold(self.negatives_dev_spoof, self.positives_dev_spoof)
far_dev_spoof, frr_dev_spoof = bob.measure.farfrr(self.negatives_dev_spoof, self.positives_dev_spoof, eer_threshold_spoof)
far_test_spoof, frr_test_spoof = bob.measure.farfrr(self.negatives_test_spoof, self.positives_test_spoof, eer_threshold_spoof)
roc_points_dev_spoof = bob.measure.roc(self.negatives_dev_spoof, self.positives_dev_spoof, 100)
roc_points_test_spoof = bob.measure.roc(self.negatives_test_spoof, self.positives_test_spoof, 100)
dev_hist_neg_spoof, dev_bin_neg_spoof = numpy.histogram(self.negatives_dev_spoof, self.n_bins_attack)
test_hist_neg_spoof, test_bin_neg_spoof = numpy.histogram(self.negatives_test_spoof, self.n_bins_attack)
# writes the output back to the platform
output.write({
'EER_licit': numpy.float32((far_dev_licit+frr_dev_licit) / 2.),
'threshold_licit': numpy.float32(eer_threshold_licit),
'FAR_dev_licit': numpy.float32(far_dev_licit),
'FRR_dev_licit': numpy.float32(frr_dev_licit),
'HTER_licit': numpy.float32((far_test_licit+frr_test_licit) / 2.),
'FAR_test_licit': numpy.float32(far_test_licit),
'FRR_test_licit': numpy.float32(frr_test_licit),
'number_of_positives_dev_licit': numpy.int32(len(self.positives_dev_licit)),
'number_of_negatives_dev_licit': numpy.int32(len(self.negatives_dev_licit)),
'number_of_positives_test_licit': numpy.int32(len(self.positives_test_licit)),
'number_of_negatives_test_licit': numpy.int32(len(self.negatives_test_licit)),
'EER_spoof': numpy.float32((far_dev_spoof+frr_dev_spoof) / 2.),
'threshold_spoof': numpy.float32(eer_threshold_spoof),
'FAR_dev_spoof': numpy.float32(far_dev_spoof),
'FRR_dev_spoof': numpy.float32(frr_dev_spoof),
'HTER_spoof': numpy.float32((far_test_spoof+frr_test_spoof) / 2.),
'FAR_test_spoof': numpy.float32(far_test_spoof),
'FRR_test_spoof': numpy.float32(frr_test_spoof),
'number_of_positives_dev_spoof': numpy.int32(len(self.positives_dev_spoof)),
'number_of_negatives_dev_spoof': numpy.int32(len(self.negatives_dev_spoof)),
'number_of_positives_test_spoof': numpy.int32(len(self.positives_test_spoof)),
'number_of_negatives_test_spoof': numpy.int32(len(self.negatives_test_spoof)),
'roc_dev': {
"data":
[
{
"label": "licit-protocol",
"false_positives": roc_points_dev_licit[0],
"false_negatives": roc_points_dev_licit[1],
"number_of_positives": numpy.uint64(len(self.positives_dev_licit)),
"number_of_negatives": numpy.uint64(len(self.negatives_dev_licit)),
},
{
"label": "spoof-protocol",
"false_positives": roc_points_dev_spoof[0],
"false_negatives": roc_points_dev_spoof[1],
"number_of_positives": numpy.uint64(len(self.positives_dev_spoof)),
"number_of_negatives": numpy.uint64(len(self.negatives_dev_spoof)),
}
]
},
'roc_test': {
"data":
[
{
"label": "licit-protocol",
"false_positives": roc_points_test_licit[0],
"false_negatives": roc_points_test_licit[1],
"number_of_positives": numpy.uint64(len(self.positives_test_licit)),
"number_of_negatives": numpy.uint64(len(self.negatives_test_licit)),
},
{
"label": "spoof-protocol",
"false_positives": roc_points_test_spoof[0],
"false_negatives": roc_points_test_spoof[1],
"number_of_positives": numpy.uint64(len(self.positives_test_spoof)),
"number_of_negatives": numpy.uint64(len(self.negatives_test_spoof)),
}
]
},
'dev_histograms': {
"data":
[
{
"label": "Attacks",
"x": dev_bin_neg_spoof[:-1],
"y": dev_hist_neg_spoof,
},
{
"label": "Zero-impostors",
"x": dev_bin_neg_licit[:-1],
"y": dev_hist_neg_licit,
},
{
"label": "Genuine",
"x": dev_bin_pos_licit[:-1],
"y": dev_hist_pos_licit,
}
]
},
'test_histograms': {
"data":
[
{
"label": "Attacks",
"x": test_bin_neg_spoof[:-1],
"y": test_hist_neg_spoof,
},
{
"label": "Zero-impostors",
"x": test_bin_neg_licit[:-1],
"y": test_hist_neg_licit,
},
{
"label": "Genuine",
"x": test_bin_pos_licit[:-1],
"y": test_hist_pos_licit,
}
]
}
})
return True
The code for this algorithm in Python
The ruler at 80 columns indicate suggested POSIX line breaks (for readability).
The editor will automatically enlarge to accomodate the entirety of your input
Use keyboard shortcuts for search/replace and faster editing. For example, use Ctrl-F (PC) or Cmd-F (Mac) to search through this box
An algorithm that implements standard metrics for biometric system evaluation.
Specifically, it returns:
This implementation relies on the 'measure' package from the `Bob <http://www.idiap.ch/software/bob>`_ library.
Updated | Name | Databases/Protocols | Analyzers | |||
---|---|---|---|---|---|---|
pkorshunov/pkorshunov/isv-asv-pad-fusion-complete/1/asv_isv-pad_lbp_hist_ratios_lr-fusion_lr-pa_aligned | avspoof/2@physicalaccess_verification,avspoof/2@physicalaccess_verify_train,avspoof/2@physicalaccess_verify_train_spoof,avspoof/2@physicalaccess_antispoofing,avspoof/2@physicalaccess_verification_spoof | pkorshunov/spoof-score-fusion-roc_hist/1 | ||||
pkorshunov/pkorshunov/isv-asv-pad-fusion-complete/1/asv_isv-pad_gmm-fusion_lr-pa | avspoof/2@physicalaccess_verification,avspoof/2@physicalaccess_verify_train,avspoof/2@physicalaccess_verify_train_spoof,avspoof/2@physicalaccess_antispoofing,avspoof/2@physicalaccess_verification_spoof | pkorshunov/spoof-score-fusion-roc_hist/1 |
This table shows the number of times this algorithm has been successfully run using the given environment. Note this does not provide sufficient information to evaluate if the algorithm will run when submitted to different conditions.