सामग्री पर जाएँ
9/30अध्याय 9 / 30

Average से निकला Attention और Transformer Block

context के सबसे सस्ते सार—average—से शुरू करें, उसकी विफलता मापें, और repair से attention formula निकलते देखें।

इस पेज पर

आप यहाँ Chapter 7 के tokenizer, Chapter 8 की embedding table, और उनके साथ आने वाले objective के साथ पहुँचते हैं: अब तक के tokens दिए हों, तो अगले token पर probability लगानी है.

जो गायब है, वह बीच का हिस्सा है. token tt predict करने के लिए model को उससे पहले की हर चीज़ का सार देने वाला एक vector चाहिए, और आपने जो बनाया है उसमें से कुछ भी ऐसा vector नहीं बनाता. token t1t-1 की embedding वह नहीं है — वह तो bigram model है, और उसे यह नहीं पता हो सकता कि sentence एक question से शुरू हुआ था. पिछली सभी embeddings को concatenate करना भी जवाब नहीं है: उनकी संख्या हर step पर बदलती है, और fixed weight matrix variable-length input नहीं ले सकती.

तो: एक fixed-size vector, जो variable number of vectors को summarize करे. यही पूरा problem है, और attention वही है जो इसे सबसे आलसी तरीके से solve करने और फिर टूटने वाली दो चीज़ों को repair करने से मिलता है.

Field के पास जो जवाब था, और हम उसे क्यों नहीं बना रहे

सेक्शन का लिंक: Field के पास जो जवाब था, और हम उसे क्यों नहीं बना रहे

1997 से लगभग 2017 तक summary एक recurrent state था: एक vector h\mathbf{h} रखो और हर token पर उसे update करो, ht=f(ht1,xt)\mathbf{h}_t = f(\mathbf{h}_{t-1}, \mathbf{x}_t). Fixed size, variable input, बिल्कुल सही shape.

वह तीन तरीकों से fail हुआ, और इस chapter की architecture तीनों का जवाब देती है. TT steps में backpropagating करने से TT Jacobians multiply होते हैं, इसलिए gradient vanish या explode होता है — वही बीमारी जिसे Chapter 5 ने एक single tanh\tanh node के भीतर मापा था. LSTM1 को ठीक इसी के विरुद्ध design किया गया था और उसने usable range को tens of steps से hundreds तक बढ़ाया, बिना इस तथ्य को बदले कि token 5 की information token 500 तक केवल 495 sequential updates survive करके पहुँचती है. पूरे source को एक vector में fit होना पड़ता था: sequence-to-sequence translation2 में encoder input को अपनी final state में compress करता है. Bahdanau, Cho और Bengio ने 2014 में, transformer से तीन साल पहले, उस bottleneck को नाम दिया और fix किया, decoder को all encoder states का weighted sum लेने देकर, उन weights के साथ जिन्हें वह खुद compute करता था.3 नीचे की हर चीज़ वही idea है, जिसे एक sequence पर उसी के लिए apply किया गया है, recurrence हटाकर. और update construction से ही sequential है: ht\mathbf{h}_t को ht1\mathbf{h}_{t-1} चाहिए, और दस हज़ार cores वाला GPU भी इससे कुछ नहीं कर सकता. जो architecture जीती वह ज़रूरी नहीं कि साफ़ तौर पर smarter थी; वह वह थी जिसका expensive step matrix multiply है.

दूसरा classical inductive bias, convolution — पूरे input पर एक छोटा filter slide करना, ताकि कहीं भी detected feature हर जगह detected हो — यहाँ भी नहीं बनाया गया; यह images के लिए लगभग बिल्कुल सही है और vision course को सौंपा गया है. इस page के बाद न recurrence लौटता है न convolution, इसलिए दोनों को chapter नहीं मिलता: Chapter 1 ने वादा किया था कि omissions को चुपचाप नहीं, घोषित किया जाएगा.

Variable number of vectors से एक vector लौटाने वाला सबसे obvious function average है:

ct=1ti=1txi\mathbf{c}_t = \frac{1}{t}\sum_{i=1}^{t} \mathbf{x}_i

कितने भी inputs, fixed output size, differentiable, मुफ्त. Embedding table plus यह average plus vocabulary तक एक linear layer — पंद्रह lines में complete language model. यह भयानक भी है, और यह कैसे भयानक है, वही पूरी derivation है.

नीचे का corpus Shakespeare का एक megabyte है, 1,115,394 characters, Chapter 7 में बनाए गए kind के byte-level BPE tokenizer से, vocabulary 1024: 459,760 tokens, हर token 2.43 characters, 90/10 split. हर model 128 wide है, 128 tokens देखता है, और 10310^{-3} पर AdamW के 3000 steps train होता है, batch 64 के साथ. Perplexity held-out split पर है.4

modelparametersvalidation perplexity
सिर्फ current token, कोई context नहीं263,16859.71
plus उससे पहले की हर चीज़ का uniform average263,168248.07
plus learned position embeddings279,552245.93
uniform average token को replace करने के बजाय उसमें add किया गया263,16860.45

दूसरी row को दो बार पढ़िए. Context को average करना थोड़ा सा मदद नहीं करता; यह model को context को पूरी तरह ignore करने से चार गुना worse बना देता है. दो कारण, दोनों empirical नहीं बल्कि provable.

Average order नहीं देख सकता. Addition commute करता है, इसलिए window shuffle करने पर summary unchanged रहती है — लगभग नहीं, सचमुच:

order.pyPYTHON
A = torch.tril(torch.ones(T, T))
A = A / A.sum(1, keepdim=True)          # rows of the averaging matrix
y = x[torch.randperm(T)]                # the same tokens, shuffled
print((A[-1] @ x - A[-1] @ y).abs().max().item())
TEXT
2.9802322387695312e-08

