Ultralytics YOLO27: Iscriviti alla lista d'attesa.
Get Started
Crea con Ultralytics Platform·Crea il dataset·Lezione 4/10
Lezioneintermedio

Selezione, deduplicazione e suddivisione

Individua i duplicati tra split e le lacune nelle classi con due brevi script, suddividi i dati in base all'unità rilevante e blocca una versione del dataset verificata.

L'affidabilità di un punteggio di validazione dipende da quanto è corretto lo split. COCO128, un popolare dataset dimostrativo, usa intenzionalmente le stesse 128 immagini per train e val; una versione accidentale di questo scenario nei tuoi dati ti dà un modello «ottimo» che fallisce con la fotocamera successiva. In questa lezione eseguirai due verifiche su dati reali, un controllo dei duplicati e un controllo delle classi per split, quindi suddividerai i dati per fotocamera e bloccherai una versione che ha superato entrambi.

Esito

Puoi dimostrare che una versione del dataset non contiene immagini condivise tra gli split, che nessuna fotocamera o sessione è presente in due split e che la validazione contiene istanze sufficienti di ogni classe, quindi bloccarla come versione numerata.

Percorso rapido
Se sai già come muoverti, ecco la versione breve.
  1. Calcola l'hash delle immagini per ogni split: un hash presente in due split indica una contaminazione.

  2. Verifica l'esportazione NDJSON: ogni classe deve avere esempi di training e un numero sufficiente di istanze in val per poter essere misurata.

  3. Esegui Clustering con la colorazione per split per individuare i quasi duplicati che sfuggono al controllo degli hash.

  4. Assegna gli split in base alla fotocamera, al sito o alla sessione; non ridistribuire mai in modo casuale i fotogrammi video.

  5. Crea una versione numerata con una descrizione e addestra il modello solo su versioni che hanno superato i controlli.

Pratico

Esempio pratico: trovare immagini condivise tra gli split#

La piattaforma conserva una sola copia di un'immagine per split e chiede come gestire le collisioni durante il caricamento, ma nulla impedisce alla stessa immagine o scena di finire sia in train sia in val. Controlla prima di caricare e di nuovo dopo aver unito i dataset:

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

Ogni immagine di validazione di COCO128 è anche un'immagine di training. È intenzionale per un dataset di test rapido, ed è proprio per questo che il suo mAP di validazione non dice nulla sulla generalizzazione. Nei tuoi dati, qualsiasi conteggio diverso da zero indica una contaminazione: sposta o elimina una copia di ciascuna immagine prima del training.

Individua i quasi duplicati con Clustering#

Gli hash rilevano solo byte identici. I fotogrammi video consecutivi, le foto a raffica e le copie ricodificate differiscono per pochi pixel. Apri l'icona del grafico a dispersione nella barra degli strumenti della galleria e fai clic su Analyze Dataset (da 20 a 200,000 immagini, solo dataset caricati):

Galleria Ultralytics Platform del dataset medical-pills con il pannello Clustering aperto, che rappresenta ogni immagine come un punto in un grafico a dispersione 2D, in cui le immagini visivamente simili sono vicine

  • Colora per split: un gruppo compatto che mescola punti train e val indica una contaminazione da quasi duplicati.
  • Colora per cluster o classi: un grande gruppo composto da una sola classe mostra quali elementi sono sovrarappresentati nel dataset; i punti isolati sono valori anomali (fotocamera sbagliata, fotogramma danneggiato, immagine etichettata in modo errato).
  • Seleziona con il lazo o fai clic su una regione per filtrare la galleria e mostrare quelle immagini (fino a 1,000), quindi eliminale, spostale o rietichettale.

Gli stessi embedding alimentano Trova immagini simili nel menu contestuale dell'immagine, che aggiunge a train immagini simili provenienti da dataset pubblici e del team, come immagini non etichettate: il modo più rapido per colmare una lacuna individuata dalla verifica qui sotto.

Esempio pratico: verifica delle classi per split#

Scarica l'esportazione NDJSON dall'intestazione del dataset o dalla scheda Versions. Ogni riga dopo l'intestazione corrisponde a un'immagine con il relativo split e le etichette, quindi bastano poche righe di Python per contare ogni classe in ogni split. Qui viene usata l'esportazione pubblica di COCO8:

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

Come leggerla: la riga di intestazione contiene class_names; ogni box di rilevamento è [class, x, y, w, h]. Assente in train significa che il modello non può imparare affatto la classe e che il suo AP in val sarà zero. Troppo poche istanze in val significa che il suo AP varierà molto da un'esecuzione all'altra: con 7 pallet in val, un pallet mancato sposta l'AP dei pallet di circa 14 punti. COCO8 è un test rapido con 8 immagini, quindi tutte le classi non superano il controllo; la tua versione di produzione non dovrebbe generare alcuna segnalazione. Colma le lacune raccogliendo altri esempi, non modificando i parametri.

Scheda Classes di Ultralytics Platform nel dataset medical-pills, con un istogramma della distribuzione delle classi e una tabella delle classi che riporta il numero di annotazioni e immagini

La scheda Classes mostra gli stessi conteggi per il dataset attivo, con un'opzione per la scala logaritmica per i dati sbilanciati. Unisci in una raggruppa classi duplicate come car, automobile e vehicle in un'unica classe senza perdere annotazioni; Elimina rimuove una classe e tutte le sue annotazioni.

Suddividi in base all'unità rispetto a cui vuoi generalizzare#

