KitsuVp commited on
Commit
6e488b2
·
verified ·
1 Parent(s): cc37174

Update modeling_neollm.py

Browse files
Files changed (1) hide show
  1. modeling_neollm.py +98 -18
modeling_neollm.py CHANGED
@@ -676,7 +676,9 @@ class VectorMultiplier(nn.Module):
676
  class LinearWithMultipliers(nn.Module):
677
  """
678
  Linear layer with optional row and/or column learnable multipliers.
679
- Implements: y = (r ⊙ (W @ (c ⊙ x))) + b
 
 
680
  """
681
  def __init__(
682
  self,
@@ -684,16 +686,18 @@ class LinearWithMultipliers(nn.Module):
684
  out_features: int,
685
  bias: bool = True,
686
  use_row_multiplier: bool = False,
687
- use_column_multiplier: bool = False
 
688
  ):
689
  super().__init__()
690
  self.linear = nn.Linear(in_features, out_features, bias=bias)
691
- self.use_row_multiplier = use_row_multiplier
692
- self.use_column_multiplier = use_column_multiplier
 
693
 
694
- if use_row_multiplier:
695
  self.row_multiplier = VectorMultiplier(out_features, multiplier_type="row")
696
- if use_column_multiplier:
697
  self.column_multiplier = VectorMultiplier(in_features, multiplier_type="column")
698
 
699
  def forward(self, x: torch.Tensor) -> torch.Tensor:
@@ -705,6 +709,53 @@ class LinearWithMultipliers(nn.Module):
705
  return x
706
 
707
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  # ==================== LEVIATHAN CONTINUOUS TOKEN GENERATOR ====================
709
 
710
  class LeviathanGenerator(nn.Module):
@@ -3204,7 +3255,9 @@ class NeoLLMAttention(nn.Module):
3204
 
3205
  o_proj variants (controlled by config.use_hadamard_o_proj):
3206
  False (default): dense LinearWithMultipliers — full expressivity,
3207
- develops high κ during training (FP8 risk).
 
 
3208
  True: HadamardOProj — fixed WHT + learnable α/β,
3209
  κ = 1 by construction, 25% fewer attention params,
3210
  FP8-friendly (Aggarwal & Kumar, 2026, arXiv:2603.08343).
@@ -3242,6 +3295,7 @@ class NeoLLMAttention(nn.Module):
3242
  getattr(config, "lucid_attention_eps", config.rms_norm_eps)
3243
  )
3244
  self.use_hadamard_o_proj = getattr(config, "use_hadamard_o_proj", False)
 
3245
 