Reordered sum पर floating-point noise: दोनों summaries same vector हैं. जिस model का context पर एकमात्र view average है, वह the dog bit the man और the man bit the dog में फर्क नहीं कर सकता. Row three साबित करती है कि inputs में positions add करने से यह fix नहीं होता — average करने से पहले हर token पर learned position embedding ने 188 में से 2.14 points खरीदे. Positions sum में जाती हैं, और sum उन्हें भूल जाता है.

और average present को डुबो देता है. Position 100 पर current token summary का one hundredth है. इसका cheap fix आपके पास पहले से है: token रखें और summary को उसमें add करें — Chapter 6 का residual connection, और row four दिखाती है कि वह क्या करता है. Dilution repair होने पर uniform average कुछ भी contribute नहीं करता: baseline 59.71 के मुकाबले 60.45. हर token वहाँ है, बराबर weight के साथ, और equal weighting का अर्थ no information है.

Problem averaging नहीं है. Problem weights हैं.

Growing prefix पर average लेना loop जैसा दिखता है. यह lower-triangular matrix से एक multiplication है जिसकी rows का sum one है — और ठीक-ठीक, एक softmax भी:

mechanics.pyPYTHON
loop = torch.stack([x[:t + 1].mean(0) for t in range(T)])   # the obvious version

A = torch.tril(torch.ones(T, T))
A = A / A.sum(1, keepdim=True)
mat = A @ x                                                  # the same thing

S = torch.zeros(T, T).masked_fill(torch.tril(torch.ones(T, T)) == 0, float("-inf"))
soft = F.softmax(S, dim=-1) @ x                              # and the same thing again
TEXT
loop vs matmul   max |diff| = 5.960464477539063e-08
loop vs softmax  max |diff| = 5.960464477539063e-08

the averaging matrix A (rows sum to 1, upper triangle is zero):
  1.000 0.000 0.000 0.000 0.000 0.000
  0.500 0.500 0.000 0.000 0.000 0.000
  0.333 0.333 0.333 0.000 0.000 0.000
  0.250 0.250 0.250 0.250 0.000 0.000
  0.200 0.200 0.200 0.200 0.200 0.000
  0.167 0.167 0.167 0.167 0.167 0.167

Transformer के तीन named components अब screen पर हैं. Triangle causal mask है, objective द्वारा forced: अगर position tt position t+1t{+}1 को देख सके तो answer input में ही होगा — वही leak जिसे Chapter 6 ने audit करने को कहा था, बस architecture के भीतर. Softmax mask implement करने का तरीका है: forbidden entries को -\infty set करने से वे exactly zero हो जाती हैं और बाकी normalise हो जाता है, इसलिए masking और normalising एक operation हैं. (-1e9 नहीं, -\infty use करें: यही वह value है जिसका masking मतलब है, यह float16 cast में -\infty के रूप में बचती है, और आपको यह तय करने से बचाती है कि आपकी चुनी constant उस range के लिए बड़ी enough है या नहीं जिसमें आप हैं — जो Chapter 2 का floating-point box आपसे ऐसा question पूछ रहा है जिसका जवाब आपको नहीं देना.) और scores free parameter हैं. Uniform average तब मिलता है जब हर allowed score same number हो; कोई भी numbers रखिए और softmax उन्हें valid weights में बदल देता है.

इस chapter का बाकी हिस्सा एक question है: वे numbers आते कहाँ से हैं?

वे plain parameters नहीं हो सकते. Learned T×TT \times T matrix हर sentence के लिए identical होगा — वह “चार tokens पीछे देखो” encode कर सकता है लेकिन कभी “उस noun को देखो जिसे यह pronoun refer करता है” नहीं. Position tt को position ii से जोड़ने वाला weight दोनों positions पर क्या है, इस पर depend करना चाहिए, क्योंकि relevance relation है, property नहीं: word it intrinsically relevant नहीं है, वह किसी चीज़ के लिए relevant है.

दो vectors से number लौटाने वाला सबसे cheap function Chapter 1 का dot product है. Position ii को position tt के लिए xtxi\mathbf{x}_t \cdot \mathbf{x}_i की तरह score करें और mechanism काम करता है — बुरी तरह, दो तरीकों से जो बाकी सब force करते हैं. Vector का खुद के साथ dot product उसका squared norm है, इसलिए हर token mostly खुद पर attend करेगा. और relation symmetric होगा: अगर it strongly animal पर attend करता है, तो animal strongly it पर attend करेगा, जो language के बारे में false है, जहाँ adjective को अपने noun की noun को adjective से कहीं अधिक ज़रूरत होती है.

इसलिए हर token को दो roles दें, उसके दो learned linear maps के रूप में: यह position क्या ढूँढ रही है, qt=Wqxt\mathbf{q}_t = W_q\mathbf{x}_t, query; और यह किस रूप में ढूँढे जाने की पेशकश करती है, ki=Wkxi\mathbf{k}_i = W_k\mathbf{x}_i, key. Score qtki\mathbf{q}_t \cdot \mathbf{k}_i और symmetry चली गई, क्योंकि WqWkW_q \neq W_k: token एक चीज़ advertise कर सकता है और दूसरी search कर सकता है.

एक चीज़ अभी भी गलत है. Weighted sum खुद xi\mathbf{x}_i पर था, जिससे जो चीज़ copy होती है वही चीज़ match भी होनी पड़ती है. Matching को token identify करने वाले features चाहिए; copying को downstream useful features चाहिए. इसलिए तीसरा map learn करें, vi=Wvxi\mathbf{v}_i = W_v\mathbf{x}_i, value, और उन्हें sum करें.

