Skip to content

Fix orthogonal_ init for low-precision dtypes (bf16/fp16)#47252

Open
janbernloehr wants to merge 2 commits into
huggingface:mainfrom
janbernloehr:fix-orthogonal-init-low-precision
Open

Fix orthogonal_ init for low-precision dtypes (bf16/fp16)#47252
janbernloehr wants to merge 2 commits into
huggingface:mainfrom
janbernloehr:fix-orthogonal-init-low-precision

Conversation

@janbernloehr

@janbernloehr janbernloehr commented Jul 10, 2026

Copy link
Copy Markdown

CI

What does this PR do?

torch.nn.init.orthogonal_ relies on torch.linalg.qr, whose geqrf kernel is only implemented for float32/float64 — on both CUDA ("geqrf_cuda" not implemented for 'BFloat16') and CPU ("geqrf_cpu" not implemented for 'BFloat16'). Since v5 materializes weights in the requested dtype before _init_weights runs, constructing any model that uses orthogonal init (e.g. RWKV) with dtype=torch.bfloat16/float16 crashes:

with torch.device("cuda"):
    model = AutoModelForCausalLM.from_config(config, dtype=torch.bfloat16)  # NotImplementedError

This PR makes the orthogonal_ wrapper in src/transformers/initialization.py run the QR-based init in a temporary float32 tensor (same device) and copy the result back when the target dtype is a floating dtype below 32 bits. Full-precision behavior is unchanged, and the _is_hf_initialized guard is preserved. Since guard_torch_init_functions patches the torch modules with these wrappers, remote-code models calling torch.nn.init.orthogonal_ directly are covered as well.

Added tests/utils/test_initialization.py: verifies bf16/fp16 init succeeds and produces finite, orthogonal rows scaled by gain (fails with NotImplementedError without the fix), that the fp32 path exactly matches torch.nn.init.orthogonal_, and that _is_hf_initialized is respected. Also validated end-to-end: RWKV from_config in bf16 now constructs on CPU and CUDA (H100), and trains with decreasing loss (see issue).

Fixes #47225

Disclosure: this fix was implemented with the assistance of a code agent (Claude), per my proposal in the linked issue, and reviewed and validated by me.

Before submitting

Who can review?

@Cyrilvallez (author of the v5 weight-initialization refactor in #42191)

torch.nn.init.orthogonal_ relies on torch.linalg.qr, whose geqrf kernel
is only implemented for float32/float64 (on both CPU and CUDA). Since v5
materializes weights in the requested dtype before _init_weights runs,
any QR-based init on a bf16/fp16 tensor crashes with e.g.
NotImplementedError: "geqrf_cuda" not implemented for 'BFloat16'
(RWKV being one affected model).

Run the init in float32 and copy the result back for low-precision
floating dtypes, on any device.

Fixes huggingface#47225

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

CI recap

Dashboard: View test results in Grafana
Latest run: 29099244966
Result: success | Grafana metrics are not available yet.

@Rocketknight1 Rocketknight1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Can we drop the new test file, though, and instead just add a small test into an existing file? With the comment this is unlikely to regress too, so even dropping the test entirely is fine I think.

Address review: drop the standalone test file and keep a single
condensed low-precision regression test in an existing file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your contribution 🤗!

CI Security Gate — automatic approval blocked

This PR was not automatically approved for CI because the security gate failed.

Possible reasons:

  • The PR touches 50 or more files — only PRs with fewer than 50 changed files are automatically approved
  • A changed file is outside the allowed directories (src/, tests/, docs/, utils/), has a disallowed extension (only .py, .txt, .md permitted outside tests/ and docs/), or is not .md/.yml inside docs/
  • A new high-severity security issue was detected in the changed Python files (Bandit check)

See the workflow run for the exact violations.

A maintainer can review and manually approve CI if a finding is a false positive.

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.

orthogonal_ weight init crashes with geqrf_cuda not implemented for BFloat16 under v5 bf16 on-device init (RWKV and any QR-based init)

2 participants