Classificazione di immagini

La classificazione di immagini assegna una distribuzione di etichette all'immagine intera e non localizza nulla al suo interno. La chiave del task è classify.

Definizione

La classificazione di immagini produce un punteggio per classe sull'immagine intera e nessuna coordinata. Risponde a che cosa c'è nella foto, mai a dove, ed è questo che la separa dal rilevamento di oggetti.

classify è la chiave canonica del task, e il suffisso -cls nel nome del file di un checkpoint la seleziona. Nelle famiglie di classificazione quel suffisso è obbligatorio anziché opzionale, quindi LibreResNet50.pt non viene letto come un classificatore e solo LibreResNet50-cls.pt viene letto come tale.

predict() riempie result.probs e lascia boxes vuoto. .data è il vettore completo dei punteggi, .top1 l'indice del punteggio più alto e .top1conf il suo valore, .top5 i cinque indici più alti in ordine decrescente e .top5conf i loro punteggi. Gli indici si riferiscono a result.names. Fare lo slicing di un oggetto Results non tronca mai probs, perché il vettore appartiene all'immagine e non a una singola riga.

Modelli

I classificatori di immagini addestrabili includono: ResNet, ConvNeXt, MobileNetV4, EfficientNetV2 e DINOv2. I primi quattro funzionano con il pacchetto base e distribuiscono pesi pubblicati. DINOv2 richiede pip install "libreyolo[rfdetr]" e non ha checkpoint ospitati da LibreYOLO: carica il backbone upstream con una testa lineare inizializzata casualmente, quindi è un punto di partenza per il fine-tuning, non un predittore pronto.

Altre cinque predicono, validano ed esportano, ma il loro train() solleva NotImplementedError: ViT, Swin, VGG, AlexNet e DeiT.

CLIP e SigLIP2 classificano senza un insieme fisso di etichette. Confrontano l'immagine con dei prompt testuali, quindi set_classes() definisce le classi al momento della chiamata e per un nuovo insieme di etichette non c'è alcun passaggio di addestramento. Entrambe coprono anche il task embed.

ConvNeXt V2 aggiunge la classificazione supervisionata con pesi preaddestrati CC-BY-NC-4.0. PE supporta la classificazione zero-shot; V-JEPA 2 addestra probe di classificazione video.

Predizione

I pesi si scaricano da Hugging Face al primo uso e restano in cache in locale.

Python
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Il suffisso -cls nel nome del file seleziona il task, quindi non# serve alcun argomento task.model = LibreYOLO("LibreResNet50-cls.pt")result = model(SAMPLE_IMAGE, save=True) print(result.names[result.probs.top1], float(result.probs.top1conf))print(result.probs.top5)
CLI
libreyolo predict model=LibreResNet50-cls.pt save=True \  source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg
L'intera distribuzione
from libreyolo import LibreYOLO, SAMPLE_IMAGE result = LibreYOLO("LibreResNet50-cls.pt")(SAMPLE_IMAGE)probs = result.probs # .data è il vettore completo (C,); top5/top5conf sono viste ordinate.print(probs.data.shape)for index, score in zip(probs.top5, probs.top5conf):    print(result.names[index], float(score))
Zero-shot, senza addestramento
from libreyolo import LibreYOLO, SAMPLE_IMAGE # CLIP confronta l'immagine con dei prompt testuali, quindi l'insieme# di etichette si definisce alla chiamata invece di essere fissato nel checkpoint.model = LibreYOLO("LibreCLIPb32-cls.pt")model.set_classes(["a person jumping", "an empty street", "a parked car"])result = model(SAMPLE_IMAGE) print(model.names[result.probs.top1], float(result.probs.top1conf))

conf, iou e max_det qui non hanno effetto: non ci sono candidati da filtrare con una soglia o da sopprimere, solo una distribuzione. Vedi predizione per sorgenti, streaming e gestione dei risultati.

Formato del dataset

La classificazione usa un albero di directory, non file di etichette e non uno YAML. data è la radice del dataset.

dataset/  train/    tench/000001.jpg    parachute/000002.jpg  val/    tench/000101.jpg    parachute/000102.jpg

train/ è obbligatorio per l'addestramento e definisce la corrispondenza tra classe e indice ordinando i nomi delle cartelle, quindi la prima cartella in ordine alfabetico diventa la classe 0. val/ è obbligatorio per la validazione. Può essere presente uno split test/, e i comandi predefiniti di addestramento e validazione non lo usano. Ogni split diverso da train deve contenere gli stessi nomi di cartelle di classe dell'insieme di classi atteso, ed è questo che fa sì che una discrepanza dia subito errore invece di essere conteggiata come una predizione sbagliata. Le estensioni di immagine accettate sono .jpg, .jpeg, .png, .bmp, .webp, .tif e .tiff.

data accetta tre cose: un percorso a una directory che contiene uno split train/, un URL .zip, oppure uno dei nomi di dataset noti, imagenette160 e smoke10, che si scaricano e restano in cache al primo uso.