Formula अब bookkeeping है:

Attention(Q,K,V)=softmax ⁣(QKdk+M)V\mathrm{Attention}(Q, K, V) = \mathrm{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}} + M\right)V

जहाँ MM causal mask है, diagonal पर और उसके नीचे zero, और ऊपर -\infty. Code में यह तीस lines है, जिनमें से twenty shapes हैं:

attention.pyPYTHON
class Head(nn.Module):
    """One head of causal self-attention."""

    def __init__(self, d_model, d_head, block):
        super().__init__()
        self.q = nn.Linear(d_model, d_head, bias=False)      
        self.k = nn.Linear(d_model, d_head, bias=False)      
        self.v = nn.Linear(d_model, d_head, bias=False)      
        self.d_head = d_head
        self.register_buffer("mask", torch.tril(torch.ones(block, block)).bool())

    def forward(self, x):
        T = x.shape[1]
        q, k, v = self.q(x), self.k(x), self.v(x)
        s = q @ k.transpose(-2, -1) / math.sqrt(self.d_head)          
        s = s.masked_fill(~self.mask[:T, :T], float("-inf"))          
        w = F.softmax(s, dim=-1)                                      
        return w @ v                                                  

Score, mask, normalise, mix. बाकी सब projection है.

dk\sqrt{d_k} की लगभग हर explanation कहती है “softmax को saturate होने से रोकने के लिए”, जो सही है और कुछ explain नहीं करती. Argument Chapter 2 की variance की दो lines है. अगर q\mathbf{q} और k\mathbf{k} की entries independent हैं, mean zero और variance one के साथ, तो हर product qjkjq_j k_j का variance one है, और independent चीज़ों के variances add होते हैं:

Var(qk)=j=1dkVar(qjkj)=dk\mathrm{Var}(\mathbf{q}\cdot\mathbf{k}) = \sum_{j=1}^{d_k}\mathrm{Var}(q_j k_j) = d_k

तो scores की standard deviation dk\sqrt{d_k} है. Twenty thousand random pairs पर measured:

TEXT
     d     Var(q.k)         std   sqrt(d)
     4        3.975       1.994     2.000
    16       16.071       4.009     4.000
    64       64.249       8.016     8.000
   256      253.065      15.908    16.000
  1024     1015.562      31.868    32.000

यह क्यों matter करता है: softmax scale-sensitive है, जिस तरह linear layer नहीं होती. Linear layer के input को double करने से output double होता है; softmax से पहले scores को ten से multiply करने से soft blend hard choice बन जाता है. 64 scores की एक row, division के साथ और बिना:

dkd_klargest weight, undividedentropyeffective tokenslargest weight, dividedentropyeffective tokens
40.2052.94419.00.0813.75842.9
160.4381.6925.40.0753.84946.9
640.4890.8742.40.0853.67339.4
2560.99990.00071.00.1433.54734.7
10241.00000.00001.00.1323.64438.3

“Effective tokens” entropy का exponential है: row सच में कितनी positions पर average करती है. Undivided, dk=256d_k = 256 पर, freshly initialised head 64 में से exactly एक token पर attend करता है, जिसे random draw के अलावा कुछ नहीं चुनता.

यह forward में bad है और backward में worse, उसी shape में जिसे Chapter 5 ने पहले ही एक tanh\tanh पर मापा था. One entry पर committed softmax की derivative लगभग नहीं होती: उसके Jacobian का diagonal wi(1wi)w_i(1-w_i) है, दोनों ends पर zero. Two thousand random rows पर:

dkd_kiwi(1wi)\sum_i w_i(1-w_i) undivideddividedrows saturated (largest weight above 0.99)
40.84270.95680.2 % → 0.0 %
640.29400.960917.9 % → 0.0 %
2560.14060.960949.1 % → 0.0 %
10240.06810.961170.4 % → 0.0 %

dk=1024d_k = 1024 पर, ten में seven rows training शुरू होने से पहले frozen हैं, और जो head frozen शुरू होता है वह क्या देखना है सीख नहीं सकता. Divided होने पर quantity हर width पर 0.96 पर flat है और कुछ saturate नहीं होता.

अब वह part जो कोई publish नहीं करता: क्या इससे final perplexity बदलती है? Division delete करें और four head widths पर train करें:

head widthundivideddivided by dk\sqrt{d_k}divided by dkd_k
four heads, dk=32d_k = 3237.2938.0737.89
one head, dk=128d_k = 12848.5146.1045.99
one head, dk=256d_k = 25665.3747.53
one head, dk=512d_k = 51267.0649.15
one head, dk=1024d_k = 102476.6959.17

पहली दो rows ऊपर के 3000-step budget से आती हैं; last three shorter run हैं — 1500 steps, batch 32, one head, projections से पहले no normalisation — दोनों variants identical settings के साथ.

dk=32d_k = 32 पर division की कीमत कुछ नहीं और उसके बिना run बहुत थोड़ा आगे है. यह उसे drop करने का licence नहीं है, क्योंकि 256 पर यह perplexity के 18 points और 1024 पर 17 points के बराबर है. Mechanism scores में खुद दिखता है:

dkd_kscore std at initafter 1500 steps, undividedafter 1500 steps, dividedrows saturated, undivideddivided
25610.49121.672.1391.9 %0.8 %
51215.13836.852.6698.7 %1.3 %
102421.155147.463.4499.9 %16.5 %

