Klasyfikacja obrazów

Klasyfikacja obrazów przypisuje jeden rozkład etykiet do całego obrazu i nie lokalizuje żadnych elementów. Kluczem zadania jest classify.

Definicja

Klasyfikacja obrazów tworzy jeden wskaźnik na klasę dla całego obrazu i nie zwraca żadnych współrzędnych. Odpowiada na pytanie, co znajduje się na obrazie, a nigdy gdzie, co odróżnia ją od detekcji obiektów.

classify jest kanonicznym kluczem zadania, a sufiks -cls w nazwie pliku checkpointu je wybiera. Ten sufiks jest wymagany, a nie opcjonalny dla rodzin klasyfikacyjnych. Dlatego LibreResNet50.pt nie jest interpretowany jako klasyfikator, a LibreResNet50-cls.pt już tak.

Funkcja predict() wypełnia result.probs i pozostawia boxes puste. .data jest pełnym wektorem wskaźników, .top1 indeksem największego wskaźnika, a .top1conf jego wartością. .top5 zawiera pięć największych indeksów w kolejności malejącej, a .top5conf ich wskaźniki. Indeksy odwołują się do result.names. Wycinanie obiektu Results nigdy nie skraca probs, ponieważ wektor należy do obrazu, a nie do pojedynczego wiersza.

Modele

Pięć rodzin obsługuje zarówno trenowanie, jak i predykcję: ResNet, ConvNeXt, MobileNetV4, EfficientNetV2 oraz DINOv2. Pierwsze cztery działają z pakietem bazowym i mają opublikowane wagi. DINOv2 wymaga pip install "libreyolo[rfdetr]" i nie ma checkpointu hostowanego przez LibreYOLO. Wczytuje backbone projektu źródłowego z losowo inicjowaną głowicą liniową, dlatego stanowi punkt początkowy do dostrajania, a nie gotowy model predykcyjny.

Kolejnych pięć rodzin obsługuje predykcję, walidację i eksport, ale ich funkcja train() zgłasza NotImplementedError: ViT, Swin, VGG, AlexNet oraz DeiT.

CLIP i SigLIP2 klasyfikują bez stałego zestawu etykiet. Oceniają obraz względem promptów tekstowych, dlatego set_classes() definiuje klasy podczas wywołania i w ogóle nie ma etapu trenowania dla nowego zestawu etykiet. Obie rodziny obsługują również zadanie embed.

Predykcja

Przy pierwszym użyciu wagi są pobierane z Hugging Face i zapisywane w lokalnej pamięci podręcznej.

Python
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Sufiks -cls w nazwie pliku wybiera zadanie, więc argument task# nie jest potrzebny.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
Pełny rozkład
from libreyolo import LibreYOLO, SAMPLE_IMAGE result = LibreYOLO("LibreResNet50-cls.pt")(SAMPLE_IMAGE)probs = result.probs # .data jest pełnym wektorem (C,), a top5/top5conf to uporządkowane widoki.print(probs.data.shape)for index, score in zip(probs.top5, probs.top5conf):    print(result.names[index], float(score))
Zero-shot bez trenowania
from libreyolo import LibreYOLO, SAMPLE_IMAGE # CLIP ocenia obraz względem promptów tekstowych, dlatego zestaw etykiet# ustala się przy wywołaniu, zamiast zapisywać w checkpointcie.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))

Argumenty conf, iou i max_det nie mają tutaj wpływu. Nie ma kandydatów do filtrowania progiem ani tłumienia, a jedynie jeden rozkład. Informacje o źródłach, streamingu i obsłudze wyników zawiera strona predykcji.

Format zbioru danych

Klasyfikacja korzysta z drzewa katalogów, a nie z plików etykiet ani pliku YAML. data jest katalogiem głównym zbioru danych.

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

