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.
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):

- 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 valSo 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.

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:
| Werkzeug | Zuweisungsweise | Verwendung |
|---|---|---|
train/, val/ und test/ als Ordner in einem Upload | Behält deine Zuweisung bei | Gruppenaufteilungen offline vorbereiten |
| Filter für die Aufteilung vor dem Hochladen festlegen | Alle Dateien dieses Uploads kommen in die ausgewählte Aufteilung | Je eine Kamera pro Aufteilung hochladen |
| In Aufteilung verschieben in der Tabellenansicht | Verschiebt die ausgewählten Bilder | Bestimmte Bilder korrigieren |
| Leiste für Aufteilungen, Aufteilungen neu verteilen | Weist alle Bilder zufällig neu zu | Nur für unabhängige Fotos |

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#
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.
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.
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.
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.