Undivided head recover नहीं करता. वह run away करता है: उसके scores की standard deviation initialisation पर 21 से 5147 हो जाती है, attention entropy zero तक गिर जाती है, और 99.9 % rows अपना 0.99 से अधिक weight single token पर रखती हैं. एक बार head hard selector बन जाए तो उसका gradient nearly zero होता है और कुछ उसे वापस नहीं खींचता, इसलिए collapse stable है. Divided head उसी training के बाद 3.44 की score standard deviation पर बैठता है, जो soft blend है जिसे अभी भी बदला जा सकता है.

Vaswani et al. exactly यही और इससे अधिक नहीं कहते — उन्हें suspect है कि products “dkd_k के large values के लिए magnitude में grow large” होते हैं और divide करते हैं.5 Word large load-bearing है, और tables बताती हैं कि large कहाँ शुरू होता है: 32 पर कुछ नहीं, 256 तक everything.

एक से अधिक opinion, और वे two thirds जिनकी बात कोई नहीं करता

सेक्शन का लिंक: एक से अधिक opinion, और वे two thirds जिनकी बात कोई नहीं करता

One head हर position के लिए one softmax row है, इसलिए “यहाँ क्या relevant है” का one answer रखता है. the animal that crossed the wet street में the के बाद word predict करने के लिए syntactic slot, subject और previous token एक साथ चाहिए, और one probability distribution तीन जगह concentrate नहीं हो सकता. इसलिए कई heads parallel चलाएँ, हर एक width dmodel/hd_{\text{model}}/h का, concatenate करें, और एक और matrix WoW_o से mix करें: आपने width partition की है, add नहीं की.

Attention exactly एक काम भी करता है — positions के बीच information move करता है. ऊपर के code में हर operation feature axis के साथ linear है, और Chapter 5 ने prove किया कि linear maps का stack क्या होता है. इसलिए हर block एक छोटा MLP भी रखता है जो हर position पर independently apply होता है, width को four से expand करके वापस आता है, बीच में GELU के साथ. Labour division याद रखने लायक है: attention positions के across mix करता है, feed-forward network position के भीतर compute करता है.

पूरी ladder, हर row अपने ऊपर वाली row में एक piece add करती है:

modelparametersvalidation perplexity
uniform average, added279,55260.45
one attention head, token को replace करते हुए328,70455.47
one attention head, added328,70446.10
one के बजाय four heads345,21643.21
plus feed-forward network476,92839.87
plus LayerNorm — complete block477,69638.07

Learned weights uniform ones को perplexity के 14 points से beat करते हैं, जो एक row में इस chapter का पूरा argument है. Four heads 16,512 extra parameters के लिए another 3 खरीदते हैं. और same head replacing की तुलना में added होने पर 9 points अधिक worth है: attention information लाता है, यह decide नहीं करता कि position क्या है.

अब parameters वास्तव में कहाँ बैठते हैं, जो diagram ही देखने वालों को surprise करता है:

widthheadsattentionfeed-forwardtotal per block
128465,664 (33.2 %)131,712 (66.6 %)197,888
768122,360,064 (33.3 %)4,722,432 (66.6 %)7,085,568
40963267,112,960 (33.3 %)134,238,208 (66.7 %)201,367,552

हर transformer block के two thirds feed-forward network हैं, हर scale पर, क्योंकि attention के पास चार d×dd \times d matrices हैं और MLP के पास उसके equivalent eight. Model जो भी जानता हो, उसे hold करने वाले अधिकांश parameters per-position MLP में हैं.

LayerNorm Chapter 6 में बनाया और measured किया गया था, और यह chapter उसे वहीं छोड़े गए रूप में use करता है; residual connections वहाँ named और ablated थे, और यहाँ बनाए गए हैं. ऊपर की “added, not replacing” rows residual connections हैं, average के लिए perplexity के 188 points और one head के लिए 9 worth. LayerNorm7 हर example को उसके features के across normalise करता है, और Chapter 6 ने कारण दिए कि यहाँ BatchNorm नहीं बल्कि यही क्यों survive हुआ — batch पर no dependence, no running statistics, training और inference में identical, sequence length के प्रति indifferent — ये सभी तब requirement बनते हैं जब आप एक user के लिए एक time पर one token generate करते हैं, जहाँ Chapter 13 पहुँचता है. इसकी cost 768 parameters है और यह perplexity के 1.8 points खरीदता है.

block.pyPYTHON
class Block(nn.Module):
    def forward(self, x):
        x = x + self.att(self.ln1(x))     
        x = x + self.ff(self.ln2(x))      
        return x

देखिए normalisation कहाँ बैठता है: हर sub-layer के input पर, input से output तक residual path कभी normalised नहीं. यह pre-norm है. 2017 paper opposite करता है, x = LayerNorm(x + Att(x))post-norm, जो residual path पर ही LayerNorm रखता है.

Xiong et al. ने difference को initialisation पर gradient के through explain किया, जो post-norm network में depth के साथ badly scaled होता है — यही कारण कि original transformer को train करने के लिए learning-rate warmup चाहिए था.8 Twelve blocks, 1000 steps, learning rate 3×1033 \times 10^{-3}:

TEXT
gradient norm per block at initialisation, before any step
  pre-norm    block 1 0.0498 ... block 12 0.0657   ratio last/first  1.32
  post-norm   block 1 0.0977 ... block 12 0.1613   ratio last/first  1.65

  pre-norm,  no warmup          perplexity   37.82
  pre-norm,  200-step warmup    perplexity   37.62
  post-norm, no warmup          perplexity  308.05
  post-norm, 200-step warmup    perplexity   37.88

Warmup के बिना post-norm eight times worse है, और warmup के साथ post-norm pre-norm से exactly match करता है. यहाँ warmup कोई general good practice नहीं; यह normalisation की specific arrangement के लिए patch है, और LayerNorm को move करने से इसकी ज़रूरत हट जाती है. इसलिए 2019 के बाद से लगभग हर model pre-norm है, और 2017 diagram को specification के बजाय history की तरह पढ़ना चाहिए.

