स्टेप 5 · एक पूरा छोटा GPT
हर हिस्सा जोड़कर एक ऐसा मॉडल तैयार किया गया है जिसे आप वाकई आज रात ट्रेन कर सकते हैं। 100 से भी कम लाइनों में, और बनावट में बिल्कुल एक फ्रंटियर मॉडल जैसा।
60 सेकंड में
स्टेप 5 · एक पूरा छोटा GPT
हर हिस्सा जोड़कर एक ऐसा मॉडल तैयार किया गया है जिसे आप वाकई आज रात ट्रेन कर सकते हैं। 100 से भी कम लाइनों में, और बनावट में बिल्कुल एक फ्रंटियर मॉडल जैसा।
import torch, torch.nn as nn, torch.nn.functional as F
from dataclasses import dataclass
@dataclass
class Config:
vocab_size: int = 8192
n_layer: int = 6
n_head: int = 6
d_model: int = 384
block_size: int = 256 # max context length
dropout: float = 0.1
class TinyGPT(nn.Module):
def __init__(self, cfg):
super().__init__()
self.cfg = cfg
self.tok = nn.Embedding(cfg.vocab_size, cfg.d_model)
self.pos = nn.Embedding(cfg.block_size, cfg.d_model)
self.drop = nn.Dropout(cfg.dropout)
self.blocks = nn.ModuleList(
Block(cfg.d_model, cfg.n_head) for _ in range(cfg.n_layer))
self.norm = RMSNorm(cfg.d_model)
self.head = nn.Linear(cfg.d_model, cfg.vocab_size, bias=False)
self.head.weight = self.tok.weight # weight tying
self.apply(self._init)
def _init(self, m):
if isinstance(m, nn.Linear):
nn.init.normal_(m.weight, std=0.02)
elif isinstance(m, nn.Embedding):
nn.init.normal_(m.weight, std=0.02)
def forward(self, idx, targets=None):
B, T = idx.shape
pos = torch.arange(T, device=idx.device)
x = self.drop(self.tok(idx) + self.pos(pos))
for b in self.blocks:
x = b(x)
logits = self.head(self.norm(x)) # (B, T, vocab)
loss = None
if targets is not None:
loss = F.cross_entropy(
logits.view(-1, logits.size(-1)),
targets.view(-1))
return logits, loss
@torch.no_grad()
def generate(self, idx, max_new=100, temperature=1.0, top_k=50):
for _ in range(max_new):
idx_cond = idx[:, -self.cfg.block_size:] # crop to context
logits, _ = self(idx_cond)
logits = logits[:, -1, :] / temperature # last position only
if top_k:
v, _ = torch.topk(logits, top_k)
logits[logits < v[:, [-1]]] = -float("inf")
probs = F.softmax(logits, dim=-1)
nxt = torch.multinomial(probs, num_samples=1)
idx = torch.cat((idx, nxt), dim=1)
return idxइन दो ज़रूरी लाइनों को फिर से पढ़ें
- 1
टारगेट्स वही इनपुट्स हैं, बस एक कदम आगे खिसके हुए (shifted by one)
targets = idx[1:]। यही पूरा ट्रेनिंग ऑब्जेक्टिव है। सीक्वेंस में हर जगह एक साथ अगले टोकन का अंदाज़ा लगाना। इसके अलावा कोई और सुपरविज़न नहीं है। - 2
जेनरेशन उसी फ़ॉरवर्ड पास का एक लूप है
आख़िरी पोज़ीशन पर मौजूद logits लें, एक टोकन सैंपल करें, उसे आगे जोड़ें, और फिर से रन करें। एक LLM जो कुछ भी बनाता है, वह सब इसी लूप से निकलता है।
ट्रेन करने से पहले अपने पैरामीटर्स गिन लें
def count(cfg):
emb = cfg.vocab_size * cfg.d_model # tied with output head
attn = 4 * cfg.d_model * cfg.d_model # q, k, v, proj
ff = 3 * cfg.d_model * int(8 * cfg.d_model / 3) # gate, up, down
per_layer = attn + ff
total = emb + cfg.n_layer * per_layer
print(f"embedding {emb/1e6:.1f}M")
print(f"per layer {per_layer/1e6:.1f}M x {cfg.n_layer}")
print(f"TOTAL {total/1e6:.1f}M")
return total
count(Config()) # ~ 14M parametersजब आप इसे चलाएंगे तो क्या उम्मीद करें
| ट्रेनिंग का समय | Loss | यह क्या बनाता है |
|---|---|---|
| 30 सेकंड | ~5.5 | उल्टे-सीधे कैरेक्टर्स |
| 2 मिनट | ~3.0 | शब्दों जैसा दिखने वाला बिना सिर-पैर का टेक्स्ट, जिसमें सही स्पेसिंग हो |
| 10 मिनट | ~2.0 | असली शब्द, लेकिन टूटी-फूटी ग्रामर |
| 1 घंटा | ~1.5 | धाराप्रवाह लगने वाले वाक्य, जिनका कोई मतलब नहीं होता |
| रात भर में, छोटे डेटासेट पर | ~1.2 | रटना (याद करना) — चेक करें कि कहीं ओवरफ़िटिंग तो नहीं हो रही |
और देखें और पढ़ें
लैब
आपके द्वारा खुद ट्रेन किया गया एक लैंग्वेज मॉडल, जो असली शब्द बना रहा है।
समस्या
if step % 200 == 0:
ctx = torch.zeros((1,1), dtype=torch.long, device=device)
print(f"--- step {step} loss {loss.item():.3f} ---")
print(decode(model.generate(ctx, max_new=120)[0].tolist()))आपका काम तब पूरा होगा जब
कठिन सवाल
उत्तर देखने से पहले ख़ुद जवाब देने की कोशिश करें। अगर आप इनके जवाब दे सकते हैं, तो आप पाठ समझ गए हैं।
Q1आपका ट्रेनिंग loss लगातार गिर रहा है लेकिन सैंपल्स में सुधार होना बंद हो गया है। इसके दो सबसे संभावित कारण बताएं और यह भी बताएं कि दोनों में फ़र्क कैसे पहचानें।दिखाएं
अक्सर पूछे जाने वाले सवाल
मुझे कौन सा डेटासेट इस्तेमाल करना चाहिए?
कुछ मेगाबाइट की एक सिंगल टेक्स्ट फ़ाइल से शुरुआत करें — पब्लिक-डोमेन किताबों का कलेक्शन अच्छा काम करता है। इतना छोटा कि मिनटों में बदलाव करके देखा जा सके, और इतना बड़ा कि मॉडल इसे आसानी से सिर्फ रट न ले। इसके बाद TinyStories या किसी छोटे वेब-टेक्स्ट सैंपल जैसी चीज़ पर बढ़ें।
मेरा loss 10 के आसपास क्यों अटका हुआ है?
यह लगभग हमेशा मॉडल बग के बजाय डेटा या शेप का बग होता है। चेक करें कि टारगेट्स ठीक एक कदम आगे खिसके (shifted) हैं या नहीं, कहीं आप गलती से पैडिंग को टारगेट्स के रूप में तो नहीं भेज रहे हैं, और आपके टोकन ids वोकैबुलरी की रेंज के अंदर हैं या नहीं।
क्या मैं इसे लैपटॉप पर चला सकता हूँ?
हाँ, इस साइज़ पर चला सकते हैं। Apple Silicon (MPS बैकएंड के ज़रिए) या सादा CPU एक छोटी फ़ाइल पर 14M कॉन्फ़िगरेशन को कुछ ही मिनटों में ट्रेन कर देगा। अगर मेमोरी कम पड़ रही हो तो block_size कम कर दें।
यह GPT-2 से कैसे अलग है?
स्केल में, और कुछ सुधारों में। GPT-2 स्मॉल में 124M पैरामीटर्स, 12 लेयर्स, d_model 768, कॉन्टेक्स्ट 1024 हैं, और इसे 40 GB टेक्स्ट पर ट्रेन किया गया था। यह वही आर्किटेक्चर है जिसमें नंबर्स को कम किया गया है और RMSNorm व SwiGLU को जोड़ा गया है।
पाठ का टेस्ट
5 सवाल। पास होने और इस पाठ को पूरा करने के लिए 3 सही होने चाहिए (60%)।