oai-flash-28m / src /model.py
DevX
Upload folder using huggingface_hub
605f3d7 verified
Raw History Blame Contribute Delete
3.31 kB
import math, torch, torch.nn as nn, torch.nn.functional as F
def sinusoidal_position_embedding(seq_len, dim, device):
pe = torch.zeros(seq_len, dim, device=device)
position = torch.arange(0, seq_len, device=device).unsqueeze(1)
div_term = torch.exp(torch.arange(0, dim, 2, device=device) * (-math.log(10000.0) / dim))
pe[:, 0::2] = torch.sin(position * div_term); pe[:, 1::2] = torch.cos(position * div_term)
return pe
class CausalSelfAttention(nn.Module):
def __init__(self, d_model, n_heads, dropout):
super().__init__()
assert d_model % n_heads == 0
self.n_heads = n_heads; self.head_dim = d_model // n_heads
self.qkv = nn.Linear(d_model, 3*d_model, bias=False)
self.proj = nn.Linear(d_model, d_model, bias=False)
self.attn_drop = nn.Dropout(dropout); self.resid_drop = nn.Dropout(dropout)
self.register_buffer("mask", None, persistent=False)
def forward(self, x):
B, T, C = x.size()
if self.mask is None or self.mask.size(0) < T:
self.mask = torch.tril(torch.ones(T, T, device=x.device)).unsqueeze(0).unsqueeze(1)
qkv = self.qkv(x); q, k, v = qkv.split(C, dim=2)
def split(t): return t.view(B, T, self.n_heads, self.head_dim).transpose(1,2)
q, k, v = map(split, (q,k,v))
att = (q @ k.transpose(-2,-1)) / math.sqrt(self.head_dim)
att = att.masked_fill(self.mask[:,:,:T,:T]==0, float('-inf'))
att = F.softmax(att, dim=-1); att = self.attn_drop(att)
y = att @ v; y = y.transpose(1,2).contiguous().view(B, T, C)
return self.resid_drop(self.proj(y))
class MLP(nn.Module):
def __init__(self, d_model, dropout):
super().__init__()
self.fc1 = nn.Linear(d_model, 4*d_model); self.fc2 = nn.Linear(4*d_model, d_model)
self.drop = nn.Dropout(dropout)
def forward(self, x):
return self.drop(self.fc2(self.drop(F.gelu(self.fc1(x)))))
class Block(nn.Module):
def __init__(self, d_model, n_heads, dropout):
super().__init__()
self.ln1 = nn.LayerNorm(d_model); self.attn = CausalSelfAttention(d_model, n_heads, dropout)
self.ln2 = nn.LayerNorm(d_model); self.mlp = MLP(d_model, dropout)
def forward(self, x): x = x + self.attn(self.ln1(x)); return x + self.mlp(self.ln2(x))
class GPT(nn.Module):
def __init__(self, vocab_size, d_model=512, n_heads=8, n_layers=8, n_positions=512, dropout=0.1):
super().__init__()
self.vocab_size = vocab_size; self.n_positions = n_positions
self.tok_emb = nn.Embedding(vocab_size, d_model)
self.pos_emb = nn.Parameter(torch.zeros(n_positions, d_model), requires_grad=False)
self.drop = nn.Dropout(dropout)
self.blocks = nn.ModuleList([Block(d_model, n_heads, dropout) for _ in range(n_layers)])
self.ln_f = nn.LayerNorm(d_model); self.head = nn.Linear(d_model, vocab_size, bias=False)
with torch.no_grad():
self.pos_emb.copy_(sinusoidal_position_embedding(n_positions, d_model, device='cpu'))
def forward(self, idx):
B, T = idx.shape; tok = self.tok_emb(idx); pos = self.pos_emb[:T, :].unsqueeze(0).expand(B, -1, -1)
x = self.drop(tok + pos)
for blk in self.blocks: x = blk(x)
x = self.ln_f(x); return self.head(x)