Position embeddings delete करें और model फिर भी train करता है; वह बस यह नहीं बता सकता कि कुछ कहाँ है, और यह training failure नहीं बल्कि symmetry है. Attention score में खुद tt या ii का कोई mention नहीं, इसलिए input permute करने से output permute हो जाता है: self-attention permutation-equivariant है. यह average की order-blindness का बेहतर disguise है — causal mask कुछ order restore करता है, क्योंकि हर position different prefix देखती है, लेकिन prefix के भीतर सभी orderings alike हैं.

Position inject करने के four ways, 64-token windows पर trained और 64, 128 और 256 पर evaluated — किसी भी seen length से आगे:

positionsperplexity at 64at 128at 256
बिल्कुल none48.7952.6357.52
learned absolute embeddings38.63108.47181.94
fixed sinusoids42.9695.26152.25
RoPE44.1250.5284.84
ALiBi44.9543.5142.49

Learned absolute embeddings — हर position के लिए one vector, token में added — trained length पर जीतते हैं और फिर cliff से गिरते हैं, क्योंकि position 100 कभी batch में नहीं था और उसकी embedding अभी भी वही random vector है जिससे वह शुरू हुई थी. Sinusoids, original choice, learned नहीं बल्कि computed हैं, geometrically spaced frequencies पर sines और cosines से; 2017 paper ने उम्मीद की कि यह extrapolate करेगा, और table कहती है कि नहीं — function position 200 पर defined है, लेकिन model ने उसे वहाँ पढ़ना कभी नहीं सीखा. RoPE9 कुछ add नहीं करता और इसके बजाय query और key को position के proportional angle से, two-dimensional slices में rotate करता है; क्योंकि dot product के दोनों sides को equally rotate करने से वह unchanged रहता है, score अंततः केवल tit - i पर depend करता है, इसलिए position free में relative बन जाती है और कोई table खत्म नहीं होती. यह degrade करता है, पर degrade करता है. ALiBi10 यहाँ सबसे simple और सबसे strange result है: distance के proportional score पर linear penalty, हर head के लिए different slope के साथ. Window training length से आगे बढ़ने पर इसकी perplexity improve होती है, 44.95 से 42.49, क्योंकि penalty किसी भी distance पर defined है और हर head वही करता रहता है जिसके लिए train हुआ था.

Lesson table से अधिक टिकता है: जो architecture किसी चीज़ को represent नहीं कर सकती, वह उस चीज़ से अलग problem है जिसने वह range कभी learn नहीं की, और काटती दूसरी ही है. यही machinery हर “हमने context को 128K तक extend किया” announcement के पीछे भी है — वे लगभग हमेशा rotary encoding की re-scalings हैं, और इसी कारण Chapter 16 कहता है कि context limit disappear नहीं होती, move होती है.

Dropout भी उसी तरह inherited है: यह softmax के बाद attention weights पर, residual addition से पहले हर sub-layer के output पर, और embedding sum पर आता है, exactly वही करते हुए जो Chapter 6 ने describe किया. Large pretraining runs में इसे अक्सर zero set किया जाता है, क्योंकि जो model हर token को once देखता है वह overfit करने की position में नहीं होता.

Layer में दो tensors का shape n×nn \times n है, जहाँ nn tokens की संख्या है: scores और softmax के बाद weights. बाकी सब — हर projection, पूरा MLP — nn में linear है.

One attention layer, 512 wide, 8 heads, batch one, float32, laptop GPU पर. दो millisecond columns को केवल उनके ratios के लिए पढ़ें: वे 8 GB laptop card पर wall clock हैं जो गरम होने पर 1,785 MHz से under 300 MHz तक throttle करता है, इसलिए इसी code का cold run seven to ten times faster लौटता है और busy one उससे भी slow. Megabyte columns allocator byte counts हैं और नहीं बदलते.

TEXT
  tokens   ms total    ms x4   ms projections   attn matrix MB    peak MB    MB x4
     128      2.246        -            1.324              0.5       14.6        -
     256      2.855     1.27            2.113              2.0       19.2     1.31
     512      5.761     2.02            3.105              8.0       34.4     1.79
    1024     16.414     2.85            4.008             32.0       89.1     2.59
    2048     51.573     3.14            9.989            128.0      296.1     3.32
    4096    225.432     4.37           20.176            512.0     1100.1     3.72
    8192    832.838     3.69           40.106           2048.0     4300.1     3.91
   16384   OUT OF MEMORY                                 8192.0

fitted exponent (log-log slope, last four rows):  time ~ n^1.91   memory ~ n^1.87

x4 columns ऊपर वाली row के ratio हैं, और nn का doubling time और memory दोनों के लिए exactly 4 पर converge करता है — theoretical 4 के मुकाबले last step पर 3.91. Projections column control है: 1024 tokens पर 4.0 ms से 8192 पर 40.1 ms, factor eight के लिए factor ten. Linear, जैसा advertise किया.

फिर last row. One attention layer, one sequence, उसके आसपास कोई model नहीं, 16,384 tokens पर 8 GB GPU की memory खत्म कर देता है — score matrix अकेली 8 GB होगी, क्योंकि 8 heads times 16,384 times 16,384 times 4 bytes. Model नहीं; one layer में one intermediate tensor.

यही physical fact तीन later chapters के नीचे है. इसी वजह से context window की limit होती है, जिसे Chapter 16 price में बदलता है. इसी वजह से FlashAttention exists करता है, same result को tiles में compute करते हुए बिना matrix store किए — speed optimisation होने से पहले memory optimisation.11 और यही long prompt की price के पीछे arithmetic है, जिसे Chapter 24 agent loop में pay करता है — उस chapter की दूसरी finding से अलग matter, कि model long context को worse use भी करता है, जिसे वह measure करता है और इस formula पर blame करने से मना करता है.

