अटेंशन प्लस MLP, दोहराया गया
दो सबलेयर्स
एक ट्रांसफॉर्मर ब्लॉक में ठीक दो सबलेयर्स होते हैं, प्रत्येक [batch, seq_len, d_model] आकार के टोकन सीक्वेंस पर कार्य करता है:
1. मल्टी-हेड अटेंशन सबलेयर। टोकन एक-दूसरे को देखते हैं। एक्टिविटी 68 ने इसकी विस्तृत जानकारी दी थी। आउटपुट शेप इनपुट शेप से मेल खाता है।
2. फीड-फॉरवर्ड MLP सबलेयर। प्रत्येक टोकन स्वतंत्र रूप से दो-लेयर परसेप्ट्रॉन के माध्यम से परिवर्तित होता है। कोई क्रॉस-टोकन जानकारी प्रवाह नहीं। आउटपुट शेप इनपुट शेप से मेल खाता है।
दोनों सबलेयर [batch, seq_len, d_model] शेप को संरक्षित रखते हैं। यह संरक्षण ब्लॉकों को स्टैक करने की अनुमति देता है: लेयर N का आउटपुट लेयर N+1 के इनपुट को बिना किसी शेप एक्रोबेटिक्स के फीड करता है।
प्रत्येक सबलेयर क्या योगदान देता है
अटेंशन जानकारी को पोजीशन्स के अक्रॉस स्थानांतरित करता है: पोजीशन 17 पर एक टोकन पोजीशन्स 1 से 16 तक की जानकारी खींच सकता है। MLP जानकारी को प्रत्येक पोजीशन के अंदर परिवर्तित करता है: एक टोकन का प्रतिनिधित्व सीखे गए नॉन-लीनियर फंक्शन्स के माध्यम से रीशेप होता है, लेकिन कभी अपने पड़ोसियों को नहीं देखता।
ब्लॉकों को ढेर करने से ये दो संचालन वैकल्पिक होते हैं। लेयर 1 अटेंशन पोजीशन्स को मिश्रित करता है। लेयर 1 MLP प्रति-पोजीशन को पुन: आकार देता है। लेयर 2 अटेंशन फिर से मिश्रित करता है, अब पुन: आकारित प्रतिनिधित्वों पर। यह वैकल्पिकता गहराई के साथ अभिव्यंजक शक्ति को बढ़ाती है।
ANDREA का स्टैक
| Variant | n_layer | n_head | d_model | mlp_dim |
|---|---|---|---|---|
| ANDREA-12M | 6 | 12 | 384 | 1536 |
| ANDREA-120M | 12 | 12 | 768 | 3072 |
| ANDREA-480M | 16 | 24 | 1536 | 6144 |
परिवार में mlp_dim = 4 × d_model का अनुपात देखें। यह अनुपात लगभग हर आधुनिक ट्रांसफॉर्मर में लागू होता है। धारा 3 में इसका कारण समझाया गया है।
सबलेयर्स का नामकरण
स्किप कनेक्शन क्यों महत्वपूर्ण हैं
अवशेष पैटर्न
प्रत्येक सबलेयर अपनी गणना को अवशेष कनेक्शन में लपेटता है। आउटपुट में इनपुट को वापस जोड़ा जाता है:
x = x + Attention(LayerNorm(x)) # ध्यान सबलेयर
x = x + MLP(LayerNorm(x)) # MLP सबलेयर
प्रत्येक सबलेयर के अंदर, Attention(...) या MLP(...) फंक्शन एक डेल्टा उत्पन्न करता है। ब्लॉक इनपुट को प्रतिस्थापित नहीं करता; यह एक सीखी गई सुधार जोड़ता है।
यह क्यों महत्वपूर्ण है
गहन वास्तुकलों में रेसिडुअल कनेक्शनों के प्रभुत्व के तीन कारण:
1. ग्रेडिएंट प्रवाह। बैकप्रोपगेशन के दौरान, जोड़ (addition) ग्रेडिएंट्स को आउटपुट से इनपुट तक सीधा मार्ग प्रदान करता है, सबलेयर को बायपास करते हुए। बिना रेसिड्यूअल्स के 12-लेयर स्टैक एम्बेडिंग्स तक पहुँचने से पहले ही ग्रेडिएंट सिग्नल खो देगा; रेसिड्यूअल्स के साथ, ग्रेडिएंट की परिमाण सैकड़ों लेयर्स तक उपयोग योग्य रहती है।
2. पहचान प्रारंभिकरण (Identity initialization)। प्रारंभिकरण पर, सबलेयर वेट्स छोटे आउटपुट उत्पन्न करते हैं। रेसिड्यूअल कनेक्शन का मतलब है कि लेयर N प्रारंभ में लगभग अपरिवर्तित पास होती है। ट्रेनिंग एक कार्यशील प्रारंभिक बिंदु से धीरे-धीरे डेल्टा सीखती है।
3. रचनात्मक अधिगम (Compositional learning)। प्रत्येक ब्लॉक एक परिष्करण सीखता है, न कि प्रतिस्थापन। लेयर 1 स्थिति संबंधी जानकारी जोड़ सकती है। लेयर 2 वाक्यरचना संरचना जोड़ सकती है। लेयर 7 अर्थगत संबंध जोड़ सकती है। रेसिड्यूअल स्ट्रीम संचयित होती है।
लेयर नॉर्मलाइजेशन (Layer Normalization)
प्रत्येक सबलेयर से पहले, LayerNorm प्रत्येक टोकन के प्रतिनिधित्व को शून्य माध्य और इकाई विचलन (zero mean & unit variance) पर पुनःस्केल करता है, फिर प्रति-फीचर लाभ और पूर्वाग्रह (learned per-feature gain & bias) लागू करता है:
y = gamma * (x - mean(x)) / sqrt(var(x) + epsilon) + beta
औसत और विवरण d_model आयाम के पार गणना की जाती है, प्रत्येक टोकन के लिए अलग-अलग। दो सीखे गए वेक्टर (gamma, beta, प्रत्येक आकार [d_model]) अभिव्यंजक स्केल को पुनर्स्थापित करते हैं। सामान्यीकरण सक्रियणों को संख्यात्मक रूप से स्थिर रेंज में रखता है; इसके बिना, छोटी प्रशिक्षण अस्थिरताएँ NaN ग्रेडिएंट्स में बर्फ़बारी बन जाती हैं।
प्री-नॉर्म बनाम पोस्ट-नॉर्म
एक सूक्ष्म लेकिन महत्वपूर्ण विकल्प
```रीज़िडुअल सबलेयर में लेयर नॉर्म को वायर करने के दो तरीके:
पोस्ट-नॉर्म (मूल 2017 पेपर):
x = LayerNorm(x + Attention(x))
लेयर नॉर्म रीज़िडुअल जोड़ने के बाद आता है। रीज़िडुअल स्ट्रीम खुद हर लेयर पर नॉर्मलाइज़ होता है।
प्री-नॉर्म (आधुनिक मानक, ANDREA में उपयोग किया गया):
x = x + Attention(LayerNorm(x))
लेयर नॉर्म सबलेयर से पहले स्थित है, अवशिष्ट शाखा के अंदर। अवशिष्ट स्ट्रीम अन-नॉर्मलाइज्ड रहती है; केवल सबलेयर के इनपुट को रीस्केल किया जाता है।
प्री-नॉर्म क्यों जीता
पोस्ट-नॉर्म LR वार्मअप और सावधानीपूर्वक हाइपरपैरामीटर ट्यूनिंग के बिना खराब ट्रेन करता है। शुरुआती लेयर्स में ग्रेडिएंट्स फट जाते हैं क्योंकि प्रत्येक लेयर नॉर्म अवशिष्ट स्ट्रीम की संचित स्थिति को बिखेर देता है। मूल 2017 पेपर ने पोस्ट-नॉर्म का व्यापक ट्यूनिंग के साथ उपयोग किया; बाद के कार्य (GPT-2, LLaMA, ANDREA) ने प्री-नॉर्म को मानक बनाया।
प्री-नॉर्म स्थिर रूप से प्रशिक्षित करता है। रेसिडुअल स्ट्रीम सभी लेयर्स में साफ़ जमा होता है; केवल सबलेयर इनपुट्स को संख्यात्मक स्थिरता के लिए नॉर्मलाइज़ किया जाता है। आधुनिक ट्रांसफॉर्मर्स डिफ़ॉल्ट रूप से प्री-नॉर्म का उपयोग करते हैं, & ANDREA भी वही विकल्प अपनाता है।
अंतिम ब्लॉक समीकरण
रेसिडुअल्स, प्री-नॉर्म स्थिति में लेयर नॉर्म, & दोनों सबलेयर्स को मिलाकर ANDREA का पूर्ण ब्लॉक मिलता है:
```python
def block_forward(x):
```
x = x + Attention(LayerNorm(x)) # attention sublayer
x = x + MLP(LayerNorm(x)) # MLP sublayer
return x
दो सबलेयर्स, दो residual additions, दो layer norms (नोट: प्रत्येक सबलेयर का अपना layer norm है; ANDREA-120M में 12 ब्लॉक्स में 24 layer norms प्लस आउटपुट पर एक अंतिम, कुल 25). 12 बार दोहराएं. यही ANDREA-120M का trunk है.
Pre-Norm प्रशिक्षण को स्थिर क्यों करता है
दो रैखिक लेयर्स, एक सक्रियण
तीन संचालन
MLP सबलेयर दो-लेयर पर्सेप्ट्रॉन है जिसमें लेयर्स के बीच एक गैर-रैखिक सक्रियण होता है:
def mlp_forward(x):
h = x · W_1 + b_1 # विस्तार: d_model → mlp_dim
h = GELU(h) # गैर-रैखिक सक्रियण
y = h · W_2 + b_2 # संकुचन: mlp_dim → d_model
return y
तीन संचालन। दो रैखिक, एक गैर-रैखिक। पहला रैखिक चौड़ाई बढ़ाता है; दूसरा वापस सिकुड़ाता है।
4× विस्तार अनुपात
आधुनिक ट्रांसफॉर्मर mlp_dim = 4 × d_model सेट करते हैं। ANDREA-120M:
d_model = 768
mlp_dim = 4 × 768 = 3072
W_1 का आकार = [768, 3072] # ~2.36M पैरामीटर
W_2 का आकार = [3072, 768] # ~2.36M पैरामीटर
प्रति ब्लॉक MLP पैरामीटर = 4.72M (बायस को नजरअंदाज करते हुए)
हर ध्यान उपलेयर जोड़ी के बीच दो MLP स्थित होते हैं (प्रति ब्लॉक एक)। बारह ब्लॉक × 4.72M ≈ 56.6M MLP पैरामीटर कुल मिलाकर ANDREA-120M में, सभी पैरामीटरों का लगभग आधा हिस्सा।
4× क्यों
4× अनुपात प्रयोगात्मक रूप से उभरा। छोटे अनुपात मॉडल क्षमता को कम करते हैं। बड़े अनुपात प्रति पैरामीटर व्यय पर घटते रिटर्न देते हैं। दशकों के आर्किटेक्चर खोज में, 4× टिका हुआ है; यह GPT, BERT, T5, LLaMA, और ANDREA में दिखता है।
हाल का कार्य (PaLM, Chinchilla) ने पाया कि गेटिंग तंत्र (SwiGLU) 8/3× विस्तार का उपयोग कम लागत पर तुलनीय क्षमता के साथ कर सकते हैं; ANDREA सरलता के लिए क्लासिक GELU + 4× के साथ रहता है।
GELU: एक सुगम सक्रियण
GELU क्या गणना करता है
GELU (Gaussian Error Linear Unit) आधुनिक ट्रांसफॉर्मर्स में MLP लेयर्स के बीच मानक सक्रियण है। इसका सूत्र:
GELU(x) = x · Φ(x)
Φ(x) मानक सामान्य वितरण का संचयी वितरण फलन है: एक मानक गaussian यादृच्छिक चर के x पर या नीचे गिरने की संभावना। संख्यात्मक रूप से गणना की गई:
Φ(x) ≈ 0.5 × (1 + tanh(sqrt(2/π) × (x + 0.044715 × x³)))
क्षेत्र के अनुसार व्यवहार
- बड़े धनात्मक x के लिए: Φ(x) ≈ 1, इसलिए GELU(x) ≈ x। ReLU की तरह।
- बड़े ऋणात्मक x के लिए: Φ(x) ≈ 0, इसलिए GELU(x) ≈ 0। ReLU की तरह।
- x = 0 के पास: Φ(x) ≈ 0.5, इसलिए GELU(0) = 0 बिल्कुल। मूल बिंदु के माध्यम से सुगम संक्रमण।
ReLU के विपरीत, GELU कुछ ऋणात्मक इनपुट को Φ(x) द्वारा भारित करके पार होने देता है। एक छोटा ऋणात्मक इनपुट अभी भी एक छोटा ऋणात्मक आउटपुट योगदान देता है, बस पूर्ण इनपुट से कम।
GELU का ReLU से बेहतर प्रदर्शन क्यों
प्रयोगात्मक रूप से, GELU के साथ प्रशिक्षित ट्रांसफॉर्मर समान पैरामीटर संख्या पर ReLU के साथ प्रशिक्षित ट्रांसफॉर्मर से कम लॉस तक पहुँचते हैं। शून्य के आसपास की चिकनाहट मायने रखती है: ReLU का शून्य पर कठोर कटऑफ ग्रेडिएंट असातत्य पैदा करता है; GELU का चिकना वक्र बैकप्रोपगेशन के लिए साफ़ ग्रेडिएंट प्रदान करता है।
ANDREA का ट्रेनिंग इंजन microgpt_cuda.cu एक हस्तलिखित GELU CUDA kernel के साथ आता है। यह kernel ऊपर दिए गए tanh अनुमान का उपयोग करता है; आधुनिक GPUs में tanh एकल-निर्देश op के रूप में शामिल है।
MLP पैरामीटर्स की गणना
बारह ब्लॉक्स मिलकर बनाते हैं ANDREA-120M
ब्लॉक से मॉडल तक
ANDREA-120M का पूरा फॉरवर्ड पास:
def model_forward(token_ids):
x = token_embed(token_ids) + position_embed(positions)
for block_idx in range(n_layer): # 12 ब्लॉक्स
x = block_forward(x) # attention + MLP w/ residuals
x = LayerNorm(x) # अंतिम norm
logits = x · token_embed.T # आउटपुट प्रोजेक्शन के लिए tied weights
return logits
छह लाइनें। मुख्य भाग block_forward के अंदर रहता है, जिसे बारह बार बुलाया जाता है। एम्बेडिंग्स पाइपलाइन शुरू करती हैं; बंधी अनएम्बेडिंग (इनपुट लुकअप के लिए इस्तेमाल की गई समान मैट्रिक्स, आउटपुट प्रोजेक्शन के लिए ट्रांसपोज्ड) इसे समाप्त करती है।
गहराई के रूप में संरचना
प्रत्येक ब्लॉक रेसिडुअल स्ट्रीम को पढ़ता है, एक डेल्टा की गणना करता है, और इसे वापस जोड़ देता है। बारह पास के बाद, स्ट्रीम में हर ब्लॉक से संचित योगदानों का समावेश होता है। आंतरिक रूप से, लेयर्स विशेषज्ञता की ओर झुकती हैं:
- प्रारंभिक लेयर्स (1-3): वाक्यविन्यास पैटर्न, स्थिति संरचना
- मध्य लेयर्स (4-8): शब्द संबंध, वाक्यांश सीमाएँ
- अंतिम लेयर्स (9-12): अर्थगत सामग्री, तथ्यात्मक स्मरण
यह विशेषज्ञता प्रशिक्षण दबाव से उभरती है, वास्तुशिल्प विकल्पों से नहीं। एक ही समान ब्लॉक डिज़ाइन भाषा पर प्रशिक्षित होने पर विशेषज्ञीकृत परतें उत्पन्न करता है।
कुल ब्लॉक पैरामीटर
| घटक | प्रति ब्लॉक | 12 ब्लॉकों में |
|---|---|---|
| ध्यान प्रक्षेपण (4×W) | 2.36M | 28.3M |
| MLP वजन (W_1 + W_2) | 4.72M | 56.6M |
| लेयर नॉर्म्स (gamma, beta) | ~3K (नगण्य) | ~37K |
| प्रति ब्लॉक कुल | ~7.1M | ~85M |
ट्रंक में 85M पैरामीटर। टोकन एम्बेडिंग्स में ~13M जोड़ें (8449 vocab × 768 d_model × 2 बंधे input/output के लिए) प्लस अंतिम लेयर नॉर्म, & ANDREA-120M का पैरामीटर काउंट लगभग 120M पर पहुँच जाता है। ब्लॉक डिज़ाइन दो-तिहाई के लिए जिम्मेदार; शेष एम्बेडिंग्स।