> This is the documentation for LibreYOLO 1.6.0. Current version: https://www.libreyolo.com/docs/train/hyperparameters

# Hyperparameters
Every training argument is a field on a TrainConfig dataclass. The base class defines the field and its default; each model family subclasses it and overrides the defaults that its published recipe changes.
Verified against LibreYOLO v1.6.0.

## Setting arguments

`train()` takes keyword arguments and the CLI takes the same names in
`key=value` form.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreYOLO9s.pt")
results = model.train(
    data="my-dataset.yaml",
    epochs=100,
    batch=16,
    imgsz=640,
    lr0=0.01,
)

print(results["best_mAP50_95"])
```

**CLI**

```bash
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \
  epochs=100 batch=16 imgsz=640 lr0=0.01
```

Both paths end at the same place. The kwargs are handed to
`TrainConfig.from_kwargs()`, which builds the family's config dataclass.

## A typo does not raise

`from_kwargs()` drops any key that is not a field on the config and emits a
`UserWarning` naming it. Training then starts with the default in place:

```python
# UserWarning: Unknown training config keys (ignored): ['learning_rate']
model.train(data="my-dataset.yaml", learning_rate=0.001)
```

Nothing fails, the run completes, and the learning rate was never what the caller
asked for. Read the warnings on the first epoch of a new recipe. The CLI is
stricter, because it validates flag names before the config is built, so a
misspelled CLI flag is rejected outright.

## Defaults are per family

`TrainConfig` defines the field and a base default. Each family subclasses it and
overrides what its published recipe changes, so there is no single correct answer
to "what is the default learning rate".

The base defaults are `optimizer="sgd"`, `lr0=0.01`, `momentum=0.937`,
`weight_decay=5e-4`, `scheduler="yoloxwarmcos"`, `epochs=300`, `batch=16`,
`imgsz=640` and `amp=True`. Three examples of how far a family moves from that:

| Field | Base | YOLOv9 | D-FINE | YOLO-NAS |
|---|---|---|---|---|
| `optimizer` | `sgd` | `sgd` | `adamw` | `adamw` |
| `lr0` | `0.01` | `0.01` | `2e-4` | `5e-4` |
| `weight_decay` | `5e-4` | `5e-4` | `1e-4` | `1e-5` |
| `scheduler` | `yoloxwarmcos` | `linear` | `flat_cosine` | `cos` |
| `epochs` | `300` | `300` | `132` | `300` |
| `amp` | `True` | `True` | `True` | `True` |

D-FINE, DEIM, RT-DETRv4 and YOLO-NAS detection default to `amp=True` with `amp_dtype="float16"`. Dome-DETR, PP-YOLOE and YOLO-NAS OBB retain FP32 defaults. Pass `amp=False` when FP32 is required.

To read a family's real defaults rather than guessing:

**Read a family's resolved defaults**

```python
from dataclasses import fields

from libreyolo import LibreYOLO9
from libreyolo.training.config import TrainConfig

family_cfg = LibreYOLO9.TRAIN_CONFIG()
base_cfg = TrainConfig()

for f in fields(family_cfg):
    family_value = getattr(family_cfg, f.name)
    base_value = getattr(base_cfg, f.name, None)
    if not hasattr(base_cfg, f.name) or family_value != base_value:
        print(f"{f.name}: {family_value}")
```

**CLI**

```bash
# Prints the train, val and predict defaults, including family overrides.
libreyolo cfg
```

## Batch size

`batch` is the global batch. Under multi-GPU training each rank loads
`batch // world_size`, so the number you pass is the number of images per
optimizer step regardless of how many GPUs are involved. See
[Multi-GPU training](/docs/v1.6.0/train/multi-gpu).

`batch=-1` turns on autobatch. The trainer probes the model in training mode with
a real backward pass at powers of two, fits a line to the memory curve, and picks
the largest power of two strictly below the extrapolated value that fits within
60 percent of total VRAM.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreYOLO9s.pt")

