Image classification

Image classification assigns one label distribution to a whole image and locates nothing inside it. The task key is classify.

Definition

Image classification produces one score per class for the whole image and no coordinates at all. It answers what is in the picture, never where, which is what separates it from object detection.

classify is the canonical task key, and the -cls suffix in a checkpoint filename selects it. That suffix is required rather than optional on classification families, so LibreResNet50.pt is not read as a classifier and only LibreResNet50-cls.pt is.

predict() fills result.probs and leaves boxes empty. .data is the full score vector, .top1 the index of the highest score and .top1conf its value, .top5 the five highest indices in descending order and .top5conf their scores. Indices point into result.names. Slicing a Results object never truncates probs, because the vector belongs to the image rather than to one row.

Models

Five families both train and predict: ResNet, ConvNeXt, MobileNetV4, EfficientNetV2 and DINOv2. The first four run on the base package and ship published weights. DINOv2 needs pip install "libreyolo[rfdetr]" and has no LibreYOLO-hosted checkpoint: it loads the upstream backbone with a randomly initialized linear head, so it is a fine-tuning starting point rather than a ready predictor.

Five more predict, validate and export, but their train() raises NotImplementedError: ViT, Swin, VGG, AlexNet and DeiT.

CLIP and SigLIP2 classify without a fixed label set. They score the image against text prompts, so set_classes() defines the classes at call time and there is no training step for a new label set at all. Both also serve the embed task.

Predict

Weights download from Hugging Face on first use and are cached locally.

Python
from libreyolo import LibreYOLO, SAMPLE_IMAGE # The -cls suffix in the filename selects the task, so no task# argument is needed.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
The whole distribution
from libreyolo import LibreYOLO, SAMPLE_IMAGE result = LibreYOLO("LibreResNet50-cls.pt")(SAMPLE_IMAGE)probs = result.probs # .data is the full (C,) vector; top5/top5conf are ordered views.print(probs.data.shape)for index, score in zip(probs.top5, probs.top5conf):    print(result.names[index], float(score))
Zero-shot, no training
from libreyolo import LibreYOLO, SAMPLE_IMAGE # CLIP scores the image against text prompts, so the label set is# set at call time instead of baked into the 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 and max_det have no effect here: there are no candidates to threshold or suppress, only one distribution. See prediction for sources, streaming and result handling.

Dataset format

Classification uses a directory tree, not label files and not a YAML. data is the dataset root.

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

train/ is required for training and it defines the class-to-index mapping by sorted folder name, so the first folder alphabetically becomes class 0. val/ is required for validation. A test/ split may be present and the default train and validate commands do not use it. Any split other than train has to contain the same class folder names as the expected class set, which is what makes a mismatch fail loudly rather than score as a wrong prediction. The accepted image extensions are .jpg, .jpeg, .png, .bmp, .webp, .tif and .tiff.

data accepts three things: a path to a directory containing a train/ split, a .zip URL, or one of the known dataset names, imagenette160 and smoke10, which download and cache on first use.

The canonical loader is libreyolo.data.classify_dataset.

Train

Python
from libreyolo import LibreYOLO # imagenette160 is a known dataset name and downloads on first use.# Pass a directory with a train/ split for your own data.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

There is no nc to declare: the class count comes from the folder names under train/, and the final linear layer is rebuilt to match it while the backbone transfers unchanged. See training for datasets, augmentation, multi-GPU and loggers.

Validate

val() returns a plain dictionary of metrics/ keys, computed over the val/ split of the dataset root.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreResNet50-cls.pt") # val() returns a plain dict, not an object.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 is the share of images whose highest-scoring class is the true one, and it is the headline number, the one training uses to pick the best epoch. metrics/accuracy_top5 is the share whose true class appears anywhere in the five highest-scoring classes, which says less the fewer classes the dataset has. The dictionary also carries fitness, a copy of the top-1 value.

Export

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreResNet50-cls.pt")model.export(format="onnx")
CLI
libreyolo export model=LibreResNet50-cls.pt format=onnx
Use the exported file
from libreyolo import LibreYOLO, SAMPLE_IMAGE # The factory routes on the file suffix, so an exported artifact loads# like a checkpoint and returns the same Results object.model = LibreYOLO("LibreResNet50-cls.onnx")result = model(SAMPLE_IMAGE) print(result.probs.top1, result.probs.top1conf)

An exported artifact loads back through LibreYOLO() on its file suffix, so a .onnx or .engine file behaves like a checkpoint and returns the same Results. Format coverage differs by family; the matrix on each model page is generated from the validated set rather than typed by hand. See export and deploy for the formats, their extras and their constraints.

Verified against LibreYOLO v1.5.0.