Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix silently random-initializing RTDetrModel/SEWDForCTC loads (wrong base_model_prefix) - #48744

Open
abhinav-phi wants to merge 1 commit into
huggingface:mainfrom
abhinav-phi:fix-base-model-prefix-48722
Open

Fix silently random-initializing RTDetrModel/SEWDForCTC loads (wrong base_model_prefix)#48744
abhinav-phi wants to merge 1 commit into
huggingface:mainfrom
abhinav-phi:fix-base-model-prefix-48722

Conversation

@abhinav-phi

@abhinav-phi abhinav-phi commented Sep 12, 2026

Copy link
Copy Markdown

CPU CI GPU run-slow

What does this PR do?

Fixes #48722

RTDetrModel.from_pretrained("PekingU/rtdetr_r18vd") returned a model with all 502 weights randomly initialized (526 unexpected keys), and SEWDForCTC.from_pretrained("asapp/sew-d-tiny-100k") likewise left all 222 weights random — silently, with only a warning.

Root cause. When loading across the base-model/head-model boundary, the weight loader adds or strips base_model_prefix (see rename_source_key in core_model_loading.py, step 3) based on what the target model's state dict expects. For these families the declared prefix never matches the attribute that actually nests the base model:

  • RTDetrForObjectDetection nests the base model in self.model, but base_model_prefix was "rt_detr" (same for rt_detr_v2, pp_doclayout_v2, pp_doclayout_v3, d_fine, deimv2 via the modular converter). Detection checkpoints store every weight under model., so loading *Model stripped nothing → 100% missing/unexpected.
  • SEWDForCTC nests the base model in self.sew_d, but base_model_prefix was "sew-d" with a dash — an impossible Python attribute name — so base checkpoints (unprefixed keys) never got the sew_d. prefix added.

Fix. Align base_model_prefix with the actual attribute ("model" in the RT-DETR family — changed once in modular_rt_detr.py and propagated to the generated files — "sew_d" for SEW-D), matching what sibling architectures already do: DeformableDetr, TableTransformer, RfDetr all use "model", SEW uses "sew".

Before / after

Verified locally against the exact checkpoints from the issue:

Load before after
RTDetrModelPekingU/rtdetr_r18vd 502 missing / 526 unexpected 0 missing / 24 unexpected (only the class_embed/bbox_embed heads)
RTDetrForObjectDetection ← same 0 missing 0 missing (unchanged)
SEWDForCTCasapp/sew-d-tiny-100k 222 missing / 220 unexpected only lm_head.weight/bias missing, all 220 encoder weights loaded and equal to SEWDModel's
SEWDModel ← same 0 missing 0 missing (unchanged)

Same class of bug, same fix — also verified on real hub checkpoints for RTDetrV2Model (PekingU/rtdetr_v2_r50vd: base 0 missing), PPDocLayoutV2/V3Model, and confirmed the model.-prefixed hub layout for d_fine/deimv2 (ustc-community/dfine-*-coco). (For PP-DocLayoutV2/V3 the remaining "missing" entries are num_batches_tracked buffers the converted checkpoints do not store; PP-DocLayoutV3 additionally has a pre-existing size mismatch on denoising_class_embed between the base model and what its head stores — a modeling inconsistency unrelated to key mapping.)

Tests

  • Cross-class save/load regression tests for both directions in all seven affected families (rt_detr, rt_detr_v2, pp_doclayout_v2, pp_doclayout_v3, d_fine, deimv2, sew_d; tiny configs, no network).
  • @slow hub tests pinning the exact issue repro: RTDetrModel from PekingU/rtdetr_r50vd, SEWDForCTC from asapp/sew-d-tiny-100k.
  • Re-enabled the generic test_correct_missing_keys (test_missing_keys = False was needed only because model.base_model used to return the head model itself with the broken prefix; it now returns the base model and the generic test passes) for rt_detr, rt_detr_v2, pp_doclayout_v2, pp_doclayout_v3, d_fine and deimv2.

Locally: full non-slow suites pass for all touched families + controls (deformable_detr, sew); make quality clean (ruff check/format on src + tests, check_copies, check_repo, check_modular_conversion --check_all).

@huggingface/transformers-core

@abhinav-phi

abhinav-phi commented Sep 12, 2026

Copy link
Copy Markdown
Author

@Cyrilvallez @ydzork friendly ping for a review when you get a chance 🙏

This is a small, self-contained loading fix: the only hand-edited source line is base_model_prefix = "model" in modular_rt_detr.py (+ "sew_d" in modeling_sew_d.py, which has no modular), everything else in the diff is generated files, regression tests for both cross-loading directions in the seven affected families, and re-enabled test_correct_missing_keys in the six detection test files. Full CI is green (including Check repository consistency), so the main thing worth eyeballing is the prefix-alignment rationale in the description and the PP-DocLayoutV3 denoising_class_embed size note (pre-existing, called out but not fixed here).

…-initialized loads

`RTDetrModel.from_pretrained("PekingU/rtdetr_r18vd")` and
`SEWDForCTC.from_pretrained("asapp/sew-d-tiny-100k")` silently returned a
fully randomly-initialized model (502/502 and 222/222 missing keys
respectively), because the weight loader adds/strips `base_model_prefix`
when crossing the base-model/head-model boundary, and for these families the
declared prefix never matches the actual attribute:

- `RTDetrForObjectDetection` nests the base model in `self.model`, but the
  prefix was `"rt_detr"` (materialized as `"rt_detr_v2"`, `"pp_doclayout_v2"`,
  `"pp_doclayout_v3"`, `"d_fine"`, `"deimv2"` for the subclasses through the
  modular converter). Detection checkpoints store every weight under `model.`,
  which was never stripped when loading the base `*Model` classes.
- `SEWDForCTC` nests the base model in `self.sew_d` while the prefix was
  `"sew-d"` (with a dash), which can never match a Python attribute name, so
  base checkpoints (unprefixed keys) never got the `sew_d.` prefix added.

Align the prefix with the actual attribute (`"model"` in the RT-DETR family,
`"sew_d"` for SEW-D), matching what sibling architectures already do
(`DeformableDetr`/`TableTransformer`/`RfDetr` use `"model"`; `SEW` uses
`"sew"`). For the RT-DETR family the fix lives in `modular_rt_detr.py` and is
propagated to all generated modeling files.

This also un-breaks `model.base_model` for these classes (it used to return
the head model itself), so the generic `test_correct_missing_keys`
(`test_missing_keys = False`) is re-enabled for rt_detr, rt_detr_v2,
pp_doclayout_v2, pp_doclayout_v3, d_fine and deimv2.

Add cross-class save/load regression tests for all seven families, plus
hub-level tests for the exact checkpoints reported in the issue.

Fixes huggingface#48722
@abhinav-phi
abhinav-phi force-pushed the fix-base-model-prefix-48722 branch from 2b48a1e to 77e6a1e Compare September 13, 2026 11:00
@github-actions

Copy link
Copy Markdown
Contributor

[For maintainers] Suggested jobs to run (before merge)

run-slow: d_fine, deimv2, pp_doclayout_v2, pp_doclayout_v3, rt_detr, rt_detr_v2, sew_d

@github-actions

Copy link
Copy Markdown
Contributor

CI recap

Dashboard: View test results in Grafana
Latest run: 34697993491:2
Result: success | Jobs: 4 | Tests: 2,367 | Failures: 0 | Duration: 18m 5s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Loading RTDetrModel from a detection checkpoint (or SEWDForCTC from a SEW-D checkpoint) gives a model with every weight randomly initialized

1 participant