Attention اور Transformer block: ایک اوسط سے اخذ شدہ
context کے سستے ترین خلاصے، اوسط، سے شروع کریں؛ اس کی ناکامی ناپیں، اور attention formula کو مرمت سے نکلتا دیکھیں۔
اس صفحے پر
آپ یہاں Chapter 7 کے tokenizer، Chapter 8 کی embedding table، اور ان کے ساتھ آنے والے objective کے ساتھ پہنچتے ہیں: اب تک کے tokens دیے جائیں تو اگلے token پر probability لگانی ہے۔
جو چیز غائب ہے وہ درمیان ہے۔ token predict کرنے کے لیے model کو اپنے سے پہلے سب کچھ summarize کرنے والا ایک vector چاہیے، اور آپ نے اب تک جو کچھ بنایا ہے وہ ایسا vector نہیں دیتا۔ token کی embedding وہ نہیں — وہ bigram model ہے، اور اسے معلوم نہیں ہو سکتا کہ sentence ایک question سے شروع ہوا تھا۔ پچھلی تمام embeddings کی concatenation بھی نہیں: ان کی تعداد ہر step پر بدلتی ہے، اور fixed weight matrix variable-length input نہیں لے سکتی۔
تو: ایک fixed-size vector، جو vectors کی variable تعداد کو summarize کرے۔ یہی پورا مسئلہ ہے، اور attention وہ چیز ہے جو اسے سب سے سست طریقے سے حل کرنے اور پھر ٹوٹنے والی دو چیزوں کی مرمت کرنے سے ملتی ہے۔
field کے پاس جو answer تھا، اور ہم اسے کیوں نہیں بنا رہے
اس حصے کا لنک: field کے پاس جو answer تھا، اور ہم اسے کیوں نہیں بنا رہے1997 سے تقریباً 2017 تک summary ایک recurrent state تھا: ایک vector رکھیں اور ہر token پر اسے update کریں، ۔ fixed size، variable input، بالکل درست shape۔
یہ تین طریقوں سے ناکام ہوا، اور اس chapter کا architecture تینوں کا answer دیتا ہے۔ steps کے ذریعے Backpropagating کرنے سے Jacobians multiply ہوتے ہیں، اس لیے gradient غائب یا explode ہو جاتا ہے — وہی بیماری جو Chapter 5 نے ایک واحد node کے اندر ناپی تھی۔ LSTM1 اسی کے خلاف design کیا گیا تھا اور usable range کو tens of steps سے hundreds تک لے گیا، مگر یہ fact نہیں بدلا کہ 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 کو تمام encoder states کا weighted sum لینے دیا، جس کے weights وہ خود compute کرتا تھا۔3 نیچے سب کچھ وہی idea ہے، جسے ایک sequence نے خود اپنے اوپر apply کیا ہے، recurrence حذف کر کے۔ اور update اپنی construction ہی سے sequential ہے: کو چاہیے، اور دس ہزار cores والا GPU اس کے ساتھ کچھ نہیں کر سکتا۔ جو architecture جیتا وہ لازماً زیادہ smart نہیں؛ وہ وہ ہے جس کا expensive step matrix multiply ہے۔
دوسرا classical inductive bias، convolution — پورے input پر ایک چھوٹا filter slide کریں، تاکہ کہیں بھی detect ہونے والا feature ہر جگہ detect ہو — یہاں بھی نہیں بنایا گیا؛ یہ images کے لیے تقریباً بالکل درست ہے اور vision course کے حوالے کیا گیا ہے۔ recurrence اور convolution میں سے کوئی بھی اس page کے بعد دوبارہ نہیں آتا، اسی لیے کسی کو chapter نہیں ملتا: Chapter 1 نے promise کیا تھا کہ omissions کو خاموشی سے نہیں بلکہ صاف بتایا جائے گا۔
سب سے سستا summary
اس حصے کا لنک: سب سے سستا summaryvectors کی variable تعداد سے ایک vector واپس کرنے والا سب سے obvious function average ہے:
inputs جتنے بھی ہوں، output size fixed، differentiable، free۔ Embedding table جمع یہ average جمع vocabulary تک linear layer — پندرہ lines میں مکمل language model۔ یہ بہت برا بھی ہے، اور یہ کس طرح برا ہے، یہی پوری derivation ہے۔
نیچے corpus Shakespeare کا ایک megabyte ہے، 1,115,394 characters، Chapter 7 میں بنائے گئے type کے byte-level BPE tokenizer سے، vocabulary 1024: 459,760 tokens، ہر ایک 2.43 characters، split 90/10۔ ہر model 128 wide ہے، 128 tokens دیکھتا ہے، اور 64 کے batch کے ساتھ پر AdamW کے 3000 steps train کرتا ہے۔ Perplexity held-out split پر ہے۔4
| model | parameters | validation perplexity |
|---|---|---|
| صرف current token، context بالکل نہیں | 263,168 | 59.71 |
| plus اس سے پہلے سب کچھ کا uniform average | 263,168 | 248.07 |
| plus learned position embeddings | 279,552 | 245.93 |
| uniform average کو token replace کرنے کے بجائے add کیا گیا | 263,168 | 60.45 |
دوسری row دو بار پڑھیں۔ context کا average تھوڑی مدد نہیں کرتا؛ یہ model کو context کو مکمل ignore کرنے سے چار گنا worse بنا دیتا ہے۔ دو reasons، دونوں empirical کے بجائے provable۔
average order نہیں دیکھ سکتا۔ Addition commutes، اس لیے window shuffle کرنے سے summary unchanged رہتا ہے — تقریباً نہیں، واقعی:
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())2.9802322387695312e-08reordered sum پر floating-point noise: دونوں summaries وہی vector ہیں۔ ایک model جس کا context پر صرف view average ہو، the dog bit the man کو the man bit the dog سے distinguish نہیں کر سکتا۔ row three ثابت کرتی ہے کہ inputs میں positions add کر کے یہ fix نہیں ہوتا — averaging سے پہلے ہر token پر learned position embedding نے 188 میں سے صرف 2.14 points خریدے۔ positions sum میں جاتے ہیں، اور sum انہیں بھلا دیتا ہے۔
اور average present کو drown کر دیتا ہے۔ position 100 پر current token summary کا one hundredth ہے۔ اس کا ایک سستا fix آپ کے پاس پہلے سے ہے: token کو رکھیں اور summary کو اس میں add کریں — Chapter 6 سے residual connection، اور row four دکھاتی ہے کہ یہ کیا کرتا ہے۔ dilution repair ہونے کے بعد uniform average کچھ بھی contribute نہیں کرتا: baseline 59.71 کے مقابلے میں 60.45۔ ہر token وہاں ہے، برابر weighted، اور equal weighting no information کے برابر ہے۔
مسئلہ averaging نہیں۔ مسئلہ weights ہیں۔
average ایک matrix multiply ہے، اور mask ایک softmax ہے
اس حصے کا لنک: average ایک matrix multiply ہے، اور mask ایک softmax ہےgrowing prefix پر averaging loop جیسی لگتی ہے۔ یہ lower-triangular matrix سے ایک multiplication ہے جس کی rows sum to one ہیں — اور عین اسی طرح ایک softmax بھی:
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 againloop 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.167transformer کے تین named components اب screen پر ہیں۔ triangle causal mask ہے، objective کے ذریعے forced: اگر position position دیکھ سکتی، تو answer input میں ہوتا — وہ leak جس کا audit Chapter 6 نے کہا تھا، بس architecture کے اندر۔ softmax وہ طریقہ ہے جس سے mask implement ہوتا ہے: forbidden entries کو set کرنا انہیں exactly zero بھیجتا ہے اور جو باقی رہتا ہے اسے normalise کرتا ہے، اس لیے masking اور normalising ایک operation ہیں۔ (-1e9 نہیں، use کریں: یہی وہ value ہے جس کا masking مطلب ہے، float16 میں cast ہونے پر کے طور پر survive کرتی ہے، اور آپ کو یہ decide کرنے سے بچاتی ہے کہ آپ کا chosen constant اس range کے لیے کافی large ہے یا نہیں جس میں آپ اس وقت ہیں — جو Chapter 2 کا floating-point box ایک ایسا question پوچھ رہا ہے جس کا answer آپ کو نہیں دینا پڑتا۔) اور scores free parameter ہیں۔ uniform average وہ ہے جو آپ کو تب ملتا ہے جب ہر allowed score ایک ہی number ہو؛ کوئی بھی numbers وہاں رکھیں اور softmax انہیں valid weights میں بدل دیتا ہے۔
اس chapter کا باقی حصہ ایک question ہے: یہ numbers آتے کہاں سے ہیں؟
Query، key، value
اس حصے کا لنک: Query، key، valueیہ plain parameters نہیں ہو سکتے۔ ایک learned matrix ہر sentence کے لیے identical ہوتی — یہ “look four tokens back” encode کر سکتی تھی مگر کبھی “look at the noun this pronoun refers to” نہیں۔ position کو position سے link کرنے والا weight دونوں positions پر موجود چیز پر depend کرنا چاہیے، کیونکہ relevance property نہیں relation ہے: word it intrinsically relevant نہیں، یہ کسی چیز کے لیے relevant ہے۔
دو vectors کا سب سے سستا function جو number واپس کرے Chapter 1 کا dot product ہے۔ position کو position کے لیے کے طور پر score کریں اور mechanism کام کرتا ہے — بری طرح، دو ways میں جو باقی سب 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 کیا تلاش کر رہی ہے، ، query؛ اور یہ کس چیز کے طور پر found ہونے کو offer کرتی ہے، ، key۔ score کریں اور symmetry ختم ہو جاتی ہے، کیونکہ : token ایک چیز advertise کر سکتا ہے اور دوسری search کر سکتا ہے۔
ایک چیز اب بھی غلط ہے۔ weighted sum خود پر تھا، جو اس چیز کو جو copy ہوتی ہے اسی چیز پر force کرتا ہے جو match ہوتی ہے۔ Matching وہ features چاہتی ہے جو token identify کرتے ہیں؛ copying وہ features چاہتی ہے جو downstream useful ہیں۔ اس لیے تیسرا map learn کریں، ، value، اور انہیں sum کریں۔
formula اب bookkeeping ہے:
جہاں causal mask ہے، diagonal پر اور اس سے نیچے zero، اور اوپر ۔ code میں یہ thirty lines ہے، جن میں سے twenty shapes ہیں:
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 ہے۔
square root سے division، اور یہ کس کے خلاف defend کرتی ہے
اس حصے کا لنک: square root سے division، اور یہ کس کے خلاف defend کرتی ہےکی تقریباً ہر explanation کہتی ہے “softmax کو saturate ہونے سے بچانے کے لیے”، جو true ہے مگر explain کچھ نہیں کرتی۔ argument Chapter 2 کے variance کی دو lines ہے۔ اگر اور کی entries independent، mean zero اور variance one ہیں، تو ہر product کا variance one ہے، اور independent چیزوں کے variances add ہوتے ہیں:
تو scores کی standard deviation ہے۔ twenty thousand random pairs پر measured:
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 کے ساتھ اور بغیر:
| largest weight, undivided | entropy | effective tokens | largest weight, divided | entropy | effective tokens | |
|---|---|---|---|---|---|---|
| 4 | 0.205 | 2.944 | 19.0 | 0.081 | 3.758 | 42.9 |
| 16 | 0.438 | 1.692 | 5.4 | 0.075 | 3.849 | 46.9 |
| 64 | 0.489 | 0.874 | 2.4 | 0.085 | 3.673 | 39.4 |
| 256 | 0.9999 | 0.0007 | 1.0 | 0.143 | 3.547 | 34.7 |
| 1024 | 1.0000 | 0.0000 | 1.0 | 0.132 | 3.644 | 38.3 |
“Effective tokens” entropy کا exponential ہے: row واقعی کتنی positions پر average کرتی ہے۔ undivided، پر، freshly initialised head 64 میں سے exactly ایک token کو attend کرتا ہے، جسے random draw کے سوا کچھ نہیں چنتا۔
یہ forward میں برا ہے اور backward میں بدتر، ایک shape میں جسے Chapter 5 پہلے ہی پر measure کر چکا ہے۔ ایک softmax جو ایک entry پر committed ہو، اس کا derivative تقریباً نہیں ہوتا: اس کے Jacobian کا diagonal ہے، دونوں ends پر zero۔ two thousand random rows پر:
| undivided | divided | rows saturated (largest weight above 0.99) | |
|---|---|---|---|
| 4 | 0.8427 | 0.9568 | 0.2 % → 0.0 % |
| 64 | 0.2940 | 0.9609 | 17.9 % → 0.0 % |
| 256 | 0.1406 | 0.9609 | 49.1 % → 0.0 % |
| 1024 | 0.0681 | 0.9611 | 70.4 % → 0.0 % |
پر، دس میں سات rows training شروع ہونے سے پہلے frozen ہیں، اور جو head frozen شروع ہو وہ سیکھ نہیں سکتا کہ کہاں دیکھنا ہے۔ divided، quantity ہر width پر 0.96 پر flat ہے اور کچھ saturate نہیں ہوتا۔
اب وہ part جو کوئی publish نہیں کرتا: کیا یہ final perplexity بدلتا ہے؟ division delete کریں اور train کریں، چار head widths پر:
| head width | undivided | divided by | divided by |
|---|---|---|---|
| four heads, | 37.29 | 38.07 | 37.89 |
| one head, | 48.51 | 46.10 | 45.99 |
| one head, | 65.37 | 47.53 | — |
| one head, | 67.06 | 49.15 | — |
| one head, | 76.69 | 59.17 | — |
پہلی دو rows اوپر کے 3000-step budget سے آتی ہیں؛ آخری تین shorter run ہیں — 1500 steps، batch of 32، one head، projections سے پہلے no normalisation — دونوں variants identical settings کے تحت۔
پر division کچھ نہیں دیتی اور اس کے بغیر run بہت ذرا آگے ہے۔ یہ اسے drop کرنے کا licence نہیں، کیونکہ 256 پر یہ 18 perplexity points کے برابر ہے اور 1024 پر 17۔ mechanism scores ہی میں visible ہے:
| score std at init | after 1500 steps, undivided | after 1500 steps, divided | rows saturated, undivided | divided | |
|---|---|---|---|---|---|
| 256 | 10.49 | 121.67 | 2.13 | 91.9 % | 0.8 % |
| 512 | 15.13 | 836.85 | 2.66 | 98.7 % | 1.3 % |
| 1024 | 21.15 | 5147.46 | 3.44 | 99.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 تقریباً zero ہوتا ہے اور کچھ اسے واپس نہیں کھینچتا، اس لیے collapse stable ہے۔ divided head اسی training کے بعد score standard deviation 3.44 پر بیٹھتا ہے، جو soft blend ہے جسے ابھی بھی changed کیا جا سکتا ہے۔
Vaswani et al. عین یہی کہتے ہیں اور اس سے زیادہ نہیں — انہیں suspect ہے کہ products کی large values کے لیے “grow large in magnitude” کرتے ہیں اور divide کرتے ہیں۔5 لفظ large load-bearing ہے، اور tables بتاتی ہیں کہ large کہاں شروع ہوتا ہے: 32 پر کچھ نہیں، 256 تک سب کچھ۔
ایک سے زیادہ opinion، اور وہ دو thirds جن پر کوئی بات نہیں کرتا
اس حصے کا لنک: ایک سے زیادہ opinion، اور وہ دو thirds جن پر کوئی بات نہیں کرتاOne head ہر position کے لیے ایک softmax row ہے، اس لیے یہ “یہاں relevant کیا ہے” کا ایک answer رکھتا ہے۔ the animal that crossed the wet street میں the کے بعد word predict کرنے کے لیے syntactic slot، subject اور previous token ایک ساتھ چاہیے، اور ایک probability distribution تین جگہوں پر concentrated نہیں ہو سکتی۔ اس لیے کئی heads parallel چلائیں، ہر ایک width کے ساتھ، concatenate کریں، اور ایک اور matrix سے mix کریں: آپ نے width partition کی ہے، add نہیں کی۔
Attention بھی exactly ایک کام کرتا ہے — یہ positions کے درمیان information move کرتا ہے۔ اوپر کے code میں ہر operation feature axis کے ساتھ linear ہے، اور Chapter 5 نے prove کیا کہ linear maps کا stack کیا ہوتا ہے۔ اس لیے ہر block ایک چھوٹا MLP بھی carry کرتا ہے جو ہر position پر independently apply ہوتا ہے، width کو four سے expand کر کے واپس لاتا ہے، بیچ میں GELU کے ساتھ۔ labour کی division یاد رکھنے کے قابل ہے: attention positions کے across mix کرتا ہے، feed-forward network ایک position کے within compute کرتا ہے۔
full ladder، ہر row اپنے اوپر والی row میں ایک piece add کرتی ہے:
| model | parameters | validation perplexity |
|---|---|---|
| uniform average, added | 279,552 | 60.45 |
| one attention head, replacing the token | 328,704 | 55.47 |
| one attention head, added | 328,704 | 46.10 |
| four heads instead of one | 345,216 | 43.21 |
| plus the feed-forward network | 476,928 | 39.87 |
| plus LayerNorm — the complete block | 477,696 | 38.07 |
Learned weights uniform weights کو 14 perplexity points سے beat کرتے ہیں، جو ایک row میں اس chapter کا پورا argument ہے۔ Four heads 16,512 extra parameters کے لیے مزید 3 خریدتے ہیں۔ اور وہی head added ہونے پر replacing کے مقابلے میں 9 points زیادہ worth رکھتا ہے: attention information اندر لاتا ہے، یہ decide نہیں کرتا کہ position کیا ہے۔
اب parameters اصل میں کہاں بیٹھتے ہیں، جو diagram دیکھنے والوں کو surprise کرتا ہے:
| width | heads | attention | feed-forward | total per block |
|---|---|---|---|---|
| 128 | 4 | 65,664 (33.2 %) | 131,712 (66.6 %) | 197,888 |
| 768 | 12 | 2,360,064 (33.3 %) | 4,722,432 (66.6 %) | 7,085,568 |
| 4096 | 32 | 67,112,960 (33.3 %) | 134,238,208 (66.7 %) | 201,367,552 |
ہر transformer block کے دو thirds feed-forward network ہیں، ہر scale پر، کیونکہ attention کے پاس چار matrices ہیں اور MLP کے پاس آٹھ کے equivalent۔ model جو بھی جانتا ہے، اسے رکھنے والے زیادہ تر parameters per-position MLP میں ہیں۔
Residuals اور LayerNorm، Chapter 6 سے inherited
اس حصے کا لنک: Residuals اور LayerNorm، Chapter 6 سے inheritedLayerNorm Chapter 6 میں بنایا اور measure کیا گیا تھا، اور یہ chapter اسے وہیں چھوڑے گئے طریقے سے use کرتا ہے؛ residual connections وہاں name اور ablate کیے گئے تھے، اور یہاں built ہیں۔ اوپر “added, not replacing” rows residual connections ہیں، average کے لیے 188 perplexity points اور one head کے لیے 9 کے برابر۔ LayerNorm7 ہر example کو اس کے features across normalise کرتا ہے، اور Chapter 6 نے reasons دیے کہ یہاں BatchNorm کے بجائے یہی کیوں survive ہوا — batch پر dependence نہیں، running statistics نہیں، training اور inference میں identical، sequence length سے indifferent — یہ سب requirement بن جاتے ہیں جب آپ ایک user کے لیے ایک وقت میں ایک token generate کرتے ہیں، جہاں Chapter 13 آخر پہنچتا ہے۔ اس کی cost 768 parameters ہے اور یہ 1.8 perplexity points خریدتا ہے۔
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 پر، residual path input سے output تک کبھی normalised نہیں۔ یہ pre-norm ہے۔ 2017 paper اس کا الٹ کرتا ہے، x = LayerNorm(x + Att(x)) — post-norm، جو residual path خود پر LayerNorm رکھتا ہے۔
Xiong et al. نے difference کو initialisation پر gradient کے ذریعے explain کیا، جو post-norm network میں depth کے ساتھ badly scaled ہوتا ہے — یہی reason تھا کہ original transformer کو train کرنے کے لیے learning-rate warmup چاہیے تھا۔8 Twelve blocks، 1000 steps، learning rate :
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.88warmup کے بغیر post-norm آٹھ گنا worse ہے، اور warmup کے ساتھ post-norm exactly pre-norm match کرتا ہے۔ warmup یہاں general good practice نہیں؛ یہ normalisation کی ایک specific arrangement کے لیے patch ہے، اور LayerNorm کو move کرنے سے اس کی ضرورت ختم ہو جاتی ہے۔ اسی لیے 2019 کے بعد سے تقریباً ہر model pre-norm ہے، اور 2017 diagram کو specification کے بجائے history کے طور پر پڑھنا چاہیے۔
token کہاں ہے؟
اس حصے کا لنک: token کہاں ہے؟position embeddings delete کریں اور model پھر بھی train ہوتا ہے؛ بس اسے معلوم نہیں ہو سکتا کہ کچھ کہاں ہے، اور یہ training failure نہیں بلکہ symmetry ہے۔ attention score میں خود یا کا ذکر نہیں، اس لیے input permute کرنے سے output permute ہوتا ہے: self-attention permutation-equivariant ہے۔ یہ average کی order-blindness کا بہتر disguise ہے — causal mask کچھ order restore کرتا ہے، کیونکہ ہر position ایک different prefix دیکھتی ہے، مگر ایک prefix کے اندر تمام orderings alike ہیں۔
position inject کرنے کے چار طریقے، 64-token windows پر trained اور 64، 128 اور 256 پر evaluated — کسی بھی دیکھی ہوئی length سے آگے:
| positions | perplexity at 64 | at 128 | at 256 |
|---|---|---|---|
| none at all | 48.79 | 52.63 | 57.52 |
| learned absolute embeddings | 38.63 | 108.47 | 181.94 |
| fixed sinusoids | 42.96 | 95.26 | 152.25 |
| RoPE | 44.12 | 50.52 | 84.84 |
| ALiBi | 44.95 | 43.51 | 42.49 |
Learned absolute embeddings — ہر position کے لیے ایک 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 آخر میں صرف پر depend کرتا ہے، اس لیے position free میں relative بن جاتی ہے اور ختم ہونے والی کوئی table نہیں۔ یہ degrade کرتا ہے، مگر degrade کرتا رہتا ہے۔ ALiBi10 یہاں سب سے simple اور سب سے strange result ہے: distance کے proportional score پر linear penalty، ہر head کے لیے different slope کے ساتھ۔ اس کی perplexity training length سے آگے window بڑھنے پر improve ہوتی ہے، 44.95 سے 42.49 تک، کیونکہ penalty کسی بھی distance پر defined ہے اور ہر head وہی کرتا رہتا ہے جس کے لیے train ہوا تھا۔
lesson table سے زیادہ lasting ہے: ایسا architecture جو کوئی چیز represent نہیں کر سکتا، اس architecture سے different problem ہے جس نے وہ range کبھی learn نہیں کی، اور دوسرا وہ ہے جو کاٹتا ہے۔ یہ ہر “we extended the context to 128K” announcement کے پیچھے machinery بھی ہے — وہ تقریباً ہمیشہ 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 ایک بار دیکھتا ہے وہ overfit کرنے کی position میں نہیں۔
اس کی cost کیا ہے
اس حصے کا لنک: اس کی cost کیا ہےlayer میں دو tensors کی shape ہے، جہاں tokens کی تعداد ہے: scores اور softmax کے بعد weights۔ باقی سب — ہر projection، پورا MLP — میں linear ہے۔
One attention layer، 512 wide، 8 heads، batch of one، float32، laptop GPU پر۔ دو millisecond columns کو صرف ان کے ratios کے لیے پڑھیں: یہ 8 GB laptop card پر wall clock ہیں جو hot ہونے پر 1,785 MHz سے under 300 MHz تک throttle کرتا ہے، اس لیے اسی code کی cold run سات سے دس گنا fast واپس آتی ہے اور busy run اس سے بھی slow۔ megabyte columns allocator byte counts ہیں اور move نہیں کرتے۔
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.87x4 columns اوپر والی row کے ratio ہیں، اور کے 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 of eight کے لیے factor of ten۔ Linear، جیسا advertised تھا۔
پھر 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 نہیں؛ ایک layer میں ایک intermediate tensor۔
یہ physical fact تین later chapters کے نیچے ہے۔ یہی reason ہے کہ context window کی limit سرے سے ہوتی ہے، جسے Chapter 16 price میں بدلتا ہے۔ یہی وجہ ہے FlashAttention exist کرتا ہے، matrix کو کبھی store کیے بغیر tiles میں same result compute کرتے ہوئے — speed optimisation سے پہلے memory optimisation۔11 اور یہی long prompt کی price کے پیچھے arithmetic ہے، جو Chapter 24 ایک agent loop میں pay کرتا ہے — اس chapter کی دوسری finding سے separate matter، کہ model long context کو worse use بھی کرتا ہے، جسے وہ measure کرتا ہے اور اس formula پر blame کرنے سے انکار کرتا ہے۔
تفصیلات دکھائیں
دو cache-shrinking variants، یہاں named اور Chapter 13 میں paid for۔
Generation پہلے processed tokens کی keys اور values cache کرتی ہے — ایک key اور ایک value per token، per head per layer۔ Multi-query attention12 query projections رکھتا ہے مگر تمام heads کے لیے shared single key اور value projection، اس cache کو سے divide کرتے ہوئے۔ Grouped-query attention13 interpolate کرتا ہے: heads grouped ہیں، ہر group ایک key اور value share کرتا ہے، اس لیے ordinary attention ہے اور multi-query۔ 2023 کے بعد تقریباً ہر open model اسے 4 یا 8 groups کے ساتھ use کرتا ہے۔ دونوں quality کے لیے exist نہیں کرتے؛ دونوں اس cache کے size کے لیے exist کرتے ہیں، اور Chapter 13 وہ arithmetic کرتا ہے جو اسے “which model fits in your GPU” میں بدلتی ہے۔
دو shapes، اور ایک کا size
اس حصے کا لنک: دو shapes، اور ایک کا size2017 paper ایک encoder-decoder describe کرتا ہے: ایک stack source کو unmasked attention کے ساتھ پڑھتا ہے، دوسرا target کو causally generate کرتا ہے، اور درمیان میں attention کی تیسری قسم جہاں decoder کی queries encoder کی keys سے ملتی ہیں۔ یہ translation کے لیے درست ہے، جہاں input اور output دو sequences ہیں۔
جو جیتا وہ decoder-only half تھا — one stack، throughout causal، input اور output same sequence میں — اور reason elegance نہیں۔ “Predict the next token” کسی بھی text پر چلتا ہے، اس لیے training set parallel corpus کے بجائے internet ہے، اور سب کچھ وہی ایک task بن جاتا ہے: translation ایک document ہے جس میں source پھر target ہے، question اور اس کا answer ایک document ہیں، درمیان میں tool call والی conversation ایک document ہے۔ Chapter 11 اس بارے میں ہے کہ وہ last one کیسے manufactured ہوتا ہے۔ Encoders disappeared نہیں ہوئے — ایک encoder پورا input ایک ساتھ دیکھتا ہے، جو آپ تب چاہتے ہیں جب job text کو continue کرنے کے بجائے represent کرنا ہو، اور اسی لیے Chapter 19 کی retrieval embeddings encoders سے آتی ہیں، chat کرنے والے model سے نہیں۔
block define ہونے کے بعد، model size arithmetic ہے۔ per block، width اور four-times expansion کے ساتھ: for ، تمام چار پر biases کے ساتھ، جیسے GPT-2 میں ہیں — اوپر table ان میں سے تین کا bias چھوڑتی ہے، hence پر per block 2,304 fewer؛ MLP کے لیے ؛ دو LayerNorms کے لیے — ، plus کی token table اور، absolute positions کے لیے، ۔ GPT-2 small کی shape کے لیے — ، 12 blocks، vocabulary 50,257، context 1024، output layer embedding weights share کرتی ہے:
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 کا تقریباً ایک third embedding table ہے، اسی لیے vocabulary size architectural decision ہے preprocessing والا نہیں — وہ trade-off جو Chapter 7 نے set up کیا۔
head اصل میں کیا دیکھتا ہے
اس حصے کا لنک: head اصل میں کیا دیکھتا ہےPerplexity corpus کے بارے میں number ہے۔ ایک head کیا کرتا ہے، یہ different question ہے، اور Shakespeare کے megabyte پر trained 500,000-parameter model اس کے لیے wrong 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، جہاں ایک word referent کو street پر move کرتا ہے۔ یہ Winograd schemas14 ہیں — sentence pairs جو ایک word کے سوا identical ہیں، جہاں وہ word decide کرتا ہے کہ pronoun کس کو refer کرتا ہے۔
یہ cheating سے solvable بھی ہیں، جو part tutorials skip کرتے ہیں۔ اگر دو candidates animal اور place ہیں، tired اور wet referent کو category سے identify کرتے ہیں، اور ایسا model جو صرف جانتا ہے کون سے words present ہیں، order کے بارے میں کچھ جانے بغیر درست answer دیتا ہے۔ task کے اس version پر، held-out animal/place pairs کے ساتھ measured:
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 کے ایک pool سے draw کریں، جن میں سے کوئی بھی کسی بھی slot میں آ سکتا ہے، اور adjectives کو category کے بجائے role سے split کریں — چار it کو crosser بناتے ہیں (tired, scared, slow, weak)، چار اسے crossed بناتے ہیں (wet, wide, busy, steep)۔
the {x} did not cross the {y} because it was too {adj} , so the {ref} waited .ordinary next-token predictor کے طور پر train کریں، ایک position score کریں — so the کے بعد word — اور held-out set ان noun pairs سے build کریں جن کا reversed order training میں تھا، تاکہ جو چیز صرف یہ جانتی ہو کہ کون سے two nouns present ہیں مگر یہ نہیں کہ پہلے کون آیا، اسے backwards answer دینا پڑے۔
| model | parameters | held-out | names the other noun |
|---|---|---|---|
| current token only | 5,796 | 5.2 % | 5.2 % |
| uniform causal average | 5,796 | 27.9 % | 50.0 % |
| one head of learned attention | 18,084 | 35.4 % | 64.6 % |
| four heads | 22,244 | 75.0 % | 15.6 % |
| one transformer block | 55,716 | 92.7 % | 4.2 % |
| two transformer blocks | 105,508 | 100.0 % | 0.0 % |
present دو nouns کے درمیان chance 50 % ہے۔ uniform average 27.9 % پر land کرتا ہے اور pair کے wrong noun سے exactly half the time answer دیتا ہے — یہ signature ہے ایسی چیز کی جو جانتی ہے کہ words کون سے ہیں اور ان کے order کے بارے میں کچھ نہیں، جیسا shuffle test نے تین sections پہلے predict کیا۔
اب map: اس position پر attention جسے referent name کرنا ہے، ہر block کے four heads پر averaged، ان two sentences کے لیے جو ایک word سے differ کرتے ہیں۔ uniform average پندرہ visible tokens میں سے ہر ایک پر 0.067 رکھتا۔
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.25Block 1 دونوں sentences میں identical ہے — first noun پر 0.70، adjective کوئی بھی ہو۔ یہ failure نہیں بلکہ proof ہے: first layer میں position پر query اس position کے اپنے token اور index کا function ہے، اور position 14 پر the دونوں sentences میں same token ہے۔ first-layer head کسی ایسے word پر condition نہیں کر سکتا جسے اس نے ابھی fetch نہیں کیا۔ اس لیے block 1 وہی useful thing کرتا ہے جو available ہے اور first noun کو forward drag کرتا ہے۔
Block 2 وہ جگہ ہے جہاں sentences الگ ہوتے ہیں، اور تمام eight adjectives پر same row rule دکھاتی ہے جو model نے find کیا:
| adjective | block 2 on animal | on street | on the adjective | answer |
|---|---|---|---|---|
| tired, scared, slow, weak | 0.000 | 0.000 | 1.000 | animal |
| wet, wide, busy, steep | 0.000 | 0.491 | 0.00–0.03 | street |
crosser-adjective کے لیے second block اپنا entire weight adjective پر spend کرتا ہے، کیونکہ answer residual stream میں پہلے ہی ہے — block 1 نے اسے وہاں رکھا — اور اسے صرف confirmation چاہیے۔ crossed-adjective کے لیے یہ جا کر other noun fetch کرتا ہے۔ یہ two-hop circuit ہے: ایک head candidate کو forward move کرتا ہے، later layer میں head ایک token پڑھتا ہے جو decide کرتا ہے کہ اسے keep کرنا ہے یا نہیں۔ layers across composition mechanism ہے، اور یہی وجہ ہے کہ one block 92.7 % اور two blocks 100 % تک پہنچے۔
یہ real models میں best-documented circuit کی shape بھی ہے۔ Induction heads — previous-token head جو next layer میں ایسے head کو feed کرتا ہے جو pattern [A][B] … [A] → [B] complete کرتا ہے — وہ ہیں جنہیں 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، PyTorch کے اپنے weights سے copied weights کے ساتھ:
ours vs nn.MultiheadAttention max |diff| = 1.7881393432617188e-07
ours vs F.scaled_dot_product_attention max |diff| = 1.7881393432617188e-07outputs پر جن کی mean magnitude 0.159 ہے: float32 precision پر different order میں same arithmetic۔
یہ آگے کہاں جاتا ہے
اس حصے کا لنک: یہ آگے کہاں جاتا ہےآپ کے پاس وہ architecture ہے جس سے اس course کے باقی ہر model built ہے، اور یہ اپنی reputation سے چھوٹا ہے: weighted average جس کے weights learned ہیں، per-position MLP جو parameters کے دو thirds رکھتا ہے، دو normalisations اور دو additions، stacked۔
جو آپ کے پاس نہیں وہ ایسا model ہے جو کچھ جانتا ہو، اور stacking اکیلی اسے fix نہیں کرے گی۔ اس corpus پر two blocks training perplexity 14.49 اور validation perplexity 40.57 تک پہنچتے ہیں، one block کے 18.77 اور 38.07 کے مقابلے میں — زیادہ capacity، جو اس نے دیکھا اس پر بہتر، جو نہیں دیکھا اس پر بدتر، یعنی Chapter 6 کی table جس میں transformer ہے۔ اس model اور ان models کے درمیان distance جن سے Chapters 14 to 30 بات کرتے ہیں architectural نہیں۔ یہ وہی block ہے، زیادہ times repeated، vastly more text پر۔
جس سے یہ accounting problem بن جاتا ہے، اور accounting دکھنے سے زیادہ strange ہے۔ کتنا text، اور کوئی اسے کہاں سے حاصل کرتا ہے؟ کتنی arithmetic، اور money spend ہونے سے پہلے آپ اسے کیسے estimate کرتے ہیں؟ fixed budget دیا جائے تو model کو bigger بنانا بہتر ہے یا اسے more data دکھانا — اور کیا کوئی correct answer ہے، یا صرف fashion؟ Chapter 10 measurement سے تینوں کا answer دیتا ہے، اور question کی cheapest useful form پر price لگاتا ہے: آج، GPT-2 جیسا model nothing سے train کرنے کی cost کیا ہے؟
Sources and method
اس حصے کا لنک: Sources and methodاس material کی تین explanations اپنے مقصد کے لیے اس سے بہتر ہیں، اور یہ chapter ان کے ساتھ پڑھنے کے لیے لکھا گیا ہے۔ Jay Alammar کا The Illustrated Transformer data flow کی اب تک drawn بہترین 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 دو گھنٹے میں same model 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 سے۔
حوالہ جات
اس حصے کا لنک: حوالہ جات-
Hochreiter, S. and Schmidhuber, J. Long Short-Term Memory. Neural Computation 9(8), pp. 1735–1780 (1997). ↩
-
Sutskever, I., Vinyals, O. and Le, Q. V. Sequence to Sequence Learning with Neural Networks. arXiv:1409.3215 (2014). وہ encoder-decoder جس کا single context vector bottleneck ہے۔ ↩
-
Bahdanau, D., Cho, K. and Bengio, Y. Neural Machine Translation by Jointly Learning to Align and Translate. arXiv:1409.0473 (2014). Attention، transformer سے تین سال پہلے۔ ↩
-
Perplexity mean cross-entropy per token کا exponential ہے، Chapter 8 سے۔ یہاں ہر number وہی tokenizer اور وہی validation split use کرتا ہے، جو واحد condition ہے جس کے تحت دو perplexities compare کی جا سکتی ہیں۔ ↩
-
Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł. and Polosukhin, I. Attention Is All You Need. arXiv:1706.03762 (2017). Section 3.2.1 کے بارے میں وہ ایک sentence ہے جسے یہ chapter ایک section میں measure کرتا ہے۔ ↩
-
Shazeer, N., Mirhoseini, A., Maziarz, K., Davis, A., Le, Q., Hinton, G. and Dean, J. Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer. arXiv:1701.06538 (2017). ↩
-
Ba, J. L., Kiros, J. R. and Hinton, G. E. Layer Normalization. arXiv:1607.06450 (2016). Chapter 6 میں introduced اور measured؛ یہاں unchanged used۔ ↩
-
Xiong, R., Yang, Y., He, D., Zheng, K., Zheng, S., Xing, C., Zhang, H., Lan, Y., Wang, L. and Liu, T.-Y. On Layer Normalization in the Transformer Architecture. arXiv:2002.04745 (2020). pre-norm کے پیچھے gradient analysis، اور یہ argument کہ warmup ایک symptom ہے۔ ↩
-
Su, J., Lu, Y., Pan, S., Murtadha, A., Wen, B. and Liu, Y. RoFormer: Enhanced Transformer with Rotary Position Embedding. arXiv:2104.09864 (2021). ↩
-
Press, O., Smith, N. A. and Lewis, M. Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation. arXiv:2108.12409 (2021). اوپر reproduce کیا گیا extrapolation result۔ ↩
-
Dao, T., Fu, D. Y., Ermon, S., Rudra, A. and Ré, C. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135 (2022). ↩
-
Shazeer, N. Fast Transformer Decoding: One Write-Head is All You Need. arXiv:1911.02150 (2019). ↩
-
Ainslie, J., Lee-Thorp, J., de Jong, M., Zemlyanskiy, Y., Lebrón, F. and Sanghai, S. GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints. arXiv:2305.13245 (2023). ↩
-
Levesque, H. J., Davis, E. and Morgenstern, L. The Winograd Schema Challenge. KR (2012). ہر attention tutorial میں use ہونے والے animal / street sentence کے پیچھے construction۔ ↩