Files
Jirka Borovec 207a0bb87f refine(datasets): schedule aug_config removal (#1398)
- Gave the rfdetr.datasets.aug_config compatibility shim a concrete deadline. Its FutureWarning said only "will be removed in a future release"; it now reads "deprecated since v1.9.0 and will be removed in v1.12.0". The shim itself keeps working unchanged until then, re-exporting AUG_CONFIG, AUG_CONSERVATIVE, AUG_AGGRESSIVE, AUG_AERIAL and AUG_INDUSTRIAL from aug_configs.
- Documented the deprecation, which had shipped without any record of it. The module was renamed in 1.8.0 as a documented breaking change with no shim; the singular path reappeared in 1.9.0 with a warning but no CHANGELOG entry, no migration-guide section and no removal target. Added a CHANGELOG "Deprecated" entry under Unreleased and a "Deprecated in v1.9 -> Remove in v1.12" section under "Upgrade 1.8 -> 1.9" in docs/getting-started/migration.md, dated to the release the warning started firing in. The 1.7 -> 1.8 breaking-change block is left alone: that rename genuinely shipped shim-less.
- Explained in the module docstring why this uses warnings.warn rather than the project's usual pyDeprecate: pyDeprecate exposes function, class and instance decorators only, and none of them fire on a bare module import.
- Added tests/datasets/test_aug_config_shim.py, covering a path that had none. It asserts the warning fires, names v1.12.0, and points at the replacement module; that all five presets are identity-equal to their aug_configs originals rather than copies; and that __all__ lists every one of them so star imports keep working. Its fixture evicts the module from sys.modules first, because a module-level warning fires once per process and would otherwise be unobservable depending on collection order. Matching the version in the regex means moving the deadline in the docs without moving it in the code fails here.
- Consolidated AugmentationBackend._is_albu_available, _is_kornia_available and _is_tv_available into one _is_available method driven by a new _AUGMENTATION_BACKEND_PROBE_MODULES table keyed on the backend value, so the GPU alias for KORNIA needs no special case. TV has no table entry and reports available unconditionally, matching torchvision being a hard dependency. Probing stays inside from_str rather than moving to module-level constants, so importing rfdetr still never pulls in Albumentations or Kornia.
- Dropped _is_tv_available outright rather than folding it in: it had no callers anywhere in src or tests.
- Moved functools.lru_cache from the two per-backend classmethods onto _package_importable, caching by dotted module name instead of by method. Carried the caching and patching warning into the _is_available docstring, retargeted to say tests must patch _is_available itself and never _package_importable, since a real probe result now persists process-wide.
- Updated the six call sites in config.py, datasets/kornia_transforms.py and training/module_data.py to the member form, and rewrote the twelve patch sites across tests/datasets/test_coco.py, tests/datasets/test_kornia_transforms.py and tests/training/test_module_data.py to patch _is_available with a plain function so it binds and receives the member, preserving each site's per-backend intent that a single return_value could not express.

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
2026-08-24 09:11:35 +02:00

21 KiB

description
description
Per-version migration guide for RF-DETR. Covers breaking changes and deprecated APIs for each release series.

Migration Guide

Read each section between your current version and your target — every section covers only the delta between two adjacent releases.

1.4.x  →  1.5 →  1.6  →  1.7  →  1.8  →  1.9  →  1.10

You can apply all changes in one go; working through sections one release at a time and verifying between each step is optional but makes failures easier to isolate. Deprecated APIs emit a DeprecationWarning, while deprecated configuration fields emit a FutureWarning, until the version marked for removal. See the Changelog for the full list of changes in each release.


Upgrade 1.9 → 1.10

Breaking changes

!!! warning "Breaking: log_per_class_metrics now defaults to False"

`TrainConfig.log_per_class_metrics` defaults to `False` (was `True`). Per-class AP keys (`test/AP/<class>`, `val/AP/<class>`) are no longer emitted by default — validation/test now skip that per-class computation. Set it explicitly to restore the old behavior:

```python
train_config = TrainConfig(log_per_class_metrics=True)
```

!!! warning "Breaking: compute_val_loss now defaults to \"auto\""

`TrainConfig.compute_val_loss` defaults to `"auto"` (was `True`). In `"auto"` mode, validation loss is computed only when something actually consumes it — a `ReduceLROnPlateau` scheduler monitoring `val/loss`, or a callback (e.g. `ModelCheckpoint(monitor="val/loss")`, early stopping) that requires it — and is skipped otherwise. For a default run with no such consumer, `val/loss` no longer appears in `metrics.csv`, TensorBoard, or W&B. Set it explicitly to restore the old unconditional behavior:

```python
train_config = TrainConfig(compute_val_loss=True)
```

!!! warning "Breaking: validation evaluates one model, and val/mAP_* follows it"

Validation now runs **one** forward pass per batch instead of two: through the EMA weights when `use_ema=True` (the default), through the base weights otherwise. `val/mAP_50_95`, `val/mAP_50`, `val/mAP_75`, `val/mAR`, and per-class `val/AP/<class>` therefore report the EMA model on a default run — they used to report the base model — while the matching `val/ema_*` namespace remains available. Best-checkpoint selection is unaffected in substance (it already preferred EMA), but the "regular" track no longer writes `checkpoint_best_regular.pth` on such runs; `checkpoint_best_total.pth` is copied from the EMA checkpoint.

`val/F1` and `val/loss` (when computed) follow the same single forward, so they now describe the EMA model too — consistent with the mAP under the primary key, but a change of meaning if you monitor `val/loss` with a `ReduceLROnPlateau` scheduler, `ModelCheckpoint`, or early stopping.

Restore the previous two-forward behavior, both metric namespaces and both checkpoint tracks:

```python
train_config = TrainConfig(eval_base_model=True)
```

Deprecated in v1.10 → Remove in v1.13

!!! note "eval_ema_only is deprecated"

Evaluating only the selected model is the default. Explicit legacy `TrainConfig(eval_ema_only=True)` preserves EMA-only evaluation and emits a `FutureWarning`; explicit `eval_ema_only=False` is migrated to the old base-plus-EMA behavior and also warns. Drop the field from new configurations. Use `eval_base_model=True` if you want the base model evaluated as well; `eval_ema_only=True` still requires `use_ema=True` and conflicts with that opt-in.

One improvement for existing `eval_ema_only` users: `val/mAP_50_95` is now populated (with the EMA score) instead of staying absent, so monitors pointed at it start receiving values again.

Upgrade 1.8 → 1.9

Breaking changes

!!! warning "Breaking: albumentations and kornia extras merged into augment"

**PyPI extras renamed.** Default training/validation/prediction/export augmentations now use torchvision-native transforms, so `[train]` no longer installs Albumentations. Custom CPU (Albumentations) and GPU (Kornia) augmentation both live behind a single new `augment` extra.

| Old extra                                | New extra               |
| ---------------------------------------- | ----------------------- |
| `rfdetr[train]` (implied albumentations) | `rfdetr[train,augment]` |
| `rfdetr[kornia]`                         | `rfdetr[augment]`       |

```bash
# Before
pip install 'rfdetr[train]'    # bundled albumentations
pip install 'rfdetr[kornia]'

# After
pip install 'rfdetr[train,augment]'   # custom aug_config or GPU backend
pip install 'rfdetr[augment]'
```

!!! note "augmentation_backend values renamed"

`augmentation_backend="tv"` and `"albu"` are renamed to `"torchvision"` and `"albumentations"`. The old strings (and `"gpu"`) still work as aliases, so no code changes are required — see [Augmentation Backend Values](../learn/train/augmentations.md#augmentation-backend-values) for the full accepted set.

!!! warning "Breaking: default resize interpolation changed — pixel values and mAP may shift"

The default resize backend changed from Albumentations (cv2 `INTER_LINEAR`, no antialias) to torchvision (`BILINEAR` + `antialias=True`). Resized pixel values differ slightly from previous versions, and mAP may drift on existing benchmarks. **This affects training as well as validation and test preprocessing** — not just the training split.

To restore the previous pixel-exact 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]` alone is **not** sufficient to pin this behaviour — with Albumentations installed, `augmentation_backend="auto"`/`"cpu"` (the default) auto-selects Albumentations for you, but identical code on a machine without `[augment]` installed silently falls back to torchvision instead. The only setting that pins resize behaviour regardless of what is installed is:

```python
train_config = TrainConfig(augmentation_backend="torchvision")
```

Removed

The following APIs were deprecated in earlier releases and are removed as of v1.9. Update your code before upgrading.

!!! warning "Removed: rfdetr.util.* and rfdetr.deploy.* import paths"

Deprecated since v1.6, removed in v1.9. Use the canonical replacements listed in the [Upgrade 1.5 → 1.6](#upgrade-15--16) section.

```python
# These imports now raise ImportError; update to the canonical paths
from rfdetr.util.coco_classes import COCO_CLASSES  # → rfdetr.assets.coco_classes
from rfdetr.util.misc import get_rank  # → rfdetr.utilities
from rfdetr.deploy import export_onnx  # → rfdetr.export.main
```

!!! warning "Removed: build_namespace(model_config, train_config)"

Deprecated since v1.7, removed in v1.9. Use `build_model_from_config` and `build_criterion_from_config` instead.

!!! warning "Removed: load_pretrain_weights(nn_model, model_config, train_config) with train_config"

Deprecated since v1.7, removed in v1.9. Drop the `train_config` positional argument.

!!! warning "Removed: start_epoch kwarg in train()"

Deprecated since v1.7, removed in v1.9. PyTorch Lightning resumes automatically via `resume=`.

!!! warning "Removed: do_benchmark kwarg in train()"

Deprecated since v1.7, removed in v1.9. Use the `rfdetr.export.benchmark` module instead.

!!! warning "Removed: callbacks dict kwarg in train()"

Deprecated since v1.7, removed in v1.9. Pass PTL `Callback` objects directly via the Lightning API instead.

!!! warning "Removed: misplaced config fields"

The following `TrainConfig` and `ModelConfig` fields moved to their correct config class in v1.7; the deprecated compatibility shims are removed in v1.9. Passing one of these fields on its old config class now raises a pydantic validation error:

| Field               | Removed from  | Use in        |
| ------------------- | ------------- | ------------- |
| `group_detr`        | `TrainConfig` | `ModelConfig` |
| `ia_bce_loss`       | `TrainConfig` | `ModelConfig` |
| `segmentation_head` | `TrainConfig` | `ModelConfig` |
| `num_select`        | `TrainConfig` | `ModelConfig` |
| `cls_loss_coef`     | `ModelConfig` | `TrainConfig` |

!!! warning "Removed: RFDETRLarge silent fallback to deprecated Large config"

`RFDETRLarge()` no longer catches checkpoint/config incompatibility errors and silently retries with `RFDETRLargeDeprecatedConfig`. Loading legacy deprecated-Large weights through `RFDETRLarge` now raises the original `ValueError`/`RuntimeError` instead of falling back. `RFDETRLargeDeprecated` itself is unaffected — use it directly to load those checkpoints.

```python
# Before (silently retried with the deprecated config and logged a warning)
model = RFDETRLarge(pretrain_weights="old_large_checkpoint.pth")

# After
from rfdetr import RFDETRLargeDeprecated

model = RFDETRLargeDeprecated(pretrain_weights="old_large_checkpoint.pth")
```

Deprecated in v1.9 → Remove in v1.11

!!! note "Deprecated: RFDETR.optimize_for_inference() renamed to RFDETR.inference()"

**`optimize_for_inference(compile=..., batch_size=..., dtype=..., inplace=...)`** — renamed to `inference()` with the same signature.

```python
# Before (deprecated)
model.optimize_for_inference(dtype=torch.float16)

# After
model.inference(dtype=torch.float16)
```

!!! note "Deprecated: TrainConfig.lr_drop and TrainConfig.lr_min_factor"

**`lr_drop` / `lr_min_factor`** — pass them through `lr_scheduler_kwargs` instead. For the managed `"step"` / `"cosine"` presets the fields are still folded into `lr_scheduler_kwargs` (with a `FutureWarning`); set with an explicit scheduler they are inert and warn.

```python
# Before (deprecated)
TrainConfig(lr_scheduler="step", lr_drop=80, lr_min_factor=0.1)

# After
TrainConfig(lr_scheduler="step", lr_scheduler_kwargs={"lr_drop": 80, "min_factor": 0.1})
```

Deprecated in v1.9 → Remove in v1.12

!!! note "rfdetr.datasets.aug_config is deprecated"

The module was renamed to `rfdetr.datasets.aug_configs` (plural) in v1.8.0 — see the "Upgrade 1.7 → 1.8" section below, where it is listed as a breaking change because that rename shipped with no compatibility shim. A shim was added in v1.9.0, so the singular path imports again and emits a `FutureWarning`. It is scheduled for removal in **v1.12.0**; migrate before then.

The preset constants are unchanged — only the module path moves.

```python
# Before (deprecated, warns since v1.9.0)
from rfdetr.datasets.aug_config import AUG_AGGRESSIVE

# After
from rfdetr.datasets.aug_configs import AUG_AGGRESSIVE
```

Upgrade 1.7 → 1.8

Breaking changes

!!! note "Breaking in v1.8.2: default keypoint schema changed to active-first [17]"

New checkpoints created from v1.8.2 onwards use `class_id=0` for person. Legacy `[0, 17]` checkpoints are still supported — RF-DETR auto-detects the schema from the checkpoint at load time.

If your post-processing code offsets class IDs by 1 (common for background-first models), update it:

```python
# Before (background-first [0, 17]: person was at class_id=1)
class_name = "person" if detection.class_id == 1 else "other"

# After (active-first [17]: person is at class_id=0)
class_name = "person" if detection.class_id == 0 else "other"
```

Use `detection.data["class_name"]` for schema-agnostic name resolution.

!!! warning "Breaking: rfdetr.datasets.aug_config renamed to rfdetr.datasets.aug_configs"

The augmentation config module was renamed (singular → plural). If you import from it directly:

```python
# Before
from rfdetr.datasets.aug_config import AUG_AGGRESSIVE

# After
from rfdetr.datasets.aug_configs import AUG_AGGRESSIVE
```

All preset constants (`AUG_AGGRESSIVE`, `AUG_CONSERVATIVE`, etc.) are unchanged.

!!! warning "Breaking: supervision>=0.29.0 now required"

Required for `sv.KeyPoints` support. `pip install rfdetr==1.8.0` pulls this automatically. If another dependency pins `supervision<0.29.0`, resolve the conflict manually.

!!! warning "Breaking: pyDeprecate constraint narrowed to >=0.9,<0.10"

Was `>=0.6,<0.8`. If another package pins an older version, resolve with:

```bash
pip install "rfdetr==1.8.0" "pyDeprecate>=0.9,<0.10"
```

Upgrade 1.6 → 1.7

Breaking changes

!!! warning "Breaking: peft removed from the default install"

LoRA fine-tuning now requires the `lora` extra. If you use LoRA adapters during training, update your install command.

```bash
# Before
pip install rfdetr

# After
pip install 'rfdetr[lora]'
```

!!! warning "Breaking: predict() stores source image in detections.metadata"

**`predict()` stores the source image in `detections.metadata`, not `detections.data`.**

```python
# Before (1.6.4 and earlier)
source = detections.data["source_image"]

# After
source = detections.metadata["source_image"]
```

!!! warning "Breaking: pyDeprecate constraint changed to >=0.6,<0.8"

Was `>=0.3,<0.6`. If another package pins an older version, resolve with:

```bash
pip install "rfdetr==1.7.0" "pyDeprecate>=0.6,<0.8"
```

Deprecated in v1.7 → Remove in v1.9

!!! note "Deprecated: build_namespace() split into two functions"

**`build_namespace(model_config, train_config)`** — use `build_model_from_config` or `build_criterion_from_config` instead.

```python
# Before (deprecated)
from rfdetr.models import build_namespace

ns = build_namespace(model_config, train_config)

# After
from rfdetr.models import build_model_from_config, build_criterion_from_config

model = build_model_from_config(model_config)
criterion = build_criterion_from_config(model_config, train_config)
```

!!! note "Deprecated: load_pretrain_weights() no longer takes train_config"

**`load_pretrain_weights(nn_model, model_config, train_config)`** — drop the `train_config` positional argument.

```python
# Before (deprecated)
from rfdetr.models import load_pretrain_weights

load_pretrain_weights(nn_model, model_config, train_config)

# After
from rfdetr.models import load_pretrain_weights

load_pretrain_weights(nn_model, model_config)
```

!!! note "Deprecated: config fields moved between ModelConfig and TrainConfig"

**Config fields placed in the wrong config object.** Move them as shown:

| Field               | Was in        | Move to       |
| ------------------- | ------------- | ------------- |
| `group_detr`        | `TrainConfig` | `ModelConfig` |
| `ia_bce_loss`       | `TrainConfig` | `ModelConfig` |
| `segmentation_head` | `TrainConfig` | `ModelConfig` |
| `num_select`        | `TrainConfig` | `ModelConfig` |
| `cls_loss_coef`     | `ModelConfig` | `TrainConfig` |

```python
# Before (deprecated)
train_config = TrainConfig(group_detr=13, cls_loss_coef=2.0)

# After
model_config = ModelConfig(group_detr=13)
train_config = TrainConfig(cls_loss_coef=2.0)
```

Deprecated in v1.7 → Remove in v2.0

!!! note "Deprecated: RFDETRBase replaced by size-specific classes"

**`RFDETRBase`** defaulted to the small variant and is replaced by size-specific classes. Choose the variant that matches your previous model size. If you used `RFDETRBase()` without arguments, switch to `RFDETRSmall()`.

```python
# Before (deprecated)
from rfdetr import RFDETRBase

model = RFDETRBase()

# After — pick one
from rfdetr import RFDETRNano, RFDETRSmall, RFDETRMedium, RFDETRLarge

model = RFDETRSmall()
```

!!! note "Deprecated: RFDETRSegPreview replaced by size-specific segmentation classes"

**`RFDETRSegPreview`** defaulted to the small variant and is replaced by size-specific segmentation classes. If you used `RFDETRSegPreview()` without arguments, switch to `RFDETRSegSmall()`.

```python
# Before (deprecated)
from rfdetr import RFDETRSegPreview

model = RFDETRSegPreview()

# After — pick one
from rfdetr import RFDETRSegNano, RFDETRSegSmall, RFDETRSegMedium, RFDETRSegLarge

model = RFDETRSegSmall()
```

Upgrade 1.5 → 1.6

Breaking changes

!!! warning "Breaking: transformers minimum version raised to >=5.1.0"

**`transformers` minimum version raised to `>=5.1.0,<6.0.0`.**

Projects pinned to `transformers<5.0.0` must upgrade. If upgrading is not possible, pin `rfdetr<1.6.0`.

```bash
pip install 'transformers>=5.1.0,<6.0.0'
```

!!! warning "Breaking: PyPI extras renamed"

**PyPI extras renamed.**

Update your `pip install` commands and `requirements*.txt` files.

| Old extra            | New extra         |
| -------------------- | ----------------- |
| `rfdetr[metrics]`    | `rfdetr[loggers]` |
| `rfdetr[onnxexport]` | `rfdetr[onnx]`    |

```bash
# Before
pip install 'rfdetr[metrics]'
pip install 'rfdetr[onnxexport]'

# After
pip install 'rfdetr[loggers]'
pip install 'rfdetr[onnx]'
```

!!! warning "Breaking: draw_synthetic_shape() now returns a tuple"

**`draw_synthetic_shape()` now returns `(image, polygon)` instead of `image`.**

Update every call site that unpacks only the image.

```python
# Before
img = draw_synthetic_shape(...)

# After
img, polygon = draw_synthetic_shape(...)
```

Deprecated in v1.6 → Removed in v1.8

!!! note "Deprecated: simplify and force arguments in RFDETR.export()"

**`RFDETR.export(..., simplify=..., force=...)`** — both arguments are no-ops. Remove them from your calls.

```python
# Before (deprecated)
model.export("model.onnx", simplify=True, force=True)

# After
model.export("model.onnx")
```

Deprecated in v1.6 → Remove in v1.9

!!! note "Deprecated: rfdetr.util.* and rfdetr.deploy.* import paths"

Backward-compatibility shims are still active but emit `DeprecationWarning` on import. Replace with the canonical paths listed in the table below.

| Deprecated module                 | Canonical replacement              |
| --------------------------------- | ---------------------------------- |
| `rfdetr.util.coco_classes`        | `rfdetr.assets.coco_classes`       |
| `rfdetr.util.misc`                | `rfdetr.utilities`                 |
| `rfdetr.util.logger`              | `rfdetr.utilities.logger`          |
| `rfdetr.util.box_ops`             | `rfdetr.utilities.box_ops`         |
| `rfdetr.util.files`               | `rfdetr.utilities.files`           |
| `rfdetr.util.package`             | `rfdetr.utilities.package`         |
| `rfdetr.util.get_param_dicts`     | `rfdetr.training.param_groups`     |
| `rfdetr.util.drop_scheduler`      | `rfdetr.training.drop_schedule`    |
| `rfdetr.util.visualize`           | `rfdetr.visualize.data`            |
| `rfdetr.deploy`                   | `rfdetr.export`                    |
| `rfdetr.models.segmentation_head` | `rfdetr.models.heads.segmentation` |

**Examples:**

```python
# Before (deprecated)
from rfdetr.util.coco_classes import COCO_CLASSES
from rfdetr.util.misc import get_rank, get_world_size, is_main_process, save_on_master
from rfdetr.util.logger import get_logger
from rfdetr.util.box_ops import box_cxcywh_to_xyxy, generalized_box_iou
from rfdetr.util.get_param_dicts import get_param_dict
from rfdetr.util.drop_scheduler import drop_scheduler
from rfdetr.util.visualize import save_gt_predictions_visualization
from rfdetr.deploy import export_onnx
from rfdetr.models.segmentation_head import SegmentationHead

# After
from rfdetr.assets.coco_classes import COCO_CLASSES
from rfdetr.utilities.distributed import get_rank, get_world_size, is_main_process, save_on_master
from rfdetr.utilities.logger import get_logger
from rfdetr.utilities.box_ops import box_cxcywh_to_xyxy, generalized_box_iou
from rfdetr.training.param_groups import get_param_dict
from rfdetr.training.drop_schedule import drop_scheduler
from rfdetr.visualize.data import save_gt_predictions_visualization
from rfdetr.export.main import export_onnx
from rfdetr.models.heads.segmentation import SegmentationHead
```

Upgrade 1.4 → 1.5

Breaking changes

!!! warning "Breaking: ModelConfig rejects unknown keyword arguments"

**`ModelConfig` now raises `ValidationError` on unknown keyword arguments.**

Previously, unrecognised fields were silently ignored. Remove or rename any unrecognised keys you pass to `ModelConfig(...)`.

```python
# Before — silently accepted
config = ModelConfig(unknown_field=True)

# Now raises ValidationError — remove the unknown key
config = ModelConfig()
```

Deprecated in v1.5 → Removed in v1.7

!!! note "Deprecated: OPEN_SOURCE_MODELS replaced by ModelWeights enum"

**`OPEN_SOURCE_MODELS` constant** — use the `ModelWeights` enum instead. A `DeprecationWarning` is emitted on access. See the [API reference](../reference/rfdetr.md) for available enum values.

```python
# Before (deprecated)
from rfdetr import OPEN_SOURCE_MODELS

# After
from rfdetr.assets.model_weights import ModelWeights
```