# batch=-1 probes GPU memory and resolves to a concrete power of two.
model.train(data="my-dataset.yaml", batch=-1, imgsz=640)
```

**CLI**

```bash
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml batch=-1
```

Probing in training mode with a backward pass is the point: an inference-mode
probe misses the retained activations and gradient tensors, which for a deep CNN
are several times the inference footprint. RF-DETR lowers the target fraction to
45 percent, because the probe's synthetic backward still underestimates what its
criterion and auxiliary decoder layers cost.

Autobatch is a CUDA feature. On CPU or MPS it logs one line and keeps the
default batch.

`min_samples=0` leaves epoch length unchanged. A positive floor samples shorter detection datasets with replacement. `class_balanced=False` enables per-image repeat-factor sampling when set to true; it combines with `min_samples` and DDP. Specialized loaders that bypass the shared sampler reject enabled balancing.

## Gradient accumulation

`nbs` sets the nominal, or effective, batch size. The trainer accumulates
`round(nbs / batch)` micro-batches per optimizer step.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreYOLO9s.pt")

# 4 micro-batches of 16 per optimizer step, effective batch 64.
model.train(data="my-dataset.yaml", batch=16, nbs=64)
```

Left as `None`, the default, accumulation is off and training is unchanged.

## Learning rate and schedule

`lr0` is the initial learning rate and `optimizer` accepts `sgd`, `adam` and
`adamw`. `momentum` is SGD momentum or Adam's beta1, `weight_decay` is the L2
term, and `nesterov` applies to SGD.

The schedule is shaped by `scheduler`, `warmup_epochs`, `warmup_lr_start` and
`min_lr_ratio`. `no_aug_epochs` sets how many final epochs run without strong
augmentation, and several schedules use it to shape their tail as well, so it is
not purely an augmentation knob. What each family does with the augmentation half
of it is on [Augmentations](/docs/v1.6.0/train/augmentations).

Some families add their own learning-rate knobs. `backbone_lr_mult` scales the
backbone group against the head, `clip_max_norm` sets gradient clipping, and
SegFormer uses `head_lr_mult` to run its decode head at ten times the backbone
rate. These live on the family's config subclass, not the base one.

## EMA

`ema=True` keeps an exponential moving average of the weights alongside the
trained ones. It is on by default everywhere except FOMO.

`ema_decay` is the target decay. The decay ramps in rather than starting at its
target: the effective value at update `n` is `ema_decay * (1 - exp(-n / tau))`
with `tau` defaulting to 2000, so early updates track the model more closely and
late updates smooth it. Family defaults range from `0.997` on YOLO-NAS pose
through `0.9998` on YOLOX to `0.9999` on YOLOv9 and the DETR line.

The EMA weights are what gets validated and what `best.pt` and `last.pt` carry.
The raw trained weights are also stored, under the `train_model` key, so a resume
continues from the trained trajectory rather than from the average.

## Precision

`amp=True` runs the forward pass under CUDA autocast. `amp_dtype` selects
`float16` (the default) or `bfloat16`; `fp16` and `bf16` are accepted spellings.

Float16 needs dynamic loss scaling and gets a live `GradScaler`. Bfloat16's wider
exponent range does not, so its scaler is constructed but disabled, which keeps
the optimizer path identical. Asking for bfloat16 on a CUDA device without
bfloat16 support raises at setup rather than degrading silently.

## Output, checkpoints and stopping

Runs are written to `project/name`. `project` defaults to `runs/train`
everywhere, but `name` is one of the per-family overrides: the base default is
`exp`, while YOLOv9 uses `yolo9_exp` and D-FINE uses `dfine_exp`. With
`exist_ok=False`, the default, an existing directory gets an incremented suffix
instead of being overwritten.

`save_period` writes an extra `weights/epoch_<N>.pt` every N epochs, on top of
`weights/last.pt` after each epoch and `weights/best.pt` whenever the tracked
metric improves. `eval_interval` sets how often validation runs, and the final
epoch always validates; `val=False` turns validation off, and such a run writes
no `best.pt`. `patience` stops the run after that many epochs without
improvement, with `0` disabling early stopping.

