Skip to content

Commit bfdfe10

Browse files
authored
Fix zero-centered gamma parity for ET RMSNorm (pytorch#23193)
Summary: Preserve zero-centered gamma semantics for transformer block and output RMSNorms in both ExecuTorch and rlformers ET paths while leaving Q/K norms unchanged. Preserve output_norm_gain_center_type so center-zero output weights are not shifted. Authored with assistance from Codex. Differential Revision: D121895059 Pull Request resolved: pytorch#23193
1 parent 5bea649 commit bfdfe10

4 files changed

Lines changed: 53 additions & 6 deletions

File tree

‎examples/models/llama/llama_transformer.py‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,13 +227,17 @@ def __init__(
227227
self.attention_norm = RMSNorm(
228228
args.dim,
229229
eps=args.norm_eps,
230-
add_unit_offset=args.rms_norm_add_unit_offset,
230+
add_unit_offset=(
231+
args.rms_norm_add_unit_offset or args.norm_zero_centered_gamma
232+
),
231233
)
232234
if self.mlp_type != "skip":
233235
self.ffn_norm = RMSNorm(
234236
args.dim,
235237
eps=args.norm_eps,
236-
add_unit_offset=args.rms_norm_add_unit_offset,
238+
add_unit_offset=(
239+
args.rms_norm_add_unit_offset or args.norm_zero_centered_gamma
240+
),
237241
)
238242

239243
if args.use_residual_gate:
@@ -346,7 +350,13 @@ def __init__(self, params: ModelArgs, layers: nn.ModuleList, rope: Rope):
346350
self.norm = RMSNorm(
347351
params.dim,
348352
eps=params.norm_eps,
349-
add_unit_offset=params.rms_norm_add_unit_offset,
353+
add_unit_offset=(
354+
params.rms_norm_add_unit_offset
355+
or (
356+
params.norm_zero_centered_gamma
357+
and params.output_norm_gain_center_type != "zero"
358+
)
359+
),
350360
)
351361
self.output = (
352362
nn.Linear(params.dim, params.vocab_size, bias=False)

‎examples/models/llama/model_args.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ class ModelArgs:
195195
# effective scale is ``weight + 1``. rlformers applies this in
196196
# RMSNormWithInputScale; ignoring it silently rescales every post-FFN norm.
197197
norm_zero_centered_gamma: bool = False
198+
output_norm_gain_center_type: str = "one"
198199
output_soft_cap_temp: Optional[float] = None
199200
output_linear_intermediate_dim: int = 0
200201

‎examples/models/llama/norm.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def forward(self, x):
5555

5656

5757
class RMSNormCoreML(torch.nn.Module):
58-
def __init__(self, dim: int, eps: float = 1e-6):
58+
def __init__(self, dim: int, eps: float = 1e-6, add_unit_offset: bool = False):
5959
"""
6060
CoreML-friendly RMSNorm — uses `torch.linalg.vector_norm` so the op is
6161
preserved in the CoreML graph for numerical stability.
@@ -78,6 +78,7 @@ def __init__(self, dim: int, eps: float = 1e-6):
7878
)
7979
self.dim = dim
8080
self.eps = eps
81+
self.add_unit_offset = add_unit_offset
8182
self.weight = nn.Parameter(torch.ones(dim))
8283

8384
def _norm(self, x):
@@ -99,7 +100,7 @@ def _norm(self, x):
99100

100101
def forward(self, x):
101102
output = self._norm(x)
102-
return output * self.weight
103+
return output * (1.0 + self.weight if self.add_unit_offset else self.weight)
103104

104105

105106
class RMSNormWithInputScale(torch.nn.Module):

‎examples/models/llama/tests/test_transformer_block.py‎

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,46 @@
88

99
import torch
1010
from executorch.examples.models.llama.attention import AttentionSkip
11-
from executorch.examples.models.llama.llama_transformer import TransformerBlock
11+
from executorch.examples.models.llama.llama_transformer import (
12+
Transformer,
13+
TransformerBlock,
14+
)
1215
from executorch.examples.models.llama.model_args import ModelArgs
16+
from executorch.examples.models.llama.rope import Rope
1317

1418

1519
class TestTransformerBlock(unittest.TestCase):
20+
def test_zero_centered_gamma_applies_to_main_norms(self) -> None:
21+
args = ModelArgs(
22+
dim=4,
23+
hidden_dim=8,
24+
n_heads=1,
25+
n_kv_heads=1,
26+
head_dim=4,
27+
norm_zero_centered_gamma=True,
28+
)
29+
block = TransformerBlock(args, AttentionSkip()).eval()
30+
model = Transformer(args, torch.nn.ModuleList([block]), Rope(args)).eval()
31+
32+
self.assertTrue(block.ffn_norm.add_unit_offset)
33+
self.assertTrue(model.norm.add_unit_offset)
34+
35+
center_zero_args = ModelArgs(
36+
dim=4,
37+
hidden_dim=8,
38+
n_heads=1,
39+
n_kv_heads=1,
40+
head_dim=4,
41+
norm_zero_centered_gamma=True,
42+
output_norm_gain_center_type="zero",
43+
)
44+
center_zero_model = Transformer(
45+
center_zero_args,
46+
torch.nn.ModuleList(),
47+
Rope(center_zero_args),
48+
).eval()
49+
self.assertFalse(center_zero_model.norm.add_unit_offset)
50+
1651
def test_attention_skip_applies_gated_zero_branch_residual(self) -> None:
1752
args = ModelArgs(
1853
dim=4,

0 commit comments

Comments
 (0)