> This is the documentation for LibreYOLO 1.5.0. Current version: https://www.libreyolo.com/docs/models/deim

# DEIM
A detection transformer trained with dense one-to-one matching, which converges in far fewer epochs than the DETR recipes it builds on. LibreYOLO carries two versions of it, told apart by the checkpoint you load.
Tasks: Detection. Install: pip install libreyolo.
Verified against LibreYOLO v1.5.0.

## Install

Neither version needs an optional extra. Everything they import is in the base
install.

```bash
pip install libreyolo
```

Adapter fine-tuning with `lora=True` is the exception, and needs the `lora`
extra.

```bash
pip install "libreyolo[lora]"
```

## Predict

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

**Python**

```python
from libreyolo import LibreYOLO, SAMPLE_IMAGE

model = LibreYOLO("LibreDEIMn.pt")
result = model(SAMPLE_IMAGE, save=True)

for box in result.boxes:
    print(box.cls, box.conf, box.xyxy)
```

**CLI**

```bash
libreyolo predict model=LibreDEIMn.pt save=True \
  source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg
```

**Video**

```python
from libreyolo import LibreYOLO

# The version is part of the file name, and the factory routes on the
# checkpoint, so both load the same way.
model = LibreYOLO("LibreDEIMv2pico.pt")

# Any source the library accepts: file, folder, URL, webcam index,
# RTSP stream, or a .streams list
for result in model.predict("clip.mp4", stream=True, save=True):
    print(len(result.boxes))
```

The returned `Results` object is the one every family returns, so swapping in a
different detector is a one line change. `conf` and `max_det` filter a top-k
decode over queries and classes; there is no NMS step to tune, and `iou` is
accepted but unused. See [prediction](/docs/v1.5.0/predict) for sources, streaming and
result handling.

## Variants

Version 1 ships five sizes, all at the same input size. Version 2 keeps those
five names and adds three smaller ones, `atto`, `femto` and `pico`, the first
two of which are native at a lower input size than the rest. Five size codes
therefore exist in both versions and name different models; the version is
written into the checkpoint file name.

| Checkpoint | Input (px) | mAP 50-95 | Params (M) |
| --- | --- | --- | --- |
| `LibreDEIMl` | 640 | 57.8 | 31.24 |
| `LibreDEIMm` | 640 | 55.4 | 19.59 |
| `LibreDEIMn` | 640 | 46.8 | 3.78 |
| `LibreDEIMs` | 640 | 52.1 | 10.32 |
| `LibreDEIMx` | 640 | 59.6 | 62.62 |
| `LibreDEIMv2atto` | 320 | 27.5 | 0.51 |
| `LibreDEIMv2femto` | 416 | 34.5 | 0.98 |
| `LibreDEIMv2l` | 640 | 58.6 | 32.55 |
| `LibreDEIMv2m` | 640 | 56.0 | 18.36 |
| `LibreDEIMv2n` | 640 | 46.7 | 3.6 |
| `LibreDEIMv2pico` | 640 | 42.2 | 1.54 |
| `LibreDEIMv2s` | 640 | 53.0 | 9.78 |
| `LibreDEIMv2x` | 640 | 61.3 | 51.21 |

COCO val2017, 500 images. Published on https://www.visionanalysis.org/

Interactive chart: https://www.visionanalysis.org/embed/scatter?highlight=deim-l%2Cdeim-m%2Cdeim-n%2Cdeim-s%2Cdeim-x%2Cdeimv2-atto%2Cdeimv2-femto%2Cdeimv2-l%2Cdeimv2-m%2Cdeimv2-n%2Cdeimv2-pico%2Cdeimv2-s%2Cdeimv2-x&title=DEIM%20on%20COCO&subtitle=Accuracy%20against%20latency%2C%20every%20benchmarked%20model