train/ jest wymagany do trenowania i definiuje mapowanie klas na indeksy na podstawie posortowanych nazw folderów. Pierwszy folder alfabetycznie staje się klasą 0. val/ jest wymagany do walidacji. Podział test/ może być obecny, ale domyślne polecenia trenowania i walidacji go nie używają. Każdy podział inny niż train musi zawierać te same nazwy folderów klas co oczekiwany zestaw klas. Dzięki temu niezgodność powoduje wyraźny błąd, a nie ocenę jako błędna predykcja. Akceptowane rozszerzenia obrazów to .jpg, .jpeg, .png, .bmp, .webp, .tif i .tiff.

data przyjmuje trzy rodzaje wartości: ścieżkę do katalogu zawierającego podział train/, adres URL pliku .zip lub jedną ze znanych nazw zbiorów danych, imagenette160 i smoke10, które są pobierane i zapisywane w pamięci podręcznej przy pierwszym użyciu.

Kanonicznym modułem wczytującym jest libreyolo.data.classify_dataset.

Trenowanie

Python
from libreyolo import LibreYOLO # imagenette160 jest znaną nazwą zbioru danych i zostanie pobrany przy pierwszym użyciu.# W przypadku własnych danych przekaż katalog zawierający podział train/.model = LibreYOLO("LibreResNet50-cls.pt")model.train(data="imagenette160", epochs=5)
CLI
libreyolo train model=LibreResNet50-cls.pt data=imagenette160 epochs=5
Wiele GPU
libreyolo train model=LibreResNet50-cls.pt data=imagenette160 \  epochs=50 device=0,1 batch=-1

Nie deklaruje się nc. Liczba klas pochodzi z nazw folderów w train/, a końcowa warstwa liniowa jest przebudowywana odpowiednio do tej liczby, podczas gdy backbone jest przenoszony bez zmian. Informacje o zbiorach danych, augmentacji, wielu GPU i modułach rejestrujących zawiera strona trenowania.

Walidacja

Funkcja val() zwraca zwykły słownik kluczy metrics/, obliczany na podziale val/ katalogu głównego zbioru danych.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreResNet50-cls.pt") # val() zwraca zwykły słownik, a nie obiekt.metrics = model.val(data="imagenette160") print(metrics["metrics/accuracy_top1"])print(metrics["metrics/accuracy_top5"])
CLI
libreyolo val model=LibreResNet50-cls.pt data=imagenette160

metrics/accuracy_top1 jest udziałem obrazów, dla których klasa z największym wskaźnikiem jest klasą prawdziwą. To główny wynik używany podczas trenowania do wyboru najlepszej epoki. metrics/accuracy_top5 jest udziałem obrazów, dla których prawdziwa klasa znajduje się wśród pięciu klas o największym wskaźniku. Metryka mówi tym mniej, im mniej klas zawiera zbiór danych. Słownik obejmuje również fitness, kopię wartości top-1.

Eksport

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreResNet50-cls.pt")model.export(format="onnx")
CLI
libreyolo export model=LibreResNet50-cls.pt format=onnx
Użycie wyeksportowanego pliku
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Funkcja fabrykująca wybiera ścieżkę na podstawie sufiksu pliku, więc# wyeksportowany artefakt wczytuje się jak checkpoint i zwraca ten sam obiekt Results.model = LibreYOLO("LibreResNet50-cls.onnx")result = model(SAMPLE_IMAGE) print(result.probs.top1, result.probs.top1conf)

Wyeksportowany artefakt wczytuje się ponownie przez LibreYOLO() na podstawie sufiksu pliku. Plik .onnx lub .engine działa więc jak checkpoint i zwraca ten sam obiekt Results. Zakres formatów różni się między rodzinami, a macierz na stronie każdego modelu jest generowana ze zweryfikowanego zestawu, a nie wpisywana ręcznie. Formaty, ich zestawy zależności i ograniczenia opisuje strona eksportu i wdrożenia.

Zweryfikowano z LibreYOLO v1.5.0.