From 2d167d1cc64868fec2308b80cfa73b37c16f4c6a Mon Sep 17 00:00:00 2001 From: Tiago Freitas Pereira <tiagofrepereira@gmail.com> Date: Sun, 14 Feb 2021 19:39:39 +0100 Subject: [PATCH] Included two new baselines --- .../mobilenetv2_msceleb_arcface_2021.py | 34 ++++++++ .../baseline/resnet50_msceleb_arcface_2021.py | 34 ++++++++ bob/bio/face/embeddings/mobilenet_v2.py | 79 +++++++++++++++++++ bob/bio/face/embeddings/resnet50.py | 79 +++++++++++++++++++ .../face/embeddings/tf2_inception_resnet.py | 8 -- setup.py | 4 + 6 files changed, 230 insertions(+), 8 deletions(-) create mode 100644 bob/bio/face/config/baseline/mobilenetv2_msceleb_arcface_2021.py create mode 100644 bob/bio/face/config/baseline/resnet50_msceleb_arcface_2021.py create mode 100644 bob/bio/face/embeddings/mobilenet_v2.py create mode 100644 bob/bio/face/embeddings/resnet50.py diff --git a/bob/bio/face/config/baseline/mobilenetv2_msceleb_arcface_2021.py b/bob/bio/face/config/baseline/mobilenetv2_msceleb_arcface_2021.py new file mode 100644 index 00000000..e68e7ef3 --- /dev/null +++ b/bob/bio/face/config/baseline/mobilenetv2_msceleb_arcface_2021.py @@ -0,0 +1,34 @@ +from bob.bio.face.embeddings.mobilenet_v2 import MobileNetv2_MsCeleb_ArcFace_2021 +from bob.bio.face.config.baseline.helpers import embedding_transformer_112x112 +from bob.bio.base.pipelines.vanilla_biometrics import ( + Distance, + VanillaBiometricsPipeline, +) + +memory_demanding = False +if "database" in locals(): + annotation_type = database.annotation_type + fixed_positions = database.fixed_positions + + memory_demanding = ( + database.memory_demanding if hasattr(database, "memory_demanding") else False + ) +else: + annotation_type = None + fixed_positions = None + + +def load(annotation_type, fixed_positions=None): + transformer = embedding_transformer_112x112( + MobileNetv2_MsCeleb_ArcFace_2021(memory_demanding=memory_demanding), + annotation_type, + fixed_positions, + ) + + algorithm = Distance() + + return VanillaBiometricsPipeline(transformer, algorithm) + + +pipeline = load(annotation_type, fixed_positions) +transformer = pipeline.transformer diff --git a/bob/bio/face/config/baseline/resnet50_msceleb_arcface_2021.py b/bob/bio/face/config/baseline/resnet50_msceleb_arcface_2021.py new file mode 100644 index 00000000..dfeb4b74 --- /dev/null +++ b/bob/bio/face/config/baseline/resnet50_msceleb_arcface_2021.py @@ -0,0 +1,34 @@ +from bob.bio.face.embeddings.resnet50 import Resnet50_MsCeleb_ArcFace_2021 +from bob.bio.face.config.baseline.helpers import embedding_transformer_112x112 +from bob.bio.base.pipelines.vanilla_biometrics import ( + Distance, + VanillaBiometricsPipeline, +) + +memory_demanding = False +if "database" in locals(): + annotation_type = database.annotation_type + fixed_positions = database.fixed_positions + + memory_demanding = ( + database.memory_demanding if hasattr(database, "memory_demanding") else False + ) +else: + annotation_type = None + fixed_positions = None + + +def load(annotation_type, fixed_positions=None): + transformer = embedding_transformer_112x112( + Resnet50_MsCeleb_ArcFace_2021(memory_demanding=memory_demanding), + annotation_type, + fixed_positions, + ) + + algorithm = Distance() + + return VanillaBiometricsPipeline(transformer, algorithm) + + +pipeline = load(annotation_type, fixed_positions) +transformer = pipeline.transformer diff --git a/bob/bio/face/embeddings/mobilenet_v2.py b/bob/bio/face/embeddings/mobilenet_v2.py new file mode 100644 index 00000000..4966583f --- /dev/null +++ b/bob/bio/face/embeddings/mobilenet_v2.py @@ -0,0 +1,79 @@ +from bob.bio.face.embeddings import download_model + + +from .tf2_inception_resnet import TransformTensorflow +import pkg_resources +import os +from bob.extension import rc +import tensorflow as tf + + +class MobileNetv2_MsCeleb_ArcFace_2021(TransformTensorflow): + """ + MobileNet Backbone trained with the MSCeleb 1M database. + + The bottleneck layer (a.k.a embedding) has 512d. + + The configuration file used to trained is: + + ```yaml + batch-size: 128 + face-size: 112 + face-output_size: 112 + n-classes: 85742 + + + ## Backbone + backbone: 'mobilenet-v2' + head: 'arcface' + s: 10 + bottleneck: 512 + m: 0.5 + + # Training parameters + solver: "sgd" + lr: 0.01 + dropout-rate: 0.5 + epochs: 500 + + + train-tf-record-path: "<PATH>" + validation-tf-record-path: "<PATH>" + + ``` + + + """ + + def __init__(self, memory_demanding=False): + internal_path = pkg_resources.resource_filename( + __name__, os.path.join("data", "mobilenet-v2-msceleb-arcface-2021"), + ) + + checkpoint_path = ( + internal_path + if rc["bob.bio.face.models.mobilenet-v2-msceleb-arcface-2021"] is None + else rc["bob.bio.face.models.mobilenet-v2-msceleb-arcface-2021"] + ) + + urls = [ + "https://www.idiap.ch/software/bob/data/bob/bob.bio.face/master/tf2/mobilenet-v2-msceleb-arcface-2021.tar.gz", + "http://www.idiap.ch/software/bob/data/bob/bob.bio.face/master/tf2/mobilenet-v2-msceleb-arcface-2021.tar.gz", + ] + + download_model(checkpoint_path, urls, "mobilenet-v2-msceleb-arcface-2021.tar.gz") + + super(MobileNetv2_MsCeleb_ArcFace_2021, self).__init__( + checkpoint_path, + preprocessor=lambda X: X / 255.0, + memory_demanding=memory_demanding, + ) + + def inference(self, X): + if self.preprocessor is not None: + X = self.preprocessor(tf.cast(X, "float32")) + + prelogits = self.model.predict_on_batch(X)[0] + embeddings = tf.math.l2_normalize(prelogits, axis=-1) + return embeddings + diff --git a/bob/bio/face/embeddings/resnet50.py b/bob/bio/face/embeddings/resnet50.py new file mode 100644 index 00000000..8a75b2ed --- /dev/null +++ b/bob/bio/face/embeddings/resnet50.py @@ -0,0 +1,79 @@ +from bob.bio.face.embeddings import download_model + + +from .tf2_inception_resnet import TransformTensorflow +import pkg_resources +import os +from bob.extension import rc +import tensorflow as tf + + +class Resnet50_MsCeleb_ArcFace_2021(TransformTensorflow): + """ + Resnet50 Backbone trained with the MSCeleb 1M database. + + The bottleneck layer (a.k.a embedding) has 512d. + + The configuration file used to trained is: + + ```yaml + batch-size: 128 + face-size: 112 + face-output_size: 112 + n-classes: 85742 + + + ## Backbone + backbone: 'resnet50' + head: 'arcface' + s: 10 + bottleneck: 512 + m: 0.5 + + # Training parameters + solver: "sgd" + lr: 0.01 + dropout-rate: 0.5 + epochs: 500 + + + train-tf-record-path: "<PATH>" + validation-tf-record-path: "<PATH>" + + ``` + + + """ + + def __init__(self, memory_demanding=False): + internal_path = pkg_resources.resource_filename( + __name__, os.path.join("data", "resnet50_msceleb_arcface_2021"), + ) + + checkpoint_path = ( + internal_path + if rc["bob.bio.face.models.resnet50_msceleb_arcface_2021"] is None + else rc["bob.bio.face.models.resnet50_msceleb_arcface_2021"] + ) + + urls = [ + "https://www.idiap.ch/software/bob/data/bob/bob.bio.face/master/tf2/resnet50_msceleb_arcface_2021.tar.gz", + "http://www.idiap.ch/software/bob/data/bob/bob.bio.face/master/tf2/resnet50_msceleb_arcface_2021.tar.gz", + ] + + download_model(checkpoint_path, urls, "resnet50_msceleb_arcface_2021.tar.gz") + + super(Resnet50_MsCeleb_ArcFace_2021, self).__init__( + checkpoint_path, + preprocessor=lambda X: X / 255.0, + memory_demanding=memory_demanding, + ) + + def inference(self, X): + if self.preprocessor is not None: + X = self.preprocessor(tf.cast(X, "float32")) + + prelogits = self.model.predict_on_batch(X)[0] + embeddings = tf.math.l2_normalize(prelogits, axis=-1) + return embeddings + diff --git a/bob/bio/face/embeddings/tf2_inception_resnet.py b/bob/bio/face/embeddings/tf2_inception_resnet.py index 18a2bc15..52ad8d26 100644 --- a/bob/bio/face/embeddings/tf2_inception_resnet.py +++ b/bob/bio/face/embeddings/tf2_inception_resnet.py @@ -52,14 +52,6 @@ class TransformTensorflow(TransformerMixin, BaseEstimator): def load_model(self): self.model = tf.keras.models.load_model(self.checkpoint_path) - def inference(self, X): - if self.preprocessor is not None: - X = self.preprocessor(tf.cast(X, "float32")) - - prelogits = self.model.predict_on_batch(X) - embeddings = tf.math.l2_normalize(prelogits, axis=-1) - return embeddings - def transform(self, X): def _transform(X): X = tf.convert_to_tensor(X) diff --git a/setup.py b/setup.py index daf7cdb0..34bcf0e2 100644 --- a/setup.py +++ b/setup.py @@ -146,6 +146,8 @@ setup( "lgbphs = bob.bio.face.config.baseline.lgbphs:pipeline", "lda = bob.bio.face.config.baseline.lda:pipeline", "dummy = bob.bio.face.config.baseline.dummy:pipeline", + "resnet50-msceleb-arcface-2021 = bob.bio.face.config.baseline.resnet50_msceleb_arcface_2021:pipeline", + "mobilenetv2-msceleb-arcface-2021 = bob.bio.face.config.baseline.mobilenetv2_msceleb_arcface_2021", ], "bob.bio.config": [ "facenet-sanderberg = bob.bio.face.config.baseline.facenet_sanderberg", @@ -174,6 +176,8 @@ setup( "fargo = bob.bio.face.config.database.fargo", "meds = bob.bio.face.config.database.meds", "morph = bob.bio.face.config.database.morph", + "resnet50-msceleb-arcface-2021 = bob.bio.face.config.baseline.resnet50_msceleb_arcface_2021", + "mobilenetv2-msceleb-arcface-2021 = bob.bio.face.config.baseline.mobilenetv2_msceleb_arcface_2021", ], "bob.bio.cli": [ "display-face-annotations = bob.bio.face.script.display_face_annotations:display_face_annotations", -- GitLab