I fotogrammi della stessa fotocamera, sessione o giornata sono correlati. Se compaiono sia in train sia in val, il modello viene valutato su scene che ha già visto. Escludi intere unità relative a ciò che varia in produzione: se variano le fotocamere, escludi alcune fotocamere; se sono le stesse fotocamere in giornate diverse, escludi alcune giornate.

Gli strumenti di suddivisione della piattaforma si differenziano proprio per questo:

StrumentoModalità di assegnazioneUsala per
Cartelle train/, val/, test/ in un caricamentoMantiene la tua assegnazioneSplit di gruppi preparati offline
Filtro dello split impostato prima del caricamentoTutti i file di quel caricamento vengono assegnati allo split selezionatoCaricamento di una fotocamera per split
Sposta nello split nella vista TableSposta le immagini selezionateCorrezione di immagini specifiche
Barra degli split, Ridistribuisci splitRiassegna casualmente tutte le immaginiSolo foto indipendenti

Finestra di dialogo Redistribute Splits di Ultralytics Platform nel dataset medical-pills, con una barra degli split e campi percentuali impostati su 80 train, 20 validation e 0 test

La lezione Suddividere correttamente il dataset spiega come scegliere l'unità; per dataset molto piccoli, la convalida incrociata k-fold permette di ottenere più informazioni. Per controllare i gruppi dopo il caricamento, aggiungi una chiave di gruppo alla verifica delle classi (per esempio record["file"].split("_")[0] per i file chiamati cam07_000123.jpg, oppure un campo camera nei metadati dell'immagine) e segnala ogni gruppo presente in due split.

Blocca una versione che ha superato i controlli#

Il training richiede uno snapshot fisso. Nella scheda Versions, inserisci una descrizione («v5: cam07 esclusa, +80 immagini di pallet») e fai clic su New Version. Ogni versione è uno snapshot NDJSON numerato e immutabile che puoi scaricare, confrontare o ripristinare; la finestra di dialogo del training, con Save Dataset Version, fa lo stesso all'avvio e riutilizza una versione corrispondente se non è cambiato nulla. Le versioni non sono disponibili per i dataset cloud connessi o On Premise.

Insidie#

Ridistribuire le partizioni nei fotogrammi video

Sintomo: dopo aver fatto clic su Auto 80/20, la mAP di convalida aumenta, ma l'accuratezza in produzione no. Soluzione: Ridistribuisci partizioni riassegna casualmente ogni immagine (rimuovendo anche i duplicati esatti) e inserisce fotogrammi adiacenti nelle partizioni di addestramento e convalida. Per i dati raggruppati, usa le cartelle di caricamento o Sposta nella partizione.

Unire o eliminare una classe sposta tutti gli ID delle classi

Sintomo: un'esportazione precedente o le predizioni di un modello iniziano improvvisamente a riportare nomi di classe errati. Soluzione: gli ID delle classi sono posizionali, quindi unire o eliminare una classe sposta verso il basso tutti gli indici successivi. Crea una versione prima di qualsiasi modifica alle classi e riaddestra il modello invece di riutilizzare i vecchi file di etichette.

Modificare la partizione a progetto avviato

Sintomo: una nuova esecuzione ottiene un punteggio inferiore di 5 punti e non è cambiato nient'altro. Soluzione: le metriche sono confrontabili solo se calcolate sulla stessa partizione. Quando modifichi la partizione, annotalo nella descrizione della versione e riesegui il baseline sulla nuova versione prima di fare qualsiasi confronto.

Provalo

Esegui cross_split_dupes.py sul tuo dataset locale e class_audit.py sull'esportazione NDJSON della piattaforma, specificando una chiave di gruppo basata sul nome della fotocamera o della sessione. Correggi tutte le contaminazioni e lacune segnalate (Sposta nello split, Trova immagini simili, altri dati), ripeti entrambi i controlli finché non danno risultati puliti, verifica Clustering con la colorazione per split e crea una versione descritta.

Criteri di completamento
La lezione è completata quando tutte le seguenti condizioni sono soddisfatte.
  • Il controllo dei duplicati segnala identical in both: 0 e nessun gruppo di fotocamera o sessione è presente in due split.

  • La verifica delle classi non segnala alcun missing in train e hai deciso come intervenire su ciascun too few in val.

  • Esiste una versione numerata la cui descrizione specifica la regola di suddivisione e le modifiche apportate.

Mostra la soluzione

Soluzione svolta per un dataset di carrelli elevatori ripresi da 8 fotocamere. Il controllo dei duplicati rileva 41 immagini identiche tra train e val, tutte provenienti da una cartella caricata di nuovo; elimina le copie in val. La verifica, ampliata con group = record['file'].split('_')[0], mostra cam02 sia in train sia in val: seleziona quindi le sue immagini in val nella vista Table e scegli Sposta nello split > Train. Segnala anche pallet: train 63, val 7, too few in val: usa Trova immagini simili su due immagini di pallet per aggiungere 40 immagini simili non etichettate, etichettale e sposta 15 immagini di pallet di cam07 in val, così cam07 rimane interamente nello stesso split. Ripeti i controlli: 0 duplicati, 0 gruppi con contaminazioni, 22 pallet in val. Clustering con la colorazione per split non mostra gruppi misti. Salva v5: cam07 val, cam08 test, +40 pallets.

Prossimi passi

Hai dati puliti e versionati. Ora ti occuperai del training, dell'analisi dell'esecuzione e del fine-tuning corretto.

Accedi per salvare i progressi