विवरण दिखाएँ

दो cache-shrinking variants, यहाँ named और Chapter 13 में paid for.

Generation पहले processed tokens की keys और values cache करती है — हर token के लिए one key और one value, per head per layer. Multi-query attention12 hh query projections रखता है लेकिन सभी heads द्वारा shared single key और value projection, उस cache को hh से divide करता है. Grouped-query attention13 interpolate करता है: heads grouped हैं, हर group one key और value share करता है, इसलिए g=hg = h ordinary attention है और g=1g = 1 multi-query. 2023 के बाद से लगभग हर open model इसे 4 या 8 groups के साथ use करता है. दोनों quality के लिए नहीं हैं; दोनों उस cache के size के लिए हैं, और Chapter 13 वह arithmetic करता है जो इसे “कौन सा model आपके GPU में fit होता है” में बदलता है.

2017 paper एक encoder-decoder describe करता है: source को unmasked attention से पढ़ता one stack, target को causally generate करता second, और बीच में third kind of attention जहाँ decoder की queries encoder की keys से मिलती हैं. Translation के लिए यह सही है, जहाँ input और output two sequences हैं.

जो जीता वह decoder-only half था — one stack, पूरे में causal, input और output same sequence में — और reason elegance नहीं है. “अगला token predict करो” किसी भी text पर चलता है, इसलिए training set parallel corpus के बजाय internet है, और सब कुछ वही one task बन जाता है: translation source फिर target वाला document है, question और उसका answer एक document हैं, बीच में tool call वाली conversation एक document है. Chapter 11 इस बारे में है कि last one कैसे manufactured होता है. Encoders गायब नहीं हुए — एक encoder पूरे input को once देखता है, जो आप तब चाहते हैं जब job text को represent करना हो, continue करना नहीं, और इसलिए Chapter 19 की retrieval embeddings encoders से आती हैं, chatting करने वाले model से नहीं.

Block defined होने पर, model size arithmetic है. Per block, width dd और four-times expansion के साथ: 4d2+4d4d^2 + 4d for Wq,Wk,Wv,WoW_q, W_k, W_v, W_o with biases on all four, जैसा GPT-2 में है — ऊपर की table उनमें से three से bias छोड़ती है, इसलिए d=768d = 768 पर per block 2,304 कम; MLP के लिए 8d2+5d8d^2 + 5d; दो LayerNorms के लिए 4d4d12d2+13d12d^2 + 13d, plus V×dV \times d की token table और, absolute positions के लिए, nctx×dn_{\text{ctx}} \times d. GPT-2 small के shape के लिए — d=768d = 768, 12 blocks, 50,257 की vocabulary, 1024 का context, output layer embedding weights share करती हुई:

TEXT
  token embeddings     50,257 x 768 = 38,597,376
  position embeddings   1,024 x 768 =    786,432
  one block                             7,087,872
  12 blocks                            85,054,464
  final LayerNorm         2 x 768 =        1,536
  total (weights tied)                124,439,808

जो उस model का published size है. Formula approximation नहीं है; वही model है. यह भी note करें कि small model का nearly a third embedding table है, इसलिए vocabulary size architectural decision है, preprocessing decision नहीं — वही trade-off जिसे Chapter 7 ने set up किया.

Perplexity corpus के बारे में number है. One head क्या करता है, यह अलग question है, और Shakespeare के एक megabyte पर trained model उसके लिए गलत instrument है: 500,000-parameter model के attention map के बारे में honest बात यह कहना है कि वह mostly interpretable नहीं है. तो: एक language जहाँ question का right answer है.

Classic illustration है the animal did not cross the street because it was too tired, जहाँ it animal है, बनाम …because it was too wet, जहाँ one word referent को street पर move करता है. ये Winograd schemas14 हैं — sentence pairs जो one word को छोड़कर identical हैं, और वही word decide करता है कि pronoun किसे refer करता है.

वे cheating से solvable भी हैं, जो tutorials skip करते हैं. अगर two candidates animal और place हैं, तो tired और wet referent को category से identify करते हैं, और जो model केवल यह जानता है कि कौन से words present हैं वह order के बारे में कुछ जाने बिना सही हो जाता है. Task के उस version पर measured, held-out animal/place pairs के साथ:

TEXT
uniform causal average           held-out referent accuracy 100.0 %
one transformer block            held-out referent accuracy  91.7 %

Bag of words transformer को beat करता है. उस sentence पर बनी कोई भी demonstration attention के बारे में कुछ prove नहीं करती.

तो hole बंद करें: दोनों candidates को sixteen nouns के one pool से draw करें, जिनमें से कोई भी किसी भी slot में आ सकता है, और adjectives को category के बजाय role से split करें — four जो it को crosser बनाते हैं (tired, scared, slow, weak), four जो crossed बनाते हैं (wet, wide, busy, steep).

TEXT
the {x} did not cross the {y} because it was too {adj} , so the {ref} waited .

Ordinary next-token predictor की तरह train करें, one position score करें — so the के बाद word — और held-out set उन noun pairs से build करें जिनका reversed order training में था, ताकि जो भी केवल यह जानता है कि कौन से two nouns present हैं लेकिन कौन पहले आया नहीं जानता, उसे backwards answer करना पड़े.

modelparametersheld-outother noun नाम करता है
current token only5,7965.2 %5.2 %
uniform causal average5,79627.9 %50.0 %
learned attention का one head18,08435.4 %64.6 %
four heads22,24475.0 %15.6 %
one transformer block55,71692.7 %4.2 %
two transformer blocks105,508100.0 %0.0 %

