feat: max_eval_orig_size to restrain eval images loaded to a maximum size on the longest side - #1033
feat: max_eval_orig_size to restrain eval images loaded to a maximum size on the longest side#1033thepian wants to merge 2 commits into
max_eval_orig_size to restrain eval images loaded to a maximum size on the longest side#1033Conversation
…size on the longest side This helps speed up validation epochs
max_eval_orig_size to restrain eval images loaded to a maximum size on the longest side
@thepian could you pls sign or share a printscreen documenting that you did, and it is just not projected in CI |
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (81%) is below the target coverage (95%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## develop #1033 +/- ##
=======================================
- Coverage 80% 80% -0%
=======================================
Files 101 101
Lines 8524 8553 +29
=======================================
+ Hits 6848 6871 +23
- Misses 1676 1682 +6 🚀 New features to boost your workflow:
|
|
help me understand: the goal here is to reduce memory / RLE conversion runtime for seg models by capping the max size that the mask is stored at? probably the right test is to see what mAP the COCO models get when using different caps to show that your guess that it doesn't hurt much is right |
@thepian ^^ 🦝 |
There was a problem hiding this comment.
Pull request overview
Adds a new max_eval_orig_size knob to cap evaluation-time “original size” used during postprocessing/COCO evaluation, aiming to reduce mask upsampling/memory and speed up validation epochs (without changing training-time behavior).
Changes:
- Introduces
TrainConfig.max_eval_orig_size(optional) and wires it intoCOCOEvalCallback. - Caps
orig_sizespassed intoPostProcessduring val/test steps, and adds COCO-eval-side conversions to keep preds/targets consistent under the cap. - Adds unit tests covering mask/box scaling behavior and config defaults/inheritance.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/training/test_coco_eval_callback.py | Adds tests asserting masks/boxes/targets are resized/scaled consistently when capped. |
| tests/models/test_config.py | Adds config tests for the new field’s default and inheritance. |
| src/rfdetr/training/trainer.py | Plumbs max_eval_orig_size from TrainConfig into COCOEvalCallback. |
| src/rfdetr/training/module_model.py | Caps orig_sizes before calling PostProcess in val/test to reduce upsampling cost. |
| src/rfdetr/training/callbacks/coco_eval.py | Applies the cap for EMA eval path and normalizes preds/targets under the capped size. |
| src/rfdetr/config.py | Adds max_eval_orig_size to TrainConfig. |
| eval_max_dets: int = 500 | ||
| eval_interval: int = 1 | ||
| log_per_class_metrics: bool = True | ||
| max_eval_orig_size: Optional[int] = None | ||
| aug_config: Optional[Dict[str, Any]] = None |
| cap = getattr(self.train_config, "max_eval_orig_size", None) | ||
| if cap is not None: | ||
| scale = (cap / orig_sizes.float().amax(dim=1, keepdim=True)).clamp(max=1.0) | ||
| orig_sizes = (orig_sizes.float() * scale).long() |
| cap = getattr(self.train_config, "max_eval_orig_size", None) | ||
| if cap is not None: | ||
| scale = (cap / orig_sizes.float().amax(dim=1, keepdim=True)).clamp(max=1.0) | ||
| orig_sizes = (orig_sizes.float() * scale).long() |
| if self._max_eval_orig_size is not None: | ||
| # Cap each (H, W) so the longer side ≤ max_eval_orig_size. | ||
| # Masks are upsampled to orig_size inside postprocess; capping here | ||
| # keeps mask buffers small without affecting training. | ||
| scale = (self._max_eval_orig_size / orig_sizes.float().amax(dim=1, keepdim=True)).clamp(max=1.0) | ||
| orig_sizes = (orig_sizes.float() * scale).long() |
| scale = self._max_eval_orig_size / max(h, w) | ||
| new_h = max(1, int(h * scale)) | ||
| new_w = max(1, int(w * scale)) | ||
| masks = F.interpolate( | ||
| masks.float().unsqueeze(1), | ||
| size=(new_h, new_w), | ||
| mode="nearest", | ||
| ).squeeze(1) | ||
| if "boxes" in entry: | ||
| entry["boxes"] = entry["boxes"] * scale | ||
| entry["masks"] = masks |
This helps speed up validation epochs
What does this PR do?
Allows you to do eval with images sized to represent the scaled down images rf-detr works on.
Related Issue(s): 416
Type of Change
Testing
Test details:
I haven't tested it a bunch. I am giving it a run with my fine tuning runs. Hopefully I get the expected speedup.
Checklist