Ultralytics YOLO27 : Inscris-toi sur la liste d’attente.
Get Started
Créer des jeux de données YOLO hautes performances·Entraîner et itérer·Leçon 8/10
Leçondébutant

Savoir quand le jeu de données est prêt

Conditionne le premier entraînement à huit vérifications réussite/échec, automatise les trois qu’un script peut vérifier et identifie la correction requise pour chaque échec.

Chaque projet arrive au moment où l’équipe veut lancer l’entraînement. Parfois, le jeu de données est prêt ; parfois, il contient encore une fuite entre les découpages ou une classe insuffisamment annotée, ce qui fera perdre une semaine de calcul GPU et produira un chiffre auquel personne ne devrait se fier. Huit vérifications, chacune notée oui, non ou exception documentée, permettent de prendre cette décision objectivement plutôt qu’au gré de l’humeur.

Résultat

Évalue ton jeu de données à l’aide des huit critères de préparation, en faisant vérifier par un script les trois critères quantifiables, puis prononce un feu vert ou établis une liste de corrections classées par priorité.

Parcours accéléré
Si tu connais déjà les bases, voici la version courte.
  1. Évalue les huit critères : oui, non ou exception documentée.

  2. Laisse readiness.py évaluer le volume, les fuites, la couverture des découpages et la proportion d’images d’arrière-plan.

  3. Corrige dans les données chaque réponse négative, pas avec des hyperparamètres.

  4. Ne passe à la production avec une lacune connue que si son impact attendu est consigné.

Pratique

Les huit vérifications#

#VérificationCritères de réussiteEn cas d’échec, reprendre
1Objectif clairL’objectif, la tâche, les classes et un test d’acceptation sont consignés et validés par tousCommencer par l’objectif métier
2Classes définiesChaque classe a une définition et un exemple ressemblant explicitement excluObjectif et guide d’annotation
3Images représentativesChaque scénario de la spécification respecte son quota, avec des images provenant principalement de sources de productionCollecter des données de haute qualité et représentatives
4Volume suffisant≥ 1 500 images et ≥ 10 000 instances par classe, ou exception documentéeSpécification et collecte
5Annotations cohérentesGuide rédigé, session de calibration effectuée, accord ≥ 90 %Bonnes pratiques d’annotation
6Contrôle qualité terminéScript d’audit sans erreur, cas suspects examinés, notes de contrôle qualité rédigéesContrôle qualité du jeu de données
7Découpages sans fuiteDécoupage par groupes, aucun groupe présent dans deux découpages, chaque classe présente dans chaque découpageDécouper correctement le jeu de données
8Images d’arrière-plan0–10 % des images sont des images sans annotationSpécification et collecte

La liste de contrôle regroupe en une seule décision go/no-go les mêmes points que le guide de collecte et d’annotation des données aborde un par un.

Automatiser les vérifications quantifiables#

Les vérifications 4, 7 et 8 reposent sur des calculs ; un script les évalue donc de la même façon à chaque fois. Celui-ci lit le jeu de pratique et les listes de découpages générés par group_split.py dans la leçon précédente :

from collections import Counter
from pathlib import Path

root = Path("datasets/practice")  # images/, labels/, and the train/val/test.txt lists from group_split.py
splits = {s: [Path(p).stem for p in (root / f"{s}.txt").read_text().split()] for s in ("train", "val", "test")}

def classes(stem):
    label = root / "labels" / f"{stem}.txt"
    return [int(r.split()[0]) for r in label.read_text().splitlines() if r.strip()] if label.exists() else []

stems = [s for split in splits.values() for s in split]
instances = Counter(c for s in stems for c in classes(s))
images = Counter(c for s in stems for c in set(classes(s)))
background = sum(not classes(s) for s in stems) / len(stems)
groups = {split: {s.rsplit("_", 1)[0] for s in names} for split, names in splits.items()}
per_split = {split: {c for s in names for c in classes(s)} for split, names in splits.items()}
shared = (groups["train"] & groups["val"]) | (groups["train"] & groups["test"]) | (groups["val"] & groups["test"])
weakest = min(instances, key=lambda c: (images[c], instances[c]))

checks = {
    "4 volume": (images[weakest] >= 1500 and instances[weakest] >= 10_000,
                 f"weakest class {weakest}: {images[weakest]} images, {instances[weakest]} instances"),
    "7 no shared groups": (not shared, f"{len(shared)} groups appear in more than one split"),
    "7 every class in every split": (all(per_split[s] == set(instances) for s in splits),
                                     ", ".join(f"{s} misses {len(set(instances) - per_split[s])}" for s in splits)),
    "8 background 0-10%": (background <= 0.10, f"{background:.1%} background images"),
}
for name, (ok, detail) in checks.items():
    print(f"{'PASS' if ok else 'FAIL'}  {name:<29} {detail}")
FAIL  4 volume                      weakest class 30: 1 images, 1 instances
PASS  7 no shared groups            0 groups appear in more than one split
FAIL  7 every class in every split  train misses 5, val misses 36, test misses 41
PASS  8 background 0-10%            1.6% background images

Le découpage par groupes a corrigé la fuite, mais le jeu de pratique est loin d’être prêt : sa classe la plus faible (30, skis) ne compte qu’une seule instance annotée, et l’évaluation ne peut pas mesurer la moitié des classes. C’est le verdict attendu pour 128 images de démonstration, et précisément celui que cette vérification doit fournir avant une semaine d’entraînement.

Un script propre ne garantit pas une liste de vérification bien remplie

Le script couvre ce qui peut être compté. Les points 1, 2, 3, 5 et 6 nécessitent une intervention humaine : un objectif convenu, des définitions écrites, une couverture conforme au cahier des charges, un score d’accord mesuré et des notes de contrôle qualité. Évalue-les manuellement, avec une ligne de preuve pour chaque point.

