Zum Inhalt springen

K-fache Kreuzvalidierung mit Ultralytics

Einführung

Dieser umfassende Leitfaden veranschaulicht die Implementierung der K-Fold Cross Validation für Objekterkennungsdatensätze innerhalb des Ultralytics Ökosystems. Wir nutzen das YOLO Erkennungsformat und die wichtigsten Python Bibliotheken wie sklearn, pandas und PyYaml, um Sie durch die notwendige Einrichtung, den Prozess der Erzeugung von Merkmalsvektoren und die Ausführung einer K-Fold-Datensatzaufteilung zu führen.

K-Fold Cross Validation Überblick

Unabhängig davon, ob Ihr Projekt den Fruit Detection-Datensatz oder eine benutzerdefinierte Datenquelle umfasst, soll dieses Tutorial Ihnen helfen, die K-Fold Cross Validation zu verstehen und anzuwenden, um die Zuverlässigkeit und Robustheit Ihrer Daten zu verbessern. maschinelles Lernen Modelle. Während wir die k=5 Beachten Sie, dass die optimale Anzahl der Faltungen von Ihrem Datensatz und den Besonderheiten Ihres Projekts abhängen kann.

Ohne weitere Umschweife, lasst uns eintauchen!

Einrichtung

  • Ihre Anmerkungen sollten im ErkennungsformatYOLO verfasst sein.

  • In diesem Leitfaden wird davon ausgegangen, dass die Anmerkungsdateien lokal verfügbar sind.

  • Für unsere Demonstration verwenden wir den Datensatz "Fruit Detection".

    • Dieser Datensatz enthält insgesamt 8479 Bilder.
    • Sie umfasst 6 Klassenlabels, deren Gesamtanzahl der Instanzen unten aufgeführt ist.
Klasse Etikett Anzahl der Instanzen
Apfel 7049
Weintrauben 7202
Ananas 1613
Orange 15549
Banane 3536
Wassermelone 1976
  • Die erforderlichen Python Pakete umfassen:

    • ultralytics
    • sklearn
    • pandas
    • pyyaml
  • Dieses Lernprogramm arbeitet mit k=5 Falten. Sie sollten jedoch die beste Anzahl von Faltungen für Ihren spezifischen Datensatz ermitteln.

  • Starten Sie eine neue virtuelle Umgebung Python (venv) für Ihr Projekt und aktivieren Sie es. Verwenden Sie pip (oder Ihren bevorzugten Paketmanager) zu installieren:

    • Die Bibliothek Ultralytics : pip install -U ultralytics. Alternativ können Sie auch die offizielle Repo.
    • Scikit-Learn, Pandas und PyYAML: pip install -U scikit-learn pandas pyyaml.
  • Stellen Sie sicher, dass Ihre Anmerkungen im ErkennungsformatYOLO vorliegen.

    • Für dieses Lernprogramm befinden sich alle Anmerkungsdateien im Verzeichnis Fruit-Detection/labels Verzeichnis.

Generierung von Merkmalsvektoren für Objekterkennungsdatensätze

  1. Beginnen Sie mit der Erstellung eines neuen example.py Python Datei für die folgenden Schritte.

  2. Fahren Sie fort, um alle Etikettendateien für Ihren Datensatz abzurufen.

    from pathlib import Path
    
    dataset_path = Path("./Fruit-detection")  # replace with 'path/to/dataset' for your custom data
    labels = sorted(dataset_path.rglob("*labels/*.txt"))  # all data in 'labels'
    
  3. Lesen Sie nun den Inhalt der YAML-Datei des Datensatzes und extrahieren Sie die Indizes der Klassenbezeichnungen.

    yaml_file = "path/to/data.yaml"  # your data YAML with data directories and names dictionary
    with open(yaml_file, "r", encoding="utf8") as y:
        classes = yaml.safe_load(y)["names"]
    cls_idx = sorted(classes.keys())
    
  4. Initialisieren einer leeren pandas DataFrame.

    import pandas as pd
    
    indx = [label.stem for label in labels]  # uses base filename as ID (no extension)
    labels_df = pd.DataFrame([], columns=cls_idx, index=indx)
    
  5. Zählen Sie die Instanzen jedes Klassen-Labels in den Annotationsdateien.

    from collections import Counter
    
    for label in labels:
        lbl_counter = Counter()
    
        with open(label, "r") as lf:
            lines = lf.readlines()
    
        for line in lines:
            # classes for YOLO label uses integer at first position of each line
            lbl_counter[int(line.split(" ")[0])] += 1
    
        labels_df.loc[label.stem] = lbl_counter
    
    labels_df = labels_df.fillna(0.0)  # replace `nan` values with `0.0`
    
  6. Nachfolgend sehen Sie eine Beispielansicht des ausgefüllten DataFrame:

                                                           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
    

