v1.9.0: Configurable Training, ExecuTorch & CoreML Export
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
model = RFDETRSmall()
model.export(format="executorch", backend="xnnpack") # or "coreml", "qnn"Native CoreML export
model = RFDETRSmall()
model.export(format="coreml", coreml_precision="float16") # .mlpackage, no ONNX intermediaryMulti-GPU / multi-node keypoint training
RFDETRKeypointPreview().train(
dataset_dir="...",
strategy="ddp",
devices=4,
grad_accum_steps=1,
)Configurable optimizer & LR scheduler
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
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:
pip install 'rfdetr[augment]'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.*andrfdetr.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.exportbuild_namespace(model_config, train_config)(deprecated since v1.7) →build_model_from_config/build_criterion_from_configload_pretrain_weights(nn_model, model_config, train_config)'strain_configargument (deprecated since v1.7) → call(nn_model, model_config)start_epoch,do_benchmark,callbackskwargs on.train()/.evaluate()(deprecated since v1.7) →resume=,rfdetr.export.benchmark, PTLCallbackobjects 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 toRFDETRLargeDeprecatedConfigon checkpoint/config incompatibility — now raises the original error; useRFDETRLargeDeprecateddirectly for legacy Large weights
Deprecated in v1.9 → Remove in v1.11
RFDETR.optimize_for_inference()renamed toRFDETR.inference()(same signature) — old name kept as an alias, emitsFutureWarningTrainConfig.lr_dropandlr_min_factor— pass throughlr_scheduler_kwargsinstead
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 fromtorch.export, no ONNX intermediary;coreml_precision="float32"|"float16"controls compute precision. Install withpip install 'rfdetr[coreml]'(macOS only,coremltools>=8.0,<10.0). Distinct from ExecuTorch'sformat="executorch", backend="coreml".ptepath. (#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.trtengines in-process; configurablefp16: bool = Trueprecision 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"plusoptimizer_kwargs. (#1006) - Configurable LR schedulers —
TrainConfig.lr_scheduler: str | Callable = "step"pluslr_scheduler_kwargs,lr_scheduler_interval,lr_scheduler_monitor; end-to-endReduceLROnPlateausupport. (#1217) TrainConfig.scale_jitter: bool = True— independent control of the resize→crop→resize training branch, decoupled fromaug_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 raiseValueErrorinstead of silently training with defaults. (#1178)
🌱 Changed
- Always save EMA-named checkpoints (
checkpoint_best_ema.pth,last_ema.pth) whenmonitor_emais set;checkpoint_best_total.pthrecords 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_iouhelpers instead of building the full NxN pairwise matrix and reading its diagonal, reducing peak GPU memory during loss calculation. (#1245) [tensorrt]no longer installspycuda— it's only needed forTRTInference'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()'strain_configarg,start_epoch/do_benchmark/callbackstrain() kwargs, misplacedTrainConfig/ModelConfigfields,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 subsequentbackward()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_indexesoverride 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 buildingonnxsimfrom source on CPython 3.11/3.13 and Linux aarch64 — theonnxsim<0.6.0pin resolved to a version with no prebuilt wheels for those targets; nowonnxsim>=0.7.0. (#1242)
🔒 Security
- Safe checkpoint loading by default —
RFDETR.from_checkpoint()usesweights_only=True; opt into full pickle deserialization viatrust_checkpoint=Truefor trusted/legacy files. (#1179) - TensorRT export no longer shells out to
trtexec— engines build in-process via thepolygraphyPython API, removing the subprocess/shell-injection surface entirely. (#853)
🏆 Contributors
- Anatoly Ryabchenko (@anatoly-ryabchenko, LinkedIn) — ExecuTorch (.pte) export;
RFDETR.evaluate()in-memory COCO eval - Robin Cole (@robmarkcole, LinkedIn) — 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) — 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) — decoupled the resize scale-jitter branch from
aug_configvia the newscale_jitterflag - Brian Cong (@congbrian, LinkedIn) — native CoreML export; typed
drop_schedule/models.math; fixed the ExecuTorch export level-dim shape mismatch - Ömer Günaydın (@siromermer, LinkedIn) — fixed YOLO split-directory resolution to honor
data.yamlpaths - Deependu (@deependujha) — fixed a spurious
pyDeprecateCLI warning - Peter Robicheaux (@probicheaux, LinkedIn) — docs: NAS platform availability note, citation author correction
- Matvei Popov (@Matvezy, LinkedIn) — 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) — GA4 tracking on the docs site
- Sergii Bondariev (@sergii-bond, LinkedIn) — 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 staleonnxsimpin - Jirka Borovec (@Borda, LinkedIn) — safe checkpoint loading by default, TensorRT export rewrite onto in-process polygraphy (no more
trtexecsubprocess), 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: 1.8.3...1.9.0