Décider : entraîner, livrer malgré une lacune ou corriger#

Lorsqu’une vérification échoue, l’étape suivante tentante consiste presque toujours à faire autre chose que corriger les données :

Raccourci tentantPourquoi ça ne marche pas
« Essaie un modèle plus grand. »Un modèle plus grand apprend le bruit des annotations tout aussi fidèlement.
« Règle le taux d’apprentissage. »Aucun réglage de l’optimiseur ne peut ajouter une classe ou un scénario manquant.
« Entraîne le modèle pendant plus d’époques. »Avec des données trop limitées, davantage d’époques accélèrent le surapprentissage.
« Ajoute plus d’augmentation. »L’augmentation ne peut pas créer des scénarios absents des données.

Trois situations où le jeu de données est presque prêt#

SituationVérification en échecÀ quoi ça ressembleCorrectif
Volume sans diversité35 000 images, une seule caméra, aucun cas limiteCollecte des images provenant de davantage de caméras, de sites et de moments avant l’entraînement
Diversité sans cohérence5Les annotateurs ne s’accordent pas sur les limites des boîtes ni sur l’occlusionTermine le guide, effectue la calibration et réannote l’échantillon concerné
Fuite discrète7Découpage aléatoire par image sur des images vidéoRefais la répartition par clip, caméra ou jour ; attends-toi à une baisse du mAP de validation, car cette baisse reflète la réalité

Déploie en connaissant les lacunes#

Souvent, le bon choix consiste à créer un premier modèle ciblé avant que tous les contrôles soient au vert : un pilote, un prototype ou une v1 sur un sous-ensemble de caméras. Un modèle en production révèle plus vite les vrais problèmes que le peaufinage des données dans le noir. Si tu déploies avec une lacune, consigne trois choses :

  • Le contrôle qui a échoué.
  • L'impact attendu, par exemple « aucune donnée de nuit ; attends-toi à un rappel plus faible après la tombée de la nuit ».
  • Le plan de collecte qui permettra de combler la lacune pendant l'exécution de la v1.
Une exception sans impact n’est qu’un contrôle ignoré

« Volume : exception » n’apprend rien à la personne suivante. « Volume : pallet à 700 instances, rappel des palettes probablement plus faible dans les zones encombrées ; 2 000 étiquettes supplémentaires d’ici juin » correspond à un risque maîtrisé. Chaque exception doit indiquer son impact prévu sur le test d’acceptation.

Relance les contrôles avant chaque nouvel entraînement#

Qualité du modèle au fil du temps : la qualité se maintient pendant l'arrivée de nouvelles données annotées, puis se dégrade après le point de dégradation prévu, ce qui soulève la question de savoir s'il faut réentraîner maintenant ou attendre

Un jeu de données prêt pour la v1 n'est pas automatiquement prêt pour la v3. De nouvelles classes, de nouvelles sources et de nouveaux annotateurs peuvent chacun faire échouer un contrôle qui réussissait auparavant, tandis que les données de production dérivent à mesure que les nouvelles annotations s'accumulent. Relance readiness.py et réévalue les contrôles manuels avant chaque nouvel entraînement ; cela prend quelques minutes, et sauter cette étape peut te coûter une semaine d'entraînement sur un jeu de données défectueux.

Essayer

Exécute readiness.py sur ton jeu de données réparti (ou sur le jeu d'exercice), puis évalue manuellement les cinq contrôles en ajoutant une ligne de preuve pour chacun. Classe chaque contrôle échoué selon le risque qu'il fait peser sur le test d'acceptation. Livrable : une liste de contrôle de huit lignes, notée, avec une décision de lancement ou une liste de corrections classées par priorité, enregistrée à côté des notes de contrôle qualité.

Terminé lorsque
Tu as terminé la leçon lorsque tous les éléments suivants sont réunis.
  • Les huit contrôles ont chacun une note et une ligne de preuve ; les trois contrôles quantifiables proviennent du script.

  • Chaque exception précise son impact attendu sur le test d'acceptation et un plan pour y remédier.

  • La décision (entraîner, déployer avec une lacune documentée ou corriger d'abord) est consignée avec la liste de contrôle.

Afficher la solution

Une liste de contrôle notée pour le jeu d'exercice :

#VérificationNotePreuve
1Objectif clairouiobjective.md et acceptance_test.py de la leçon 1
2Classes définiesnonLes 80 noms de COCO n'ont ni définitions écrites ni exemples de ressemblances à exclure
3Images représentativesnoncoverage.py : cam2–cam4 sous le quota
4Volume suffisantnonreadiness.py : la classe la moins représentée ne compte qu'une image
5Annotations cohérentesnonAccord de 47 % lors de la phase de calibration
6Contrôle qualité terminépartielAudit effectué ; les cas suspects dans 000000000438.jpg restent à traiter
7Répartitions sans fuitenonAucun groupe partagé, mais le jeu de validation ne contient que 35 des 71 classes
8Images d'arrière-planoui1.6%

Décision : corriger d'abord. Par ordre de risque pour le test d'acceptation : (1) réduire la liste de classes aux classes requises par l'objectif, ce qui allège d'un coup les contrôles 2, 4 et 7 ; (2) collecter davantage de groupes pour ces classes ; (3) compléter la règle du guide concernant les personnes éloignées et réannoter. Un jeu de démonstration échoue à ce contrôle, et c'est normal.

Et ensuite ?

Une fois la liste de contrôle validée, la leçon suivante entraîne un modèle de référence par ajustement fin et transforme ses résultats en prochaine correction du jeu de données.