DINOv3 ToothVLM: Dental Disease Detection & Periodontal Classification (Sonata)
Models fine-tuned on the Sonata dental dataset, built on a DINOv3 (ViT-B/16) backbone.
License notice: these weights are derived from the DINOv3 pretrained backbone (
dinov3_vitb16_pretrain_lvd1689m), which is released under the DINOv3 License (non-commercial). By using these models you agree to the original DINOv3 license terms.
Repository Layout
weights/
├── detection/best_map.pth # Multi-disease detector (1.1 GB)
└── classification/best_val_acc.pth # Periodontal classifier (661 MB)
1. Detector — Multi-Disease Detection (weights/detection/best_map.pth)
DINOv3 ViT-B/16 backbone + YOLOv10-style end-to-end detection head (NMS-free),
trained on the Sonata All_Diseases COCO split (mixed training of all disease
categories).
Classes (4)
caries · calculus · mouth_ulcer · tooth_discoloration
Performance (COCO bbox, validation)
| Metric | Value |
|---|---|
| mAP@0.5:0.95 | 0.444 |
| mAP@0.5 | 0.699 |
| mAP@0.75 | 0.477 |
| mAP small / medium / large | 0.360 / 0.454 / 0.419 |
| Best mAP (training) | 0.451 |
Training setup
| Hyperparameter | Value |
|---|---|
| Backbone | DINOv3 ViT-B/16 (lvd1689m pretrained) |
| Epochs | 50 |
| Batch size | 8 |
| Base LR / backbone LR | 0.001 / 0.0001 |
| Warmup epochs | 5 |
| Unfrozen transformer blocks | 6 |
| Loss | E2E (YOLOv10) |
Usage
import torch
ckpt = torch.load("weights/detection/best_map.pth", map_location="cpu")
# State dict contains the DINOv3 backbone + v10Detect head.
# See train_detector_sonata.py in the source repo for the exact architecture,
# preprocessing (resize to 1024, normalization) and inference (e2e, no NMS) code.
2. Classifier — Periodontal Disease Classification (weights/classification/best_val_acc.pth)
DINOv3 ViT-B/16 backbone + CNN classification head
(Conv+BN+ReLU → GAP → Dropout → FC), trained on the Sonata
Periodontal_Disease subset with a stratified 70/15/15 train/val/test split.
Classes (3)
gingival_diseases · non_periodontal_disease · periodontitis
Performance (test set, n = 353)
| Metric | Value |
|---|---|
| Accuracy | 0.771 |
| Macro-F1 | 0.772 |
Per-class F1:
| Class | Precision | Recall | F1 |
|---|---|---|---|
| gingival_diseases | 0.788 | 0.741 | 0.764 |
| non_periodontal_disease | 0.641 | 0.750 | 0.691 |
| periodontitis | 0.883 | 0.838 | 0.860 |
Training setup
Same backbone fine-tuning strategy as the detector (frozen backbone, last 6 transformer blocks unfrozen, backbone LR 0.0001).
Usage
import torch
ckpt = torch.load("weights/classification/best_val_acc.pth", map_location="cpu")
# See train_classifier_periodontal.py for the model definition,
# image preprocessing (resize 512, ImageNet normalization) and inference.
Citation
If you use these models in your research, please cite the DINOv3 paper:
@article{oquab2025dinov3,
title={DINOv3: Learning Robust Visual Features without Pretraining},
author={Oquab, Maxime and others},
journal={arXiv preprint arXiv:2505.18478},
year={2025}
}