Skip to content

v1.9.0: Configurable Training, ExecuTorch & CoreML Export

Choose a tag to compare

@Borda Borda released this 29 Jul 09:03
· 145 commits to develop since this release
a700efc

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 intermediary

Multi-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 ValueErrorTrainConfig 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_coefTrainConfig (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 exportRFDETR.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) exportRFDETR.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 improvementsRFDETR.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 optimizerTrainConfig.optimizer: str | Callable = "adamw" plus optimizer_kwargs. (#1006)
  • Configurable LR schedulersTrainConfig.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 backendsAugmentationBackend.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_factorlr_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) — 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_config via the new scale_jitter flag
  • 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.yaml paths
  • Deependu (@deependujha) — fixed a spurious pyDeprecate CLI 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 stale onnxsim pin
  • Jirka Borovec (@Borda, LinkedIn) — 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: 1.8.3...1.9.0