Ultralytics YOLO27 : Inscris-toi sur la liste d’attente.
Get Started
Développer avec Ultralytics Platform·Créer le jeu de données·Leçon 4/10
Leçonintermédiaire

Organiser, dédoublonner et partitionner

Repère les doublons entre partitions et les lacunes de classes avec deux scripts courts, partitionne selon l’unité qui compte et fige une version auditée du jeu de données.

La fiabilité d’un score de validation dépend de celle de la partition. COCO128, un jeu de données de démonstration populaire, utilise intentionnellement les mêmes 128 images pour l’entraînement et la validation. Si la même erreur se glisse dans tes propres données, tu obtiens un « excellent » modèle qui échoue dès qu’il voit la caméra suivante. Cette leçon effectue deux audits sur des données réelles : une vérification des doublons et un audit des classes par partition. Elle répartit ensuite les données par caméra et fige une version ayant réussi les deux vérifications.

Résultat

Tu peux prouver qu’une version du jeu de données ne contient aucune image partagée entre les partitions, qu’aucune caméra ni session ne se trouve dans deux partitions et que chaque classe possède assez d’instances dans la validation, puis la figer sous la forme d’une version numérotée.

Parcours accéléré
Si tu connais déjà les bases, voici la version courte.
  1. Calcule le hachage des images par partition : tout hachage présent dans deux partitions signale une fuite.

  2. Vérifie l’export NDJSON : chaque classe doit avoir des exemples d’entraînement et assez d’instances de validation pour permettre une mesure.

  3. Lance Clustering, coloré selon les partitions, pour repérer les quasi-doublons que les hachages ne détectent pas.

  4. Attribue les partitions par caméra, site ou session ; ne redistribue jamais aléatoirement les images d’une vidéo.

  5. Crée une version numérotée avec une description et entraîne le modèle uniquement sur les versions qui ont réussi les vérifications.

Pratique

Exemple détaillé : repérer les images partagées entre partitions#

La plateforme conserve une seule copie d’une image par partition et te demande comment gérer les collisions lors du téléversement, mais rien n’empêche une même image ou scène de se retrouver à la fois dans l’entraînement et la validation. Vérifie avant le téléversement, puis de nouveau après la fusion des jeux de données :

import hashlib
from pathlib import Path

from ultralytics.data.utils import check_det_dataset

data = check_det_dataset("coco128.yaml")  # any local YOLO dataset YAML before you upload it

def hashes(split_dir):
    return {hashlib.md5(p.read_bytes()).hexdigest(): p.name for p in Path(split_dir).rglob("*.jpg")}

train, val = hashes(data["train"]), hashes(data["val"])
shared = train.keys() & val.keys()
print(f"train {len(train)} images, val {len(val)} images, identical in both: {len(shared)}")
print("examples:", sorted(val[h] for h in shared)[:3])
train 128 images, val 128 images, identical in both: 128
examples: ['000000000009.jpg', '000000000025.jpg', '000000000030.jpg']

Toutes les images de validation de COCO128 sont aussi des images d’entraînement. C’est intentionnel pour un jeu de données de test rapide, et c’est exactement pourquoi son mAP de validation ne dit rien sur la capacité de généralisation. Dans tes données, tout décompte non nul signale une fuite : déplace ou supprime une copie de chaque image avant l’entraînement.

Repérer les quasi-doublons avec Clustering#

Les hachages ne détectent que les octets identiques. Les images vidéo consécutives, les photos en rafale et les copies réencodées diffèrent de quelques pixels. Ouvre l’icône de nuage de points dans la barre d’outils de la galerie et clique sur Analyze Dataset (de 20 à 200 000 images, jeux de données téléversés uniquement) :

Galerie Ultralytics Platform de pilules médicales, panneau Clustering ouvert, représentant chaque image par un point dans un nuage de points 2D où les images visuellement similaires sont proches les unes des autres

  • Colorer par partition : un îlot compact qui mélange des points d’entraînement et de validation signale une fuite de quasi-doublons.
  • Colorer par clusters ou classes : un grand îlot d’une seule classe révèle ce que le jeu de données surreprésente ; les points isolés sont des valeurs aberrantes (mauvaise caméra, image corrompue, image mal étiquetée).
  • Trace un lasso ou clique sur une région pour filtrer la galerie et n’afficher que ces images (jusqu’à 1 000), puis supprime-les, déplace-les ou réétiquette-les.