Die Zeilen indizieren die Etikettendateien, die jeweils einem Bild in Ihrem Datensatz entsprechen, und die Spalten entsprechen den Indizes Ihrer Klassenetiketten. Jede Zeile stellt einen Pseudo-Feature-Vektor dar, der die Anzahl der in Ihrem Datensatz vorhandenen Klassen-Labels enthält. Diese Datenstruktur ermöglicht die Anwendung der K-Fold Cross Validation auf einen Objekterkennungsdatensatz.

K-Fold Dataset Split

  1. Jetzt werden wir die KFold Klasse von sklearn.model_selection zu erzeugen k Aufteilung des Datensatzes.

    • Das ist wichtig:
      • Einstellung shuffle=True gewährleistet eine zufällige Verteilung der Klassen in Ihren Splits.
      • Durch die Einstellung random_state=M wobei M eine ausgewählte ganze Zahl ist, können Sie wiederholbare Ergebnisse erzielen.
    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))
    
  2. Der Datensatz wurde nun aufgeteilt in k Falten, jede mit einer Liste von train und val Indizes. Wir werden einen DataFrame konstruieren, um diese Ergebnisse deutlicher darzustellen.

    folds = [f"split_{n}" for n in range(1, ksplit + 1)]
    folds_df = pd.DataFrame(index=indx, columns=folds)
    
    for idx, (train, val) in enumerate(kfolds, start=1):
        folds_df[f"split_{idx}"].loc[labels_df.iloc[train].index] = "train"
        folds_df[f"split_{idx}"].loc[labels_df.iloc[val].index] = "val"
    
  3. Nun berechnen wir die Verteilung der Klassenbezeichnungen für jede Falte als Verhältnis der Klassen, die in val für die Anwesenden in train.

    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}"] = ratio
    

    Im Idealfall sollten alle Klassenverhältnisse für jeden Split und über alle Klassen hinweg einigermaßen ähnlich sein. Dies hängt jedoch von den Besonderheiten Ihres Datensatzes ab.

  4. Als Nächstes erstellen wir die Verzeichnisse und YAML-Dateien für jeden Split.

    import datetime
    
    supported_extensions = [".jpg", ".jpeg", ".png"]
    
    # Initialize an empty list to store image file paths
    images = []
    
    # Loop through supported extensions and gather image files
    for ext in supported_extensions:
        images.extend(sorted((dataset_path / "images").rglob(f"*{ext}")))
    
    # Create the necessary directories and dataset YAML files (unchanged)
    save_path = Path(dataset_path / f"{datetime.date.today().isoformat()}_{ksplit}-Fold_Cross-val")
    save_path.mkdir(parents=True, exist_ok=True)
    ds_yamls = []
    
    for split in folds_df.columns:
        # Create directories
        split_dir = save_path / split
        split_dir.mkdir(parents=True, exist_ok=True)
        (split_dir / "train" / "images").mkdir(parents=True, exist_ok=True)
        (split_dir / "train" / "labels").mkdir(parents=True, exist_ok=True)
        (split_dir / "val" / "images").mkdir(parents=True, exist_ok=True)
        (split_dir / "val" / "labels").mkdir(parents=True, exist_ok=True)
    
        # Create dataset YAML files
        dataset_yaml = split_dir / f"{split}_dataset.yaml"
        ds_yamls.append(dataset_yaml)
    
        with open(dataset_yaml, "w") as ds_y:
            yaml.safe_dump(
                {
                    "path": split_dir.as_posix(),
                    "train": "train",
                    "val": "val",
                    "names": classes,
                },
                ds_y,
            )
    
  5. Kopieren Sie schließlich Bilder und Beschriftungen in das jeweilige Verzeichnis ('train' oder 'val') für jeden Split.

    • HINWEIS: Die für diesen Teil des Codes benötigte Zeit hängt von der Größe Ihres Datensatzes und Ihrer Systemhardware ab.
    import shutil
    
    for image, label in zip(images, labels):
        for split, k_split in folds_df.loc[image.stem].items():
            # Destination directory
            img_to_path = save_path / split / k_split / "images"
            lbl_to_path = save_path / split / k_split / "labels"
    
            # Copy image and label files to new directory (SamefileError if file already exists)
            shutil.copy(image, img_to_path / image.name)
            shutil.copy(label, lbl_to_path / label.name)
    