Present two nouns के बीच chance 50 % है. Uniform average 27.9 % पर land करता है और pair के wrong noun exactly half the time से answer करता है — उस चीज़ की signature जो जानती है कि कौन से words वहाँ हैं और उनके order के बारे में कुछ नहीं, जैसा shuffle test ने तीन sections पहले predict किया.

अब map: referent नाम करने वाली position पर attention, हर block के four heads पर averaged, उन two sentences के लिए जो one word से differ करते हैं. Uniform average fifteen visible tokens में से हर एक पर 0.067 रखता.

TEXT
the animal did not cross the street because it was too tired , so the animal waited .
  blk 1  the:0.00 animal:0.70 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.06
         because:0.00 it:0.00 was:0.00 too:0.00 tired:0.00 ,:0.05 so:0.00 the:0.19
  blk 2  the:0.00 animal:0.00 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.00
         because:0.00 it:0.00 was:0.00 too:0.00 tired:1.00 ,:0.00 so:0.00 the:0.00

the animal did not cross the street because it was too wet , so the street waited .
  blk 1  the:0.00 animal:0.70 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.06
         because:0.00 it:0.00 was:0.00 too:0.00   wet:0.00 ,:0.05 so:0.00 the:0.19
  blk 2  the:0.00 animal:0.00 did:0.00 not:0.00 cross:0.03 the:0.00 street:0.49
         because:0.00 it:0.00 was:0.00 too:0.20   wet:0.03 ,:0.00 so:0.00 the:0.25

Block 1 दोनों sentences में identical है — first noun पर 0.70, adjective जो भी हो. यह failure नहीं बल्कि proof है: first layer में position पर query उस position के own token और index का function है, और position 14 पर the दोनों sentences में same token है. First-layer head उस word पर condition नहीं कर सकता जिसे उसने अभी fetched नहीं किया. इसलिए block 1 उपलब्ध एकमात्र useful चीज़ करता है और first noun को forward खींचता है.

Block 2 वह है जहाँ sentences अलग होते हैं, और all eight adjectives पर same row model ने पाया rule दिखाती है:

adjectiveblock 2 on animalon streeton the adjectiveanswer
tired, scared, slow, weak0.0000.0001.000animal
wet, wide, busy, steep0.0000.4910.00–0.03street

Crosser-adjective के लिए second block अपना पूरा weight adjective पर spend करता है, क्योंकि answer residual stream में पहले से है — block 1 ने उसे वहाँ रखा — और उसे बस confirmation चाहिए. Crossed-adjective के लिए यह जाकर other noun fetch करता है. यह two-hop circuit है: one head candidate को forward move करता है, later layer में head एक token पढ़ता है जो decide करता है कि उसे keep करना है या नहीं. Layers के across composition mechanism है, और इसी कारण one block 92.7 % और two 100 % पहुँचे.

यह real models में best-documented circuit का shape भी है. Induction heads — previous-token head feeding a head in the next layer that completes the pattern [A][B] … [A] → [B] — वही हैं जिन्हें Anthropic का interpretability work in-context learning के बड़े हिस्से के पीछे identify करता है, और वे pretraining के दौरान identifiable moment पर form होते हैं. यह chapter वह analysis attempt नहीं करता: उसे references में दोनों papers के साथ delegate किया गया है, क्योंकि real model से circuits पढ़ना research field है, section नहीं.

आखिर में, implementation. ऊपर की thirty lines, जिनके weights PyTorch के अपने से copied हैं:

TEXT
ours vs nn.MultiheadAttention           max |diff| = 1.7881393432617188e-07
ours vs F.scaled_dot_product_attention  max |diff| = 1.7881393432617188e-07

Mean magnitude 0.159 वाले outputs पर 1.8×1071.8 \times 10^{-7}: same arithmetic different order में, float32 precision पर.

आपके पास वह architecture है जिससे इस course के बाकी हर model built है, और यह अपनी reputation से छोटी है: एक weighted average जिसके weights learned हैं, two thirds parameters रखता per-position MLP, दो normalisations और दो additions, stacked.

आपके पास जो नहीं है वह ऐसा model है जो कुछ जानता हो, और stacking अकेले इसे fix नहीं करेगी. इस corpus पर two blocks training perplexity 14.49 और validation perplexity 40.57 तक पहुँचते हैं, one block के 18.77 और 38.07 के मुकाबले — more capacity, जो देखा है उस पर better, जो नहीं देखा उस पर worse, यानी Chapter 6 की table जिसमें transformer है. इस model और Chapters 14 से 30 जिन models से बात करते हैं उनके बीच distance architectural नहीं है. यह वही block है, अधिक बार repeated, बहुत अधिक text पर.

जिससे यह accounting problem बन जाता है, और accounting दिखने से ज्यादा strange है. कितना text, और कोई उसे कहाँ से पाता है? कितना arithmetic, और पैसे खर्च होने से पहले आप उसे estimate कैसे करते हैं? Fixed budget के साथ, model बड़ा बनाना बेहतर है या उसे अधिक data दिखाना — और क्या कोई correct answer है, या केवल fashion? Chapter 10 measurement से तीनों का answer देता है, और question के सबसे cheap useful form पर price लगाता है: आज, scratch से GPT-2 जैसा model train करने की cost क्या है?


