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( ...@@ -55,7 +55,6 @@ extractor = functools.partial(
node_distance=(8, 8), node_distance=(8, 8),
) )
transformer = make_pipeline( transformer = make_pipeline(
Preprocessor(preprocessor, features_dir=os.path.join(base_dir, "face_cropper")), Preprocessor(preprocessor, features_dir=os.path.join(base_dir, "face_cropper")),
Extractor(extractor, features_dir=os.path.join(base_dir, "gabor_graph")), Extractor(extractor, features_dir=os.path.join(base_dir, "gabor_graph")),
...@@ -71,7 +70,8 @@ gabor_jet = functools.partial( ...@@ -71,7 +70,8 @@ gabor_jet = functools.partial(
gabor_sigma=math.sqrt(2.0) * math.pi, 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 # comment out the code below to disable dask
......
...@@ -19,7 +19,7 @@ class BioAlgorithm(metaclass=ABCMeta): ...@@ -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.allow_score_multiple_references = allow_score_multiple_references
self.stacked_biometric_references = None self.stacked_biometric_references = None
...@@ -126,10 +126,10 @@ class BioAlgorithm(metaclass=ABCMeta): ...@@ -126,10 +126,10 @@ class BioAlgorithm(metaclass=ABCMeta):
scores = self.score_multiple_biometric_references( scores = self.score_multiple_biometric_references(
self.stacked_biometric_references, s self.stacked_biometric_references, s
) )
# Wrapping the scores in samples # Wrapping the scores in samples
for ref, score in zip(biometric_references, scores): 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: else:
for ref in [ for ref in [
...@@ -172,7 +172,7 @@ class BioAlgorithm(metaclass=ABCMeta): ...@@ -172,7 +172,7 @@ class BioAlgorithm(metaclass=ABCMeta):
@abstractmethod @abstractmethod
def score_multiple_biometric_references(self, biometric_references, data): 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 This method is called is called if `allow_scoring_multiple_references` is set to true
Parameters Parameters
......
...@@ -3,11 +3,14 @@ from sklearn.utils.validation import check_array ...@@ -3,11 +3,14 @@ from sklearn.utils.validation import check_array
import numpy import numpy
from .abstract_classes import BioAlgorithm from .abstract_classes import BioAlgorithm
from .mixins import BioAlgCheckpointMixin from .mixins import BioAlgCheckpointMixin
from scipy.spatial.distance import cdist
class Distance(BioAlgorithm): 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.distance_function = distance_function
self.factor = factor self.factor = factor
...@@ -33,7 +36,7 @@ class Distance(BioAlgorithm): ...@@ -33,7 +36,7 @@ class Distance(BioAlgorithm):
return numpy.mean(enroll_features, axis=0) return numpy.mean(enroll_features, axis=0)
def score(self, model, probe): def score(self, biometric_reference, data):
"""score(model, probe) -> float """score(model, probe) -> float
Computes the distance of the model to the probe using the distance function specified in the constructor. Computes the distance of the model to the probe using the distance function specified in the constructor.
...@@ -54,9 +57,18 @@ class Distance(BioAlgorithm): ...@@ -54,9 +57,18 @@ class Distance(BioAlgorithm):
A similarity value between ``model`` and ``probe`` A similarity value between ``model`` and ``probe``
""" """
probe = probe.flatten() data = data.flatten()
# return the negative distance (as a similarity measure) # 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): class CheckpointDistance(BioAlgCheckpointMixin, Distance):
......
...@@ -173,12 +173,12 @@ class _NonPickableWrapper: ...@@ -173,12 +173,12 @@ class _NonPickableWrapper:
def __setstate__(self, d): def __setstate__(self, d):
# Handling unpicklable objects # Handling unpicklable objects
self._instance = None self._instance = None
#return super().__setstate__(d) # return super().__setstate__(d)
def __getstate__(self): def __getstate__(self):
# Handling unpicklable objects # Handling unpicklable objects
self._instance = None self._instance = None
#return super().__getstate__() # return super().__getstate__()
class _Preprocessor(_NonPickableWrapper, TransformerMixin, BaseEstimator): class _Preprocessor(_NonPickableWrapper, TransformerMixin, BaseEstimator):
...@@ -345,7 +345,7 @@ class AlgorithmAsTransformer(CheckpointMixin, SampleMixin, _AlgorithmTransformer ...@@ -345,7 +345,7 @@ class AlgorithmAsTransformer(CheckpointMixin, SampleMixin, _AlgorithmTransformer
return self return self
class AlgorithmAsBioAlg(BioAlgorithm, _NonPickableWrapper): class AlgorithmAsBioAlg(_NonPickableWrapper, BioAlgorithm):
"""Biometric Algorithm that handles legacy :py:class:`bob.bio.base.algorithm.Algorithm` """Biometric Algorithm that handles legacy :py:class:`bob.bio.base.algorithm.Algorithm`
...@@ -387,19 +387,35 @@ class AlgorithmAsBioAlg(BioAlgorithm, _NonPickableWrapper): ...@@ -387,19 +387,35 @@ class AlgorithmAsBioAlg(BioAlgorithm, _NonPickableWrapper):
# We should add an agregator function here so we can properlly agregate samples from # We should add an agregator function here so we can properlly agregate samples from
# a sampleset either after or before scoring. # a sampleset either after or before scoring.
# To be honest, this should be the default behaviour # 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 = [] retval = []
for subprobe_id, s in enumerate(sampleset.samples): for subprobe_id, s in enumerate(sampleset.samples):
# Creating one sample per comparison # Creating one sample per comparison
subprobe_scores = [] subprobe_scores = []
for ref in [ if self.allow_score_multiple_references:
r for r in biometric_references if r.key in sampleset.references if self.stacked_biometric_references is None:
]: self.stacked_biometric_references = [
score = self.score(ref.data, s.data) ref.data for ref in biometric_references
data = make_four_colums_score( ]
ref.subject, sampleset.subject, sampleset.path, score 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 # Creating one sampleset per probe
subprobe = SampleSet(subprobe_scores, parent=sampleset) subprobe = SampleSet(subprobe_scores, parent=sampleset)
...@@ -438,5 +454,17 @@ class AlgorithmAsBioAlg(BioAlgorithm, _NonPickableWrapper): ...@@ -438,5 +454,17 @@ class AlgorithmAsBioAlg(BioAlgorithm, _NonPickableWrapper):
reader = _get_pickable_method(self.instance.read_model) reader = _get_pickable_method(self.instance.read_model)
return DelayedSample(functools.partial(reader, path), parent=enroll_features) return DelayedSample(functools.partial(reader, path), parent=enroll_features)
def score(self, model, probe, **kwargs): def score(self, biometric_reference, data, **kwargs):
return self.instance.score(model, probe) 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