Download tiny_english/model.py from helloboy91/tiny-base-300m: direct link, hf CLI and curl.
- Browser
- Download file 4.73 kB
-
https://huggingface.co/helloboy91/tiny-base-300m/resolve/main/tiny_english/model.py
- Command line
-
hf download hf://helloboy91/tiny-base-300m/tiny_english/model.py
-
curl -L -o model.py https://huggingface.co/helloboy91/tiny-base-300m/resolve/main/tiny_english/model.py
4.73 kB
| from dataclasses import asdict, dataclass | |
| import torch | |
| from torch import nn | |
| from torch.nn import functional as functional | |
| from torch.utils.checkpoint import checkpoint | |
| class ModelConfig: | |
| vocab_size: int = 8192 | |
| context_length: int = 1024 | |
| layers: int = 8 | |
| hidden_size: int = 512 | |
| heads: int = 8 | |
| intermediate_size: int = 1408 | |
| def __post_init__(self): | |
| if any(value <= 0 for value in asdict(self).values()): | |
| raise ValueError("All model dimensions must be positive") | |
| if self.hidden_size % self.heads or (self.hidden_size // self.heads) % 2: | |
| raise ValueError("Head dimension must be an even integer") | |
| class Attention(nn.Module): | |
| def __init__(self, config): | |
| super().__init__() | |
| self.heads = config.heads | |
| self.head_size = config.hidden_size // config.heads | |
| self.qkv = nn.Linear(config.hidden_size, 3 * config.hidden_size, bias=False) | |
| self.output = nn.Linear(config.hidden_size, config.hidden_size, bias=False) | |
| frequencies = 1.0 / (10000 ** (torch.arange(0, self.head_size, 2).float() / self.head_size)) | |
| angles = torch.outer(torch.arange(config.context_length).float(), frequencies) | |
| self.register_buffer("cosines", angles.cos(), persistent=False) | |
| self.register_buffer("sines", angles.sin(), persistent=False) | |
| def rotate(self, tensor): | |
| length = tensor.size(-2) | |
| cosines = self.cosines[:length].to(tensor.dtype) | |
| sines = self.sines[:length].to(tensor.dtype) | |
| even, odd = tensor[..., 0::2], tensor[..., 1::2] | |
| return torch.stack((even * cosines - odd * sines, even * sines + odd * cosines), dim=-1).flatten(-2) | |
| def forward(self, hidden): | |
| batch_size, length, width = hidden.shape | |
| query, key, value = self.qkv(hidden).reshape(batch_size, length, 3, self.heads, self.head_size).unbind(2) | |
| attended = functional.scaled_dot_product_attention( | |
| self.rotate(query.transpose(1, 2)), | |
| self.rotate(key.transpose(1, 2)), | |
| value.transpose(1, 2), | |
| is_causal=True, | |
| ) | |
| return self.output(attended.transpose(1, 2).contiguous().view(batch_size, length, width)) | |
| class Block(nn.Module): | |
| def __init__(self, config): | |
| super().__init__() | |
| self.attention_norm = nn.RMSNorm(config.hidden_size, eps=1e-5) | |
| self.attention = Attention(config) | |
| self.ffn_norm = nn.RMSNorm(config.hidden_size, eps=1e-5) | |
| self.gate = nn.Linear(config.hidden_size, config.intermediate_size, bias=False) | |
| self.up = nn.Linear(config.hidden_size, config.intermediate_size, bias=False) | |
| self.down = nn.Linear(config.intermediate_size, config.hidden_size, bias=False) | |
| def forward(self, hidden): | |
| hidden = hidden + self.attention(self.attention_norm(hidden)) | |
| normalized = self.ffn_norm(hidden) | |
| return hidden + self.down(functional.silu(self.gate(normalized)) * self.up(normalized)) | |
| class LanguageModel(nn.Module): | |
| def __init__(self, config): | |
| super().__init__() | |
| self.config = config | |
| self.embedding = nn.Embedding(config.vocab_size, config.hidden_size) | |
| self.blocks = nn.ModuleList([Block(config) for _ in range(config.layers)]) | |
| self.norm = nn.RMSNorm(config.hidden_size, eps=1e-5) | |
| self.gradient_checkpointing = False | |
| self.apply(self.initialize) | |
| def set_gradient_checkpointing(self, enabled): | |
| self.gradient_checkpointing = enabled | |
| def initialize(module): | |
| if isinstance(module, (nn.Linear, nn.Embedding)): | |
| nn.init.normal_(module.weight, mean=0.0, std=0.02) | |
| def forward(self, tokens, targets=None, return_logits=False, logit_positions=None): | |
| if tokens.size(1) > self.config.context_length: | |
| raise ValueError("Input exceeds context length") | |
| hidden = self.embedding(tokens) | |
| for block in self.blocks: | |
| if self.gradient_checkpointing and self.training and torch.is_grad_enabled(): | |
| hidden = checkpoint(block, hidden, use_reentrant=False) | |
| else: | |
| hidden = block(hidden) | |
| hidden = self.norm(hidden) | |
| if logit_positions is not None: | |
| hidden = hidden[:, logit_positions, :] | |
| if targets is None and not return_logits: | |
| return functional.linear(hidden[:, -1:, :], self.embedding.weight) | |
| logits = functional.linear(hidden, self.embedding.weight) | |
| if targets is None: | |
| return logits | |
| return functional.cross_entropy(logits.reshape(-1, self.config.vocab_size), targets.reshape(-1)) | |