Datensätze speichern (optional)

Optional können Sie die Datensätze der K-Fold-Split- und Etikettenverteilungs-DataFrames als CSV-Dateien zur späteren Verwendung speichern.

folds_df.to_csv(save_path / "kfold_datasplit.csv")
fold_lbl_distrb.to_csv(save_path / "kfold_label_distribution.csv")

Trainieren Sie YOLO mit K-Fold Data Splits

  1. Laden Sie zunächst das Modell YOLO .

    from ultralytics import YOLO
    
    weights_path = "path/to/weights.pt"
    model = YOLO(weights_path, task="detect")
    
  2. Als Nächstes iterieren Sie über die YAML-Dateien des Datensatzes, um das Training durchzuführen. Die Ergebnisse werden in einem Verzeichnis gespeichert, das durch die Option project und name Argumente. Standardmäßig ist dieses Verzeichnis 'exp/runs#', wobei # ein ganzzahliger Index ist.

    results = {}
    
    # Define your additional arguments here
    batch = 16
    project = "kfold_demo"
    epochs = 100
    
    for k in range(ksplit):
        dataset_yaml = ds_yamls[k]
        model = YOLO(weights_path, task="detect")
        model.train(data=dataset_yaml, epochs=epochs, batch=batch, project=project)  # include any train arguments
        results[k] = model.metrics  # save output metrics for further analysis
    

Schlussfolgerung

In diesem Leitfaden haben wir den Prozess der K-Fold-Kreuzvalidierung für das Training des Objekterkennungsmodells YOLO untersucht. Wir haben gelernt, wie wir unseren Datensatz in K Partitionen aufteilen, um eine ausgewogene Klassenverteilung über die verschiedenen Foldings zu gewährleisten.

Wir haben auch das Verfahren zur Erstellung von DataFrames für Berichte untersucht, um die Datenaufteilung und die Verteilung der Bezeichnungen über diese Aufteilungen zu visualisieren, was uns einen klaren Einblick in die Struktur unserer Trainings- und Validierungssätze gibt.

Optional haben wir unsere Aufzeichnungen für eine spätere Verwendung gespeichert, was besonders bei großen Projekten oder bei der Fehlersuche in Bezug auf die Modellleistung nützlich sein kann.

Schließlich haben wir das eigentliche Modelltraining mit jedem Split in einer Schleife durchgeführt und unsere Trainingsergebnisse für weitere Analysen und Vergleiche gespeichert.

Diese Technik der K-Fold-Kreuzvalidierung ist eine robuste Methode, um das Beste aus Ihren verfügbaren Daten herauszuholen, und sie hilft sicherzustellen, dass Ihre Modellleistung zuverlässig und konsistent über verschiedene Datenuntergruppen hinweg ist. Dies führt zu einem verallgemeinerungsfähigen und zuverlässigen Modell, das weniger wahrscheinlich auf bestimmte Datenmuster zugeschnitten ist.

