From f453965e54211dafd2dc54a9f8e6fefa34aff7fc Mon Sep 17 00:00:00 2001 From: Tiago Freitas Pereira <tiagofrepereira@gmail.com> Date: Tue, 1 Jun 2021 10:46:06 +0200 Subject: [PATCH] Harmonized interfaces --- bob/bio/face/embeddings/mxnet.py | 6 +++ bob/bio/face/embeddings/pytorch.py | 26 ++++++++++++- bob/bio/face/embeddings/tensorflow.py | 2 +- bob/bio/face/test/test_baselines.py | 55 ++++++++++++--------------- 4 files changed, 55 insertions(+), 34 deletions(-) diff --git a/bob/bio/face/embeddings/mxnet.py b/bob/bio/face/embeddings/mxnet.py index 7fbb5b98..8e8d897d 100644 --- a/bob/bio/face/embeddings/mxnet.py +++ b/bob/bio/face/embeddings/mxnet.py @@ -24,6 +24,9 @@ class MxNetTransformer(TransformerMixin, BaseEstimator): config : str json file containing the DNN spec + preprocessor: + A function that will transform the data right before forward. The default transformation is `X=X` + use_gpu: bool """ @@ -33,6 +36,7 @@ class MxNetTransformer(TransformerMixin, BaseEstimator): config=None, use_gpu=False, memory_demanding=False, + preprocessor=lambda x: x, **kwargs, ): super().__init__(**kwargs) @@ -41,6 +45,7 @@ class MxNetTransformer(TransformerMixin, BaseEstimator): self.use_gpu = use_gpu self.model = None self.memory_demanding = memory_demanding + self.preprocessor = preprocessor def _load_model(self): import mxnet as mx @@ -65,6 +70,7 @@ class MxNetTransformer(TransformerMixin, BaseEstimator): self._load_model() X = check_array(X, allow_nd=True) + X = self.preprocessor(X) def _transform(X): X = mx.nd.array(X) diff --git a/bob/bio/face/embeddings/pytorch.py b/bob/bio/face/embeddings/pytorch.py index d091a581..96f72667 100644 --- a/bob/bio/face/embeddings/pytorch.py +++ b/bob/bio/face/embeddings/pytorch.py @@ -13,13 +13,35 @@ from bob.extension.download import get_file class PyTorchModel(TransformerMixin, BaseEstimator): """ + Base Transformer using pytorch models + + + Parameters + ---------- + + checkpoint_path: str + Path containing the checkpoint + + config: + Path containing some configuration file (e.g. .json, .prototxt) + + preprocessor: + A function that will transform the data right before forward. The default transformation is `X/255` + """ - def __init__(self, checkpoint_path=None, config=None, **kwargs): + def __init__( + self, + checkpoint_path=None, + config=None, + preprocessor=lambda x: x / 255, + **kwargs + ): super().__init__(**kwargs) self.checkpoint_path = checkpoint_path self.config = config self.model = None + self.preprocessor = preprocessor def transform(self, X): """__call__(image) -> feature @@ -42,7 +64,7 @@ class PyTorchModel(TransformerMixin, BaseEstimator): self._load_model() X = check_array(X, allow_nd=True) X = torch.Tensor(X) - X = X / 255 + X = self.preprocessor(X) return self.model(X).detach().numpy() diff --git a/bob/bio/face/embeddings/tensorflow.py b/bob/bio/face/embeddings/tensorflow.py index 3bab5fa9..161b53a2 100644 --- a/bob/bio/face/embeddings/tensorflow.py +++ b/bob/bio/face/embeddings/tensorflow.py @@ -33,7 +33,7 @@ class TensorflowTransformer(TransformerMixin, BaseEstimator): Path containing the checkpoint preprocessor: - Preprocessor function + A function that will transform the data right before forward memory_demanding bool If `True`, the `transform` method will run one sample at the time. diff --git a/bob/bio/face/test/test_baselines.py b/bob/bio/face/test/test_baselines.py index bfa360eb..03863953 100644 --- a/bob/bio/face/test/test_baselines.py +++ b/bob/bio/face/test/test_baselines.py @@ -18,11 +18,11 @@ from bob.bio.base.test.utils import is_library_available images = dict() images["bioref"] = ( pkg_resources.resource_filename("bob.bio.face.test", "data/testimage.jpg"), - {"reye": (131, 176), "leye": (222, 170)}, + {"reye": (176, 131), "leye": (170, 222)}, ) images["probe"] = ( pkg_resources.resource_filename("bob.bio.face.test", "data/ada.png"), - {"reye": (440, 207), "leye": (546, 207)}, + {"reye": (207, 440), "leye": (207, 546)}, ) @@ -81,7 +81,7 @@ def run_baseline(baseline, samples_for_training=[], target_scores=None): assert len(checkpoint_scores[0]) == 1 if target_scores is not None: - np.allclose(target_scores, scores[0][0].data, atol=10e-3, rtol=10e-3) + assert np.allclose(target_scores, scores[0][0].data, atol=10e-3, rtol=10e-3) assert np.isclose(scores[0][0].data, checkpoint_scores[0][0].data) @@ -114,75 +114,68 @@ def run_baseline(baseline, samples_for_training=[], target_scores=None): @pytest.mark.slow @is_library_available("tensorflow") def test_facenet_baseline(): - run_baseline("facenet-sanderberg", target_scores=[-0.9220775737526933]) + run_baseline("facenet-sanderberg", target_scores=-0.9220775737526933) @pytest.mark.slow @is_library_available("tensorflow") def test_inception_resnetv2_msceleb(): - run_baseline("inception-resnetv2-msceleb", target_scores=[-0.43447269718504244]) + run_baseline("inception-resnetv2-msceleb", target_scores=-0.43447269718504244) @pytest.mark.slow @is_library_available("tensorflow") def test_inception_resnetv2_casiawebface(): - run_baseline("inception-resnetv2-casiawebface", target_scores=[-0.634583944368043]) + run_baseline("inception-resnetv2-casiawebface", target_scores=-0.634583944368043) @pytest.mark.slow @is_library_available("tensorflow") def test_inception_resnetv1_msceleb(): - run_baseline("inception-resnetv1-msceleb", target_scores=[-0.44497649298306907]) + run_baseline("inception-resnetv1-msceleb", target_scores=-0.44497649298306907) @pytest.mark.slow @is_library_available("tensorflow") def test_inception_resnetv1_casiawebface(): - run_baseline("inception-resnetv1-casiawebface", target_scores=[-0.6411599976437636]) + run_baseline("inception-resnetv1-casiawebface", target_scores=-0.6411599976437636) @pytest.mark.slow @is_library_available("mxnet") def test_arcface_insightface(): - run_baseline("arcface-insightface", target_scores=[-0.0005965275677296544]) + run_baseline("arcface-insightface", target_scores=-0.0005965275677296544) -def test_gabor_graph(): - run_baseline("gabor_graph", target_scores=[0.4385451147418939]) - - -# def test_lda(): -# run_baseline("lda", get_fake_samples_for_training()) +@pytest.mark.slow +@is_library_available("tensorflow") +def test_arcface_resnet50_msceleb_v1(): + run_baseline("resnet50-msceleb-arcface-2021", target_scores=-0.0008105830382632018) @pytest.mark.slow -@is_library_available("opencv-python") -def test_opencv_pipe(): - run_baseline("opencv-pipe", target_scores=None) +@is_library_available("tensorflow") +def test_arcface_resnet50_vgg2_v1(): + run_baseline("resnet50-vgg2-arcface-2021", target_scores=-0.0035127080413503986) -# @pytest.mark.slow -# @is_library_available("mxnet") -# def test_mxnet_pipe(): -# run_baseline("mxnet-pipe", target_scores=None) +def test_gabor_graph(): + run_baseline("gabor_graph", target_scores=0.4385451147418939) -# @pytest.mark.slow -# @is_library_available("tensorflow") -# def test_tf_pipe(): -# run_baseline("tf-pipe", target_scores=None) +# def test_lda(): +# run_baseline("lda", get_fake_samples_for_training()) @pytest.mark.slow @is_library_available("torch") def test_afffe(): - run_baseline("afffe", target_scores=-0.7397219061544165) + run_baseline( + "afffe", target_scores=-1.0274936425058916, + ) @pytest.mark.slow @is_library_available("cv2") def test_vgg16_oxford(): - import ipdb - - ipdb.set_trace() - run_baseline("vgg16-oxford", target_scores=None) + run_baseline("vgg16-oxford", target_scores=-0.9911880900309596) -- GitLab