MobileNetV2 + GeM + Batch-Hard Quadruplet — Turtle Re-Identification (Combined Datasets)

A re-identification embedding model for individual sea-turtle recognition. It maps a turtle photo to a 512-d L2-normalisable embedding; identity is decided by nearest-neighbour retrieval (cosine / Euclidean on the unit sphere) against a labelled gallery. Trained jointly on the heads-crop SeaTurtleID2022 set plus two additional sea-turtle datasets (Amvrakikos, Reunion) so the learned embedding generalises across photography conditions and populations.

This is a reproduction of the SeaTurtleID2022 re-id protocol using a MobileNetV2 backbone (not the paper's Swin-B/ArcFace), trained with batch-hard quadruplet loss and WeightedMPerClassSampler — deliberately a small, fully-trainable backbone with a metric loss, to show how far that recipe reaches.

Model

  • Architecture: MobileNetV2 (fully unfrozen) → Generalized Mean pooling (GeM, p=3.0 learnable) → Linear(1280→512) → LayerNorm → ReLU → Dropout(0.3)
  • Embedding dim: 512 (L2-normalise before retrieval)
  • Input resolution: 384×384 (centre-crop at eval; resize→random-crop at train)
  • Loss: batch-hard quadruplet (top-k=6 soft-hard mining; alpha=0.3, beta=0.1)
  • Sampler: WeightedMPerClassSampler (m=4 instances per identity per batch)
  • Batch size: 128 (32 classes/batch → 124 negatives/anchor; larger batch both lifted R@1 and collapsed seed variance ~8× vs the v7 batch-64 config)
  • Schedule: 150 epochs, LinearLR 5-epoch warmup → CosineAnnealingWarmRestarts(T_0=75, T_mult=2), base LR 1.4e-4, AMP (fp16)

Loading

PyTorchModelHubMixin reconstructs the model from config.json; only embedding_dim is a constructor kwarg, the rest are metadata. The pretrained backbone weights are re-fetched at construction, then overwritten by the Hub state_dict on from_pretrained.

import torch
from torchvision import transforms as T

# Define the MobileNetV2ReID class exactly as in the source (or import it from the project),
# then load weights straight from the Hub:
model = MobileNetV2ReID.from_pretrained(
    "marcmarais-ru/seaturtle_reid_mobilenetv2-quadruplet-random-combined_datasets",
    embedding_dim=512,            # must match the trained dim
)
model.eval().cuda()

# Eval transform: resize so the shorter/a side hits 384, then centre-crop.
eval_transform = T.Compose([
    T.Resize((384, 384)),         
    T.ToTensor(),
    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

Retrieval recipe

Closed-set re-id, k-NN against a labelled gallery (gallery = train split, query = test split). Embeddings are not pre-normalised, so normalise before any distance:

with torch.no_grad():
    emb = model(eval_transform(image).unsqueeze(0).cuda())
emb = torch.nn.functional.normalize(emb, p=2, dim=1)   # L2-normalise -> cosine == dot product
# gallery_emb likewise L2-normalised; nearest neighbour = argmax(emb @ gallery_emb.T)

Datasets used (training)

The model is trained on the union of three sea-turtle re-id datasets, all drawn from the wildlifedatasets loader under Data/wildlifedatasets/:

Dataset (folder) Role
seaturtleidheads (v3) Heads-crop SeaTurtleID2022
amvrakikosturtles (v1) Amvrakikos Gulf turtles
reunionturtles (v1) Reunion Island turtles

Identities are merged across datasets via a global_id mapping so an individual in one dataset never collides with one in another. The split is the published split_closed_random column (random closed-set split — no identity appears in both train and test).

Results (test, random split, 384-res)

Reported as mean ± std over 3 seeds (batch 128, top-k=6, lr 1.4e-4); the published checkpoint is the best seed of that sweep (seed 2026, Overall R@1 0.7200). The data split is held fixed across seeds (SeaTurtleID2022 published split_closed_random + deterministic ClosedSetSplit for Amvrakikos/Reunion), so variance reflects weight-init / augmentation / sampler draw only.

Target split R@1 (mean ± std, n=3)
Overall Cross-Dataset 0.7166 ± 0.0036
Sea Turtle (Heads Crop) 0.7344 ± 0.0051
Amvrakikos 0.3267 ± 0.0462
Reunion 0.4762 ± 0.0119

Per-species breakdown (published seed)

Loggerhead is the heads-crop SeaTurtleID2022 test set plus the Amvrakikos test set; Green and Hawksbill are the Reunion test set filtered by its Species column.

Species n images R@1
Loggerhead 2281 0.7290
Green 50 0.5000
Hawksbill 34 0.4412

Intended use & limitations

  • Intended: individual animal re-identification research/benchmarks, closed-set retrieval.
  • Not intended: open-set detection of unseen individuals, human identification, or any use outside wildlife research.
  • Limitations: trained on three sea-turtle populations only; generalisation to other taxa or unseen photography conditions is unverified. Closed-set protocol assumes the query individual is present in the gallery. Time-aware split performance is much lower (time-overfitting); see the source paper and code for that regime's caveats.

Citation

If you use this model, please cite the relevant datasets paper and this work:

@inproceedings{adam2024seaturtleid2022,
    author = {Adam, Lukas and Cermak, Vojtech and Papafitsoros, Kostas and Picek, Lukas},
    booktitle = {2024 IEEE/CVF Winter Conference on Applications of Computer Vision (WACV)},
    title = {SeaTurtleID2022: A long-span dataset for reliable sea turtle re-identification},
    year = {2024},
    pages = {7131-7141},
    doi = {10.1109/WACV57701.2024.00699},
    publisher = {IEEE Computer Society}
}
@inproceedings{vcermak2024wildlifedatasets,
    author = {Cermak, Vojtech and Picek, Lukas and Adam, Lukas and Papafitsoros, Kostas},
    booktitle = {2024 IEEE/CVF Winter Conference on Applications of Computer Vision (WACV)},
    title = {WildlifeDatasets: An open-source toolkit for animal re-identification},
    year = {2024},
    pages = {5941-5951},
    doi = {10.1109/WACV57701.2024.00585},
    publisher = {IEEE Computer Society}
}
Downloads last month
7,540
Safetensors
Model size
2.91M params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support