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.
This checkpoint corresponds to the combined multi-species (Experiment 2) model in the
accompanying paper. It is the only released checkpoint; the single-species Experiment 1 model
is not released. Every number reported on this card is reproducible from the shipped
eval.py and model.py (no project code required): load the weights from the Hub with
MobileNetV2ReID.from_pretrained and run python eval.py to recompute the Results table
below under the closed-set train-gallery k-NN protocol with 10-crop TTA at 384.
The model class ships with the repo as model.py (self-contained, no project
dependency). 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 model import MobileNetV2ReID # model.py ships on this repo
# 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)), # SeaTurtleID2022 heads are near-square; resize is fine
T.ToTensor(),
T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
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)
For the full test-time setup (10-crop TTA, closed-set guard dropping unclosed query identities,
Recall@1/5), see the Project_Code.py source: compute_embeddings_tta and compute_recall_at_k.
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 | Notes |
|---|---|---|
seaturtleidheads (v3) |
Heads-crop SeaTurtleID2022 | Primary; 233 identities, heads only |
amvrakikosturtles (v1) |
Amvrakikos Gulf turtles | Greek population, distinct photography |
reunionturtles (v1) |
Reunion Island turtles | Indian-Ocean population, distinct photography |
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).
Reference for the SeaTurtleID2022 protocol: SeaTurtleID2022: A Large-Scale Re-Identification Benchmark for Sea Turtles (arXiv 2211.10307). The paper reports results with a Swin-B + ArcFace backbone; this model is the MobileNetV2 + quadruplet reproduction of that protocol.
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) | R@5 (mean ± std, n=3) |
|---|---|---|
| Overall Cross-Dataset | 0.7166 ± 0.0036 | 0.7722 ± 0.0056 |
| Sea Turtle (Heads Crop) | 0.7344 ± 0.0051 | 0.7880 ± 0.0051 |
| Amvrakikos | 0.3267 ± 0.0462 | 0.4400 ± 0.0200 |
| Reunion | 0.4762 ± 0.0119 | 0.5516 ± 0.0182 |
All numbers are closed-set Recall@1/5 with the closed-set guard applied (unclosed query identities dropped from scoring). Compare to the paper's Swin-B + ArcFace on the heads random split (R@1 0.872); this MobileNetV2 + quadruplet model reaches 0.734 on heads under the same protocol — a deliberately smaller backbone reaching a large fraction of the Swin-B result.
Variance note: the batch-128 config collapsed seed variance ~8× vs the earlier batch-64 config (Overall R@1 std 0.029 → 0.004). R@5 is near its ceiling (R@5−R@1 gap ≈ 0.06, matching the paper's ~0.07): doubling the negative pool and mined negatives (top-k 3→6) lifted R@1 but moved R@5 by only ~0.002, indicating R@5 is backbone/loss-capacity-limited rather than mining-limited. See the source for the full per-seed breakdown and the v7 batch-64 baseline.
Recall@1/5 partitioned by species within the combined test query set, against
the same combined 10-crop TTA gallery used for the headline numbers above
(comparable to the headline table; NOT multi-seed means). 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 | R@5 |
|---|---|---|---|
| Loggerhead | 2281 | 0.7290 | 0.7849 |
| Green | 50 | 0.5000 | 0.5600 |
| Hawksbill | 34 | 0.4412 | 0.5882 |
Green (n=50) and Hawksbill (n=34) are small per-species partitions, so their per-species R@1/R@5 are noisy point estimates (one image ≈ 0.020 / 0.029 of R@1 respectively); Loggerhead (n=2281) is the trustworthy per-species figure. The per-species R@1 values are lower-bounded by — and aggregate up to — the headline Overall R@1: weighted across species they reconstruct the published Overall R@1 (0.721 for seed 2026).
If you use this model, please cite the SeaTurtleID2022 and WildlifeDatasets papers and this paper:
@article{TIMMERMANS2026104006,
title = {Similarity learning network using quadruplet loss for animal re-identification},
journal = {Ecological Informatics},
volume = {99},
pages = {104006},
year = {2026},
issn = {1574-9541},
doi = {https://doi.org/10.1016/j.ecoinf.2026.104006},
url = {https://www.sciencedirect.com/science/article/pii/S1574954126004139},
author = {Anna Timmermans and Marc Marais},
}
@INPROCEEDINGS {10484106,
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},
volume = {},
ISSN = {},
pages = {7131-7141},
doi = {10.1109/WACV57701.2024.00699},
url = {https://doi.ieeecomputersociety.org/10.1109/WACV57701.2024.00699},
publisher = {IEEE Computer Society},
address = {Los Alamitos, CA, USA},
month =Jan}
@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}
}
@misc{mobilenetv2-quadruplet-turtles,
title = {MobileNetV2 + GeM + batch-hard quadruplet turtle re-identification (combined datasets)},
author = {Marc Marais},
year = {2026},
howpublished = {\url{https://huggingface.co/marcmarais-ru/seaturtle_reid_mobilenetv2-quadruplet-random-combined_datasets}}
}