Skip to content
Snippets Groups Projects
Commit c0cd0dca authored by Tiago de Freitas Pereira's avatar Tiago de Freitas Pereira
Browse files

Implemented score_for_multiple_biometric_references for legacy models

parent 63cd23d3
No related branches found
No related tags found
1 merge request!180[dask] Preparing bob.bio.base for dask pipelines
Pipeline #38477 failed
......@@ -55,7 +55,6 @@ extractor = functools.partial(
node_distance=(8, 8),
)
transformer = make_pipeline(
Preprocessor(preprocessor, features_dir=os.path.join(base_dir, "face_cropper")),
Extractor(extractor, features_dir=os.path.join(base_dir, "gabor_graph")),
......@@ -71,7 +70,8 @@ gabor_jet = functools.partial(
gabor_sigma=math.sqrt(2.0) * math.pi,
)
algorithm = AlgorithmAsBioAlg(callable=gabor_jet, features_dir=base_dir)
algorithm = AlgorithmAsBioAlg(callable=gabor_jet, features_dir=base_dir, allow_score_multiple_references=True)
#algorithm = AlgorithmAsBioAlg(callable=gabor_jet, features_dir=base_dir)
# comment out the code below to disable dask
......
......@@ -19,7 +19,7 @@ class BioAlgorithm(metaclass=ABCMeta):
"""
def __init__(self, allow_score_multiple_references=False):
def __init__(self, allow_score_multiple_references=False, **kwargs):
self.allow_score_multiple_references = allow_score_multiple_references
self.stacked_biometric_references = None
......@@ -126,10 +126,10 @@ class BioAlgorithm(metaclass=ABCMeta):
scores = self.score_multiple_biometric_references(
self.stacked_biometric_references, s
)
# Wrapping the scores in samples
for ref, score in zip(biometric_references, scores):
subprobe_scores.append(_write_sample(ref, sampleset, score[0]))
subprobe_scores.append(_write_sample(ref, sampleset, score))
else:
for ref in [
......@@ -172,7 +172,7 @@ class BioAlgorithm(metaclass=ABCMeta):
@abstractmethod
def score_multiple_biometric_references(self, biometric_references, data):
"""
It handles the score computation of one probe and multiple biometric references
It handles the score computation of one probe against multiple biometric references
This method is called is called if `allow_scoring_multiple_references` is set to true
Parameters
......
......@@ -3,11 +3,14 @@ from sklearn.utils.validation import check_array
import numpy
from .abstract_classes import BioAlgorithm
from .mixins import BioAlgCheckpointMixin
from scipy.spatial.distance import cdist
class Distance(BioAlgorithm):
def __init__(self, distance_function=scipy.spatial.distance.euclidean, factor=-1):
def __init__(
self, distance_function=scipy.spatial.distance.euclidean, factor=-1, **kwargs
):
super().__init__(**kwargs)
self.distance_function = distance_function
self.factor = factor
......@@ -33,7 +36,7 @@ class Distance(BioAlgorithm):
return numpy.mean(enroll_features, axis=0)
def score(self, model, probe):
def score(self, biometric_reference, data):
"""score(model, probe) -> float
Computes the distance of the model to the probe using the distance function specified in the constructor.
......@@ -54,9 +57,18 @@ class Distance(BioAlgorithm):
A similarity value between ``model`` and ``probe``
"""
probe = probe.flatten()
data = data.flatten()
# return the negative distance (as a similarity measure)
return self.factor * self.distance_function(model, probe)
return self.factor * self.distance_function(biometric_reference, data)
def score_multiple_biometric_references(self, biometric_references, data):
data = data.flatten()
references_stacked = numpy.vstack(biometric_references)
scores = self.factor * cdist(
references_stacked, data.reshape(1, -1), self.distance_function
)
return list(scores.flatten())
class CheckpointDistance(BioAlgCheckpointMixin, Distance):
......
......@@ -173,12 +173,12 @@ class _NonPickableWrapper:
def __setstate__(self, d):
# Handling unpicklable objects
self._instance = None
#return super().__setstate__(d)
# return super().__setstate__(d)
def __getstate__(self):
# Handling unpicklable objects
self._instance = None
#return super().__getstate__()
# return super().__getstate__()
class _Preprocessor(_NonPickableWrapper, TransformerMixin, BaseEstimator):
......@@ -345,7 +345,7 @@ class AlgorithmAsTransformer(CheckpointMixin, SampleMixin, _AlgorithmTransformer
return self
class AlgorithmAsBioAlg(BioAlgorithm, _NonPickableWrapper):
class AlgorithmAsBioAlg(_NonPickableWrapper, BioAlgorithm):
"""Biometric Algorithm that handles legacy :py:class:`bob.bio.base.algorithm.Algorithm`
......@@ -387,19 +387,35 @@ class AlgorithmAsBioAlg(BioAlgorithm, _NonPickableWrapper):
# We should add an agregator function here so we can properlly agregate samples from
# a sampleset either after or before scoring.
# To be honest, this should be the default behaviour
def _write_sample(ref, probe, score):
data = make_four_colums_score(ref.subject, probe.subject, probe.path, score)
return Sample(data, parent=ref)
retval = []
for subprobe_id, s in enumerate(sampleset.samples):
# Creating one sample per comparison
subprobe_scores = []
for ref in [
r for r in biometric_references if r.key in sampleset.references
]:
score = self.score(ref.data, s.data)
data = make_four_colums_score(
ref.subject, sampleset.subject, sampleset.path, score
if self.allow_score_multiple_references:
if self.stacked_biometric_references is None:
self.stacked_biometric_references = [
ref.data for ref in biometric_references
]
scores = self.score_multiple_biometric_references(
self.stacked_biometric_references, s.data
)
subprobe_scores.append(Sample(data, parent=ref))
# Wrapping the scores in samples
for ref, score in zip(biometric_references, scores):
subprobe_scores.append(_write_sample(ref, sampleset, score))
else:
for ref in [
r for r in biometric_references if r.key in sampleset.references
]:
score = self.score(ref.data, s.data)
subprobe_scores.append(_write_sample(ref, sampleset, score))
# Creating one sampleset per probe
subprobe = SampleSet(subprobe_scores, parent=sampleset)
......@@ -438,5 +454,17 @@ class AlgorithmAsBioAlg(BioAlgorithm, _NonPickableWrapper):
reader = _get_pickable_method(self.instance.read_model)
return DelayedSample(functools.partial(reader, path), parent=enroll_features)
def score(self, model, probe, **kwargs):
return self.instance.score(model, probe)
def score(self, biometric_reference, data, **kwargs):
return self.instance.score(biometric_reference, data)
def score_multiple_biometric_references(self, biometric_references, data, **kwargs):
"""
It handles the score computation of one probe against multiple biometric references using legacy
`bob.bio.base`
Basically it wraps :py:meth:`bob.bio.base.algorithm.Algorithm.score_for_multiple_models`.
"""
scores = self.instance.score_for_multiple_models(biometric_references, data)
return scores
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment