Ultralytics YOLO27: Trag dich in die Warteliste ein.
Get Started
Mit der Ultralytics Platform entwickeln·Dataset erstellen·Lektion 4/10
LektionFortgeschrittene

Daten kuratieren, Duplikate entfernen und aufteilen

Finde mit zwei kurzen Skripten Duplikate zwischen den Aufteilungen und Lücken bei Klassen, teile die Daten nach der maßgeblichen Einheit auf und fixiere eine geprüfte Datensatzversion.

Wie verlässlich ein Validierungsergebnis ist, hängt davon ab, wie sauber die Daten aufgeteilt sind. COCO128, ein beliebter Demo-Datensatz, verwendet absichtlich dieselben 128 Bilder für Training und Validierung. Ein versehentliches Pendant in deinen eigenen Daten liefert dir ein „großartiges“ Modell, das an der nächsten Kamera versagt. In dieser Lektion prüfst du echte Daten auf zwei Arten: auf Duplikate und auf Klassen pro Aufteilung. Anschließend teilst du die Daten nach Kamera auf und fixierst eine Version, die beide Prüfungen bestanden hat.

Lernergebnis

Du kannst nachweisen, dass keine Bilder in mehreren Aufteilungen vorkommen, keine Kamera und keine Sitzung mehreren Aufteilungen zugeordnet ist und für jede Klasse genügend Instanzen in der Validierung vorhanden sind. Anschließend kannst du den Datensatz als nummerierte Version fixieren.

Schnellkurs
Wenn du dich bereits auskennst, findest du hier die Kurzfassung.
  1. Erzeuge Hashes der Bilder pro Aufteilung: Kommt ein Hash in zwei Aufteilungen vor, liegt eine Überschneidung vor.

  2. Prüfe den NDJSON-Export: Jede Klasse braucht Trainingsbeispiele und genügend Validierungsinstanzen für aussagekräftige Messungen.

  3. Führe Clustering mit Einfärbung nach Aufteilung aus, um Beinahe-Duplikate zu finden, die beim Hashvergleich unentdeckt bleiben.

  4. Ordne die Aufteilungen nach Kamera, Standort oder Sitzung zu. Teile Videobilder niemals zufällig neu auf.

  5. Erstelle eine nummerierte Version mit Beschreibung und trainiere nur mit bestandenen Versionen.

Praxisnah

Durchgearbeitetes Beispiel: Bilder finden, die in mehreren Aufteilungen vorkommen#

Die Plattform behält beim Hochladen pro Aufteilung eine Kopie eines Bildes und fragt, wie sie mit Kollisionen umgehen soll. Das verhindert jedoch nicht, dass dasselbe Bild oder dieselbe Szene sowohl in Training als auch in Validierung landet. Prüfe das vor dem Hochladen und erneut nach dem Zusammenführen von Datensätzen:

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']

Jedes Validierungsbild aus COCO128 ist auch ein Trainingsbild. Das ist für einen Datensatz zum schnellen Funktionstest beabsichtigt und genau der Grund, warum seine Validierungs-mAP nichts über die Verallgemeinerungsfähigkeit aussagt. In deinen Daten ist jeder Wert ungleich null eine Überschneidung: Verschiebe oder lösche vor dem Training eine Kopie jedes betroffenen Bildes.

Beinahe-Duplikate mit Clustering finden#

Hashes finden nur bytegenau identische Dateien. Aufeinanderfolgende Videobilder, Serienfotos und neu kodierte Kopien unterscheiden sich um einige Pixel. Öffne das Symbol für Streudiagramme in der Galerieleiste und klicke auf Analyze Dataset (20 bis 200,000 Bilder, nur hochgeladene Datensätze):

Galerie der medizinischen Pillen in der Ultralytics Platform mit geöffnetem Clustering-Bereich, in dem jedes Bild als Punkt in einem zweidimensionalen Streudiagramm dargestellt ist und sich visuell ähnliche Bilder nahe beieinander befinden

  • Nach Aufteilungen einfärben: Eine dichte Insel, in der sich Punkte aus Training und Validierung mischen, weist auf eine Überschneidung durch Beinahe-Duplikate hin.
  • Nach Clustern oder Klassen einfärben: Eine riesige Insel mit nur einer Klasse zeigt, was im Datensatz überrepräsentiert ist. Vereinzelte Punkte sind Ausreißer (falsche Kamera, beschädigtes Bild, falsch beschriftetes Bild).
  • Mit dem Lasso oder durch Klicken kannst du einen Bereich auswählen und die Galerie auf die entsprechenden Bilder (bis zu 1,000) filtern. Lösche, verschiebe oder beschrifte sie dann neu.

Dieselben Einbettungen ermöglichen Ähnliche Bilder finden im Kontextmenü eines Bildes. Damit werden ähnliche Bilder aus öffentlichen Datensätzen und Teamdatensätzen als unbeschriftete Bilder zu train hinzugefügt: der schnellste Weg, eine Lücke zu schließen, die bei der folgenden Prüfung auffällt.

Durchgearbeitetes Beispiel: Klassen pro Aufteilung prüfen#

Lade den NDJSON-Export über die Kopfzeile des Datensatzes oder den Tab Versions herunter. Jede Zeile nach der Kopfzeile enthält ein Bild mit seiner Aufteilung und seinen Labels. Mit wenigen Zeilen Python kannst du daher jede Klasse in jeder Aufteilung zählen. Hier wird das Skript auf den öffentlichen COCO8-Export angewendet:

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

So liest du die Ergebnisse: Die Kopfzeile enthält class_names; jede Erkennungsbox ist [class, x, y, w, h]. Fehlt eine Klasse im Training, kann das Modell sie überhaupt nicht erlernen, und ihr AP-Wert bei der Validierung ist null. Zu wenige Instanzen in der Validierung bedeuten, dass ihr AP-Wert zwischen Durchläufen stark schwankt: Bei 7 Paletten in der Validierung verändert eine einzige übersehene Palette den Paletten-AP-Wert um etwa 14 Punkte. COCO8 ist ein Schnelltest mit 8 Bildern, daher fällt jede Klasse durch. Deine Produktionsversion sollte keine Warnungen ausgeben. Schließe Lücken, indem du mehr Beispiele sammelst, nicht durch Optimierung.

Tab Classes der Ultralytics Platform für den Datensatz medical-pills mit einem Histogramm der Klassenverteilung und einer Klassentabelle mit der Anzahl der Annotationen und Bilder

Der Tab Classes zeigt dieselben Zählwerte für den aktuellen Datensatz, mit einer Umschaltung auf eine logarithmische Skala für unausgewogene Daten. Zu einer Klasse zusammenführen fasst Duplikate wie car, automobile und vehicle zu einer Klasse zusammen, ohne Annotationen zu verlieren. Löschen entfernt eine Klasse und alle zugehörigen Annotationen.

Nach der Einheit aufteilen, auf die du verallgemeinern willst#

Bilder derselben Kamera, Sitzung oder desselben Tages sind korreliert. Kommen sie sowohl im Training als auch in der Validierung vor, wird das Modell anhand von Szenen bewertet, die es bereits gesehen hat. Halte ganze Einheiten zurück, je nachdem, was sich in der Produktion ändert: Bei neuen Kameras hältst du ganze Kameras zurück; bei denselben Kameras an neuen Tagen hältst du ganze Tage zurück.

Die Aufteilungswerkzeuge der Plattform unterscheiden sich genau in diesem Punkt:

WerkzeugZuweisungsweiseVerwendung
train/, val/ und test/ als Ordner in einem UploadBehält deine Zuweisung beiGruppenaufteilungen offline vorbereiten
Filter für die Aufteilung vor dem Hochladen festlegenAlle Dateien dieses Uploads kommen in die ausgewählte AufteilungJe eine Kamera pro Aufteilung hochladen
In Aufteilung verschieben in der TabellenansichtVerschiebt die ausgewählten BilderBestimmte Bilder korrigieren
Leiste für Aufteilungen, Aufteilungen neu verteilenWeist alle Bilder zufällig neu zuNur für unabhängige Fotos

Dialog „Aufteilungen neu verteilen“ in der Ultralytics Platform für den Datensatz medical-pills mit einer Leiste für Aufteilungen und Prozentfeldern, eingestellt auf 80 für Training, 20 für Validierung und 0 für Test

In der Lektion Datensatz richtig aufteilen geht es um die Auswahl der Einheit. Bei sehr kleinen Datensätzen holt k-fache Kreuzvalidierung mehr verwertbare Informationen heraus. Um Gruppen nach dem Hochladen zu prüfen, füge der Klassenprüfung einen Gruppenschlüssel hinzu (zum Beispiel record["file"].split("_")[0] für Dateien mit den Namen cam07_000123.jpg oder ein Feld camera in den Bildmetadaten) und gib alle Gruppen aus, die in zwei Aufteilungen vorkommen.

Eine bestandene Version fixieren#

Für das Training brauchst du einen unveränderlichen Stand. Gib im Tab Versions eine Beschreibung ein („v5: cam07 zurückgehalten, +80 Palettenbilder“) und klicke auf New Version. Jede Version ist ein unveränderlicher, nummerierter NDJSON-Stand, den du herunterladen, vergleichen oder wiederherstellen kannst. Save Dataset Version im Trainingsdialog erstellt beim Start ebenfalls eine Version und verwendet eine passende vorhandene Version wieder, wenn sich nichts geändert hat. Für verbundene Cloud-Datensätze und On-Premise-Datensätze sind Versionen nicht verfügbar.

Stolperfallen#

Aufteilungen bei Videobildern neu verteilen

Symptom: Nach einem Klick auf Automatisch mit der Aufteilung 80/20 steigt der Validierungs-mAP sprunghaft an, die Genauigkeit im Produktivbetrieb jedoch nicht. Lösung: „Aufteilungen neu verteilen“ weist jedes Bild zufällig neu zu (und entfernt dabei exakte Duplikate), sodass benachbarte Bilder in Trainings- und Validierungsdaten landen. Verwende für gruppierte Daten Upload-Ordner oder In Aufteilung verschieben.

Beim Zusammenführen oder Löschen einer Klasse verschieben sich alle Klassen-IDs

Symptom: Ein alter Export oder die Vorhersagen eines Modells tragen plötzlich die falschen Klassennamen. Lösung: Klassen-IDs sind positionsabhängig. Daher rückt beim Zusammenführen oder Löschen einer Klasse jeder höhere Index um eins nach unten. Erstelle vor jeder Klassenänderung eine Version und trainiere das Modell neu, statt alte Labeldateien wiederzuverwenden.

Die Aufteilung mitten im Projekt ändern

Symptom: Ein neuer Lauf erzielt 5 Punkte weniger, obwohl sich sonst nichts geändert hat. Lösung: Metriken lassen sich nur bei identischer Aufteilung vergleichen. Wenn du die Aufteilung änderst, vermerke das in der Versionsbeschreibung und führe die Baseline auf der neuen Version erneut aus, bevor du Ergebnisse vergleichst.

Ausprobieren

Führe cross_split_dupes.py auf deinem lokalen Datensatz und class_audit.py auf deinem NDJSON-Export von der Plattform aus. Gib dabei einen Gruppenschlüssel für die Benennung deiner Kameras oder Sitzungen an. Behebe alle gemeldeten Überschneidungen und Lücken (In Aufteilung verschieben, Ähnliche Bilder finden, weitere Daten sammeln), und führe beide Skripte erneut aus, bis sie keine Probleme mehr melden. Prüfe das Clustering mit Einfärbung nach Aufteilung und erstelle eine Version mit Beschreibung.

Abgeschlossen, wenn
Du hast die Lektion abgeschlossen, wenn alle folgenden Punkte zutreffen.
  • Die Duplikatprüfung meldet identical in both: 0, und keine Kamera- oder Sitzungsgruppe kommt in zwei Aufteilungen vor.

  • Die Klassenprüfung meldet keine missing in train-Warnungen, und du hast für jedes too few in val festgelegt, was damit geschehen soll.

  • Es gibt eine nummerierte Version, deren Beschreibung die Aufteilungsregel und die vorgenommenen Änderungen nennt.

Lösung anzeigen

Beispiellösung für einen Gabelstapler-Datensatz mit 8 Kameras. Bei der Duplikatprüfung werden 41 identische Bilder zwischen Training und Validierung gefunden, alle aus einem erneut hochgeladenen Ordner. Lösche die Kopien in der Validierung. Die um group = record['file'].split('_')[0] ergänzte Prüfung zeigt, dass cam02 sowohl im Training als auch in der Validierung vorkommt. Wähle daher die Validierungsbilder von cam02 in der Tabellenansicht aus und klicke auf In Aufteilung verschieben > Training. Außerdem wird pallet: train 63, val 7, too few in val gemeldet: Nutze bei zwei Palettenbildern die Funktion Ähnliche Bilder finden, um 40 ähnliche unbeschriftete Bilder hinzuzufügen. Beschrifte sie und verschiebe 15 Palettenbilder von cam07 in die Validierung, damit cam07 als Gruppe zusammenbleibt. Erneute Prüfung: 0 Duplikate, 0 überscheidende Gruppen, 22 Paletten in der Validierung. Beim Clustering mit Einfärbung nach Aufteilung sind keine gemischten Inseln zu sehen. Speichere v5: cam07 val, cam08 test, +40 pallets.

Wie es weitergeht

Die bereinigten, versionierten Daten liegen vor. Als Nächstes trainierst du damit, wertest den Durchlauf aus und stimmst das Modell richtig fein ab.