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