1.9.0
expressjs/express1.9.0Jul 29, 2026by Borda
AI Summary
A major release introducing configurable training (optimizer/scheduler), multi-GPU keypoint training, and new export formats including ExecuTorch and native CoreML.
Key Highlights
- Native CoreML export support for .mlpackage
- ExecuTorch export support for .pte
- Multi-GPU and multi-node keypoint training under DDP
- Configurable optimizer and LR scheduler
Breaking Changes
- `albumentations` and `kornia` extras merged into `augment`
- Default augmentation backend changed from Albumentations to torchvision
- Unrecognised `train()` kwargs now raise `ValueError`
New Features
- Native CoreML export
- ExecuTorch export
- TensorRT export improvements
- In-memory evaluation via `RFDETR.evaluate()`
- Multi-GPU keypoint training under DDP
- Configurable optimizer and LR scheduler
- Configurable `TrainConfig.scale_jitter`
- Torchvision-native augmentation backend
Full Release Notes
RF-DETR v1.9.0 makes training more configurable and deployment more portable. The training optimizer and LR scheduler are now pluggable (any `torch.optim` name, dotted import path, or callable), keypoint/pose models can train under multi-GPU and multi-node DDP, and models export to ExecuTorch (`.pte`) and native CoreML (`.mlpackage`) for on-device inference, alongside an improved TensorRT export path. Checkpoint loading is also hardened: `RFDETR.from_checkpoint()` now defaults to safe (`weights_only=True`) deserialization. The default augmentation backend changes in this release β see the migration guide before upgrading if you rely on the previous default.
## β¨ Spotlights / highlights
### ExecuTorch export
```python
model = RFDETRSmall()
model.export(format="executorch", backend="xnnpack") # or "coreml", "qnn"
```
### Native CoreML export
```python
model = RFDETRSmall()
model.export(format="coreml", coreml_precision="float16") # .mlpackage, no ONNX intermediary
```
### Multi-GPU / multi-node keypoint training
```python
RFDETRKeypointPreview().train(
dataset_dir="...",
strategy="ddp",
devices=4,
grad_accum_steps=1,
)
```
### Configurable optimizer & LR scheduler
```python
from rfdetr.config import TrainConfig
TrainConfig(
optimizer="pytorch_optimizer.Lion",
lr_scheduler="torch.optim.lr_scheduler.OneCycleLR",
lr_scheduler_kwargs={"max_lr": 1e-3, "total_steps": 10_000},
)
```
### Safe checkpoint loading by default
```python
model.from_checkpoint("checkpoint.pth") # now weights_only=True by default
model.from_checkpoint("legacy_checkpoint.pth", trust_checkpoint=True) # opt-in for trusted files
```
## π Migration guide
### Breaking changes
**`albumentations` and `kornia` extras merged into `augment`**
| Old extra | New extra |
| ---------------------------------------- | ----------------------- |
| `rfdetr[train]` (implied albumentations) | `rfdetr[train,augment]` |
| `rfdetr[kornia]` | `rfdetr[augment]` |
There is no `[kornia]` compatibility alias β `pip install 'rfdetr[kornia]'` fails after upgrading.
**Default resize interpolation changed** β pixel values and mAP may shift. The default resize backend changed from Albumentations to torchvision. To restore the previous behaviour:
```bash
pip install 'rfdetr[augment]'
```
```python
from rfdetr.datasets.aug_configs import AUG_CONFIG
train_config = TrainConfig(aug_config=AUG_CONFIG, ...)
```
Installing `rfdetr[augment]` is not by itself sufficient to pin behaviour β pass `augmentation_backend="torchvision"` explicitly to pin it regardless of what's installed.
**Unrecognised `train()` kwargs now raise `ValueError`** β `TrainConfig` uses `extra="forbid"`; a typo'd kwarg that previously trained silently with defaults now raises immediately with a suggestion.
### Removed
Deprecated in earlier releases, removed as of v1.9:
- `rfdetr.util.*` and `rfdetr.deploy.*` import paths (deprecated since v1.6) β `rfdetr.utilities.*`, `rfdetr.assets.coco_classes`, `rfdetr.training.drop_schedule`, `rfdetr.training.param_groups`, `rfdetr.visualize.data`, `rfdetr.models.heads.segmentation`, `rfdetr.export`
- `build_namespace(model_config, train_config)` (deprecated since v1.7) β `build_model_from_config` / `build_criterion_from_config`
- `load_pretrain_weights(nn_model, model_config, train_config)`'s `train_config` argument (deprecated since v1.7) β call `(nn_model, model_config)`
- `start_epoch`, `do_benchmark`, `callbacks` kwargs on `.train()`/`.evaluate()` (deprecated since v1.7) β `resume=`, `rfdetr.export.benchmark`, PTL `Callback` objects respectively
- Misplaced config fields β `TrainConfig.{group_detr, ia_bce_loss, segmentation_head, num_select}` β `ModelConfig`; `ModelConfig.cls_loss_coef` β `TrainConfig` (deprecated since v1.7)
- `RFDETRLarge`'s silent fallback to `RFDETRLargeDeprecatedConfig` on checkpoint/config incompatibility β now raises the original error; use `RFDETRLargeDeprecated` directly for legacy Large weights
### Deprecated in v1.9 β Remove in v1.11
- `RFDETR.optimize_for_inference()` renamed to `RFDETR.inference()` (same signature) β old name kept as an alias, emits `FutureWarning`
- `TrainConfig.lr_drop` and `lr_min_factor` β pass through `lr_scheduler_kwargs` instead
Full details, including code before/after examples for every item above: `docs/getting-started/migration.md` β "Upgrade 1.8 β 1.9".
## π Notable changes
### π Added
- **Native CoreML export** β `RFDETR.export(format="coreml")` produces a `.mlpackage` (mlprogram, iOS 16+) directly from `torch.export`, no ONNX intermediary; `coreml_precision="float32"|"float16"` controls compute precision. Install with `pip install 'rfdetr[coreml]'` (macOS only, `coremltools>=8.0,<10.0`). Distinct from ExecuTorch's `format="executorch", backend="coreml"` `.pte` path. (#1235, #1244)
- **ExecuTorch (`.pte`) export** β `RFDETR.export(format="executorch")` for XNNPACK CPU, Core ML, and experimental Qualcomm QNN backends; static-shape deformable-attention export, fail-fast validation for unsupported dynamic batching. (#1142, #1231, #1237)
- **TensorRT export improvements** β `RFDETR.export(format="tensorrt")` (alias `"trt"`) builds `.trt` engines in-process; configurable `fp16: bool = True` precision with automatic FP32 fallback. (#853, #1231)
- **`RFDETR.evaluate(*, split="test"|"val", **kwargs)`** β runs COCO evaluation (mAP, mAR, macro-F1, per-class AP) on the in-memory model without a checkpoint reload. (#1134)
- **Multi-GPU / multi-node keypoint (pose) training under DDP** β keypoint models train with `strategy="ddp"`/`"auto"`, `devices>1`, `num_nodes>1`. Sharded strategies (FSDP/DeepSpeed) remain unsupported and now fail with a clear error. (#1232)
- **Configurable training optimizer** β `TrainConfig.optimizer: str | Callable = "adamw"` plus `optimizer_kwargs`. (#1006)
- **Configurable LR schedulers** β `TrainConfig.lr_scheduler: str | Callable = "step"` plus `lr_scheduler_kwargs`, `lr_scheduler_interval`, `lr_scheduler_monitor`; end-to-end `ReduceLROnPlateau` support. (#1217)
- **`TrainConfig.scale_jitter: bool = True`** β independent control of the resizeβcropβresize training branch, decoupled from `aug_config`. (#1037)
- **Torchvision-native augmentation backend + selectable backends** β `AugmentationBackend.TV`/`.ALBU`/`.KORNIA`; `augmentation_backend="torchvision"` always pins torchvision. (#1112)
- **Mask-aware dataset grids** β instance-segmentation label validation renders masks in `save_grids`. (#1014)
- **`TrainConfig.eval_ema_only: bool = False`** β opt-in EMA-only evaluation. (#1225)
### β οΈ Breaking Changes
- **Augmentation backend default** β training/validation/export now resolve to torchvision-native transforms unless Albumentations is installed; `[train]` no longer bundles Albumentations/Kornia. See migration guide. (#1112)
- **Unrecognised `train()`/`evaluate()` kwargs now raise `ValueError`** instead of silently training with defaults. (#1178)
### π± Changed
- Always save EMA-named checkpoints (`checkpoint_best_ema.pth`, `last_ema.pth`) when `monitor_ema` is set; `checkpoint_best_total.pth` records provenance. (#1216)
- Epoch-level train loss shown in the training progress bar. (#1211)
- Improved training performance β foreach EMA update, gated validation loop, TF32 enabled. (#1226)
- Improved evaluation performance β removed per-iteration GPU sync in matching. (#1225)
- Matched-pair IoU targets in the loss computation now use new O(N) `elementwise_box_iou`/`elementwise_generalized_box_iou` helpers instead of building the full NxN pairwise matrix and reading its diagonal, reducing peak GPU memory during loss calculation. (#1245)
- `[tensorrt]` no longer installs `pycuda` β it's only needed for `TRTInference`'s async benchmarking mode, now under the separate `[tensorrt-bench]` extra. The standard exportβengine path is unaffected. (#1246)
### ποΈ Deprecated
- `RFDETR.optimize_for_inference()` β `RFDETR.inference()` (same signature). (#1212)
- `TrainConfig.lr_drop` / `lr_min_factor` β `lr_scheduler_kwargs`. (#1217)
### β Removed
- `rfdetr.util.*`, `rfdetr.deploy`, `build_namespace()`, `load_pretrain_weights()`'s `train_config` arg, `start_epoch`/`do_benchmark`/`callbacks` train() kwargs, misplaced `TrainConfig`/`ModelConfig` fields, `RFDETRLarge`'s silent legacy-config fallback β all deprecated since v1.6/v1.7, removed as scheduled. (#1218)
- `[kornia]` pip extra β folded into `[augment]`, no compatibility alias. (#1142, #1112)
### π§ Fixed
- First `predict()`/`inference()` call no longer silently breaks subsequent `backward()` gradients. (#1178)
- Optimized keypoint models correctly return `sv.KeyPoints`. (#1210)
- `predict()` resize antialias disabled to match training/val preprocessing. (#1206)
- ONNX export at non-native resolution no longer crashes. (#1207)
- Keypoint DDP training no longer hangs on the out-of-schema loss guard (graph-connected zeros instead of detached). (#1232)
- `window_block_indexes` override now correctly forwarded to DINOv2. (#1224)
- Non-square Albumentations training resize no longer inflates every image to `max_size`. (#1112, #1183)
- **`RFDETR.from_checkpoint(..., trust_checkpoint=True)` now actually works** β it previously bypassed the safe-load check only for the checkpoint's metadata read; model construction silently reloaded the same file without the caller's trust setting and raised anyway. (#1239)
- Segmentation evaluation now resizes ground-truth masks directly to each prediction's own pixel grid instead of each image's original resolution, removing a lossy round trip vs. the mask head's native grid β segm mAP is computed on consistent pixel grids. (#1241)
- `pip install 'rfdetr[onnx]'` (and `[tflite]`) no longer hangs building `onnxsim` from source on CPython 3.11/3.13 and Linux aarch64 β the `onnxsim<0.6.0` pin resolved to a version with no prebuilt wheels for those targets; now `onnxsim>=0.7.0`. (#1242)
### π Security
- Safe checkpoint loading by default β `RFDETR.from_checkpoint()` uses `weights_only=True`; opt into full pickle deserialization via `trust_checkpoint=True` for trusted/legacy files. (#1179)
- TensorRT export no longer shells out to `trtexec` β engines build in-process via the `polygraphy` Python API, removing the subprocess/shell-injection surface entirely. (#853)
---
## π Contributors
- **Anatoly Ryabchenko** (@anatoly-ryabchenko, [LinkedIn](https://www.linkedin.com/in/anatoly-ryabchenko/)) β ExecuTorch (.pte) export; `RFDETR.evaluate()` in-memory COCO eval
- **Robin Cole** (@robmarkcole, [LinkedIn](https://www.linkedin.com/in/robmarkcole/)) β dataset augmentation refactor onto torchvision-native transforms with a selectable Albumentations/Kornia backend
- **Michael Mohamed** (@michaelmohamed) β multi-GPU/multi-node DDP keypoint (pose) training
- **M. Fazri Nizar** (@mfazrinizar, [LinkedIn](https://www.linkedin.com/in/mfazrinizar)) β third-party training optimizer support; epoch-level train loss in the progress bar
- **Stefan Schneider** (@hinogi) β strict-mypy typing cleanup across export, models, evaluation, platform, and utilities
- **Jonas Pirner** (@pirnerjonas) β mask-aware dataset grids for instance-segmentation label validation
- **Omkar Kabde** (@omkar-334, [LinkedIn](https://www.linkedin.com/in/omkar-kabde/)) β decoupled the resize scale-jitter branch from `aug_config` via the new `scale_jitter` flag
- **Brian Cong** (@congbrian, [LinkedIn](https://www.linkedin.com/in/brian-cong-babb042a0/)) β native CoreML export; typed `drop_schedule`/`models.math`; fixed the ExecuTorch export level-dim shape mismatch
- **Γmer GΓΌnaydΔ±n** (@siromermer, [LinkedIn](https://www.linkedin.com/in/%C3%B6mer-g%C3%BCnayd%C4%B1n-17811b216)) β fixed YOLO split-directory resolution to honor `data.yaml` paths
- **Deependu** (@deependujha) β fixed a spurious `pyDeprecate` CLI warning
- **Peter Robicheaux** (@probicheaux, [LinkedIn](https://www.linkedin.com/in/peter-robicheaux-01958813b/)) β docs: NAS platform availability note, citation author correction
- **Matvei Popov** (@Matvezy, [LinkedIn](https://www.linkedin.com/in/matvezy)) β platform-vs-paper NAS comparison chart in the README
- **ARDA7787** (@ARDA7787) β fixed a resource leak by closing the HTTP response with a context manager in `_download_file`
- **Erik** (@Erol444, [LinkedIn](https://linkedin.com/in/erik-kokalj)) β GA4 tracking on the docs site
- **Sergii Bondariev** (@sergii-bond, [LinkedIn](https://www.linkedin.com/in/sergiibondariev/)) β reduced peak GPU memory in the loss computation's box-IoU matching
- **Takeshi Watanabe** (@take-cheeze) β fixed the `[onnx]`/`[tflite]` install hang caused by a stale `onnxsim` pin
- **Jirka Borovec** (@Borda, [LinkedIn](https://linkedin.com/in/jirka-borovec)) β safe checkpoint loading by default, TensorRT export rewrite onto in-process polygraphy (no more `trtexec` subprocess), configurable LR schedulers, always-saved EMA checkpoints, removed the 1.9.0-scheduled deprecated APIs, TensorRT fp16 export, segmentation-eval mask-resize fix
---
**Full changelog**: https://github.com/roboflow/rf-detr/compare/1.8.3...1.9.0