Veri Kümesi Kalite Kontrolü
Bir betikle etiketleri, sınıf dengesini, yinelenenleri ve bölümlerin kapsamını denetle; eksik etiket olabilecek yerleri bir modele belirlet ve eğitimden önce bulduklarını düzelt.
Etiketleri düzeltmek genellikle hiperparametreleri ayarlamaktan daha fazla doğruluk kazandırır. Ekipler çoğu zaman mAP'te bir iki puan kazanmak için haftalarca ayarlarla uğraşır, ardından bir öğleden sonra süren denetimde bir sınıfın bir bölümünün baştan beri yanlış etiketlendiğini fark eder. Kalite kontrol, bir eğitim çalıştırması etiket hatalarını kimsenin güvenmemesi gereken bir sayıya dönüştürmeden önce, etiketleme kılavuzunun gözden kaçırdıklarını yakalar.
Uygulamalı
Yedi kontrol#
İlk eğitim çalıştırmasından önce ve her büyük etiketleme grubunun ardından bu yedi kontrolün tümünü yap. Etiketli verileri ön işleme kılavuzunda bunların birkaçı ayrıntılı olarak ele alınıyor.
| # | Kontrol | Neyi yakalar | Nasıl bulunur |
|---|---|---|---|
| 1 | Eksik etiketler | Etiketleyenlerin atladığı nesneler | Aşağıdaki şüpheli örnek incelemesi; görsel örnekleme |
| 2 | Yanlış veya geçersiz sınıflar | Karıştırılmış sınıflar, sınıf listesi dışında kalan kimlikler | Denetim betiği; ilk çalıştırmanın ardından karmaşıklık matrisi |
| 3 | Gevşek kutular | Kenar boşlukları olan veya kenarları kesilmiş kutular | Görsel örnekleme; denetimden gelen küçük kutu uyarıları |
| 4 | Yinelenenler | Birebir kopyalar ve neredeyse aynı kareler | Birebir kopyalar için denetim betiği; neredeyse aynı görüntüler için bölüme göre renklendirilmiş Ultralytics Platform Kümeleme görünümü |
| 5 | Sınıf dengesizliği | Belirtilen hedeflerin çok altında kalan sınıflar | Denetim betiği; Platform'daki Grafikler sekmesi |
| 6 | Bölümlerin kapsamı ve veri sızıntısı | Bir bölümde bulunmayan sınıflar; iki bölümde birden bulunan klipler | Denetim betiği; gruplandırılmış bölmeler (sonraki ders) |
| 7 | Arka plan oranı | Boş görüntü sayısının çok az veya çok fazla olması | Denetim betiği; hedef %0–10 |
Sayımları otomatikleştir#
2, 4, 5, 6 ve 7. kontroller sayım gerektirir; bu nedenle bunları betikleştir. Bu denetim, train: ve val: değerleri görüntü klasörlerine işaret eden bir nesne tespiti veri YAML dosyasını okur. Her bölümdeki sınıf başına örnekleri ve arka plan görüntülerini sayar; geçersiz sınıf kimliklerini, küçük kutuları, yinelenen etiket satırlarını ve bayt düzeyinde aynı görüntüleri işaretler; ayrıca doğrulama kümesinde bulunan ama eğitim kümesinde hiç bulunmayan sınıfları listeler:
import hashlib
from collections import Counter
from pathlib import Path
from ultralytics.data.utils import IMG_FORMATS, check_det_dataset, img2label_paths
data = check_det_dataset("coco8.yaml") # downloads COCO8 on first run; swap in your data YAML
names, seen = data["names"], {}
for split in ("train", "val"):
images = sorted(p for p in Path(data[split]).rglob("*.*") if p.suffix[1:].lower() in IMG_FORMATS)
instances, hashes, problems, background = Counter(), Counter(), [], 0
for img, label in zip(images, img2label_paths([str(p) for p in images])):
hashes[hashlib.md5(img.read_bytes()).hexdigest()] += 1
rows = [r.split() for r in Path(label).read_text().splitlines() if r.strip()] if Path(label).exists() else []
background += not rows
if len(rows) != len({tuple(r) for r in rows}):
problems.append(f"{img.name}: duplicate label rows")
for r in rows:
cls, w, h = int(r[0]), float(r[3]), float(r[4])
if cls not in names:
problems.append(f"{img.name}: class {cls} is not in names")
elif w * h < 1e-4:
problems.append(f"{img.name}: tiny {names[cls]} box")
instances[cls] += 1
seen[split] = set(instances)
duplicates = sum(n - 1 for n in hashes.values())
print(f"{split}: {len(images)} images, {background} background, {duplicates} duplicate images")
for cls, n in instances.most_common():
print(f" {names.get(cls, cls):>12} {n}")
for problem in problems:
print(" !", problem)
print("in val but never in train:", sorted(names[c] for c in seen["val"] - seen["train"] if c in names))train: 4 images, 0 background, 0 duplicate images
orange 4
bowl 3
giraffe 2
...
val: 4 images, 0 background, 0 duplicate images
person 10
horse 2
...
in val but never in train: ['dog', 'elephant', 'horse', 'person', 'umbrella']Son satır, bulgudur. person sınıfının doğrulama kümesinde 10 örneği, eğitim kümesinde ise hiç örneği yok; yani doğrulama, modelin hiç eğitilmediği bir sınıfı puanlıyor. COCO8, 8 görüntülük bir duman testi kümesidir; bu nedenle orada böyle bir durum beklenir. Kendi veri kümen içinse eğitimden önce bölümlemeyi düzeltmen veya daha fazla veri toplaman gerekir. Sorun varsa ilgili bölümün altında ! 000000000025.jpg: class 99 is not in names veya ! 000000000009.jpg: duplicate label rows olarak yazdırılır.
Şüpheli etiketleri modele buldur#
Eksik etiketler en çok zarar veren ve görüntüler arasında gezinerek bulması en zor hatalardır. Önceden eğitilmiş bir model bunları işaret edebilir: yakınında hiçbir etiket bulunmayan güvenilir bir tespit ya eksik etikettir ya da model hatasıdır; her iki durumda da incelemeye değer. Bu işlem COCO128 üzerinde çalışır:
from pathlib import Path
import torch
from ultralytics import YOLO
from ultralytics.data.utils import check_det_dataset, img2label_paths
from ultralytics.utils.metrics import box_iou
from ultralytics.utils.ops import xywh2xyxy
data = check_det_dataset("coco128.yaml") # swap in your data YAML
model = YOLO("yolo26n.pt") # a pretrained model, or your own first fine-tune
images = sorted(Path(data["train"]).glob("*.jpg"))
suspects = []
for result, label in zip(model(images, conf=0.6, stream=True, verbose=False), img2label_paths(map(str, images))):
rows = [r.split() for r in Path(label).read_text().splitlines() if r.strip()] if Path(label).exists() else []
boxes = xywh2xyxy(torch.tensor([[float(v) for v in r[1:5]] for r in rows]).reshape(-1, 4))
iou = box_iou(result.boxes.xyxyn, boxes) # model boxes vs labeled boxes
for j, (cls, conf) in enumerate(zip(result.boxes.cls.int().tolist(), result.boxes.conf.tolist())):
if not rows or iou[j].max() < 0.3: # confident detection with no label anywhere near it
suspects.append((conf, Path(result.path).name, model.names[cls]))
print(f"{len(suspects)} confident detections with no matching label; top 5:")
for conf, name, cls in sorted(suspects, reverse=True)[:5]:
print(f" {conf:.2f} {cls:<12} {name}")4 confident detections with no matching label; top 5:
0.77 donut 000000000438.jpg
0.75 person 000000000531.jpg
0.71 donut 000000000438.jpg
0.66 bottle 000000000436.jpg128 görüntü arasından betik, incelemeyi üç görüntüye indirir. Bu görüntüleri açtığında iki tür bulguyu da görürsün:
000000000438.jpg, bir düzine donutun bulunduğu kutunun içinde, güvenilir iki tespitin etiketli hiçbir donutla örtüşmediğini gösterir: bunlar eksik veya yanlış yerleştirilmiş etiket adaylarıdır.000000000531.jpg, tenis kortundaki fotoğrafçının gölgesini "kişi" olarak işaretler. Etiket doğrudur, model yanlıştır; bu da her şüpheli örneğin otomatik olarak eklenmek yerine bir kişi tarafından incelenmesinin nedenini gösterir.
Daha geniş bir tarama için conf değerini düşür ve ilk ince ayarını yaptıktan sonra kendi modelini kullan; çünkü modelin sınıflarını tanır.
Veri kümesi grafiklerini oku#

