musabc commited on
Commit
b5dc2be
·
verified ·
1 Parent(s): a2dbe08

upload model_v5.py

Browse files
Files changed (1) hide show
  1. model_v5.py +243 -0
model_v5.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ V5 Model — 200M parametre, V4 mimari + büyütülmüş.
3
+
4
+ Mimari:
5
+ - Layer: 18 (V4: 8)
6
+ - Head: 14 (V4: 10)
7
+ - Embd: 896 (V4: 640)
8
+ - Vocab: 32000 (V4: 16000)
9
+ - Context: 2048 (V4: 512)
10
+ - Toplam: ~210M parametre
11
+
12
+ Modern teknikler (V4'ten):
13
+ - RoPE (real-valued)
14
+ - RMSNorm
15
+ - SwiGLU (hidden ~2560)
16
+ - QK-norm
17
+ - Logit soft-cap
18
+ - Tied embeddings
19
+ - Scaled init
20
+ """
21
+
22
+ import math
23
+ from dataclasses import dataclass
24
+
25
+ import torch
26
+ import torch.nn as nn
27
+ import torch.nn.functional as F
28
+
29
+
30
+ @dataclass
31
+ class GPTConfigV5:
32
+ block_size: int = 2048
33
+ vocab_size: int = 32000
34
+ n_layer: int = 18
35
+ n_head: int = 14
36
+ n_embd: int = 896
37
+ dropout: float = 0.0
38
+ rope_theta: float = 10000.0
39
+ logit_softcap: float = 30.0
40
+
41
+
42
+ class RMSNorm(nn.Module):
43
+ def __init__(self, dim: int, eps: float = 1e-6):
44
+ super().__init__()
45
+ self.weight = nn.Parameter(torch.ones(dim))
46
+ self.eps = eps
47
+
48
+ def forward(self, x):
49
+ dtype = x.dtype
50
+ x = x.float()
51
+ rms = torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
52
+ return (self.weight * (x * rms)).to(dtype)
53
+
54
+
55
+ def precompute_rope(dim, end, theta=10000.0, device=None):
56
+ inv_freq = 1.0 / (theta ** (torch.arange(0, dim, 2, device=device).float() / dim))
57
+ t = torch.arange(end, device=device, dtype=torch.float32)
58
+ freqs = torch.outer(t, inv_freq)
59
+ emb = torch.cat([freqs, freqs], dim=-1)
60
+ return emb.cos(), emb.sin()
61
+
62
+
63
+ def rotate_half(x):
64
+ x1, x2 = x.chunk(2, dim=-1)
65
+ return torch.cat([-x2, x1], dim=-1)
66
+
67
+
68
+ def apply_rotary_emb(xq, xk, cos, sin):
69
+ cos = cos.unsqueeze(0).unsqueeze(0)
70
+ sin = sin.unsqueeze(0).unsqueeze(0)
71
+ xq_out = (xq * cos) + (rotate_half(xq) * sin)
72
+ xk_out = (xk * cos) + (rotate_half(xk) * sin)
73
+ return xq_out.to(xq.dtype), xk_out.to(xk.dtype)
74
+
75
+
76
+ class CausalSelfAttention(nn.Module):
77
+ def __init__(self, cfg):
78
+ super().__init__()
79
+ assert cfg.n_embd % cfg.n_head == 0
80
+ self.n_head = cfg.n_head
81
+ self.n_embd = cfg.n_embd
82
+ self.head_dim = cfg.n_embd // cfg.n_head
83
+ self.c_attn = nn.Linear(cfg.n_embd, 3 * cfg.n_embd, bias=False)
84
+ self.c_proj = nn.Linear(cfg.n_embd, cfg.n_embd, bias=False)
85
+ self.dropout = cfg.dropout
86
+ self.q_norm = RMSNorm(self.head_dim)
87
+ self.k_norm = RMSNorm(self.head_dim)
88
+
89
+ def forward(self, x, cos, sin):
90
+ B, T, C = x.shape
91
+ q, k, v = self.c_attn(x).split(self.n_embd, dim=2)
92
+ q = q.view(B, T, self.n_head, self.head_dim).transpose(1, 2)
93
+ k = k.view(B, T, self.n_head, self.head_dim).transpose(1, 2)
94
+ v = v.view(B, T, self.n_head, self.head_dim).transpose(1, 2)
95
+ q = self.q_norm(q)
96
+ k = self.k_norm(k)
97
+ q, k = apply_rotary_emb(q, k, cos[:T], sin[:T])
98
+ y = F.scaled_dot_product_attention(
99
+ q, k, v, dropout_p=self.dropout if self.training else 0.0, is_causal=True
100
+ )
101
+ y = y.transpose(1, 2).contiguous().view(B, T, C)
102
+ return self.c_proj(y)
103
+
104
+
105
+ class SwiGLU(nn.Module):
106
+ def __init__(self, dim, hidden_dim=None):
107
+ super().__init__()
108
+ if hidden_dim is None:
109
+ hidden_dim = int(8 * dim / 3)
110
+ hidden_dim = ((hidden_dim + 255) // 256) * 256
111
+ self.w1 = nn.Linear(dim, hidden_dim, bias=False)
112
+ self.w2 = nn.Linear(dim, hidden_dim, bias=False)
113
+ self.w3 = nn.Linear(hidden_dim, dim, bias=False)
114
+ self.hidden_dim = hidden_dim
115
+
116
+ def forward(self, x):
117
+ return self.w3(F.silu(self.w1(x)) * self.w2(x))
118
+
119
+
120
+ class Block(nn.Module):
121
+ def __init__(self, cfg):
122
+ super().__init__()
123
+ self.norm1 = RMSNorm(cfg.n_embd)
124
+ self.attn = CausalSelfAttention(cfg)
125
+ self.norm2 = RMSNorm(cfg.n_embd)
126
+ self.mlp = SwiGLU(cfg.n_embd)
127
+
128
+ def forward(self, x, cos, sin):
129
+ x = x + self.attn(self.norm1(x), cos, sin)
130
+ x = x + self.mlp(self.norm2(x))
131
+ return x
132
+
133
+
134
+ class GPTV5(nn.Module):
135
+ def __init__(self, cfg):
136
+ super().__init__()
137
+ self.cfg = cfg
138
+ self.wte = nn.Embedding(cfg.vocab_size, cfg.n_embd)
139
+ self.h = nn.ModuleList([Block(cfg) for _ in range(cfg.n_layer)])
140
+ self.norm_f = RMSNorm(cfg.n_embd)
141
+ self.lm_head = nn.Linear(cfg.n_embd, cfg.vocab_size, bias=False)
142
+ self.lm_head.weight = self.wte.weight # tied
143
+
144
+ head_dim = cfg.n_embd // cfg.n_head
145
+ cos, sin = precompute_rope(head_dim, cfg.block_size * 2, cfg.rope_theta)
146
+ self.register_buffer("rope_cos", cos, persistent=False)
147
+ self.register_buffer("rope_sin", sin, persistent=False)
148
+
149
+ self.apply(self._init_weights)
150
+ for pn, p in self.named_parameters():
151
+ if pn.endswith("c_proj.weight") or pn.endswith("w3.weight"):
152
+ nn.init.normal_(p, mean=0.0, std=0.02 / math.sqrt(2 * cfg.n_layer))
153
+
154
+ def _init_weights(self, module):
155
+ if isinstance(module, nn.Linear):
156
+ nn.init.normal_(module.weight, mean=0.0, std=0.02)
157
+ elif isinstance(module, nn.Embedding):
158
+ nn.init.normal_(module.weight, mean=0.0, std=0.02)
159
+
160
+ def num_params(self):
161
+ return sum(p.numel() for p in self.parameters())
162
+
163
+ def forward(self, idx, targets=None):
164
+ B, T = idx.shape
165
+ max_t = self.rope_cos.size(0)
166
+ assert T <= max_t, f"T={T} > rope buffer={max_t}"
167
+
168
+ x = self.wte(idx)
169
+ cos = self.rope_cos[:T]
170
+ sin = self.rope_sin[:T]
171
+ for block in self.h:
172
+ x = block(x, cos, sin)
173
+ x = self.norm_f(x)
174
+
175
+ if targets is not None:
176
+ logits = self.lm_head(x)
177
+ if self.cfg.logit_softcap > 0:
178
+ cap = self.cfg.logit_softcap
179
+ logits = cap * torch.tanh(logits / cap)
180
+ loss = F.cross_entropy(
181
+ logits.view(-1, logits.size(-1)),
182
+ targets.view(-1),
183
+ ignore_index=-1,
184
+ )
185
+ return logits, loss
186
+ else:
187
+ logits = self.lm_head(x[:, [-1], :])
188
+ if self.cfg.logit_softcap > 0:
189
+ cap = self.cfg.logit_softcap
190
+ logits = cap * torch.tanh(logits / cap)
191
+ return logits, None
192
+
193
+ @torch.no_grad()
194
+ def generate(self, idx, max_new_tokens, temperature=1.0, top_k=None,
195
+ repetition_penalty=1.15, no_repeat_ngram_size=3,
196
+ max_context=None):
197
+ if max_context is None:
198
+ max_context = self.rope_cos.size(0)
199
+ for _ in range(max_new_tokens):
200
+ idx_cond = idx if idx.size(1) <= max_context else idx[:, -max_context:]
201
+ logits, _ = self(idx_cond)
202
+ logits = logits[:, -1, :] / temperature
203
+
204
+ if repetition_penalty != 1.0:
205
+ for b in range(idx.size(0)):
206
+ seen = set(idx[b].tolist()[-256:])
207
+ for tok in seen:
208
+ if logits[b, tok] > 0:
209
+ logits[b, tok] /= repetition_penalty
210
+ else:
211
+ logits[b, tok] *= repetition_penalty
212
+
213
+ if no_repeat_ngram_size > 0 and idx.size(1) >= no_repeat_ngram_size:
214
+ for b in range(idx.size(0)):
215
+ tokens = idx[b].tolist()
216
+ n = no_repeat_ngram_size
217
+ prefix = tuple(tokens[-(n-1):])
218
+ banned = set()
219
+ for i in range(len(tokens) - n + 1):
220
+ if tuple(tokens[i:i+n-1]) == prefix:
221
+ banned.add(tokens[i+n-1])
222
+ for tok in banned:
223
+ logits[b, tok] = -float("inf")
224
+
225
+ if top_k is not None:
226
+ v, _ = torch.topk(logits, min(top_k, logits.size(-1)))
227
+ logits[logits < v[:, [-1]]] = -float("inf")
228
+ probs = F.softmax(logits, dim=-1)
229
+ next_id = torch.multinomial(probs, num_samples=1)
230
+ idx = torch.cat([idx, next_id], dim=1)
231
+ return idx
232
+
233
+
234
+ if __name__ == "__main__":
235
+ cfg = GPTConfigV5()
236
+ m = GPTV5(cfg)
237
+ print(f"V5: {m.num_params()/1e6:.2f}M param")
238
+ print(f" Layer: {cfg.n_layer}, Head: {cfg.n_head}, Embd: {cfg.n_embd}")
239
+ print(f" Vocab: {cfg.vocab_size}, Block: {cfg.block_size}")
240
+ print(f" SwiGLU hidden: {m.h[0].mlp.hidden_dim}")
241
+ x = torch.randint(0, cfg.vocab_size, (2, 64))
242
+ logits, loss = m(x, x)
243
+ print(f"Forward: loss {loss.item():.4f}")