Les mêmes plongements alimentent Rechercher des images similaires dans le menu contextuel d’une image. Cette fonction ajoute à train des images similaires provenant de jeux de données publics et d’équipe, sans étiquette : le moyen le plus rapide de combler une lacune repérée par l’audit ci-dessous.

Exemple détaillé : auditer les classes par partition#

Télécharge l’export NDJSON depuis l’en-tête du jeu de données ou l’onglet Versions. Chaque ligne suivant l’en-tête correspond à une image, avec sa partition et ses étiquettes ; quelques lignes de Python suffisent donc à compter chaque classe dans chaque partition. Voici l’exécution sur l’export public COCO8 :

import json
from collections import Counter, defaultdict

counts = defaultdict(Counter)  # split -> class name -> instances
images = Counter()
with open("coco8.ndjson") as f:  # the NDJSON export from the dataset header or Versions tab
    header = json.loads(f.readline())
    names = header["class_names"]
    for line in f:
        record = json.loads(line)
        images[record["split"]] += 1
        for box in (record.get("annotations") or {}).get("boxes", []):
            counts[record["split"]][names[str(box[0])]] += 1

print("images per split:", dict(images))
for name in sorted(set(counts["train"]) | set(counts["val"])):
    train, val = counts["train"][name], counts["val"][name]
    flag = "missing in train" if not train else "too few in val" if val < 10 else ""
    print(f"{name:<14} train {train:>3}  val {val:>3}  {flag}")
images per split: {'train': 4, 'val': 4}
bowl           train   3  val   0  too few in val
broccoli       train   1  val   0  too few in val
dog            train   0  val   1  missing in train
elephant       train   0  val   2  missing in train
giraffe        train   2  val   0  too few in val
horse          train   0  val   2  missing in train
orange         train   4  val   0  too few in val
person         train   0  val  10  missing in train
potted plant   train   1  val   1  too few in val
umbrella       train   0  val   1  missing in train
vase           train   1  val   0  too few in val
zebra          train   1  val   0  too few in val

Interprétation : la ligne d’en-tête contient class_names ; chaque boîte de détection est un [class, x, y, w, h]. Absente de l’entraînement signifie que le modèle ne peut pas du tout apprendre la classe et que son AP de validation sera nul. Trop peu d’instances dans la validation signifie que son AP variera fortement d’une exécution à l’autre : avec 7 palettes dans la validation, une palette manquée fait varier l’AP des palettes d’environ 14 points. COCO8 est un test rapide sur 8 images, donc toutes les classes échouent ; ta version de production ne devrait afficher aucun signalement. Comble les lacunes en collectant davantage d’exemples, pas en réglant les paramètres.

Onglet Classes d’Ultralytics Platform pour le jeu de données medical-pills, avec un histogramme de distribution des classes et un tableau répertoriant le nombre d’annotations et d’images

L’onglet Classes affiche les mêmes décomptes pour le jeu de données actif, avec une option d’échelle logarithmique pour les données déséquilibrées. Fusionner en une seule classe regroupe les doublons tels que car, automobile et vehicle dans une seule classe, sans perdre d’annotations ; Supprimer élimine une classe et toutes ses annotations.

Partitionner selon l’unité sur laquelle tu veux généraliser#

Les images d’une même caméra, session ou journée sont corrélées. Si elles figurent à la fois dans l’entraînement et la validation, le modèle est évalué sur des scènes qu’il a déjà vues. Réserve des unités entières correspondant aux variations en production : si tu utilises de nouvelles caméras, réserve certaines caméras ; si tu utilises les mêmes caméras à de nouvelles dates, réserve certaines journées.

Les outils de partitionnement de la plateforme se distinguent précisément sur ce point :

OutilMéthode d’attributionUtilisation
Dossiers train/, val/, test/ dans un téléversementConserve ton attributionPartitions de groupes préparées hors ligne
Filtre de partition défini avant le téléversementTous les fichiers de ce téléversement sont affectés à la partition sélectionnéeTéléversement d’une caméra par partition
Déplacer vers la partition dans la vue TableauDéplace les images sélectionnéesCorrection d’images spécifiques
Barre des partitions, Redistribuer les partitionsRéattribue aléatoirement toutes les imagesPhotos indépendantes uniquement

Boîte de dialogue Redistribuer les partitions d’Ultralytics Platform pour le jeu de données medical-pills, avec une barre de partition et des champs de pourcentage définis sur 80 pour l’entraînement, 20 pour la validation et 0 pour le test