Version 1 keeps D-FINE's architecture and swaps its classification objective
for the matchability-aware loss from the dense one-to-one recipe, so the two
families share almost every state dict key and are told apart by the metadata
in the checkpoint. Version 2 keeps that training contract and mixes backbones:
HGNetv2 below `s`, and a DINOv3 vision transformer with a spatial tuning
adapter at `s` and above. That backbone is what puts a second license on those
four checkpoints, so read [licensing](#licensing) before you ship one.

## Train

Training starts from a published checkpoint. `pretrained` never reaches the
trainer: version 1 warns that the key is unknown and ignores it, version 2
removes it. Neither gives you a randomly initialized model.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreDEIMn.pt")

# coco128.yaml downloads a 128-image sample on first use. Point `data`
# at your own dataset YAML for a real run.
model.train(data="coco128.yaml", epochs=50, batch=8, lr0=1e-4)
```

**CLI**

```bash
libreyolo train model=LibreDEIMn.pt data=coco128.yaml \
  epochs=50 batch=8 lr0=1e-4
```

**DEIMv2**

```python
from libreyolo import LibreYOLO

# Left unset, epochs, batch, imgsz and lr0 come from the released
# recipe for the size that was loaded.
model = LibreYOLO("LibreDEIMv2pico.pt")
model.train(data="coco128.yaml", epochs=50)
```

**LoRA**

```python
# Needs the lora extra: pip install "libreyolo[lora]"
from libreyolo import LibreYOLO

model = LibreYOLO("LibreDEIMn.pt")
model.train(data="coco128.yaml", epochs=50, lora=True)
```

**Multi-GPU**

```bash
libreyolo train model=LibreDEIMn.pt data=coco128.yaml \
  epochs=50 device=0,1
```

Pass `lr0` yourself on version 1. Its Python `train()` signature defaults to
`4e-4`, the rate from the published COCO recipe, while the family's training
config carries `1e-4` as its fine-tune default, and that lower value is what
the CLI resolves when the argument is absent. The config records the
measurement behind it: at the batch sizes a fine-tune actually uses, on small
datasets, the COCO rate measurably degraded transfer.

Version 2 resolves those defaults itself. Leaving `epochs`, `batch`, `imgsz`
and `lr0` unset makes it read each one from the released recipe for the size
that was loaded, so the small sizes train at their own input resolution without
being told, and a value you pass overrides the recipe. `imgsz` is the argument
it constrains: it has to be a positive multiple of 32, and version 2 raises
before the run starts otherwise.

See [training](/docs/v1.5.0/train) for datasets, augmentation, multi-GPU and loggers.

## Validate

`val()` returns a dictionary of `metrics/` keys covering precision, recall,
mAP 50 and mAP 50-95, measured against any dataset in the format you trained on.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreDEIMn.pt")

# val() returns a plain dict, not an object
metrics = model.val(data="coco128.yaml")

print(metrics["metrics/mAP50-95"])
print(metrics["metrics/mAP50"])
print(metrics["metrics/precision"], metrics["metrics/recall"])
```

**CLI**

```bash
libreyolo val model=LibreDEIMn.pt data=coco128.yaml
```

**Against COCO**

```bash
# coco-val-only.yaml fetches the 5000 val2017 images and skips the
# training set. It carries an embedded download script, so it needs
# explicit permission unless the dataset is already local.
libreyolo val model=LibreDEIMn.pt data=coco-val-only.yaml \
  allow_download_scripts=True
```

The rows in the benchmark table above come from the LibreYOLO benchmark
harness; the note under that table records which dataset produced them and
links the run records.

## Export

| Task | ONNX | TorchScript | ExecuTorch | TensorRT | OpenVINO | Paddle | MNN | RKNN | ncnn | TFLite | CoreML | Core AI |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Detection | yes | yes |  | yes | yes | yes | yes |  |  |  |  | yes |

A "yes" means the export is supported. An empty cell means the exporter refuses that combination.

The matrix covers both versions as one page: where they disagree about a
format, the cell shows the weaker of the two, so nothing here is oversold for
whichever version you load.

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`.

**Python**

```python
# Needs the onnx extra: pip install "libreyolo[onnx]"
from libreyolo import LibreYOLO

model = LibreYOLO("LibreDEIMn.pt")
path = model.export(format="onnx")
print(path)
```

**CLI**

```bash
libreyolo export model=LibreDEIMn.pt format=onnx
```

**Use the exported file**

```python
from libreyolo import LibreYOLO, SAMPLE_IMAGE

# The factory routes on the file suffix, so an exported artifact loads
# like any checkpoint and returns the same Results object.
model = LibreYOLO("LibreDEIMn.onnx")
result = model(SAMPLE_IMAGE)

print(result.boxes.xyxy)
```

## Checkpoints

Every published weight file for this family.

| File | Input (px) | Task | Weights license |
| --- | --- | --- | --- |
| `LibreDEIMn.pt` | 640 | Detection | apache-2.0 |
| `LibreDEIMs.pt` | 640 | Detection | apache-2.0 |
| `LibreDEIMm.pt` | 640 | Detection | apache-2.0 |
| `LibreDEIMl.pt` | 640 | Detection | apache-2.0 |
| `LibreDEIMx.pt` | 640 | Detection | apache-2.0 |
| `LibreDEIMv2n.pt` | 640 | Detection | apache-2.0 |
| `LibreDEIMv2s.pt` | 640 | Detection | other |
| `LibreDEIMv2m.pt` | 640 | Detection | other |
| `LibreDEIMv2l.pt` | 640 | Detection | other |
| `LibreDEIMv2x.pt` | 640 | Detection | other |
| `LibreDEIMv2atto.pt` |  | Detection | apache-2.0 |
| `LibreDEIMv2femto.pt` |  | Detection | apache-2.0 |
| `LibreDEIMv2pico.pt` |  | Detection | apache-2.0 |

## Licensing

Check the license on the Hugging Face repository of the specific weights you download. That repository is authoritative and licenses are not always uniform across a family. This is a description of the licenses involved, not legal advice.

- Original work: DEIM and DEIMv2, Intellindust AI Lab
- Upstream license: Apache-2.0; the DEIMv2 DINOv3 backbone adds Meta's DINOv3 License
- Upstream source: https://github.com/Intellindust-AI-Lab/DEIM
- LibreYOLO code: Apache-2.0
- Weights: Apache-2.0; the DEIMv2 DINOv3 backbone adds Meta's DINOv3 License, republished at https://huggingface.co/LibreYOLO
- Interpretation: Apache-2.0 is a permissive license, so these weights can be used in commercial and closed-source products. It asks you to keep its license text and attribution notices with any copy of the weights you redistribute, and it grants a patent license. It places no obligation on your own application code, and weights you train yourself on your own data are yours. DEIM is Apache-2.0 throughout, and so are the DEIMv2 sizes below S, which use an HGNetv2 backbone. The DEIMv2 S, M, L and X sizes take their backbone from DINOv3, so both their weights and the backbone source vendored in LibreYOLO are additionally governed by Meta's DINOv3 License Agreement, which is not an OSI license: redistribution has to carry the agreement with it, and it forbids use for military or warfare purposes, weapons development, espionage, nuclear industries and anything subject to ITAR. Their Hugging Face repositories declare both licenses, and DEIMv2 is also cited separately (arXiv 2509.20787).

The four DEIMv2 sizes from S upward take their backbone from DINOv3, so their
weight repositories carry both Apache-2.0 and Meta's DINOv3 License, and
LibreYOLO ships the DINOv3 backbone source under that same agreement. The rest
of this family, including every DEIMv2 size below S, is Apache-2.0 alone.

## Citation

```bibtex
@misc{huang2024deim,
      title={DEIM: DETR with Improved Matching for Fast Convergence},
      author={Shihua, Huang and Zhichao, Lu and Xiaodong, Cun and Yongjun, Yu and Xiao, Zhou and Xi, Shen},
      booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},
      year={2025},
}
```

Copied from https://github.com/Intellindust-AI-Lab/DEIM#5-citation

DEIMv2 is a separate paper and has its own citation block at
[github.com/Intellindust-AI-Lab/DEIMv2](https://github.com/Intellindust-AI-Lab/DEIMv2#5-citation);
cite that one if you used a version 2 checkpoint.