Il loader canonico è libreyolo.data.classify_dataset.

Addestramento

Python
from libreyolo import LibreYOLO # imagenette160 è un nome di dataset noto e si scarica al primo uso.# Per i tuoi dati passa una directory con uno split train/.model = LibreYOLO("LibreResNet50-cls.pt")model.train(data="imagenette160", epochs=5)
CLI
libreyolo train model=LibreResNet50-cls.pt data=imagenette160 epochs=5
Multi-GPU
libreyolo train model=LibreResNet50-cls.pt data=imagenette160 \  epochs=50 device=0,1 batch=-1

Non c'è nessun nc da dichiarare: il numero di classi viene dai nomi delle cartelle sotto train/, e il layer lineare finale viene ricostruito per adattarsi a quel numero, mentre il backbone viene trasferito invariato. Vedi addestramento per dataset, augmentation, multi-GPU e logger.

ResNet, ConvNeXt, ConvNeXt V2, MobileNetV4, EfficientNetV2 e DINOv2 supportano la ponderazione della loss con cls_pw o class_weights. Per la classificazione, scale controlla l'area del ritaglio e crop_pct il ritaglio di valutazione. Vedi augmentation.

Il filtro di ridimensionamento fa parte del modello. Imposta model.interpolation su "bilinear", "bicubic", "nearest" o "bilinear_no_antialias" prima dell'addestramento: addestramento, val(), predict(), calibrazione INT8 ed esportazione lo usano tutti, e save(), best.pt e last.pt lo registrano, quindi un ricaricamento lo mantiene. Qualsiasi altro nome solleva ValueError. "bilinear_no_antialias" ridimensiona con un bilineare semplice e senza antialiasing ovunque, RandomResizedCrop compreso, per i modelli che gireranno dietro un ridimensionamento a runtime senza antialiasing. MobileNetV4, ResNet, ConvNeXt, ConvNeXt V2, EfficientNetV2, DeiT, Swin e ViT usano bicubic di default; AlexNet e VGG bilinear.

Validazione

val() restituisce un dizionario di chiavi metrics/, calcolate sullo split val/ della radice del dataset.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreResNet50-cls.pt") # Un dict di chiavi metrics/, più top1, top5 e confusion_matrix.metrics = model.val(data="imagenette160") print(metrics["metrics/accuracy_top1"])print(metrics["metrics/accuracy_top5"])print(metrics.top1, metrics.top5)
CLI
libreyolo val model=LibreResNet50-cls.pt data=imagenette160

metrics/accuracy_top1 è la quota di immagini la cui classe con il punteggio più alto è quella vera, ed è il numero di riferimento, quello che l'addestramento usa per scegliere l'epoca migliore. metrics/accuracy_top5 è la quota di immagini la cui classe vera compare in una qualsiasi delle cinque classi con il punteggio più alto, e diventa tanto meno informativa quante meno classi ha il dataset. Il dizionario contiene anche fitness, una copia del valore top-1.

La validazione ImageFolder restituisce anche le metriche macro metrics/precision, metrics/recall e metrics/f1, calcolate come media sulle classi presenti nei target di validazione. Le classi mai predette contribuiscono con precisione zero. La fitness predefinita resta l'accuratezza top-1. Validazione e calibrazione usano la trasformazione di valutazione del modello.

Il risultato è una sottoclasse di dict con tre attributi: top1 e top5 contengono i due valori di accuratezza, e confusion_matrix conta ogni immagine alla sua classe top-1 rispetto alla sua etichetta, indicizzata matrix[predicted, true]. plots=True la scrive come conteggi in confusion_matrix.png e come quote di ogni etichetta in confusion_matrix_normalized.png. Sopra le 2.000 classi la matrice densa e i suoi grafici non sono disponibili, e nonzero(), tp_fp() e class_accuracy() leggono invece i conteggi; vedi Validazione e metriche.

Esportazione

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreResNet50-cls.pt")model.export(format="onnx")
CLI
libreyolo export model=LibreResNet50-cls.pt format=onnx
Usare il file esportato
from libreyolo import LibreYOLO, SAMPLE_IMAGE # La factory instrada in base al suffisso del file, quindi un artefatto# esportato si carica come un checkpoint e restituisce lo stesso oggetto Results.model = LibreYOLO("LibreResNet50-cls.onnx")result = model(SAMPLE_IMAGE) print(result.probs.top1, result.probs.top1conf)

Un artefatto esportato si ricarica tramite LibreYOLO() in base al suffisso del file, quindi un file .onnx o .engine si comporta come un checkpoint e restituisce lo stesso Results. La copertura dei formati cambia da famiglia a famiglia; la matrice su ogni pagina di modello è generata dall'insieme validato invece di essere scritta a mano. Vedi esportazione e deployment per i formati, i loro extra e i loro vincoli.

Verificato con LibreYOLO v1.6.0.