3246
  self.fan_layer = FANLayer(
3247
  hidden_size=config.hidden_size,
@@ -3254,6 +3308,7 @@ class NeoLLMAttention(nn.Module):
3254
  self.q_proj = LinearWithMultipliers(
3255
  fan_output_dim, config.num_attention_heads * self.head_dim * 2,
3256
  bias=config.attention_bias, use_row_multiplier=True, use_column_multiplier=False,
 
3257
  )
3258
  self.num_mea_component_heads = (
3259
  self.mea_component_key_value_heads
@@ -3283,6 +3338,7 @@ class NeoLLMAttention(nn.Module):
3283
  self.o_proj = LinearWithMultipliers(
3284
  _o_in, config.hidden_size,
3285
  bias=config.attention_bias, use_row_multiplier=True, use_column_multiplier=True,
 
3286
  )
3287
 
3288
  self.q_norm = SeeDNorm(self.head_dim, eps=config.rms_norm_eps)
@@ -4800,11 +4856,13 @@ class VersatileFFN(nn.Module):
4800
  self.gate_proj = LinearWithMultipliers(
4801
  fan_dim, config.intermediate_size,
4802
  bias=False, use_row_multiplier=True, use_column_multiplier=False,
 
4803
  )
4804
  self.up_proj = nn.Linear(fan_dim, config.intermediate_size, bias=False)
4805
  self.down_proj = LinearWithMultipliers(
4806
  config.intermediate_size, config.hidden_size,
4807
  bias=False, use_row_multiplier=True, use_column_multiplier=True,
 
4808
  )
4809
  self.act_fn = PolyNorm(exclusive=False)
4810
  self.dropout = nn.Dropout(config.dropout_rate)
@@ -4868,10 +4926,11 @@ class VersatileFFN(nn.Module):
4868
 
4869
  Returns x_in + expert_out (residual included, matching Eq. 8).
4870
  """
4871
- # Gate projection: sliced rows + row multiplier
4872
- g_w = self.gate_proj.linear.weight[idx] # [seg, fan_dim]
4873
- g_mul = self.gate_proj.row_multiplier.multiplier[idx] # [seg]
4874
- gate = F.linear(x_fan, g_w) * g_mul # [N, seg]
 
4875
 
4876
  # Up projection: sliced rows, no multiplier on up_proj
4877
  u_w = self.up_proj.weight[idx] # [seg, fan_dim]
@@ -4881,11 +4940,13 @@ class VersatileFFN(nn.Module):
4881
  act = self.act_fn(gate) * up # [N, seg]
4882
  act = self.dropout(act)
4883
 
4884
- # Down projection: column multiplier on input, then row on output
4885
- col_mul = self.down_proj.column_multiplier.multiplier[idx] # [seg]
4886
- d_w = self.down_proj.linear.weight[:, idx] # [hidden, seg]
4887
- row_mul = self.down_proj.row_multiplier.multiplier # [hidden]
4888
- out = F.linear(act * col_mul, d_w) * row_mul # [N, hidden]
 
 
4889
 
4890
  return x_in + out
4891
 
@@ -5186,11 +5247,13 @@ class NeoLLMMLP(nn.Module):
5186
  self.gate_proj = LinearWithMultipliers(
5187
  fan_dim, config.intermediate_size,
5188
  bias=False, use_row_multiplier=True, use_column_multiplier=False,
 
5189
  )
5190
  self.up_proj = nn.Linear(fan_dim, config.intermediate_size, bias=False)
5191
  self.down_proj = LinearWithMultipliers(
5192
  config.intermediate_size, config.hidden_size,
5193
  bias=False, use_row_multiplier=True, use_column_multiplier=True,
 
5194
  )
5195
  self.act_fn = PolyNorm(exclusive_init=0.00, exclusive=getattr(config, "polynorm_exclusive", True))
5196
  self.dropout = nn.Dropout(config.dropout_rate)
@@ -6179,6 +6242,10 @@ class NeoLLMPreTrainedModel(PreTrainedModel):
6179
  if hasattr(module, "multiplier"):
6180
  module.multiplier.data.fill_(1.0)
6181
 
 
 
 
 
6182
  elif isinstance(module, LeviathanGenerator):
6183
  nn.init.normal_(module.codebooks,
6184
  mean=0.0, std=self.config.initializer_range)
@@ -6297,9 +6364,22 @@ class NeoLLMModel(NeoLLMPreTrainedModel):
6297
  if config.use_token_generator:
6298
  self.token_generator = LeviathanGenerator(config)
6299
  else:
6300
- self.embed_tokens = nn.Embedding(
6301
- config.vocab_size, config.hidden_size, config.pad_token_id
 
 
6302
  )
 
 
 
 
 
 
 
 
 
 
 
6303
 
6304
  # ── Spelling Bee Embeddings (Rabe et al., 2026) ───────────────────────
6305
  # Active when use_spelling_bee_embeddings=True, compatible with both
 
676
  class LinearWithMultipliers(nn.Module):
677
  """
678
  Linear layer with optional row and/or column learnable multipliers.
679
+ Implements: y = (r ⊙ (W @ (c ⊙ x))) + b when enabled.
680
+ With ``enable_multipliers=False`` no multiplier parameters are instantiated
681
+ and the module reduces to its wrapped ``nn.Linear``.
682
  """
683
  def __init__(
684
  self,
 
686
  out_features: int,
687
  bias: bool = True,
688
  use_row_multiplier: bool = False,
689
+ use_column_multiplier: bool = False,
690
+ enable_multipliers: bool = True,
691
  ):
692
  super().__init__()
693
  self.linear = nn.Linear(in_features, out_features, bias=bias)
694
+ self.enable_multipliers = bool(enable_multipliers)
695
+ self.use_row_multiplier = bool(use_row_multiplier and self.enable_multipliers)
696
+ self.use_column_multiplier = bool(use_column_multiplier and self.enable_multipliers)
697
 
698
+ if self.use_row_multiplier:
699
  self.row_multiplier = VectorMultiplier(out_features, multiplier_type="row")
700
+ if self.use_column_multiplier:
701
  self.column_multiplier = VectorMultiplier(in_features, multiplier_type="column")
702
 
703
  def forward(self, x: torch.Tensor) -> torch.Tensor:
 
709
  return x
710
 
711
 
712
+
713
+ class EmbeddingWithMultipliers(nn.Module):
714
+ """
715
+ Token embedding matrix with optional vocabulary-row and hidden-channel
716
+ learnable multipliers.
717
+
718
+ Effective embedding:
719
+ E_eff[token, channel] = r_token * E[token, channel] * c_channel
720
+
721
+ This mirrors the Learnable Multipliers paper's embedding recommendation,
722
+ while keeping the actual weight available as ``.weight`` for tooling that
723
+ expects a standard ``nn.Embedding``-like object. It is only intended for
724
+ the untied, non-generator embedding path.
725
+ """
726
+ def __init__(
727
+ self,
728
+ num_embeddings: int,
729
+ embedding_dim: int,
730
+ padding_idx: Optional[int] = None,
731
+ enable_multipliers: bool = True,
732
+ ):
733
+ super().__init__()
734
+ self.embedding = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx)
735
+ self.num_embeddings = num_embeddings
736
+ self.embedding_dim = embedding_dim
737
+ self.padding_idx = padding_idx
738
+ self.enable_multipliers = bool(enable_multipliers)
739
+ self.use_row_multiplier = self.enable_multipliers
740
+ self.use_column_multiplier = self.enable_multipliers
741
+
742
+ if self.enable_multipliers:
743
+ self.row_multiplier = nn.Parameter(torch.ones(num_embeddings))
744
+ self.column_multiplier = VectorMultiplier(embedding_dim, multiplier_type="column")
745
+
746
+ @property
747
+ def weight(self) -> torch.nn.Parameter:
748
+ return self.embedding.weight
749
+
750
+ def forward(self, input_ids: torch.Tensor) -> torch.Tensor:
751
+ x = self.embedding(input_ids)
752
+ if self.use_column_multiplier:
753
+ x = self.column_multiplier(x)
754
+ if self.use_row_multiplier:
755
+ row_scale = F.embedding(input_ids, self.row_multiplier.unsqueeze(-1)).to(dtype=x.dtype)
756
+ x = x * row_scale
757
+ return x
758
+
759
  # ==================== LEVIATHAN CONTINUOUS TOKEN GENERATOR ====================
760
 
761
  class LeviathanGenerator(nn.Module):
 
3255
 
3256
  o_proj variants (controlled by config.use_hadamard_o_proj):
3257
  False (default): dense LinearWithMultipliers — full expressivity,
3258
+ with Learnable Multipliers controlled by
3259
+ config.use_learnable_multipliers; develops high κ
3260
+ during training (FP8 risk).
3261
  True: HadamardOProj — fixed WHT + learnable α/β,
3262
  κ = 1 by construction, 25% fewer attention params,
3263
  FP8-friendly (Aggarwal & Kumar, 2026, arXiv:2603.08343).
 
3295
  getattr(config, "lucid_attention_eps", config.rms_norm_eps)
3296
  )
3297
  self.use_hadamard_o_proj = getattr(config, "use_hadamard_o_proj", False)
3298
+ self.use_learnable_multipliers = getattr(config, "use_learnable_multipliers", True)
3299
 
3300
  self.fan_layer = FANLayer(
3301
  hidden_size=config.hidden_size,
 
3308
  self.q_proj = LinearWithMultipliers(
3309
  fan_output_dim, config.num_attention_heads * self.head_dim * 2,
3310
  bias=config.attention_bias, use_row_multiplier=True, use_column_multiplier=False,
3311
+ enable_multipliers=self.use_learnable_multipliers,
3312
  )
3313
  self.num_mea_component_heads = (
3314
  self.mea_component_key_value_heads
 
3338
  self.o_proj = LinearWithMultipliers(
3339
  _o_in, config.hidden_size,
3340
  bias=config.attention_bias, use_row_multiplier=True, use_column_multiplier=True,
3341
+ enable_multipliers=self.use_learnable_multipliers,
3342
  )
3343
 
3344
  self.q_norm = SeeDNorm(self.head_dim, eps=config.rms_norm_eps)
 
4856
  self.gate_proj = LinearWithMultipliers(
4857
  fan_dim, config.intermediate_size,
4858
  bias=False, use_row_multiplier=True, use_column_multiplier=False,
4859
+ enable_multipliers=getattr(config, "use_learnable_multipliers", True),
4860
  )
4861
  self.up_proj = nn.Linear(fan_dim, config.intermediate_size, bias=False)
4862
  self.down_proj = LinearWithMultipliers(
4863
  config.intermediate_size, config.hidden_size,
4864
  bias=False, use_row_multiplier=True, use_column_multiplier=True,
4865
+ enable_multipliers=getattr(config, "use_learnable_multipliers", True),
4866
  )
4867
  self.act_fn = PolyNorm(exclusive=False)
4868
  self.dropout = nn.Dropout(config.dropout_rate)
 
4926
 
4927
  Returns x_in + expert_out (residual included, matching Eq. 8).
4928
  """
4929
+ # Gate projection: sliced rows + optional row multiplier
4930
+ g_w = self.gate_proj.linear.weight[idx] # [seg, fan_dim]
4931
+ gate = F.linear(x_fan, g_w) # [N, seg]
4932
+ if self.gate_proj.use_row_multiplier:
4933
+ gate = gate * self.gate_proj.row_multiplier.multiplier[idx]
4934
 
4935
  # Up projection: sliced rows, no multiplier on up_proj
4936
  u_w = self.up_proj.weight[idx] # [seg, fan_dim]
 
4940
  act = self.act_fn(gate) * up # [N, seg]
4941
  act = self.dropout(act)
4942
 
4943
+ # Down projection: optional column multiplier on input, optional row on output
4944
+ d_w = self.down_proj.linear.weight[:, idx] # [hidden, seg]
4945
+ if self.down_proj.use_column_multiplier:
4946
+ act = act * self.down_proj.column_multiplier.multiplier[idx]
4947
+ out = F.linear(act, d_w) # [N, hidden]
4948
+ if self.down_proj.use_row_multiplier:
4949
+ out = out * self.down_proj.row_multiplier.multiplier
4950
 
4951
  return x_in + out
4952
 
 
5247
  self.gate_proj = LinearWithMultipliers(
5248
  fan_dim, config.intermediate_size,
5249
  bias=False, use_row_multiplier=True, use_column_multiplier=False,
5250
+ enable_multipliers=getattr(config, "use_learnable_multipliers", True),
5251
  )
5252
  self.up_proj = nn.Linear(fan_dim, config.intermediate_size, bias=False)
5253
  self.down_proj = LinearWithMultipliers(
5254
  config.intermediate_size, config.hidden_size,
5255
  bias=False, use_row_multiplier=True, use_column_multiplier=True,
5256
+ enable_multipliers=getattr(config, "use_learnable_multipliers", True),
5257
  )
5258
  self.act_fn = PolyNorm(exclusive_init=0.00, exclusive=getattr(config, "polynorm_exclusive", True))
5259
  self.dropout = nn.Dropout(config.dropout_rate)
 
6242
  if hasattr(module, "multiplier"):
6243
  module.multiplier.data.fill_(1.0)
6244
 
6245
+ elif isinstance(module, EmbeddingWithMultipliers):
6246
+ if hasattr(module, "row_multiplier"):
6247
+ module.row_multiplier.data.fill_(1.0)
6248
+
6249
  elif isinstance(module, LeviathanGenerator):
6250
  nn.init.normal_(module.codebooks,
6251
  mean=0.0, std=self.config.initializer_range)
 
6364
  if config.use_token_generator:
6365
  self.token_generator = LeviathanGenerator(config)
6366
  else:
6367
+ use_embedding_multipliers = (
6368
+ bool(getattr(config, "use_learnable_multipliers", True))
6369
+ and bool(getattr(config, "use_embedding_multipliers", True))
6370
+ and not bool(getattr(config, "tie_word_embeddings", False))
6371
  )
6372
+ if use_embedding_multipliers:
6373
+ self.embed_tokens = EmbeddingWithMultipliers(
6374
+ config.vocab_size,
6375
+ config.hidden_size,
6376
+ padding_idx=config.pad_token_id,
6377
+ enable_multipliers=True,
6378
+ )
6379
+ else:
6380
+ self.embed_tokens = nn.Embedding(
6381
+ config.vocab_size, config.hidden_size, config.pad_token_id
6382
+ )
6383
 
6384
  # ── Spelling Bee Embeddings (Rabe et al., 2026) ───────────────────────
6385
  # Active when use_spelling_bee_embeddings=True, compatible with both