इस material की तीन explanations अपने उद्देश्य के लिए इससे बेहतर हैं, और यह chapter उनके साथ पढ़े जाने के लिए लिखा गया है. Jay Alammar की The Illustrated Transformer data flow की अब तक draw की गई best picture है. Harvard NLP की The Annotated Transformer 2017 paper है जिसमें running code line by line interleaved है. Andrej Karpathy की Let’s build GPT: from scratch, in code, spelled out वही model दो hours में live build करती है, और ऊपर की ablations की ladder वही spine है जिसे different corpus पर measured किया गया है. Interpretability question के लिए जिसे यह chapter केवल touch करता है, primary sources Elhage et al., A Mathematical Framework for Transformer Circuits (2021) और Olsson et al., In-context Learning and Induction Heads (2022) हैं, दोनों Anthropic के interpretability group से.

  1. Hochreiter, S. और Schmidhuber, J. Long Short-Term Memory. Neural Computation 9(8), pp. 1735–1780 (1997).

  2. Sutskever, I., Vinyals, O. और Le, Q. V. Sequence to Sequence Learning with Neural Networks. arXiv:1409.3215 (2014). वह encoder-decoder जिसका single context vector bottleneck है.

  3. Bahdanau, D., Cho, K. और Bengio, Y. Neural Machine Translation by Jointly Learning to Align and Translate. arXiv:1409.0473 (2014). Attention, transformer से तीन साल पहले.

  4. Perplexity mean cross-entropy per token का exponential है, Chapter 8 से. यहाँ हर number same tokenizer और same validation split use करता है, जो एकमात्र condition है जिसके तहत two perplexities की तुलना की जा सकती है.

  5. Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł. और Polosukhin, I. Attention Is All You Need. arXiv:1706.03762 (2017). Section 3.2.1 dk\sqrt{d_k} के बारे में वह one sentence है जिसे यह chapter एक section भर measure करता है.

  6. Shazeer, N., Mirhoseini, A., Maziarz, K., Davis, A., Le, Q., Hinton, G. और Dean, J. Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer. arXiv:1701.06538 (2017).

  7. Ba, J. L., Kiros, J. R. और Hinton, G. E. Layer Normalization. arXiv:1607.06450 (2016). Chapter 6 में introduced और measured; यहाँ unchanged used.

  8. Xiong, R., Yang, Y., He, D., Zheng, K., Zheng, S., Xing, C., Zhang, H., Lan, Y., Wang, L. और Liu, T.-Y. On Layer Normalization in the Transformer Architecture. arXiv:2002.04745 (2020). Pre-norm के पीछे gradient analysis, और argument कि warmup symptom है.

  9. Su, J., Lu, Y., Pan, S., Murtadha, A., Wen, B. और Liu, Y. RoFormer: Enhanced Transformer with Rotary Position Embedding. arXiv:2104.09864 (2021).

  10. Press, O., Smith, N. A. और Lewis, M. Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation. arXiv:2108.12409 (2021). ऊपर reproduced extrapolation result.

  11. Dao, T., Fu, D. Y., Ermon, S., Rudra, A. और Ré, C. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135 (2022).

  12. Shazeer, N. Fast Transformer Decoding: One Write-Head is All You Need. arXiv:1911.02150 (2019).

  13. Ainslie, J., Lee-Thorp, J., de Jong, M., Zemlyanskiy, Y., Lebrón, F. और Sanghai, S. GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints. arXiv:2305.13245 (2023).

  14. Levesque, H. J., Davis, E. और Morgenstern, L. The Winograd Schema Challenge. KR (2012). हर attention tutorial द्वारा use किए जाने वाले animal / street sentence के पीछे construction.


निर्माता

David Vicente Campos

NeuraLIA Labs के संस्थापक और MyRealFood के सह-संस्थापक

मैं लेओन विश्वविद्यालय से कंप्यूटर इंजीनियर हूँ। मैंने MyRealFood की सह-स्थापना की, जहाँ CTO के रूप में मैंने वह ऐप बनाया जिसे लाखों लोग बेहतर खान-पान के लिए इस्तेमाल कर चुके हैं, और मैंने NeuraLIA Labs की स्थापना की, जहाँ मैं AI प्रोडक्ट्स बनाता हूँ। यहाँ मैं उन बातों के बारे में लिखता हूँ जो इस सफ़र में मुझे समझनी पड़ीं, उस तरह जिस तरह काश किसी ने मुझे समझाई होतीं।

लेखक के बारे में और जानें

NeuraLIA Labs द्वारा प्रकाशित।

नए पोस्ट अपने इनबॉक्स में पाएं

AI समाचार, गाइड और प्रोडक्ट अपडेट — जब भी हम कुछ उपयोगी प्रकाशित करें, एक छोटा ईमेल।

कोर्स सूची

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev13 मिनट पढ़ें

Jev AI मॉडल गद्य के लिए नहीं, निर्णयों के लिए बना है

TypeSafe AI का Jev ध्यान खींच रहा है क्योंकि यह सॉफ्टवेयर इंटेलिजेंस को संभावना की समस्या मानता है: सही शाखा चुनें, भरोसे का स्तर जोड़ें, और जब कोड को निर्णय चाहिए तो LLM से टेक्स्ट लिखवाने पर खर्च न करें।

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering14 मिनट पढ़ें

लॉन्ग-होराइजन AI एजेंट्स के लिए कॉन्टेक्स्ट इंजीनियरिंग

लंबे समय तक चलने वाले एजेंट सिर्फ इसलिए असफल नहीं होते कि विंडो छोटी है। वे तब असफल होते हैं जब फ़ाइलें, टूल आउटपुट और पुराना इतिहास उस काम को ही पीछे धकेल देते हैं जिसे एजेंट को पूरा करना था।

मॉडल चुनने का काम LIA पर छोड़ने के लिए तैयार हैं?

हर AI मॉडल एक ही जगह — आज ही मुफ़्त शुरू करें।