Ultralytics YOLO27 : Inscris-toi sur la liste d’attente.
Get Started
Leçonintermédiaire

Évaluer et déployer chaque tâche

Définis un seuil pour chaque tâche à l’aide de sa propre métrique et de la taille de déploiement, valide toutes les tâches dans une seule boucle et exporte chaque modèle vers ONNX avec une prédiction vérifiée.

Chaque tâche a sa propre définition de la réussite : chevauchement des pixels, similarité des points clés, IoU des boîtes orientées, prédiction top-1 correcte ou rapport de profondeur. Les équipes qui réutilisent leur liste de vérification de détection déploient des modèles de segmentation évalués selon la mAP des boîtes et des modèles de pose évalués selon des boîtes qui ne correspondent jamais au produit. Même un modèle qui franchit son seuil peut échouer après l’export : dans cette leçon, les mêmes poids de pose détectent 5 personnes à une taille d’entrée et 3 à une autre, tandis que les distances du modèle de profondeur doublent presque.

Résultat

Produis un tableau de mise en production indiquant la métrique de validation et imgsz pour chaque modèle de tâche, ainsi qu’un export ONNX vérifié pour chacun, qui se recharge avec la bonne tâche et prédit correctement sur une image du domaine concerné.

Parcours accéléré
Si tu connais déjà les bases, voici la version courte.
  1. Évalue la segmentation selon la mAP50-95 des masques, la segmentation sémantique selon la mIoU, la pose selon la mAP50-95 de pose, les OBB selon la mAP50-95 des OBB, la classification selon le top-1 et la profondeur selon δ1.

  2. Lis les valeurs principales dans metrics.results_dict avec la clé de la tâche et note imgsz à côté de chaque valeur.

  3. Exporte avec model.export(format="onnx", imgsz=...) à la taille que tu as validée.

  4. Recharge l’export avec YOLO("model.onnx") et effectue une prédiction sur une image du domaine propre au modèle avant le déploiement.

Pratique

Un seuil par tâche#

TâcheÉvaluer selonClé results_dictAttribut PythonÉvalué par
segmentationmAP50-95 des masquesmetrics/mAP50-95(M)metrics.seg.mapIoU des pixels par instance
sémantiquemIoU (+ IoU par classe)metrics/mIoUmetrics.miouIoU des pixels par classe
posemAP50-95 de posemetrics/mAP50-95(P)metrics.pose.mapOKS
obbmAP50-95 OBBmetrics/mAP50-95(B)metrics.box.mapIoU des boîtes orientées
classificationprécision top-1metrics/accuracy_top1metrics.top1classe top-1 correcte
profondeurδ1 (+ AbsRel)metrics/delta1metrics.delta1proportion de pixels dont la profondeur est à moins d’un facteur 1,25 de la profondeur réelle

Le guide des métriques de performance explique chaque score. Les exécutions de segmentation et de pose rapportent aussi des métriques de boîte ; conserve-les comme outil de diagnostic — un écart entre la boîte et le masque indique un problème de qualité du contour — mais elles ne représentent pas le produit. Les méthodes d’analyse propres à la détection, comme les balayages de seuils et la matrice de confusion, restent applicables après Validation et diagnostic.

Valider toutes les tâches dans une seule boucle#

Le mode Val accepte les poids de n’importe quelle tâche avec le jeu de données correspondant ; une seule boucle produit donc les valeurs du tableau de mise en production :

from ultralytics import YOLO

runs = {
    "yolo26n-seg.pt": ("coco8-seg.yaml", "metrics/mAP50-95(M)"),
    "yolo26n-sem.pt": ("cityscapes8.yaml", "metrics/mIoU"),
    "yolo26n-pose.pt": ("coco8-pose.yaml", "metrics/mAP50-95(P)"),
    "yolo26n-obb.pt": ("dota8.yaml", "metrics/mAP50-95(B)"),
    "yolo26n-depth.pt": ("depth8.yaml", "metrics/delta1"),
}
for weights, (data, key) in runs.items():
    metrics = YOLO(weights).val(data=data, device="cpu", plots=False, verbose=False)
    print(f"{weights:17s} {key:22s} {metrics.results_dict[key]:.3f}")
yolo26n-seg.pt    metrics/mAP50-95(M)    0.538
yolo26n-sem.pt    metrics/mIoU           0.610
yolo26n-pose.pt   metrics/mAP50-95(P)    0.419
yolo26n-obb.pt    metrics/mAP50-95(B)    0.857
yolo26n-depth.pt  metrics/delta1         0.377