La leçon Partitionner correctement le jeu de données traite du choix de l’unité ; pour les très petits jeux de données, la validation croisée k-fold permet de tirer davantage d’informations des données. Pour vérifier les groupes après le téléversement, ajoute une clé de groupe à l’audit des classes (par exemple record["file"].split("_")[0] pour les fichiers nommés cam07_000123.jpg, ou un champ camera dans les métadonnées des images) et signale tout groupe présent dans deux partitions.

Figer une version ayant réussi les vérifications#

L’entraînement nécessite un instantané fixe. Dans l’onglet Versions, saisis une description (« v5 : cam07 réservée, +80 images de palettes »), puis clique sur Nouvelle version. Chaque version est un instantané NDJSON numéroté et immuable que tu peux télécharger, comparer ou restaurer ; la boîte de dialogue d’entraînement propose la même opération au lancement avec Enregistrer la version du jeu de données et réutilise une version correspondante si rien n’a changé. Les versions ne sont pas disponibles pour les jeux de données connectés au cloud ou sur site.

Pièges#

Redistribuer les partitions sur des images vidéo

Symptôme : après avoir cliqué sur Auto pour répartir les données à 80/20, le mAP de validation bondit, mais pas la précision en production. Correctif : Redistribuer les partitions réattribue aléatoirement chaque image (et supprime au passage les doublons exacts), plaçant des images voisines dans les partitions d’entraînement et de validation. Utilise des dossiers de téléversement ou Déplacer vers la partition pour les données regroupées.

Fusionner ou supprimer une classe décale l’ID de toutes les classes

Symptôme : un ancien export ou les prédictions d’un modèle portent soudain les mauvais noms de classe. Correctif : les ID de classe sont déterminés par leur position ; fusionner ou supprimer une classe décale donc tous les index supérieurs d’une position. Crée une version avant tout changement de classe et réentraîne le modèle plutôt que de réutiliser d’anciens fichiers d’annotations.

Modifier la partition en cours de projet

Symptôme : un nouvel entraînement obtient un score inférieur de 5 points, alors que rien d’autre n’a changé. Correctif : les métriques ne sont comparables que sur la même partition. Lorsque tu modifies la partition, note-le dans la description de la version et relance l’évaluation de référence sur la nouvelle version avant toute comparaison.

Essayer

Exécute cross_split_dupes.py sur ton jeu de données local et class_audit.py sur l’export NDJSON de ta plateforme, avec une clé de groupe correspondant au nom de ta caméra ou de ta session. Corrige chaque fuite et lacune signalée (Déplacer vers la partition, Rechercher des images similaires, ajouter des données), puis relance les deux scripts jusqu’à ce qu’ils ne signalent plus rien. Vérifie les clusters colorés par partition et crée une version avec une description.

Terminé lorsque
Tu as terminé la leçon lorsque tous les éléments suivants sont réunis.
  • La vérification des doublons signale identical in both: 0, et aucun groupe de caméras ou de sessions ne s’étend sur deux partitions.

  • L’audit des classes ne signale aucun problème missing in train, et tu as décidé quoi faire pour chaque too few in val.

  • Il existe une version numérotée dont la description indique la règle de partitionnement et les modifications apportées.

Afficher la solution

Exemple de réponse pour un jeu de données de chariots élévateurs filmés par 8 caméras. La vérification des doublons trouve 41 images identiques entre l’entraînement et la validation, toutes provenant d’un dossier retéléversé ; supprime les copies de validation. L’audit, complété par group = record['file'].split('_')[0], indique que cam02 apparaît dans l’entraînement et la validation. Sélectionne donc ses images de validation dans la vue Tableau, puis choisis Déplacer vers la partition > Entraînement. L’audit signale aussi pallet: train 63, val 7, too few in val : utilise Rechercher des images similaires sur deux images de palettes pour ajouter 40 images similaires non étiquetées, étiquette-les et déplace 15 images de palettes de cam07 vers la validation afin que cam07 reste dans une seule partition. Relance les vérifications : 0 doublon, 0 groupe en fuite, 22 palettes dans la validation. Les clusters colorés par partition ne montrent aucun îlot mixte. Enregistre v5: cam07 val, cam08 test, +40 pallets.

Et ensuite ?

Tu as des données propres et versionnées. Ensuite, tu vas les utiliser pour entraîner le modèle, lire les résultats et effectuer correctement un ajustement fin.