Ultralytics Platform'da veri kümesinin Grafikler sekmesi, bölüm dağılımını, sınıf sayılarını ve kutu istatistiklerini gösterir (veri kümesi belgeleri). Bu ekran görüntüsünde bir kalite kontrol bulgusu zaten var: sınıf listesinde iki sınıf bulunuyor, ancak tablet sınıfının 1.755 etiket arasında hiç etiketi yok. Etiketi olmayan bir sınıf öğrenilemez. Eğitimden önce ya bu sınıfa etiket ekle ya da sınıf listesinden çıkar.
Sınıf dengesizliğini doğru sırayla düzelt#
forklift ████████████████████████ 8000 instances
person ████████████████ 5400
pallet ██ 700 ← red flagBöyle bir fark, forkliftlerde kendinden emin olan ama paletleri kaçıran bir model ortaya çıkarır. Üç çözüm, doğru sırayla:
- Azınlık sınıfından daha fazla veri topla ve etiketle. Her zaman en iyi çözüm budur: her sınıftan ≥ 1.500 görüntü ve ≥ 10.000 örnek hedefle.
- Yalnızca eğitim kümesinde aşırı örnekleme yap. Azınlık sınıfını içeren görüntüleri eğitim dosya listesine birden fazla kez ekle; böylece model her epoch'ta bu görüntüleri daha sık görür. Kopyaları doğrulama ve test kümelerine ekleme.
- Kaybı ağırlıklandır. Eğitim argümanı
cls_pw(varsayılanı 0.0, ters frekansa göre tam ağırlıklandırmada 1.0'a kadar çıkar), nadir sınıfların sınıflandırma kaybı ağırlığını artırır. Yalnızca 1 ve 2. yöntemlerden sonra bu seçeneği kullan.
Bulanık, kalabalık veya kafa karıştırıcı görüntüleri doğrulamadan çıkarmak mAP'yi yükseltir ama modeli iyileştirmez; yalnızca daha az dürüst hâle getirir. Bir görüntü gerçek bir dağıtım karesiyse kalsın; bunun yerine etiketlerini düzelt. Yalnızca gerçek aykırı değerleri (9. hata) ve tam kopyaları çıkar.
Kalite kontrol notları yaz#
Birkaç satır yeterlidir; aylar sonra bir müşteri veya denetçi "Neleri kontrol ettin?" diye sorduğunda yanıt verir:
Dataset: forklift-v1 Audit date: 2026-05-09
Images: 4,820 Labels: 18,442 Background: 380 (7.9%)
Audit script: 3 invalid class IDs fixed, 41 duplicate label rows removed
Suspect review: 62 flagged, 19 missing labels added, 43 model errors ignored
Visual sample: 120 images, 4 mislabeled (3.3%), fixed
Split check: grouped by camera-day, every class in every split
Imbalance: pallet 2.5x below person; collecting more next round
Ready to train: yesÇözümü göster
Bu dersteki iki demo çalıştırmasına ait kalite kontrol notları:
Dataset: COCO8 + COCO128 demo Audit date: 2026-05-09
qc_audit.py (COCO8): 0 invalid classes, 0 duplicate rows, 0 duplicate images
FINDING: dog, elephant, horse, person, umbrella appear in val only
ACTION: re-split by group or collect these classes into train before training
suspect_labels.py (COCO128, conf 0.6): 4 suspects in 3 images
000000000438.jpg: 2 donuts without matching labels -> relabel the donut box
000000000531.jpg: "person" is the photographer's shadow -> model error, label kept
000000000436.jpg: bottle -> open and decide
Ready to train: no, fix the val-only classes firstSon satıra dikkat et. Yalnızca doğrulama kümesinde bulunan bir sınıfa sahip veri kümesi, her etiket tek tek doğru olsa bile kalite kontrolünden geçemez; çünkü o sınıfa ait metrik, modelin öğrenme fırsatı bulamadığı bir şeyi ölçer.