स्टेप 4 · ट्रांसफॉर्मर ब्लॉक
अटेंशन के साथ एक छोटा फ़ीड-फ़ॉरवर्ड नेटवर्क, दो नॉर्मलाइज़ेशन और दो रेसिडुअल कनेक्शन। इसे N बार दोहराएं। पूरा मॉडल बस यही है।
60 सेकंड में
स्टेप 4 · ट्रांसफॉर्मर ब्लॉक
अटेंशन के साथ एक छोटा फ़ीड-फ़ॉरवर्ड नेटवर्क, दो नॉर्मलाइज़ेशन और दो रेसिडुअल कनेक्शन। इसे N बार दोहराएं। पूरा मॉडल बस यही है।
फ़ीड-फ़ॉरवर्ड नेटवर्क
class SwiGLU(nn.Module):
def __init__(self, d_model, hidden=None):
super().__init__()
# 8/3 rather than 4x, because the gate adds a third matrix
hidden = hidden or int(8 * d_model / 3 / 64) * 64
self.up = nn.Linear(d_model, hidden, bias=False)
self.gate = nn.Linear(d_model, hidden, bias=False)
self.down = nn.Linear(hidden, d_model, bias=False)
def forward(self, x):
return self.down(F.silu(self.gate(x)) * self.up(x))रेसिडुअल्स और नॉर्मलाइज़ेशन: दो चीज़ें जो गहराई को मुमकिन बनाती हैं
- 1
रेसिडुअल कनेक्शन
x = x + block(x)। हर ब्लॉक चल रही स्ट्रीम को बदलने के बजाय उसमें एक सुधार (करेक्शन) जोड़ता है। ग्रेडिएंट्स सीधे इस जोड़ वाले रास्ते से नीचे बहते हैं, जिसकी वजह से ही 80-लेयर वाले नेटवर्क्स को ट्रेन करना मुमकिन हो पाता है। - 2
प्री-नॉर्मलाइज़ेशन
हर सब-लेयर के बाद नहीं, बल्कि उससे पहले नॉर्मलाइज़ करें। ओरिजिनल ट्रांसफॉर्मर इसे बाद में करते थे और उन्हें बिखरने (डाइवर्ज होने) से बचाने के लिए बहुत सावधानी से लर्निंग-रेट वॉर्मअप की ज़रूरत पड़ती थी। प्री-नॉर्म बहुत ज़्यादा स्टेबल है और अब हर जगह इस्तेमाल होता है। - 3
LayerNorm की जगह RMSNorm
मीन-सबट्रैक्शन और बायस को छोड़ दें; बस रूट-मीन-स्क्वायर से डिवाइड करें और स्केल करें। यह थोड़ा सस्ता पड़ता है और उतना ही अच्छा काम करता है, इसलिए आधुनिक मॉडल्स इसका इस्तेमाल करते हैं। - 4
कोई बायस नहीं
ज़्यादातर मौजूदा मॉडल्स लीनियर लेयर्स में बायस टर्म्स को पूरी तरह हटा देते हैं। कम पैरामीटर्स, कोई नपा-तुला नुकसान नहीं, और थोड़ी बेहतर स्टेबिलिटी।
class RMSNorm(nn.Module):
def __init__(self, d, eps=1e-6):
super().__init__()
self.eps = eps
self.weight = nn.Parameter(torch.ones(d))
def forward(self, x):
rms = x.pow(2).mean(-1, keepdim=True).add(self.eps).rsqrt()
return x * rms * self.weight
class Block(nn.Module):
def __init__(self, d_model, n_head):
super().__init__()
self.n1 = RMSNorm(d_model)
self.attn = CausalSelfAttention(d_model, n_head)
self.n2 = RMSNorm(d_model)
self.ff = SwiGLU(d_model)
def forward(self, x):
x = x + self.attn(self.n1(x)) # mix across positions
x = x + self.ff(self.n2(x)) # think within each position
return xऔर देखें और पढ़ें
लैब
आधुनिक ट्रांसफॉर्मर ब्लॉक की एक एब्लेशन स्टडी।
समस्या
आपका काम तब पूरा होगा जब
कठिन सवाल
उत्तर देखने से पहले ख़ुद जवाब देने की कोशिश करें। अगर आप इनके जवाब दे सकते हैं, तो आप पाठ समझ गए हैं।
Q1पोस्ट-नॉर्म बिना ध्यान से किए गए वॉर्मअप के डाइवर्ज हो जाता है; प्री-नॉर्म नहीं होता। इसका कारण समझाइए।दिखाएं
अक्सर पूछे जाने वाले सवाल
नॉलेज कहाँ स्टोर होती है?
सबूत ज़्यादातर फ़ीड-फ़ॉरवर्ड लेयर्स की तरफ़ इशारा करते हैं, जो कुछ हद तक की-वैल्यू मेमोरीज़ की तरह काम करती हैं। अटेंशन तय करता है कि क्या निकालना और रूट करना है; जो कुछ निकाला जाता है, उसमें से ज़्यादातर फ़ीड-फ़ॉरवर्ड नेटवर्क में होता है। यह कोई साफ़-सुथरा बंटवारा नहीं है।
FFN में 4x एक्सपेंशन क्यों?
तजुर्बे के आधार पर (एम्पिरिकल)। यह कई स्केल्स पर लगभग सबसे सही साबित हुआ है। गेटेड वैरिएंट्स लगभग 8/3 का इस्तेमाल करते हैं क्योंकि उनमें दो के बजाय तीन मैट्रिसेस होते हैं, जिससे पैरामीटर काउंट बराबर बना रहता है।
मॉडल कितना गहरा होना चाहिए?
चौड़ाई और गहराई के बीच एक मोटा-सा संबंध है जो अच्छा काम करता है: एक 7B मॉडल में आमतौर पर 4096 d_model के साथ लगभग 32 लेयर्स होती हैं। बहुत गहरा और पतला, या बहुत चौड़ा और उथला, दोनों ही तय पैरामीटर बजट में कमज़ोर परफॉर्म करते हैं।
क्या 2017 के बाद से वाकई कुछ नया हुआ है?
ब्लॉक लेवल पर: RoPE, RMSNorm, गेटेड FFNs, आर्काइव-क्वेरी (ग्रुप-क्वेरी) अटेंशन, और मिक्स्चर-ऑफ़-एक्सपर्ट्स रूटिंग। असली सुधार, पर सभी छोटे-छोटे कदम। क्रांतिकारी बदलाव स्केल, डेटा की क्वालिटी और पोस्ट-ट्रेनिंग में आए हैं।
पाठ का टेस्ट
5 सवाल। पास होने और इस पाठ को पूरा करने के लिए 3 सही होने चाहिए (60%)।