`cache` speeds up repeated epochs by holding decoded images in RAM (`True` or
`"ram"`) or as `.npy` files beside the sources (`"disk"`). Cached reads are
byte-identical to fresh ones. With dataloader workers, `"disk"` is the safer of
the two.

`average_best=0` disables checkpoint averaging; a positive N writes `weights/average.pt` from up to N best snapshots. Floating tensors are averaged uniformly and integer buffers come from the best snapshot. `export_check=False` can be enabled to fail before epoch one if ONNX export fails. Matching raw outputs are compared at `rtol=1e-3`, `atol=1e-4`; incompatible layouts log a skipped comparison.

`precise_bn=0` disables final BatchNorm recalibration. A positive value bounds training-loader images before final validation; under DDP the budget applies per participating rank. Frozen BatchNorm stays frozen. [Custom fitness callbacks](/docs/v1.6.0/train/fitness-callbacks) can choose best checkpoints and patience.

## Resume

`resume=True` continues an interrupted run from the loaded checkpoint;
`resume="path/to/last.pt"` continues from that file instead.

**Python**

```python
from libreyolo import LibreYOLO

# Load the interrupted run's checkpoint, then ask to resume.
model = LibreYOLO("runs/train/yolo9_exp/weights/last.pt")
model.train(data="my-dataset.yaml", resume=True)
```

**CLI**

```bash
libreyolo train model=runs/train/yolo9_exp/weights/last.pt \
  data=my-dataset.yaml resume=true
```

Resume restores the run's saved training arguments, and an argument passed
explicitly overrides the saved one. It keeps writing into the checkpoint's run
directory. It restores the trained weights, the optimizer state, the EMA weights
and update count, the best-metric tracking, the `GradScaler` scale, and the
PyTorch, CUDA and NumPy random states. It starts at the checkpoint's epoch plus
one and fast-forwards the schedule to that position.

Three things it will not do. `resume=True` cannot be combined with `pretrained`,
which raises. Released weights and a run that already reached its `epochs` hold
nothing to resume, and raise a `ValueError` that says so. And when the
checkpoint's best-metric key differs from the current run's, best-metric
tracking resets to zero with a warning rather than comparing values that do not
mean the same thing.

## Recipes in a file

`cfg=` loads a YAML mapping of `TrainConfig` field names and merges it under the
explicit keyword arguments, so a kwarg always wins over the file.

**Python**

```python
from libreyolo import LibreYOLO

# Keys in the yaml are TrainConfig field names. Explicit kwargs win.
model = LibreYOLO("LibreYOLO9s.pt")
model.train(data="my-dataset.yaml", cfg="my-recipe.yaml", epochs=50)
```

`size` and `num_classes` are stripped from the file, because the model instance
already owns them. There is no `--cfg` flag on the CLI; the file path is a Python
argument.

## Related

- [Datasets](/docs/v1.6.0/train/datasets) for what `data=` accepts.
- [Augmentations](/docs/v1.6.0/train/augmentations) for the augmentation knobs and which
  families honor them.
- [Layer freezing](/docs/v1.6.0/train/layer-freezing) and [LoRA](/docs/v1.6.0/train/lora) for
  training a subset of the weights.
- [Validation and metrics](/docs/v1.6.0/train/validation) for what the run reports.

## Class selection and loss weighting

For YOLO9, RF-DETR, EdgeCrafter, RT-DETR, D-FINE, DEIM, TinyFormer and YOLO-NAS detection, `classes=None` keeps every dataset class; a list filters supervision while preserving original IDs, `nc` and `names`. `single_cls=False` can be enabled to map retained labels to class 0, named `object`. Resume and validation inherit saved settings. Model OBB training rejects `single_cls`.

ResNet, ConvNeXt, ConvNeXt V2, MobileNetV4, EfficientNetV2 and DINOv2 support `cls_pw=0.0`: values in [0, 1] weight each class by inverse frequency to that power, normalized to mean 1. `class_weights=False` selects the alternative `N / (C * n_c)` weighting when enabled. It cannot combine with positive `cls_pw`; resume requires matching weighting settings.

`plot_samples=8` sets the validation sample-image budget. Use 0 for none or -1 for all; it does not reduce the images evaluated.