Denken Sie daran, dass wir in diesem Leitfaden zwar YOLO verwendet haben, diese Schritte jedoch größtenteils auf andere Modelle für maschinelles Lernen übertragbar sind. Wenn Sie diese Schritte verstehen, können Sie die Kreuzvalidierung in Ihren eigenen Projekten für maschinelles Lernen effektiv anwenden. Viel Spaß beim Programmieren!

FAQ

Was ist K-Fold Cross Validation und warum ist sie bei der Objekterkennung nützlich?

Bei der K-Fold-Kreuzvalidierung wird der Datensatz in "k" Teilmengen (Folds) unterteilt, um die Leistung des Modells zuverlässiger zu bewerten. Jeder Fold dient sowohl als Trainings- als auch als Validierungsdaten. Im Zusammenhang mit der Objekterkennung hilft die K-Fold Cross Validation dabei, sicherzustellen, dass die Leistung Ihres Ultralytics YOLO Modells robust und über verschiedene Datensplits hinweg verallgemeinerbar ist, was seine Zuverlässigkeit erhöht. Detaillierte Anweisungen zum Einrichten der K-Fold Cross Validation mit Ultralytics YOLO finden Sie unter K-Fold Cross Validation mit Ultralytics.

Wie implementiere ich K-Fold Cross Validation mit Ultralytics YOLO ?

Um die K-Fold Cross Validation mit Ultralytics YOLO zu implementieren, müssen Sie die folgenden Schritte ausführen:

  1. Überprüfen Sie, ob die Anmerkungen im ErkennungsformatYOLO vorliegen.
  2. Verwenden Sie Python Bibliotheken wie sklearn, pandasund pyyaml.
  3. Erstellen Sie Feature-Vektoren aus Ihrem Datensatz.
  4. Teilen Sie Ihren Datensatz mit KFold von sklearn.model_selection.
  5. Trainieren Sie das Modell YOLO für jeden Split.

Eine umfassende Anleitung finden Sie im Abschnitt K-Fold Dataset Split in unserer Dokumentation.

Warum sollte ich Ultralytics YOLO für die Objekterkennung verwenden?

Ultralytics YOLO bietet modernste Objekterkennung in Echtzeit mit hoher Genauigkeit und Effizienz. Sie ist vielseitig und unterstützt mehrere Computer-Vision-Aufgaben wie Erkennung, Segmentierung und Klassifizierung. Außerdem lässt sie sich nahtlos in Tools wie Ultralytics HUB integrieren, um Modelltraining und -bereitstellung ohne Code zu ermöglichen. Weitere Einzelheiten zu den Vorteilen und Funktionen finden Sie auf unserer SeiteUltralytics YOLO .

Wie kann ich sicherstellen, dass meine Anmerkungen das richtige Format für Ultralytics YOLO haben?

Ihre Anmerkungen sollten dem Erkennungsformat YOLO entsprechen. Jede Annotationsdatei muss die Objektklasse zusammen mit den Koordinaten der Bounding Box im Bild auflisten. Das Format YOLO gewährleistet eine rationalisierte und standardisierte Datenverarbeitung für das Training von Objekterkennungsmodellen. Weitere Informationen zur korrekten Formatierung von Anmerkungen finden Sie in der Anleitung zum ErkennungsformatYOLO .

Kann ich die K-Fold Cross Validation auch mit anderen benutzerdefinierten Datensätzen als Fruit Detection verwenden?

Ja, Sie können die K-Fold Cross Validation mit jedem beliebigen benutzerdefinierten Datensatz verwenden, solange die Anmerkungen im Erkennungsformat YOLO vorliegen. Ersetzen Sie die Datensatzpfade und Klassenbeschriftungen mit denen, die für Ihren benutzerdefinierten Datensatz spezifisch sind. Diese Flexibilität stellt sicher, dass jedes Objekterkennungsprojekt von einer robusten Modellevaluation mit K-Fold Cross Validation profitieren kann. Ein praktisches Beispiel finden Sie im Abschnitt Generieren von Merkmalsvektoren.

📅 Erstellt vor 1 Jahr ✏️ Aktualisiert vor 1 Monat

Kommentare