Linear-50M-exp / modeling_linear_50m.py
User01110's picture
step 0
4c0a0c6 verified
Raw
History Blame Contribute Delete
9.96 kB
import math
import torch
import torch.nn.functional as F
from einops import rearrange
from torch import nn
from transformers import PreTrainedModel, PretrainedConfig
from transformers.modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
try:
from fla.layers.utils import get_layer_cache, update_layer_cache
from fla.models.utils import Cache, FLAUnsupportedCacheGenerationMixin
from fla.modules import FusedRMSNormSwishGate, RMSNorm, ShortConvolution
from fla.ops.gdn2 import chunk_gdn2, fused_recurrent_gdn2
except (ImportError, AttributeError) as e:
raise ImportError('Linear-50M requires a current CUDA build of flash-linear-attention: pip install "flash-linear-attention[cuda]"') from e
class Linear50MConfig(PretrainedConfig):
model_type = "linear_50m"
def __init__(self, vocab_size=32000, hidden_size=384, num_hidden_layers=16, num_heads=6,
head_dim=64, intermediate_size=1120, conv_size=4, norm_eps=1e-5,
max_position_embeddings=4096, use_cache=True, **kwargs):
for key, value in dict(bos_token_id=1, eos_token_id=2, pad_token_id=2,
tie_word_embeddings=True).items(): kwargs.setdefault(key, value)
super().__init__(**kwargs); self.vocab_size, self.hidden_size, self.num_hidden_layers = vocab_size, hidden_size, num_hidden_layers
self.num_heads, self.head_dim, self.intermediate_size = num_heads, head_dim, intermediate_size
self.conv_size, self.norm_eps, self.max_position_embeddings, self.use_cache = conv_size, norm_eps, max_position_embeddings, use_cache
class NotGDN2(nn.Module):
def __init__(self, c, layer_idx):
super().__init__(); d, h, hd = c.hidden_size, c.num_heads, c.head_dim; self.h, self.hd, self.layer_idx = h, hd, layer_idx
self.qkv = nn.Linear(d, 3*d, bias=False); self.conv = ShortConvolution(3*d, c.conv_size, bias=False, activation="silu")
self.f = nn.Sequential(nn.Linear(d, hd, False), nn.Linear(hd, d, False)); self.bw = nn.Linear(d, 2*d, bias=False)
self.gate = nn.Sequential(nn.Linear(d, hd, False), nn.Linear(hd, d, True)); self.recover = nn.Sequential(nn.Linear(d, hd, False), nn.Linear(hd, d, True))
self.A_log = nn.Parameter(torch.empty(h).uniform_(1, 16).log()); dt = torch.exp(torch.empty(d).uniform_(math.log(.001), math.log(.1)))
self.dt_bias = nn.Parameter(dt + torch.log(-torch.expm1(-dt))); self.A_log._no_weight_decay = self.dt_bias._no_weight_decay = True
self.norm = FusedRMSNormSwishGate(hd, eps=c.norm_eps); self.out = nn.Linear(d, d, bias=False)
self.apply(self._init)
for weight, parts in ((self.qkv.weight, 3), (self.bw.weight, 2)):
for part in weight.chunk(parts, 0): nn.init.xavier_uniform_(part, gain=2**-2.5)
nn.init.zeros_(self.recover[-1].weight); nn.init.zeros_(self.recover[-1].bias)
@staticmethod
def _init(m):
if getattr(m, "_is_hf_initialized", False): return
if isinstance(m, nn.Linear):
nn.init.xavier_uniform_(m.weight, gain=2**-2.5)
if m.bias is not None: nn.init.zeros_(m.bias)
m._is_hf_initialized = True
def forward(self, x, attention_mask=None, past_key_values=None, use_cache=False, **kwargs):
length = x.shape[1]; last = get_layer_cache(self, past_key_values); conv = None if last is None else last["conv_state"]; cu = kwargs.get("cu_seqlens")
qkv, conv = self.conv(self.qkv(x), cache=conv, output_final_state=use_cache, cu_seqlens=cu)
q, k, v = (rearrange(z, "b t (h d) -> b t h d", h=self.h) for z in qkv.chunk(3, -1))
g = rearrange(-self.A_log.float().exp().repeat_interleave(self.hd) *
F.softplus(self.f(x).float() + self.dt_bias.float()),
"b t (h d) -> b t h d", h=self.h)
b, w = (rearrange(z.sigmoid(), "b t (h d) -> b t h d", h=self.h) for z in self.bw(x).chunk(2, -1))
state = None if last is None else last["recurrent_state"]
op = fused_recurrent_gdn2 if use_cache and not self.training and not torch.is_grad_enabled() and x.shape[1] <= 64 else chunk_gdn2
both, state = op(*(torch.cat(z, 2) for z in ((q, q), (k, k), (v, v),
(g, torch.zeros_like(g)), (b, torch.zeros_like(b)), (w, w))),
scale=self.hd**-.5, initial_state=state, output_final_state=use_cache,
use_qk_l2norm_in_kernel=True, use_gate_in_kernel=False, cu_seqlens=cu)
a, archive = both.chunk(2, 2); protected = archive-a
support = protected*((a.float().square().mean(-1, True)+1e-6)/(protected.float().square().mean(-1, True)+1e-6)).sqrt().to(protected)
theta = rearrange(self.recover(x), "b t (h d) -> b t h d", h=self.h); o = a + theta.sin()*support
if use_cache: update_layer_cache(self, past_key_values, recurrent_state=state, conv_state=conv, offset=length)
z = rearrange(self.gate(x), "b t (h d) -> b t h d", h=self.h); return self.out(rearrange(self.norm(o, z), "b t h d -> b t (h d)"))
class SwiGLU(nn.Module):
def __init__(self, c): super().__init__(); self.up, self.down = nn.Linear(c.hidden_size, 2*c.intermediate_size, False), nn.Linear(c.intermediate_size, c.hidden_size, False)
def forward(self, x): a, b = self.up(x).chunk(2, -1); return self.down(F.silu(a)*b)
class Block(nn.Module):
def __init__(self, c, i): super().__init__(); self.n1, self.mix, self.n2, self.mlp = RMSNorm(c.hidden_size), NotGDN2(c, i), RMSNorm(c.hidden_size), SwiGLU(c)
def forward(self, x, attention_mask=None, past_key_values=None, use_cache=False, **kwargs):
x = x + self.mix(self.n1(x), attention_mask, past_key_values, use_cache, **kwargs); return x + self.mlp(self.n2(x))
class Linear50MPreTrainedModel(PreTrainedModel):
config_class, base_model_prefix, _supports_cache_class, _no_split_modules = Linear50MConfig, "model", True, ["Block"]
def _init_weights(self, m):
if getattr(m, "_is_hf_initialized", False): return
if isinstance(m, (nn.Linear, nn.Embedding)):
nn.init.normal_(m.weight, std=.02)
if getattr(m, "bias", None) is not None: nn.init.zeros_(m.bias)
class Linear50MModel(Linear50MPreTrainedModel):
def __init__(self, config):
super().__init__(config); self.embed = nn.Embedding(config.vocab_size, config.hidden_size); self.blocks = nn.ModuleList(Block(config, i) for i in range(config.num_hidden_layers)); self.norm = RMSNorm(config.hidden_size); self.post_init()
def get_input_embeddings(self): return self.embed
def set_input_embeddings(self, value): self.embed = value
def forward(self, input_ids=None, attention_mask=None, inputs_embeds=None, past_key_values=None, use_cache=None,
output_hidden_states=None, return_dict=None, **kwargs):
if (input_ids is None) == (inputs_embeds is None): raise ValueError("Pass exactly one of input_ids or inputs_embeds")
x = self.embed(input_ids) if inputs_embeds is None else inputs_embeds
if x.device.type != "cuda": raise RuntimeError("Linear-50M currently requires CUDA/FLA inference")
if attention_mask is not None:
if past_key_values is None and not bool(attention_mask.all()): raise ValueError("Variable-length padded batches are not supported yet")
attention_mask = None
output_hidden_states = self.config.output_hidden_states if output_hidden_states is None else output_hidden_states
return_dict = self.config.return_dict if return_dict is None else return_dict
use_cache = getattr(self.config, "use_cache", True) if use_cache is None and not self.training else bool(use_cache)
if use_cache and not isinstance(past_key_values, Cache): past_key_values = Cache.from_legacy_cache(past_key_values)
hidden = () if output_hidden_states else None
for block in self.blocks:
if output_hidden_states: hidden += (x,)
x = block(x, attention_mask, past_key_values, use_cache, **kwargs)
x = self.norm(x)
if output_hidden_states: hidden += (x,)
if not return_dict: return tuple(v for v in (x, past_key_values, hidden) if v is not None)
return BaseModelOutputWithPast(last_hidden_state=x, past_key_values=past_key_values, hidden_states=hidden)
class Linear50MForCausalLM(Linear50MPreTrainedModel, FLAUnsupportedCacheGenerationMixin):
_tied_weights_keys = {"lm_head.weight": "model.embed.weight"}
def __init__(self, config): super().__init__(config); self.model = Linear50MModel(config); self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False); self.post_init()
def get_input_embeddings(self): return self.model.embed
def set_input_embeddings(self, value): self.model.embed = value
def get_output_embeddings(self): return self.lm_head
def set_output_embeddings(self, value): self.lm_head = value
def get_decoder(self): return self.model
def set_decoder(self, value): self.model = value
def forward(self, input_ids=None, attention_mask=None, inputs_embeds=None, past_key_values=None, labels=None,
use_cache=None, output_hidden_states=None, return_dict=None, logits_to_keep=0, **kwargs):
return_dict = self.config.return_dict if return_dict is None else return_dict
out = self.model(input_ids, attention_mask, inputs_embeds, past_key_values, use_cache, output_hidden_states, return_dict, **kwargs); h = out[0]
logits = self.lm_head(h if labels is not None or not logits_to_keep else h[:, -logits_to_keep:]); loss = None
if labels is not None: loss = F.cross_entropy(logits[:, :-1].float().flatten(0, 1), labels[:, 1:].flatten(), ignore_index=-100)
if not return_dict: return ((loss,) if loss is not None else ()) + (logits,) + out[1:]
return CausalLMOutputWithPast(loss=loss, logits=logits, past_key_values=out.past_key_values, hidden_states=out.hidden_states)