📍 Guide principal : Détection d’objets en 2026 : pipeline YOLO v11 + Ultralytics + Roboflow. Ce tutoriel s’applique à tout modèle déjà en production, qu’il soit servi par FastAPI ou par une Jetson Orin embarquée.
Un modèle YOLO v11 qui sort excellent à la mise en production peut devenir mauvais six mois plus tard, sans qu’aucune ligne de code n’ait été modifiée. La cause : la distribution des images en production évolue. Une caméra de surveillance déplacée, un changement de luminaire, une nouvelle saison, un type d’objet jamais vu pendant l’entraînement — autant de raisons pour lesquelles la précision réelle diverge de la mAP mesurée en validation. Surveiller ce phénomène, qu’on appelle data drift et concept drift, n’est pas un luxe ; c’est ce qui sépare un projet de POC d’un système qui tient en production. Ce tutoriel détaille la chaîne complète : quoi mesurer, comment, où stocker les métriques, et quand déclencher un fine-tuning correctif.
Prérequis
- Un modèle YOLO v11 déjà déployé et qui tourne (sur serveur, edge, ou navigateur).
- Un endpoint pour pousser des métriques : Prometheus + Grafana, InfluxDB, ou une solution managée (Datadog, Grafana Cloud).
- Un mécanisme de stockage temporaire des images d’inférence (S3 privé ou volume local en rotation).
- Python 3.11 et un environnement virtuel pour les scripts de calcul de drift.
- Niveau attendu : à l’aise avec Docker, Prometheus et la lecture de métriques.
- Temps estimé : une journée pour la première mise en place complète.
Étape 1 — Distinguer data drift et concept drift
Confondre data drift et concept drift mène à des actions correctives inadaptées. Le data drift est un changement dans la distribution des images d’entrée — typiquement un changement d’éclairage, une nouvelle caméra, un changement saisonnier de scène. Le modèle voit des images dont les caractéristiques bas niveau diffèrent de ce qu’il a vu pendant l’entraînement. Le concept drift, plus subtil, est un changement dans la relation entre les images et les classes attendues — par exemple, l’apparition d’une nouvelle variante de panneau de signalisation que le modèle n’a jamais rencontrée mais qui appartient à une classe existante.
Le data drift est détectable sans étiquettes (on peut le mesurer juste en observant les images en production). Le concept drift, lui, exige des étiquettes ground truth, donc une boucle d’annotation continue. La majorité des projets se contentent de surveiller le data drift en continu et déclenchent une campagne d’annotation ponctuelle (200-500 images) tous les 3 à 6 mois pour vérifier le concept drift.
Étape 2 — Définir les métriques techniques à exposer
Le serveur d’inférence doit exposer un endpoint Prometheus avec quatre familles de métriques. Première famille : les métriques d’observabilité classiques (latence p50/p95/p99, throughput, taux d’erreur HTTP, utilisation GPU). Deuxième famille : les métriques métier (nombre de détections par classe, nombre d’images sans aucune détection). Troisième famille : les statistiques sur les scores de confiance (distribution, moyenne, p10, p90) qui sont un excellent indicateur précoce de drift. Quatrième famille : la distribution des caractéristiques d’image bas niveau (luminosité moyenne, contraste, saturation moyenne).
Avec FastAPI et prometheus-client, l’instrumentation tient en quelques lignes :
from prometheus_client import Counter, Histogram, Gauge
DETECTIONS_TOTAL = Counter("yolo_detections_total", "Détections par classe", ["class_name"])
SCORE_HIST = Histogram("yolo_score", "Distribution des scores de détection", buckets=[0.3, 0.5, 0.7, 0.85, 0.95])
LATENCY_HIST = Histogram("yolo_inference_latency_seconds", "Latence d'inférence")
IMAGE_BRIGHTNESS = Histogram("input_image_brightness", "Luminosité moyenne", buckets=[50, 100, 150, 200])
@app.post("/predict")
async def predict(image: bytes):
with LATENCY_HIST.time():
results = model(image)
for box, score, cls in extract(results):
DETECTIONS_TOTAL.labels(class_name=cls).inc()
SCORE_HIST.observe(score)
IMAGE_BRIGHTNESS.observe(compute_brightness(image))
return results
Ces métriques sont scrapées par Prometheus toutes les 15 secondes (configuration par défaut) et visualisables dans Grafana via un dashboard.
Étape 3 — Calculer un score de drift quotidien
Pour quantifier le data drift de manière exploitable par une alerte, on compare la distribution des features récentes (par exemple les 24 dernières heures) à une distribution de référence calculée pendant la phase de validation initiale. La métrique standard est le Population Stability Index (PSI), qui mesure la divergence entre deux distributions binnées :
import numpy as np
def psi(reference: np.ndarray, current: np.ndarray, bins: int = 10) -> float:
"""Calcule le PSI entre deux distributions."""
edges = np.linspace(min(reference.min(), current.min()),
max(reference.max(), current.max()), bins + 1)
ref_hist, _ = np.histogram(reference, bins=edges)
cur_hist, _ = np.histogram(current, bins=edges)
ref_pct = (ref_hist + 1e-6) / (ref_hist.sum() + 1e-6)
cur_pct = (cur_hist + 1e-6) / (cur_hist.sum() + 1e-6)
return float(np.sum((cur_pct - ref_pct) * np.log(cur_pct / ref_pct)))
# Exemple : luminosité moyenne sur 1000 images de référence vs 1000 images du jour
ref_brightness = np.load("reference_brightness.npy")
current_brightness = np.array(fetch_recent_brightness_from_metrics())
score = psi(ref_brightness, current_brightness)
print(f"PSI luminosité : {score:.3f}")
Interprétation classique : PSI < 0,1 signifie pas de drift significatif, entre 0,1 et 0,25 drift modéré à surveiller, supérieur à 0,25 drift important à investiguer rapidement. Lancer ce calcul chaque nuit sur les features clés (luminosité, distribution des scores, distribution des classes détectées) et stocker le résultat dans une table d’audit.
Étape 4 — Configurer des alertes Grafana
Une métrique non alertée n’aide personne. Configurer trois alertes minimum dans Grafana ou Alertmanager. Première alerte : taux de détection effondré (le modèle ne détecte plus rien sur des images qui en contiennent normalement) — seuil : moyenne mobile sur 1h des détections par image inférieure à 50 % de la baseline. Deuxième alerte : distribution des scores qui glisse vers le bas (le modèle est moins sûr de lui) — seuil : p50 du score qui descend sous 0,7 alors qu’il était à 0,85 en référence. Troisième alerte : PSI qui dépasse 0,25 sur une feature surveillée.
# Exemple d'alerte Prometheus
groups:
- name: yolo_drift
rules:
- alert: YoloLowDetectionRate
expr: rate(yolo_detections_total[1h]) < 0.5 * rate(yolo_detections_total[7d] offset 7d)
for: 30m
labels: { severity: warning }
annotations:
summary: "Taux de détection YOLO en chute"
description: "Le taux de détection est inférieur de 50 % à la baseline 7 jours."
- alert: YoloScoreDistributionShift
expr: histogram_quantile(0.5, yolo_score_bucket) < 0.7
for: 1h
labels: { severity: warning }
Pousser ces règles dans Prometheus, vérifier dans Status > Rules qu'elles sont actives, et tester en injectant manuellement des images modifiées (par exemple sous-exposées) pour valider que l'alerte se déclenche.
Étape 5 — Boucle de feedback humain pour le concept drift
Pour le concept drift, il faut des étiquettes ground truth. Les obtenir en production exige une boucle dédiée. Première option : exposer aux utilisateurs ou aux opérateurs un bouton « cette détection est fausse / il manque une détection », qui envoie l'image vers un bucket dédié à la ré-annotation. Deuxième option : un échantillonnage aléatoire de 1 % des images traitées chaque jour, envoyées à un annotateur via Roboflow, comparées aux prédictions du modèle. Troisième option, plus avancée : un modèle de référence plus lourd (par exemple YOLO11x) qui annote en différé un sous-échantillon, et dont les sorties servent de pseudo-ground-truth pour tester la cohérence avec le modèle de production léger.
Quel que soit le mécanisme, le KPI à suivre est le taux de désaccord : pourcentage d'images où la prédiction du modèle de production diverge de l'étiquette ground truth (manque une boîte, en ajoute une fausse, classe incorrecte). Si ce taux dépasse 5-10 % de manière soutenue alors qu'il était à 2-3 % au démarrage, c'est le signal d'un concept drift réel.
Étape 6 — Déclencher un fine-tuning correctif
Quand les alertes drift et le taux de désaccord convergent vers un signal négatif, l'action est un fine-tuning ciblé. Récupérer les images problématiques (celles où l'humain a corrigé), les annoter ou les ré-annoter dans Roboflow, créer une version 2 du dataset qui combine l'ancien dataset avec ces nouveaux exemples, et lancer un fine-tuning depuis le best.pt actuel (cf. tutoriel fine-tuning).
Avant de déployer le nouveau modèle en production, le valider en A/B : envoyer 10 % du trafic vers le nouveau modèle, comparer les métriques de drift et le taux de désaccord avec le modèle actuel. Si le nouveau modèle améliore le taux de désaccord d'au moins 30 % sans dégrader la latence, basculer 100 % du trafic. Sinon, investiguer pourquoi le fine-tuning n'a pas suffi (souvent : pas assez d'images ré-annotées, ou un concept drift qui demande de revoir la définition des classes).
Pannes typiques de la chaîne de monitoring
| Symptôme | Cause probable | Action |
|---|---|---|
| PSI qui explose chaque lundi matin | Trafic différent selon le jour de la semaine | Calculer la baseline par jour de semaine plutôt qu'en agrégé. |
| Taux de détection à 0 alors que le modèle tourne | Les images en production ne contiennent vraiment rien à détecter | Vérifier sur un échantillon visuel, ajuster le seuil métier. |
| Alertes drift toutes les heures, faux positifs constants | Seuils trop sensibles ou trop peu d'images dans la fenêtre | Augmenter la fenêtre d'agrégation à 6h ou 24h, relâcher les seuils. |
| Boucle de feedback humain ignorée | UX trop lourde pour signaler | Réduire à un bouton « erreur » d'un clic, sans formulaire long. |
| Fine-tuning correctif qui dégrade le modèle | Mauvaises annotations dans le bucket de feedback | Ajouter une étape de revue par un annotateur senior avant de ré-entraîner. |
| Coût Prometheus qui explose | Trop de labels à haute cardinalité | Limiter les labels (pas d'IP, pas d'ID utilisateur), agréger côté serveur. |
Suite logique
- Fine-tuning YOLO v11 sur un dataset métier — l'action déclenchée par les alertes drift.
- Servir YOLO v11 derrière une API FastAPI — pour exposer les métriques Prometheus.
Outils et lectures
- 🔝 Vue d'ensemble : Pipeline YOLO v11
- Evidently AI (drift detection ML) : evidentlyai.com
- Prometheus client Python : github.com/prometheus/client_python
- Grafana documentation alerting : grafana.com/docs/grafana/latest/alerting
- Article de référence sur le drift en computer vision : arXiv:2004.05785
Avec une chaîne de monitoring opérationnelle, le modèle YOLO v11 cesse d'être une boîte noire qui se dégrade en silence. Il devient un système maintenu, dont les performances sont mesurées en continu et corrigées à chaque dérive significative.