Download model.py from Aashw1n/openwebtext-103M: direct link, hf CLI and curl.
- Browser
- Download file 6.65 kB
-
https://huggingface.co/Aashw1n/openwebtext-103M/resolve/main/model.py
- Command line
-
hf download hf://Aashw1n/openwebtext-103M/model.py
-
curl -L -o model.py https://huggingface.co/Aashw1n/openwebtext-103M/resolve/main/model.py
6.65 kB
| import torch.nn as nn | |
| from einops import einsum, rearrange | |
| import torch | |
| import math | |
| def softmax(x , dim): | |
| x_max = x.max(dim=dim, keepdim=True).values | |
| exp = torch.exp(x-x_max) | |
| return exp/torch.sum(exp, dim=dim, keepdim=True) | |
| def scaled_dot_product_attention(q, k, v, mask=None): | |
| QK = einsum(q, k, "... seq_len d_k, ... seq d_k -> ... seq_len seq") | |
| d_k = q.shape[-1] | |
| root_d_k = 1/math.sqrt(d_k) | |
| s = QK * root_d_k | |
| if mask is not None: | |
| s = s.masked_fill(mask == False, float('-inf')) | |
| s_max = softmax(s, -1) | |
| return einsum(s_max, v, "... q k, ... k d_v -> ... q d_v") | |
| class Linear(nn.Module): | |
| def __init__(self, in_features: int, out_features: int, device = None, dtype = None): | |
| super().__init__() | |
| self.weight = nn.Parameter( | |
| torch.empty(out_features, in_features, device = device, dtype = dtype) | |
| ) | |
| nn.init.trunc_normal_( | |
| self.weight, | |
| mean = 0.0, | |
| std = math.sqrt(2/(in_features + out_features)), | |
| a = -3.0 * math.sqrt(2/(in_features + out_features)), | |
| b = 3.0 * math.sqrt(2/(in_features + out_features)) | |
| ) | |
| def forward(self, A): | |
| return einsum(A, self.weight, "... d_in, d_out d_in -> ... d_out") | |
| class Embedding(nn.Module): | |
| def __init__(self, num_embeddings, embedding_dim, device = None, dtype = None): | |
| super().__init__() | |
| self.weight = nn.Parameter( | |
| torch.empty(num_embeddings, embedding_dim, device=device, dtype=dtype) | |
| ) | |
| nn.init.trunc_normal_(self.weight, mean = 0.0, std = 1.0, a = -3.0, b = 3.0) | |
| def forward(self, token_ids): | |
| return self.weight[token_ids] | |
| class RMSNorm(nn.Module): | |
| def __init__(self, d_model, eps: float = 1e-5 , device = None, dtype = None): | |
| super().__init__() | |
| self.weight = nn.Parameter( | |
| torch.ones(d_model) | |
| ) | |
| self.eps = eps | |
| # No trunc normal since we're not drawing from a distribution. | |
| def forward(self, x): | |
| in_dtype = x.dtype | |
| x = x.to(torch.float32) # convert to float32 to avoid overflow | |
| sq = x*x | |
| m = sq.mean(dim=-1, keepdim= True) | |
| result = x * torch.rsqrt(m + self.eps) * self.weight | |
| return result.to(in_dtype) | |
| class SwiGLU(nn.Module): | |
| def __init__(self, d_model, d_ff): | |
| super().__init__() | |
| self.w1 = Linear(d_model, d_ff) | |
| self.w2 = Linear(d_ff, d_model) | |
| self.w3 = Linear(d_model, d_ff) | |
| def forward(self, x): | |
| w1x = self.w1(x) | |
| w3x = self.w3(x) | |
| siluw1x = w1x * torch.sigmoid(w1x) | |
| return self.w2(siluw1x * w3x) | |
| class SiLU(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| def forward(self, x): | |
| return x * torch.sigmoid(x) | |
| # RoPE | |
| class RotaryPositionalEmbedding(nn.Module): | |
| def __init__(self, theta: float, d_k: int, max_seq_len: int, device = None): | |
| super().__init__() | |
| self.theta = theta | |
| self.d_k = d_k | |
| self.max_seq_len = max_seq_len | |
| value_vector = torch.arange(0, d_k, 2).float() | |
| frequency_vector = theta ** (-(value_vector/d_k)) | |
| positions_vector = torch.arange(max_seq_len).float() | |
| angles = torch.outer(positions_vector, frequency_vector) | |
| cos_table = angles.cos() | |
| sin_table = angles.sin() | |
| self.register_buffer("cos_table", cos_table, persistent=False) | |
| self.register_buffer("sin_table", sin_table, persistent=False) | |
| def forward(self, x, token_positions): | |
| pairs = rearrange(x, '... seq (half two) -> ... seq half two', two = 2) # Get a 2d vector of pairs. | |
| a = pairs[..., 0] | |
| b = pairs[..., 1] | |
| cos = self.cos_table[token_positions] | |
| sin = self.sin_table[token_positions] | |
| a_rot = a * cos - b * sin | |
| b_rot = a * sin + b * cos | |
| stacked = torch.stack((a_rot, b_rot), dim = -1) | |
| return rearrange(stacked, '... seq half two -> ... seq (half two)') | |
| class Multihead_attention(nn.Module): | |
| def __init__(self, d_model, num_heads, max_seq_len = None, theta = None, do_rope: bool = None): | |
| super().__init__() | |
| self.num_heads = num_heads | |
| self.d_k = d_model // num_heads | |
| self.W_K = Linear(d_model, d_model) | |
| self.W_Q = Linear(d_model, d_model) | |
| self.W_V = Linear(d_model, d_model) | |
| self.W_O = Linear(d_model, d_model) | |
| self.do_rope = do_rope | |
| if self.do_rope == True: | |
| self.rope = RotaryPositionalEmbedding(theta, self.d_k, max_seq_len) | |
| def forward(self, x): | |
| Q = self.W_Q(x) | |
| K = self.W_K(x) | |
| V = self.W_V(x) | |
| Q = rearrange(Q, "batch seq (h d_k) -> batch h seq d_k", h=self.num_heads) | |
| K = rearrange(K, "batch seq (h d_k) -> batch h seq d_k", h=self.num_heads) | |
| V = rearrange(V, "batch seq (h d_k) -> batch h seq d_k", h=self.num_heads) | |
| # Apply RoPE. | |
| seq = x.shape[1] | |
| token_positions = torch.arange(seq, device= x.device) | |
| if self.do_rope == True: | |
| Q = self.rope(Q, token_positions) | |
| K = self.rope(K, token_positions) | |
| # Apply causal masking | |
| mask = torch.tril(torch.ones(seq, seq, dtype=torch.bool, device = x.device)) | |
| out = scaled_dot_product_attention(Q, K, V, mask) | |
| out = rearrange(out, "batch h seq d_k -> batch seq (h d_k)") | |
| return self.W_O(out) | |
| class TransformerBlock(nn.Module): | |
| def __init__(self, d_model, num_heads, d_ff, max_seq_len, theta): | |
| super().__init__() | |
| self.attn = Multihead_attention(d_model, num_heads, max_seq_len, theta, do_rope = True) | |
| self.ffn = SwiGLU(d_model, d_ff) | |
| self.norm1 = RMSNorm(d_model) | |
| self.norm2 = RMSNorm(d_model) | |
| def forward(self, x): | |
| x = x + self.attn(self.norm1(x)) | |
| x = x + self.ffn(self.norm2(x)) | |
| return x | |
| class TransformerLM(nn.Module): | |
| def __init__(self, vocab_size, context_length, num_layers, d_model, num_heads, d_ff, theta): | |
| super().__init__() | |
| self.embedding = Embedding(vocab_size, d_model) | |
| self.layers = nn.ModuleList( | |
| [ | |
| TransformerBlock(d_model, num_heads, d_ff, context_length, theta) | |
| for _ in range(num_layers) | |
| ] | |
| ) | |
| self.final_norm = RMSNorm(d_model) | |
| self.lm_head = Linear(d_model, vocab_size) | |
| def forward(self, token_ids): | |
| x = self.embedding(token_ids) | |
| for layer in self.layers: | |
| x = layer(x) | |
| x = self.final_norm(x) | |
| return self.lm_head(x) |