Download src/model.py from CNWPlayer/VegaLM1-42M-Base: direct link, hf CLI and curl.
- Browser
- Download file 7.65 kB
-
https://huggingface.co/CNWPlayer/VegaLM1-42M-Base/resolve/main/src/model.py
- Command line
-
hf download hf://CNWPlayer/VegaLM1-42M-Base/src/model.py
-
curl -L -o model.py https://huggingface.co/CNWPlayer/VegaLM1-42M-Base/resolve/main/src/model.py
7.65 kB
| import math | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| class RMSNorm(nn.Module): | |
| def __init__(self, dim, eps=1e-6): | |
| super().__init__() | |
| self.weight = nn.Parameter(torch.ones(dim)) | |
| self.eps = eps | |
| def forward(self, x): | |
| variance = x.float().pow(2).mean(-1, keepdim=True) | |
| x = x * torch.rsqrt(variance + self.eps) | |
| return self.weight * x | |
| def rotate_half(x): | |
| x1 = x[..., : x.shape[-1] // 2] | |
| x2 = x[..., x.shape[-1] // 2 :] | |
| return torch.cat((-x2, x1), dim=-1) | |
| def apply_rope(x, cos, sin): | |
| return (x * cos) + (rotate_half(x) * sin) | |
| class RotaryEmbedding(nn.Module): | |
| def __init__(self, head_dim, max_seq_len, base=10000.0): | |
| super().__init__() | |
| inv_freq = 1.0 / ( | |
| base ** ( | |
| torch.arange(0, head_dim, 2).float() / head_dim | |
| ) | |
| ) | |
| self.register_buffer("inv_freq", inv_freq, persistent=False) | |
| positions = torch.arange(max_seq_len).float() | |
| freqs = torch.outer(positions, inv_freq) | |
| emb = torch.cat((freqs, freqs), dim=-1) | |
| self.register_buffer( | |
| "cos_cached", | |
| emb.cos()[None, None, :, :], | |
| persistent=False, | |
| ) | |
| self.register_buffer( | |
| "sin_cached", | |
| emb.sin()[None, None, :, :], | |
| persistent=False, | |
| ) | |
| def forward(self, seq_len): | |
| return ( | |
| self.cos_cached[:, :, :seq_len, :], | |
| self.sin_cached[:, :, :seq_len, :], | |
| ) | |
| class SwiGLU(nn.Module): | |
| def __init__(self, hidden_size, intermediate_size): | |
| super().__init__() | |
| self.gate_proj = nn.Linear( | |
| hidden_size, | |
| intermediate_size, | |
| bias=False, | |
| ) | |
| self.up_proj = nn.Linear( | |
| hidden_size, | |
| intermediate_size, | |
| bias=False, | |
| ) | |
| self.down_proj = nn.Linear( | |
| intermediate_size, | |
| hidden_size, | |
| bias=False, | |
| ) | |
| def forward(self, x): | |
| return self.down_proj( | |
| F.silu(self.gate_proj(x)) * self.up_proj(x) | |
| ) | |
| class GQAttention(nn.Module): | |
| def __init__( | |
| self, | |
| hidden_size, | |
| num_heads, | |
| num_kv_heads, | |
| max_seq_len, | |
| ): | |
| super().__init__() | |
| assert hidden_size % num_heads == 0 | |
| self.num_heads = num_heads | |
| self.num_kv_heads = num_kv_heads | |
| self.head_dim = hidden_size // num_heads | |
| assert num_heads % num_kv_heads == 0 | |
| self.q_proj = nn.Linear( | |
| hidden_size, | |
| num_heads * self.head_dim, | |
| bias=False, | |
| ) | |
| self.k_proj = nn.Linear( | |
| hidden_size, | |
| num_kv_heads * self.head_dim, | |
| bias=False, | |
| ) | |
| self.v_proj = nn.Linear( | |
| hidden_size, | |
| num_kv_heads * self.head_dim, | |
| bias=False, | |
| ) | |
| self.o_proj = nn.Linear( | |
| hidden_size, | |
| hidden_size, | |
| bias=False, | |
| ) | |
| self.rope = RotaryEmbedding( | |
| self.head_dim, | |
| max_seq_len, | |
| ) | |
| def forward(self, x): | |
| batch, seq_len, hidden = x.shape | |
| q = self.q_proj(x) | |
| k = self.k_proj(x) | |
| v = self.v_proj(x) | |
| q = q.view( | |
| batch, | |
| seq_len, | |
| self.num_heads, | |
| self.head_dim, | |
| ).transpose(1, 2) | |
| k = k.view( | |
| batch, | |
| seq_len, | |
| self.num_kv_heads, | |
| self.head_dim, | |
| ).transpose(1, 2) | |
| v = v.view( | |
| batch, | |
| seq_len, | |
| self.num_kv_heads, | |
| self.head_dim, | |
| ).transpose(1, 2) | |
| cos, sin = self.rope(seq_len) | |
| q = apply_rope(q, cos, sin) | |
| k = apply_rope(k, cos, sin) | |
| # Repeat KV heads for grouped-query attention. | |
| repeat_factor = self.num_heads // self.num_kv_heads | |
| k = k.repeat_interleave( | |
| repeat_factor, | |
| dim=1, | |
| ) | |
| v = v.repeat_interleave( | |
| repeat_factor, | |
| dim=1, | |
| ) | |
| y = F.scaled_dot_product_attention( | |
| q, | |
| k, | |
| v, | |
| is_causal=True, | |
| ) | |
| y = y.transpose(1, 2).contiguous() | |
| y = y.view( | |
| batch, | |
| seq_len, | |
| hidden, | |
| ) | |
| return self.o_proj(y) | |
| class TransformerBlock(nn.Module): | |
| def __init__( | |
| self, | |
| hidden_size, | |
| num_heads, | |
| num_kv_heads, | |
| intermediate_size, | |
| max_seq_len, | |
| ): | |
| super().__init__() | |
| self.attn_norm = RMSNorm(hidden_size) | |
| self.attn = GQAttention( | |
| hidden_size, | |
| num_heads, | |
| num_kv_heads, | |
| max_seq_len, | |
| ) | |
| self.ffn_norm = RMSNorm(hidden_size) | |
| self.ffn = SwiGLU( | |
| hidden_size, | |
| intermediate_size, | |
| ) | |
| def forward(self, x): | |
| x = x + self.attn( | |
| self.attn_norm(x) | |
| ) | |
| x = x + self.ffn( | |
| self.ffn_norm(x) | |
| ) | |
| return x | |
| class VegaLM(nn.Module): | |
| def __init__( | |
| self, | |
| vocab_size=32000, | |
| hidden_size=512, | |
| num_layers=12, | |
| num_heads=8, | |
| num_kv_heads=4, | |
| intermediate_size=880, | |
| max_seq_len=2048, | |
| ): | |
| super().__init__() | |
| self.vocab_size = vocab_size | |
| self.hidden_size = hidden_size | |
| self.token_embedding = nn.Embedding( | |
| vocab_size, | |
| hidden_size, | |
| ) | |
| self.layers = nn.ModuleList( | |
| [ | |
| TransformerBlock( | |
| hidden_size=hidden_size, | |
| num_heads=num_heads, | |
| num_kv_heads=num_kv_heads, | |
| intermediate_size=intermediate_size, | |
| max_seq_len=max_seq_len, | |
| ) | |
| for _ in range(num_layers) | |
| ] | |
| ) | |
| self.final_norm = RMSNorm(hidden_size) | |
| self.lm_head = nn.Linear( | |
| hidden_size, | |
| vocab_size, | |
| bias=False, | |
| ) | |
| # Tie input embeddings and output projection. | |
| self.lm_head.weight = self.token_embedding.weight | |
| self.apply(self._init_weights) | |
| def _init_weights(self, module): | |
| if isinstance(module, nn.Linear): | |
| nn.init.normal_( | |
| module.weight, | |
| mean=0.0, | |
| std=0.02, | |
| ) | |
| elif isinstance(module, nn.Embedding): | |
| nn.init.normal_( | |
| module.weight, | |
| mean=0.0, | |
| std=0.02, | |
| ) | |
| def forward(self, input_ids, targets=None): | |
| x = self.token_embedding(input_ids) | |
| for layer in self.layers: | |
| x = layer(x) | |
| x = self.final_norm(x) | |
| logits = self.lm_head(x) | |
| loss = None | |
| if targets is not None: | |
| loss = F.cross_entropy( | |
| logits.view(-1, self.vocab_size), | |
| targets.view(-1), | |
| ) | |
| return logits, loss | |
| def count_parameters(model): | |
| return sum( | |
| p.numel() | |
| for p in model.parameters() | |
| if p.requires_grad | |
| ) | |
| if __name__ == "__main__": | |
| model = VegaLM() | |
| params = count_parameters(model) | |
| print(f"Parameters: {params:,}") | |
| print(f"Parameters: {params / 1e6:.2f}M") | |
| x = torch.randint( | |
| 0, | |
| 32000, | |
| (2, 128), | |
| ) | |
| logits, _ = model(x) | |
| print(f"Input: {x.shape}") | |
| print(f"Output: {logits.shape}") | |