Sans imgsz explicite, chaque modèle est validé à la taille utilisée pour son entraînement : 640 pour la segmentation et la pose, 768 pour la profondeur, 1024 pour la segmentation sémantique et les OBB. Ces valeurs préentraînées sont supérieures à celles des entraînements à 320 pixels réalisés plus tôt dans le cours — en partie grâce à l’entraînement, en partie grâce à la résolution. Quatre images de validation font de chaque valeur un simple test de bon fonctionnement ; par exemple, la page de la tâche de profondeur présente δ1 sur l’ensemble du benchmark NYU. La classification est volontairement exclue : valide ton classificateur affiné sur ses propres dossiers, comme dans la leçon sur la classification.

La résolution fait partie de la métrique

Les mêmes poids obtiennent des scores différents selon imgsz. Consigne imgsz à côté de chaque valeur, valide à la taille prévue pour le déploiement et ne compare jamais des valeurs mesurées à des tailles différentes.

Exporter chaque tâche#

Chaque tâche s’exporte vers ONNX avec le même appel au mode Export. La tâche est stockée dans les métadonnées du modèle, donc YOLO("model.onnx") applique le post-traitement approprié. Le choix du moteur d’exécution, les vérifications de parité et l’optimisation pour TensorRT ou OpenVINO sont abordés dans Exporter vers ONNX (et vérifier la parité) ; cette boucle vérifie que chaque tâche résiste à l’aller-retour :

from ultralytics import YOLO

for weights in ["yolo26n-seg.pt", "yolo26n-sem.pt", "yolo26n-pose.pt", "yolo26n-obb.pt", "yolo26n-cls.pt", "yolo26n-depth.pt"]:
    onnx_path = YOLO(weights).export(format="onnx", imgsz=320)
    onnx_model = YOLO(onnx_path)  # task comes from the ONNX metadata
    result = onnx_model("https://ultralytics.com/images/bus.jpg", imgsz=320, verbose=False)[0]
    print(f"{onnx_model.task:9s} {result.verbose()}")
segment   4 persons, 1 bus,
semantic
pose      3 persons,
obb       (no detections),
classify  minibus 0.38, police_van 0.21, trolleybus 0.05, amphibian 0.05, bullet_train 0.03,
depth     depth 4.67-26.91m,

Chaque export s’est rechargé avec la bonne tâche. Trois résultats méritent un examen plus attentif :

  • La pose a détecté 3 personnes à 320 pixels, alors que l’exécution PyTorch à 640 pixels en détectait 5.
  • La profondeur a interprété la scène comme s’étendant de 4,7 à 26,9 m, alors qu’avec les mêmes poids à leur résolution native de 768 pixels, elle indiquait de 2,1 à 14,9 m.
  • Les OBB n’ont rien détecté sur une photo de rue — un comportement correct pour un modèle aérien, et non un bogue d’export.

PyTorch avec imgsz=320 donne les mêmes valeurs de pose et de profondeur qu’ONNX ; aucun des deux n’est donc un bogue d’export : c’est la taille d’entrée qui a modifié le résultat. Exporte à la taille imgsz que tu as validée. Les résultats sémantiques n’ont pas de ligne récapitulative par objet ; vérifie donc plutôt result.semantic_mask.

Teste rapidement chaque export dans son domaine

Effectue une prédiction avec chaque modèle exporté sur une image similaire à celles utilisées pour son entraînement — scènes de rue pour les modèles COCO, tuiles aériennes pour OBB, scènes intérieures ou de rue à la bonne échelle pour la profondeur — avant de déclarer un export défectueux ou de le déployer.

Si tu écris ton propre post-traitement, voici les sorties ONNX brutes à imgsz=320, tirées du journal d’export :

TâcheForme(s) des sorties ONNXContenu
segmentation(1, 116, 2100) et (1, 32, 80, 80)boîtes + 80 scores de classe + 32 coefficients de masque ; prototypes de masque
sémantique(1, 320, 320)carte de classes, argmax déjà calculé dans le graphe
pose(1, 56, 2100)boîtes + 1 score + 17 × 3 valeurs de points clés
obb(1, 20, 2100)boîtes + 15 scores de classe + 1 angle
classification(1, 1000)probabilités des classes
profondeur(1, 1, 320, 320)profondeur en mètres par pixel

Sur Ultralytics Platform, la page du modèle affiche les métriques propres à la tâche (la mAP des masques pour un modèle de segmentation), au-dessus d’un onglet Export qui propose les mêmes formats :

