Validation croisée K-Fold avec Ultralytics#
Introduction#
Ce guide complet présente la mise en œuvre de la validation croisée K-Fold pour les jeux de données de détection d’objets dans l’écosystème Ultralytics. Nous utiliserons le format de détection YOLO et des bibliothèques Python essentielles telles que sklearn, pandas et PyYAML pour te guider dans la configuration nécessaire, le processus de génération des vecteurs de caractéristiques et l’exécution d’une division de jeu de données en K-Fold.
Que ton projet utilise le jeu de données Fruit Detection ou une source de données personnalisée, ce tutoriel vise à t’aider à comprendre et à appliquer la validation croisée K-Fold afin de renforcer la fiabilité et la robustesse de tes modèles de machine learning. Bien que nous utilisions k=5 folds pour ce tutoriel, garde à l’esprit que le nombre optimal de folds peut varier selon ton jeu de données et les spécificités de ton projet. La validation croisée K-Fold est particulièrement utile lorsque ton jeu de données est petit, bruité ou très variable ; pour les jeux de données volumineux et diversifiés, une division bien construite en ensembles train/val/test est généralement suffisante.
Commençons.
Configuration#
-
Tes annotations doivent être au format de détection YOLO.
-
Ce guide part du principe que les fichiers d’annotation sont disponibles localement.
-
Pour notre démonstration, nous utilisons le jeu de données Fruit Detection.
- Ce jeu de données contient 8479 images au total.
- Il comprend 6 étiquettes de classe, dont le nombre total d’instances est indiqué ci-dessous pour chacune.
| Étiquette de classe | Nombre d’instances |
|---|---|
| Pomme | 7049 |
| Raisins | 7202 |
| Ananas | 1613 |
| Orange | 15549 |
| Banane | 3536 |
| Pastèque | 1976 |
-
Les packages Python nécessaires comprennent :
ultralyticssklearnpandaspyyaml
-
Ce tutoriel utilise
k=5folds. Tu dois toutefois déterminer le nombre de folds le mieux adapté à ton jeu de données.
-
Crée un nouvel environnement virtuel Python (
venv) pour ton projet et active-le. Utilisepip(ou ton gestionnaire de packages préféré) pour installer :- La bibliothèque Ultralytics :
pip install -U ultralytics. Tu peux également cloner le repo officiel. - Scikit-learn, pandas et PyYAML :
pip install -U scikit-learn pandas pyyaml.
- La bibliothèque Ultralytics :
-
Vérifie que tes annotations sont au format de détection YOLO.
- Pour ce tutoriel, tous les fichiers d’annotation se trouvent dans le répertoire
Fruit-Detection/labels.
- Pour ce tutoriel, tous les fichiers d’annotation se trouvent dans le répertoire
Génération de vecteurs de caractéristiques pour un jeu de données de détection d’objets#
-
Commence par créer un nouveau fichier Python
example.pypour les étapes ci-dessous. -
Charge les images d’entraînement et de validation configurées via le propriétaire du jeu de données du package, en laissant la division de test intacte.
from pathlib import Path from ultralytics.data.dataset import YOLODataset from ultralytics.data.utils import check_det_dataset yaml_file = "path/to/data.yaml" data = check_det_dataset(yaml_file) dataset_path = Path(data["path"]) sources = [] for split in ("train", "val"): source = data.get(split) if source: sources.extend(source if isinstance(source, list) else [source]) dataset = YOLODataset(sources, data=data, augment=False) images = [Path(p) for p in dataset.im_files] -
Lis maintenant le contenu du fichier YAML du jeu de données et extrais les indices des étiquettes de classe.
classes = data["names"] cls_idx = sorted(classes.keys()) -
Initialise un DataFrame
pandasvide.import pandas as pd labels_df = pd.DataFrame(0.0, columns=cls_idx, index=images) -
Compte les instances de chaque classe présente dans les fichiers d’annotation.
from collections import Counter for image, label in zip(images, dataset.labels): lbl_counter = Counter(label["cls"].flatten().astype(int)) labels_df.loc[image, list(lbl_counter)] = list(lbl_counter.values()) -
Voici un aperçu du DataFrame rempli :
0 1 2 3 4 5 '0000a16e4b057580_jpg.rf.00ab48988370f64f5ca8ea4...' 0.0 0.0 0.0 0.0 0.0 7.0 '0000a16e4b057580_jpg.rf.7e6dce029fb67f01eb19aa7...' 0.0 0.0 0.0 0.0 0.0 7.0 '0000a16e4b057580_jpg.rf.bc4d31cdcbe229dd022957a...' 0.0 0.0 0.0 0.0 0.0 7.0 '00020ebf74c4881c_jpg.rf.508192a0a97aa6c4a3b6882...' 0.0 0.0 0.0 1.0 0.0 0.0 '00020ebf74c4881c_jpg.rf.5af192a2254c8ecc4188a25...' 0.0 0.0 0.0 1.0 0.0 0.0 ... ... ... ... ... ... ... 'ff4cd45896de38be_jpg.rf.c4b5e967ca10c7ced3b9e97...' 0.0 0.0 0.0 0.0 0.0 2.0 'ff4cd45896de38be_jpg.rf.ea4c1d37d2884b3e3cbce08...' 0.0 0.0 0.0 0.0 0.0 2.0 'ff5fd9c3c624b7dc_jpg.rf.bb519feaa36fc4bf630a033...' 1.0 0.0 0.0 0.0 0.0 0.0 'ff5fd9c3c624b7dc_jpg.rf.f0751c9c3aa4519ea3c9d6a...' 1.0 0.0 0.0 0.0 0.0 0.0 'fffe28b31f2a70d4_jpg.rf.7ea16bd637ba0711c53b540...' 0.0 6.0 0.0 0.0 0.0 0.0
Les lignes utilisent des chemins d’image absolus et les colonnes correspondent aux indices des classes. Les étiquettes manquantes restent des lignes d’arrière-plan entièrement nulles. Cette structure de données permet d’appliquer la validation croisée K-Fold à un jeu de données de détection d’objets.
Division du jeu de données en K-Fold#
-
Nous allons maintenant utiliser la classe
KFolddesklearn.model_selectionpour générerkdivisions du jeu de données.- Important :
- Définir
shuffle=Truegarantit une répartition aléatoire des classes dans tes divisions. - En définissant
random_state=MlorsqueMest un entier choisi, tu peux obtenir des résultats reproductibles.
- Définir
from sklearn.model_selection import KFold ksplit = 5 kf = KFold(n_splits=ksplit, shuffle=True, random_state=20) # setting random_state for repeatable results kfolds = list(kf.split(labels_df)) - Important :
-
Le jeu de données a maintenant été divisé en
kfolds, chacun contenant une liste d’indicestrainetval. Nous allons construire un DataFrame pour présenter ces résultats plus clairement.folds = [f"split_{n}" for n in range(1, ksplit + 1)] folds_df = pd.DataFrame(index=labels_df.index, columns=folds) for i, (train, val) in enumerate(kfolds, start=1): folds_df.loc[labels_df.index[train], f"split_{i}"] = "train" folds_df.loc[labels_df.index[val], f"split_{i}"] = "val" -
Nous allons maintenant calculer la répartition des étiquettes de classe pour chaque fold sous forme de ratio entre les classes présentes dans
valet celles présentes danstrain.fold_lbl_distrb = pd.DataFrame(index=folds, columns=cls_idx) for n, (train_indices, val_indices) in enumerate(kfolds, start=1): train_totals = labels_df.iloc[train_indices].sum() val_totals = labels_df.iloc[val_indices].sum() # To avoid division by zero, we add a small value (1E-7) to the denominator ratio = val_totals / (train_totals + 1e-7) fold_lbl_distrb.loc[f"split_{n}"] = ratioDans l’idéal, tous les ratios de classes devraient être raisonnablement similaires pour chaque division et entre les classes. Cela dépendra toutefois des spécificités de ton jeu de données.
-
Écris les listes d’images et un fichier YAML de jeu de données pour chaque division. Les listes textuelles évitent de copier le jeu de données
kfois.import yaml save_path = dataset_path.parent / f"{ksplit}-Fold_Cross-val" save_path.mkdir(parents=True, exist_ok=True) ds_yamls = [] for split in folds_df.columns: for partition in ("train", "val"): split_images = folds_df.index[folds_df[split] == partition] paths = "\n".join(map(str, split_images)) (save_path / f"{split}_{partition}.txt").write_text(f"{paths}\n") dataset_yaml = save_path / f"{split}.yaml" ds_yamls.append(dataset_yaml) with open(dataset_yaml, "w") as ds_y: yaml.safe_dump( { "path": save_path.as_posix(), "train": f"{split}_train.txt", "val": f"{split}_val.txt", "names": classes, }, ds_y, )
Enregistrer les résultats (facultatif)#
Tu peux éventuellement enregistrer les DataFrames de résultats de la division K-Fold et de la répartition des étiquettes dans des fichiers CSV pour consultation ultérieure.
folds_df.to_csv(save_path / "kfold_datasplit.csv")
fold_lbl_distrb.to_csv(save_path / "kfold_label_distribution.csv")Entraîner YOLO avec des divisions de données K-Fold#
-
Commence par charger le modèle YOLO.
from ultralytics import YOLO weights_path = "path/to/weights.pt" # use yolo26n.pt for a small model model = YOLO(weights_path, task="detect") -
Parcours ensuite les fichiers YAML du jeu de données pour lancer l’entraînement. Les résultats seront enregistrés dans un répertoire défini par les arguments
projectetname. Par défaut, ce répertoire est « runs/detect/train# », où # correspond à un indice entier.results = {} # Define your additional arguments here batch = 16 project = "kfold_demo" epochs = 100 for k, dataset_yaml in enumerate(ds_yamls): model = YOLO(weights_path, task="detect") results[k] = model.train( data=dataset_yaml, epochs=epochs, batch=batch, project=project, name=f"fold_{k + 1}" ) # include any additional train arguments -
Tu peux également utiliser la fonction Ultralytics data.split.autosplit pour diviser automatiquement le jeu de données :
from ultralytics.data.split import autosplit # Automatically split dataset into train/val/test autosplit(path="path/to/images", weights=(0.8, 0.2, 0.0), annotated_only=True)
Conclusion#
Dans ce guide, nous avons étudié le processus d’utilisation de la validation croisée K-Fold pour entraîner le modèle de détection d’objets YOLO. Nous avons appris à diviser l’ensemble d’entraînement et de validation en K partitions et à utiliser le tableau de ratios généré pour examiner l’équilibre des classes après une division aléatoire.
Nous avons également étudié la procédure de création de DataFrames de rapport pour visualiser les divisions de données et les répartitions d’étiquettes entre ces divisions, ce qui nous donne une vision claire de la structure de nos ensembles d’entraînement et de validation.
Nous avons aussi enregistré nos résultats pour consultation ultérieure, ce qui peut être particulièrement utile dans les projets à grande échelle ou lors du diagnostic des performances du modèle.
Enfin, nous avons mis en œuvre l’entraînement réel du modèle en utilisant chaque division dans une boucle et en enregistrant les résultats de l’entraînement pour une analyse et une comparaison ultérieures.
Cette technique de validation croisée K-Fold constitue une méthode robuste pour tirer le meilleur parti de tes données disponibles et contribue à garantir que les performances de ton modèle sont fiables et cohérentes sur différents sous-ensembles de données. Il en résulte un modèle plus généralisable et plus fiable, moins susceptible de faire du surapprentissage sur des motifs de données spécifiques.
N’oublie pas que, même si nous avons utilisé YOLO dans ce guide, ces étapes sont largement transposables à d’autres modèles de machine learning. La compréhension de ces étapes te permet d’appliquer efficacement la validation croisée dans tes propres projets de machine learning.
FAQ#
La validation croisée K-Fold est une technique qui consiste à diviser le jeu de données en « k » sous-ensembles (folds) afin d’évaluer plus fiablement les performances du modèle. Chaque fold sert à la fois de données d’entraînement et de données de validation. Dans le contexte de la détection d’objets, l’utilisation de la validation croisée K-Fold contribue à garantir que les performances de ton modèle Ultralytics YOLO sont robustes et généralisables sur différentes divisions de données, ce qui renforce sa fiabilité. Pour obtenir des instructions détaillées sur la configuration de la validation croisée K-Fold avec Ultralytics YOLO, consulte Validation croisée K-Fold avec Ultralytics.
Le workflow de ce guide cible le format de détection YOLO, mais la même approche s’adapte à toutes les tâches YOLO : la tâche modifie la manière dont tu composes les folds, et non l’utilité de la validation croisée :
Tâche Conception des folds detectEffectue la division au niveau de l’image en équilibrant la répartition des objets et des classes entre les folds. Garde les images associées (même patient, séquence vidéo, caméra ou site) dans un seul fold. segmentUtilise la même stratégie au niveau de l’image que pour la détection, en préservant également la couverture des masques et des classes dans chaque fold. classifyPrivilégie les folds stratifiés afin que les fréquences des classes restent équilibrées entre l’entraînement et la validation. poseEffectue la division par sujet ou par séquence afin que la même personne ou le même animal n’apparaisse jamais des deux côtés d’un fold. obbEffectue la division au niveau de l’image en conservant ensemble les tuiles ou les recadrages provenant de la même scène — ce qui est particulièrement important pour les images aériennes. Quelle que soit la tâche, garde les échantillons quasi dupliqués et associés hors de folds opposés : ce type de fuite gonfle les métriques de validation bien au-delà de ce que le modèle atteindra en production.
Ultralytics YOLO offre une détection d’objets de pointe en temps réel, avec une précision et une efficacité élevées. Il est polyvalent et prend en charge plusieurs tâches de vision par ordinateur, telles que la détection, la segmentation d’instances, la segmentation sémantique et la classification. Il s’intègre également parfaitement à des outils tels que Ultralytics Platform pour l’entraînement et le déploiement de modèles sans code. Pour plus de détails, découvre les avantages et les fonctionnalités sur notre page Ultralytics YOLO.
Tes annotations doivent respecter le format de détection YOLO. Chaque fichier d’annotation doit répertorier la classe de l’objet ainsi que les coordonnées de sa boîte englobante dans l’image. Le format YOLO garantit un traitement des données rationalisé et standardisé pour l’entraînement des modèles de détection d’objets. Pour plus d’informations sur le formatage correct des annotations, consulte le guide du format de détection YOLO.
Oui, tu peux utiliser la validation croisée K-Fold avec n’importe quel jeu de données personnalisé, à condition que les annotations soient au format de détection YOLO. Remplace les chemins du jeu de données et les étiquettes de classe par ceux propres à ton jeu de données personnalisé. Cette flexibilité permet à tout projet de détection d’objets de bénéficier d’une évaluation robuste du modèle grâce à la validation croisée K-Fold. Pour un exemple pratique, consulte notre section Génération de vecteurs de caractéristiques.
Pour mettre en œuvre la validation croisée K-Fold avec Ultralytics YOLO, tu dois suivre les étapes suivantes :
sklearn,pandasetpyyaml.KFoldprovenant desklearn.model_selection.Pour un guide complet, consulte la section Division du jeu de données en K-Fold de notre documentation.