Page de modèle Ultralytics Platform pour un modèle de segmentation, avec les cartes mAP50 et mAP50-95 des masques, précision et rappel au-dessus de l’onglet Export, qui liste TorchScript, ONNX, OpenVINO, TensorRT et CoreML

ONNX est le format d’échange : un même fichier exporté s’exécute dans ONNX Runtime ou se convertit vers d’autres moteurs d’exécution.

ONNX comme format d’échange : les modèles issus de PyTorch, TensorFlow, Keras et d’autres frameworks sont exportés vers ONNX et chargés dans ONNX Runtime ou un autre framework

Liste de vérification avant déploiement#

  • La métrique de validation du tableau ci-dessus atteint son objectif sur un ensemble de données réservé, à la taille de déploiement imgsz.
  • Le modèle exporté se recharge avec task attendu et correspond aux prédictions PyTorch sur un ensemble d’images fixe.
  • Les chemins de code propres à chaque tâche gèrent les résultats vides : masks is None, zéro point clé, zéro OBB.
  • Les valeurs calculées en aval (surfaces, angles, distances, probabilités des classes) sont consignées pour que tu puisses surveiller leur dérive, comme indiqué dans Observabilité et dérive.

Lorsque le seuil n’est pas atteint, « revenir aux données » signifie généralement agir sur l’un de ces trois leviers :

Trois façons d’améliorer mAP : qualité des données, optimisation du modèle et processus d’annotation

Commence par corriger la qualité des données et le processus d’annotation — les vérifications des étiquettes des leçons 2 et 6 sont le point de départ le moins coûteux — et ne modifie le modèle que lorsque les données sont propres.

Essayer

Choisis deux des tâches que tu as entraînées dans ce cours. Pour chacune, rédige une ligne de tableau de mise en production indiquant la métrique de validation à la taille de déploiement imgsz, exporte le modèle entraîné best.pt vers ONNX à cette taille, recharge-le et vérifie qu’il prédit correctement sur une image du domaine concerné.

Terminé lorsque
Tu as terminé la leçon lorsque tous les éléments suivants sont réunis.
  • Ton tableau de mise en production indique la bonne métrique de validation, sa valeur et imgsz pour les deux modèles.

  • Les deux modèles ont été exportés vers ONNX et rechargés avec le task attendu.

  • Chaque export a produit une prédiction pertinente sur une image de son propre domaine.

Afficher la solution
from ultralytics import YOLO

checks = {
    "runs/segment/train/weights/best.pt": ("coco8-seg.yaml", "metrics/mAP50-95(M)", "https://ultralytics.com/images/bus.jpg"),
    "runs/obb/train/weights/best.pt": ("dota8.yaml", "metrics/mAP50-95(B)", "https://ultralytics.com/images/boats.jpg"),
}
for weights, (data, key, image) in checks.items():
    model = YOLO(weights)
    gate = model.val(data=data, imgsz=320, plots=False, verbose=False).results_dict[key]
    onnx_model = YOLO(model.export(format="onnx", imgsz=320))
    result = onnx_model(image, imgsz=320, verbose=False)[0]
    print(f"{onnx_model.task:8s} {key} @320 = {gate:.3f} | ONNX: {result.verbose()}")

Adapte les chemins runs/... aux dossiers affichés par tes exécutions d’entraînement (Results saved to ...). Avec les entraînements d’une époque des leçons 2 et 7 :

segment  metrics/mAP50-95(M) @320 = 0.377 | ONNX: 4 persons, 1 bus,
obb      metrics/mAP50-95(B) @320 = 0.832 | ONNX: 185 ships, 3 harbors,
ModèleMétrique de validationValeurtaille d’imageONNX
segmentationmAP50-95 des masques0.377320se recharge en tant que segment, détecte le bus et 4 personnes
obbmAP50-95 OBB0.832320se recharge en tant que obb, détecte 185 navires et 3 ports

Chaque vérification utilise une image de son propre domaine : le modèle OBB reçoit la photo aérienne du port, pas la scène de rue. Les deux lignes réussissent la vérification de l’export ; aucun des deux modèles n’est prêt à être déployé, car une époque d’entraînement et quatre images de validation constituent un test de bon fonctionnement, pas un seuil de validation.

Et ensuite ?

Passe l’examen du cours pour obtenir ton certificat, puis poursuis avec Ultralytics YOLO en production pour déployer ces modèles à l’aide de moteurs d’exécution optimisés, du suivi et de la surveillance.