Attention وكتلة Transformer، مشتقان من المتوسط
ابدأ بأرخص تلخيص للسياق: المتوسط. قِس فشله، ثم دع صيغة attention تظهر من إصلاحه.
في هذه الصفحة
تصل إلى هنا ومعك tokenizer من الفصل 7، وجدول embedding من الفصل 8، والهدف المرتبط بهما: بالنظر إلى tokens الموجودة حتى الآن، ضع احتمالًا على token التالية.
ما ينقص هو الوسط. للتنبؤ بـ token يحتاج النموذج إلى متجه واحد يلخّص كل ما قبله، ولا شيء مما بنيته ينتج واحدًا. embedding الخاصة بـ token ليست ذلك — فهذا نموذج bigram، ولا يمكنه معرفة أن الجملة بدأت بسؤال. كما أن ربط كل embeddings السابقة معًا ليس هو الحل أيضًا: عددها يتغير في كل خطوة، ومصفوفة أوزان ثابتة لا تستطيع أخذ مُدخل بطول متغير.
إذن: متجه واحد بحجم ثابت، يلخّص عددًا متغيرًا من المتجهات. هذه هي المشكلة كلها، وattention هو ما تحصل عليه عندما تحلها بأكسل طريقة ممكنة ثم تصلح الشيئين اللذين ينكسران.
الإجابة التي امتلكها المجال، ولماذا لا نبنيها هنا
رابط إلى القسم: الإجابة التي امتلكها المجال، ولماذا لا نبنيها هنامن عام 1997 إلى نحو 2017 كان الملخص حالة recurrent: احتفظ بمتجه وحدّثه عند كل token، . حجم ثابت، مُدخل متغير، والشكل الصحيح تمامًا.
فشل ذلك بثلاث طرق، ومعمارية هذا الفصل تجيب عن الثلاث. إجراء backpropagation عبر خطوة يضرب من Jacobians، فيختفي gradient أو ينفجر — المرض الذي قاسه الفصل 5 داخل عقدة واحدة. صُممت LSTM1 لمقاومة ذلك بالضبط ودفعت النطاق القابل للاستخدام من عشرات الخطوات إلى مئاتها، من دون تغيير حقيقة أن المعلومة من token 5 لا تصل إلى token 500 إلا إذا نجت من 495 تحديثًا متسلسلًا. كان يجب أن يتسع المصدر كله في متجه واحد: في ترجمة sequence-to-sequence2 يضغط encoder المُدخل في حالته النهائية. سمّى Bahdanau وCho وBengio ذلك الاختناق وأصلحوه عام 2014، قبل transformer بثلاث سنوات، عبر السماح للـ decoder بأخذ مجموع موزون من كل حالات encoder بأوزان يحسبها بنفسه.3 كل ما يلي هو تلك الفكرة، مطبقة من تسلسل على نفسه، مع حذف recurrence. والتحديث متسلسل بحكم بنائه: يحتاج إلى ، ولا تستطيع GPU بعشرة آلاف نواة فعل شيء مع ذلك. المعمارية التي انتصرت ليست أذكى بوضوح؛ إنها التي تكون خطوتها المكلفة ضرب مصفوفات.
أما الانحياز الاستقرائي الكلاسيكي الآخر، convolution — مرّر مرشحًا صغيرًا واحدًا فوق كامل المُدخل، بحيث تُكتشف الميزة في أي مكان كما تُكتشف في كل مكان — فلا يُبنى هنا أيضًا؛ إنه مناسب تقريبًا تمامًا للصور ويُترك لدورة رؤية حاسوبية. لا يعود recurrence ولا convolution بعد هذه الصفحة، ولذلك لا يحصل أي منهما على فصل: الفصل 1 وعد بأن تُعلَن المحذوفات لا أن تُترك بصمت.
أرخص تلخيص موجود
رابط إلى القسم: أرخص تلخيص موجودأوضح دالة تأخذ عددًا متغيرًا من المتجهات وتعيد متجهًا واحدًا هي المتوسط:
أي عدد من المُدخلات، حجم خرج ثابت، قابلة للاشتقاق، ومجانية. جدول embedding زائد هذا المتوسط زائد طبقة خطية إلى المفردات يكوّن نموذج لغة كاملًا في خمسة عشر سطرًا. وهو أيضًا رديء جدًا، وطريقة رداءة أدائه هي الاشتقاق كله.
المتن أدناه هو ميغابايت واحد من شكسبير، 1,115,394 حرفًا، عبر tokenizer من نوع byte-level BPE كما بُني في الفصل 7 بمفردات حجمها 1024: 459,760 tokens بمعدل 2.43 حرف لكل token، مقسمة 90/10. كل نموذج عرضه 128، يرى 128 tokens، ويتدرب 3000 خطوة من AdamW عند بدفعة حجمها 64. perplexity محسوبة على قسم التحقق المحجوز.4
| النموذج | المعلمات | validation perplexity |
|---|---|---|
| token الحالية فقط، بلا سياق إطلاقًا | 263,168 | 59.71 |
| زائد المتوسط الموحد لكل ما قبلها | 263,168 | 248.07 |
| زائد learned position embeddings | 279,552 | 245.93 |
| المتوسط الموحد مضافًا إلى token بدل استبدالها | 263,168 | 60.45 |
اقرأ الصف الثاني مرتين. متوسط السياق لا يساعد قليلًا؛ بل يجعل النموذج أسوأ بأربع مرات من تجاهل السياق بالكامل. والسببان كلاهما قابلان للإثبات لا مجرد تجريبيين.
المتوسط لا يرى الترتيب. الجمع تبادلي، لذا فإن خلط النافذة يترك الملخص بلا تغيير — ليس تقريبًا:
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-08ضجيج floating-point على مجموع مُعاد ترتيبه: الملخصان هما المتجه نفسه. نموذج لا يرى السياق إلا كمتوسط لا يستطيع تمييز الكلب عض الرجل من الرجل عض الكلب. الصف الثالث يثبت أن هذا لا يُصلح بإضافة المواضع إلى المُدخلات — embedding موضعية متعلّمة على كل token قبل المتوسط اشترت 2.14 نقطة من أصل 188. المواضع تدخل في المجموع، والمجموع ينساها.
والمتوسط يُغرق الحاضر. عند الموضع 100 تكون token الحالية واحدًا من مئة من الملخص. لهذا إصلاح رخيص تملكه بالفعل: أبقِ token وأضف الملخص إليها — residual connection، من الفصل 6، والصف الرابع يبيّن أثره. بعد إصلاح التخفيف، لا يضيف المتوسط الموحد أي شيء إطلاقًا: 60.45 مقابل خط أساس 59.71. كل token موجودة هناك، موزونة بالتساوي، والتوزين المتساوي هو نفسه غياب المعلومات.
المشكلة ليست في أخذ المتوسط. إنها في الأوزان.
المتوسط ضرب مصفوفات، والقناع softmax
رابط إلى القسم: المتوسط ضرب مصفوفات، والقناع softmaxأخذ المتوسط على بادئة متنامية يبدو كحلقة. لكنه عملية ضرب واحدة بمصفوفة مثلثية سفلية مجموع صفوفها واحد — وهو أيضًا، بالضبط، 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.167تظهر الآن ثلاثة مكونات مسماة من transformer على الشاشة. المثلث هو causal mask، مفروض بسبب الهدف: لو استطاع الموضع رؤية الموضع لكانت الإجابة موجودة في المُدخل — التسريب الذي أخبرك الفصل 6 أن تدقّق فيه، لكن داخل المعمارية. softmax هو طريقة تنفيذ القناع: ضبط الخانات الممنوعة إلى يرسلها إلى صفر تمامًا ويطبّع ما تبقى، لذا فالحجب والتطبيع عملية واحدة. (استخدم ، لا -1e9: إنها القيمة التي يعنيها الحجب، وتنجو من التحويل إلى float16 كـ ، وتجنّبك تقرير ما إذا كان الثابت الذي اخترته كبيرًا بما يكفي للنطاق الذي تصادف أنك فيه — وهذا صندوق floating-point في الفصل 2 يطرح سؤالًا لا تحتاج إلى الإجابة عنه.) والدرجات هي المعلمة الحرة. المتوسط الموحد هو ما تحصل عليه عندما تكون كل درجة مسموحة الرقم نفسه؛ ضع أي أرقام هناك وسيحوّلها softmax إلى أوزان صالحة.
بقية هذا الفصل سؤال واحد: من أين تأتي تلك الأرقام؟
Query وkey وvalue
رابط إلى القسم: Query وkey وvalueلا يمكن أن تكون معلمات عادية. مصفوفة متعلّمة ستكون متطابقة لكل جملة — يمكنها ترميز «انظر أربع tokens إلى الخلف» لكنها لا تستطيع أبدًا «انظر إلى الاسم الذي يشير إليه هذا الضمير». الوزن الذي يربط الموضع بالموضع يجب أن يعتمد على ما يوجد في كلا الموضعين، لأن الصلة علاقة لا خاصية: كلمة it ليست ذات صلة بذاتها، بل هي ذات صلة بـ شيء.
أرخص دالة من متجهين تعيد رقمًا هي dot product من الفصل 1. قيّم الموضع للموضع كـ وستعمل الآلية — بشكل سيئ، بطريقتين تفرضان كل ما تبقى. dot product للمتجه مع نفسه هو مربع معياره، لذلك ستحضر كل token غالبًا إلى نفسها. كما أن العلاقة ستكون متماثلة: إذا حضرت it بقوة إلى animal، فستحضر animal بقوة إلى it، وهذا غير صحيح في اللغة، حيث تحتاج الصفة إلى اسمها أكثر بكثير مما يحتاج الاسم إلى الصفة.
لذا أعطِ كل token دورين، كتحويلين خطيين متعلمين لها: ما الذي يبحث عنه هذا الموضع، ، أي query؛ وما الذي يقدمه كي يُعثر عليه به، ، أي key. قيّم ويختفي التناظر، لأن : تستطيع token أن تعلن شيئًا وتبحث عن آخر.
يبقى شيء واحد خاطئًا. كان المجموع الموزون على نفسها، وهذا يفرض أن يكون الشيء الذي يُنسخ هو الشيء الذي يُطابق. المطابقة تريد الميزات التي تعرّف token؛ والنسخ يريد الميزات المفيدة لاحقًا. لذا تعلّم خريطة ثالثة، ، أي value، واجمع تلك.
الصيغة الآن مجرد محاسبة:
حيث هو causal mask، صفر على القطر وتحته و فوقه. في الكود هي ثلاثون سطرًا، عشرون منها أشكال:
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 قيّم، احجب، طبّع، اخلط. كل شيء آخر إسقاط.
القسمة على الجذر التربيعي، وما الذي تدافع ضده
رابط إلى القسم: القسمة على الجذر التربيعي، وما الذي تدافع ضدهتقريبًا كل شرح لـ يقول «لمنع softmax من التشبع»، وهذا صحيح ولا يشرح شيئًا. الحجة سطران من التباين في الفصل 2. إذا كانت مداخل و مستقلة بمتوسط صفر وتباين واحد، فكل حاصل ضرب له تباين واحد، وتباينات الأشياء المستقلة تُجمع:
إذن للدرجات انحراف معياري . مقاسًا على عشرين ألف زوج عشوائي:
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سبب أهمية ذلك: softmax حساس للمقياس بطريقة لا تكون فيها الطبقة الخطية كذلك. مضاعفة مُدخل طبقة خطية تضاعف خرجها؛ أما ضرب الدرجات في عشرة قبل softmax فيحوّل مزيجًا لينًا إلى اختيار حاد. صف واحد من 64 درجة، مع القسمة ومن دونها:
| أكبر وزن، بلا قسمة | entropy | tokens فعالة | أكبر وزن، مع القسمة | entropy | 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 |
«tokens الفعالة» هي أس entropy: كم موضعًا يوسّط الصف فعليًا. من دون القسمة، عند ، يحضر head مهيأ حديثًا إلى token واحدة بالضبط من أصل 64، اختارها السحب العشوائي وحده.
هذا سيئ في المرور الأمامي وأسوأ في الخلفي، بالشكل الذي قاسه الفصل 5 بالفعل على . softmax ملتزم بخانة واحدة لديه مشتقة شبه معدومة: قطر Jacobian الخاص به هو ، صفر عند الطرفين. عبر ألفي صف عشوائي:
| بلا قسمة | مع القسمة | صفوف مشبعة (أكبر وزن فوق 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 % |
عند ، سبعة صفوف من كل عشرة تكون مجمدة قبل بدء التدريب، وhead يبدأ مجمدًا لا يستطيع تعلم أين ينظر. مع القسمة، تبقى الكمية مسطحة عند 0.96 في كل عرض ولا يتشبع شيء.
والآن الجزء الذي لا ينشره أحد: هل يغيّر perplexity النهائية؟ احذف القسمة ودرّب، عند أربعة عروض للـ head:
| عرض head | بلا قسمة | مقسوم على | مقسوم على |
|---|---|---|---|
| أربعة heads، | 37.29 | 38.07 | 37.89 |
| head واحد، | 48.51 | 46.10 | 45.99 |
| head واحد، | 65.37 | 47.53 | — |
| head واحد، | 67.06 | 49.15 | — |
| head واحد، | 76.69 | 59.17 | — |
أول صفين من ميزانية 3000 خطوة أعلاه؛ وآخر ثلاثة من تشغيل أقصر — 1500 خطوة، دفعة 32، head واحد، بلا تطبيع قبل الإسقاطات — مع كلا المتغيرين تحت إعدادات متطابقة.
عند لا تساوي القسمة شيئًا والتشغيل من دونها متقدم قليلًا جدًا. هذه ليست رخصة لإسقاطها، لأنها عند 256 تساوي 18 نقطة perplexity وعند 1024 تساوي 17. الآلية مرئية في الدرجات نفسها:
| انحراف معياري للدرجات عند التهيئة | بعد 1500 خطوة، بلا قسمة | بعد 1500 خطوة، مع القسمة | صفوف مشبعة، بلا قسمة | مع القسمة | |
|---|---|---|---|---|---|
| 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 % |
الـ head غير المقسوم لا يتعافى. إنه ينفلت: ينمو الانحراف المعياري لدرجاته من 21 عند التهيئة إلى 5147، وتهبط entropy الخاصة بـ attention إلى الصفر، وتضع 99.9 % من الصفوف أكثر من 0.99 من وزنها على token واحدة. حالما يصبح head محددًا حادًا تكون gradient الخاصة به شبه صفرية ولا شيء يسحبه للعودة، لذا يكون الانهيار مستقرًا. أما head المقسوم فيجلس عند انحراف معياري للدرجات قدره 3.44 بعد التدريب نفسه، وهو مزيج لين ما زال قابلًا للتغيير.
يقول Vaswani وآخرون هذا بالضبط ولا أكثر — يشتبهون بأن حواصل الضرب «تكبر في المقدار عند قيم كبيرة من » ويقسمون.5 كلمة كبيرة تحمل العبء، والجداول تقول أين يبدأ الكِبر: لا شيء عند 32، وكل شيء بحلول 256.
أكثر من رأي واحد، والثلثان اللذان لا يتحدث عنهما أحد
رابط إلى القسم: أكثر من رأي واحد، والثلثان اللذان لا يتحدث عنهما أحدhead واحد هو صف softmax واحد لكل موضع، لذا يحمل إجابة واحدة عن «ما ذو الصلة هنا». التنبؤ بالكلمة بعد the في the animal that crossed the wet street يحتاج الخانة النحوية، والفاعل، وtoken السابقة في آن واحد، ولا يمكن لتوزيع احتمالي واحد أن يتركز في ثلاثة أماكن. لذا شغّل عدة heads بالتوازي، كل واحد بعرض ، ثم اربطها وامزجها بمصفوفة أخرى : لقد قسّمت العرض، لا أضفت إليه.
attention يفعل شيئًا واحدًا بالضبط — ينقل المعلومات بين المواضع. كل عملية في الكود أعلاه خطية على محور الميزات، وقد أثبت الفصل 5 ما تكونه كومة من الخرائط الخطية. لذلك تحمل كل كتلة أيضًا MLP صغيرة مطبقة على كل موضع بشكل مستقل، توسّع العرض أربع مرات ثم تعود، مع GELU في الوسط. تقسيم العمل يستحق الحفظ: attention يمزج عبر المواضع، وشبكة feed-forward تحسب داخل الموضع.
السلم الكامل، كل صف يضيف قطعة واحدة إلى الصف الذي فوقه:
| النموذج | المعلمات | validation perplexity |
|---|---|---|
| متوسط موحد، مضاف | 279,552 | 60.45 |
| head attention واحد، يستبدل token | 328,704 | 55.47 |
| head attention واحد، مضاف | 328,704 | 46.10 |
| أربعة heads بدل واحد | 345,216 | 43.21 |
| زائد شبكة feed-forward | 476,928 | 39.87 |
| زائد LayerNorm — الكتلة الكاملة | 477,696 | 38.07 |
الأوزان المتعلّمة تهزم الأوزان الموحدة بـ 14 نقطة perplexity، وهذه حجة هذا الفصل كاملة في صف واحد. أربعة heads تشتري 3 نقاط أخرى مقابل 16,512 معلمة إضافية. ونفس head يساوي 9 نقاط أكثر عندما يكون مضافًا لا مستبدلًا: attention يجلب المعلومات إلى الداخل، ولا يقرر ما يكونه الموضع.
والآن أين تجلس المعلمات فعليًا، وهذا يفاجئ من لم يروا إلا الرسم:
| العرض | heads | attention | feed-forward | الإجمالي لكل كتلة |
|---|---|---|---|---|
| 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 هما شبكة feed-forward، في كل مقياس، لأن attention لديه أربع مصفوفات ، ولدى MLP ما يعادل ثمانيًا. أيًا كان ما يعرفه نموذج، فمعظم المعلمات التي تحمله موجودة في MLP لكل موضع.
Residuals وLayerNorm، موروثان من الفصل 6
رابط إلى القسم: Residuals وLayerNorm، موروثان من الفصل 6بُني LayerNorm وقيس في الفصل 6، ويستخدمه هذا الفصل كما تُرك هناك؛ وسُمّيت residual connections وحُذفت تجريبيًا هناك، وتُبنى هنا. صفوف «مضاف، لا مستبدل» أعلاه هي residual connections، تساوي 188 نقطة perplexity للمتوسط و9 لـ head واحد. LayerNorm7 يطبّع كل مثال عبر ميزاته، وقد أعطى الفصل 6 الأسباب التي جعلته هو لا BatchNorm يبقى هنا — لا اعتماد على الدفعة، لا إحصاءات جارية، مطابق في التدريب والاستدلال، غير مكترث بطول التسلسل — وكل واحد منها يصبح مطلبًا عندما تولّد token واحدة في كل مرة لمستخدم واحد، وهذا ما ينتهي إليه الفصل 13. يكلف 768 معلمة ويشتري 1.8 نقطة perplexity.
class Block(nn.Module):
def forward(self, x):
x = x + self.att(self.ln1(x))
x = x + self.ff(self.ln2(x))
return xانظر إلى مكان التطبيع: على مُدخل كل طبقة فرعية، مع مسار residual من المُدخل إلى الخرج لا يُطبّع أبدًا. هذا هو pre-norm. ورقة 2017 تفعل العكس، x = LayerNorm(x + Att(x)) — post-norm، الذي يضع LayerNorm على مسار residual نفسه.
شرح Xiong وآخرون الفرق عبر gradient عند التهيئة، والذي يكون في شبكة post-norm سيئ القياس مع العمق — السبب الذي جعل transformer الأصلي يحتاج إلى warmup لمعدل التعلم كي يتدرب أصلًا.8 اثنتا عشرة كتلة، 1000 خطوة، معدل تعلم :
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.88post-norm بلا warmup أسوأ بثماني مرات، وpost-norm مع warmup يطابق pre-norm تمامًا. warmup ليس ممارسة جيدة عامة هنا؛ إنه رقعة لترتيب محدد للتطبيع، ونقل LayerNorm يزيل الحاجة إليه. لهذا أصبح عمليًا كل نموذج منذ 2019 pre-norm، ولهذا ينبغي قراءة رسم 2017 كتاريخ لا كمواصفة.
أين توجد token؟
رابط إلى القسم: أين توجد token؟احذف position embeddings وسيظل النموذج يتدرب؛ لكنه ببساطة لا يستطيع معرفة مكان أي شيء، وهذا تناظر لا فشل تدريب. لا شيء في درجة attention يذكر أو نفسيهما، لذا فإن تبديل المُدخل يبدّل الخرج: self-attention مكافئ للتبديل. إنه عمى المتوسط عن الترتيب في تنكر أفضل — يعيد causal mask بعض الترتيب، لأن كل موضع يرى بادئة مختلفة، لكن داخل البادئة كل الترتيبات متشابهة.
أربع طرق لحقن الموضع، دُرّبت على نوافذ 64-token وقُيّمت عند 64 و128 و256 — بعد أي طول رأته:
| المواضع | perplexity عند 64 | عند 128 | عند 256 |
|---|---|---|---|
| لا شيء إطلاقًا | 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 — متجه واحد لكل موضع، يُضاف إلى token — تفوز عند الطول المدرّب ثم تسقط من حافة، لأن الموضع 100 لم يكن أبدًا في دفعة وembedding الخاصة به ما زالت المتجه العشوائي الذي بدأت به. Sinusoids، الخيار الأصلي، تُحسب ولا تُتعلّم، من جيوب وجيوب تمام عند ترددات متباعدة هندسيًا؛ أملت ورقة 2017 أن يستنتج ذلك خارج النطاق، والجدول يقول إنه لا يفعل — الدالة معرّفة عند الموضع 200، لكن النموذج لم يتعلم قراءتها هناك. RoPE9 لا يضيف شيئًا بل يدوّر query وkey بزاوية متناسبة مع الموضع، في شرائح ثنائية الأبعاد؛ وبما أن تدوير طرفي dot product بالتساوي يتركه بلا تغيير، تنتهي الدرجة إلى الاعتماد فقط على ، فيصبح الموضع نسبيًا مجانًا ولا يوجد جدول ينفد. يتدهور، لكنه يتدهور فقط. ALiBi10 هو أبسط وأغرب نتيجة هنا: عقوبة خطية على الدرجة متناسبة مع المسافة، بميل مختلف لكل head. تتحسن perplexity الخاصة به مع نمو النافذة بعد طول التدريب، من 44.95 إلى 42.49، لأن العقوبة معرّفة عند أي مسافة وكل head يواصل فعل ما تدرب عليه.
الدرس يعيش أطول من الجدول: معمارية لا تستطيع تمثيل شيء هي مشكلة مختلفة عن معمارية لم تتعلم ذلك النطاق قط، والثانية هي التي تعض. وهي أيضًا الآلية خلف كل إعلان «مددنا context إلى 128K» — تلك غالبًا إعادة تحجيم لترميز rotary، ولهذا يقول الفصل 16 إن حد السياق يتحرك لا يختفي.
Dropout موروث بالطريقة نفسها: يظهر على أوزان attention بعد softmax، وعلى خرج كل طبقة فرعية قبل إضافة residual، وعلى مجموع embedding، ويفعل بالضبط ما وصفه الفصل 6. في عمليات pretraining الكبيرة يُضبط غالبًا إلى صفر، لأن نموذجًا يرى كل token مرة واحدة ليس في وضع يسمح له بفرط الملاءمة.
ما التكلفة
رابط إلى القسم: ما التكلفةيوجد موتران في الطبقة بشكل ، حيث هو عدد tokens: الدرجات والأوزان بعد softmax. كل شيء آخر — كل إسقاط، وMLP كلها — خطي في .
طبقة attention واحدة، عرضها 512، فيها 8 heads، دفعة من واحد، float32، على GPU حاسوب محمول. اقرأ عمودي الميلي ثانية من أجل النِّسب فقط: إنها زمن حائط على بطاقة حاسوب محمول 8 GB تخنق نفسها من 1,785 MHz إلى أقل من 300 MHz عندما تسخن، لذا فإن تشغيلًا باردًا للكود نفسه يعود أسرع بسبع إلى عشر مرات، وتشغيلًا مشغولًا أبطأ كذلك. أعمدة الميغابايت هي أعداد بايتات المخصّص ولا تتحرك.
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 هي النسبة إلى الصف الذي فوقها، ومضاعفة تتقارب إلى 4 بالضبط للزمن والذاكرة معًا — 3.91 في الخطوة الأخيرة مقابل 4 نظريًا. عمود الإسقاطات هو الضابط: من 4.0 ms عند 1024 tokens إلى 40.1 ms عند 8192، عامل عشرة مقابل عامل ثمانية. خطي، كما وُعد.
ثم الصف الأخير. طبقة attention واحدة، تسلسل واحد، بلا نموذج حولها، تنفد ذاكرتها على GPU بسعة 8 GB عند 16,384 tokens — مصفوفة الدرجات وحدها ستكون 8 GB، لأنها 8 heads ضرب 16,384 ضرب 16,384 ضرب 4 بايتات. ليس النموذج؛ موتر وسيط واحد في طبقة واحدة.
هذه هي الحقيقة الفيزيائية تحت ثلاثة فصول لاحقة. إنها سبب وجود حد لـ context window أصلًا، والذي يحوله الفصل 16 إلى سعر. وهي سبب وجود FlashAttention، الذي يحسب النتيجة نفسها في بلاطات من دون تخزين المصفوفة أبدًا — تحسين ذاكرة قبل أن يكون تحسين سرعة.11 وهي الحساب خلف سعر prompt طويل، الذي يدفعه الفصل 24 في حلقة agent — مسألة منفصلة عن اكتشاف ذلك الفصل الآخر، وهو أن النموذج أيضًا يستخدم السياق الطويل بشكل أسوأ، ويقيس ذلك ويرفض لوم هذه الصيغة عليه.
عرض التفاصيل
المتغيران اللذان يصغّران cache، نسميهما هنا وندفع كلفتهما في الفصل 13.
التوليد يخزّن keys وvalues الخاصة بـ tokens التي عولجت بالفعل — key واحد وvalue واحدة لكل token، لكل head في كل طبقة. Multi-query attention12 يحتفظ بـ من إسقاطات query لكن بإسقاط key وvalue واحد مشترك بين كل heads، مقسمًا ذلك cache على . Grouped-query attention13 يستوفي بينهما: تُجمّع heads، كل مجموعة تشارك key وvalue واحدين، بحيث هو attention عادي و هو multi-query. تقريبًا كل نموذج مفتوح منذ 2023 يستخدمه مع 4 أو 8 مجموعات. لا يوجد أي منهما لأجل الجودة؛ كلاهما موجود لأجل حجم ذلك cache، والفصل 13 يجري الحساب الذي يحوله إلى «أي نموذج يتسع في GPU لديك».
شكلان، وحجم واحد
رابط إلى القسم: شكلان، وحجم واحدتصف ورقة 2017 encoder-decoder: مكدس يقرأ المصدر بـ attention غير محجوب، وثانٍ يولّد الهدف سببيًا، ونوع ثالث من attention في الوسط حيث تلتقي queries الخاصة بـ decoder مع keys الخاصة بـ encoder. هذا صحيح للترجمة، حيث المُدخل والخرج تسلسلان.
ما فاز كان نصف decoder-only — مكدس واحد، سببي بالكامل، المُدخل والخرج في التسلسل نفسه — والسبب ليس الأناقة. «تنبأ بـ token التالية» يعمل على أي نص، لذا تكون مجموعة التدريب هي الإنترنت لا متنًا متوازيًا، ويصبح كل شيء تلك المهمة الواحدة: الترجمة وثيقة تحتوي المصدر ثم الهدف، والسؤال وجوابه وثيقة، ومحادثة فيها tool call في الوسط وثيقة. الفصل 11 عن كيفية تصنيع الأخيرة. لم تختفِ encoders — أحدها يرى المُدخل كله دفعة واحدة، وهذا ما تريده عندما تكون المهمة تمثيل نص لا متابعته، ولهذا تأتي retrieval embeddings في الفصل 19 من encoders لا من النموذج الذي يجري المحادثة.
بعد تعريف الكتلة، يصبح حجم النموذج حسابًا. لكل كتلة، بعرض وتوسيع أربع مرات: من أجل مع biases على الأربعة كلها، كما في GPT-2 — الجدول أعلاه يترك bias خارج ثلاثة منها، ومن هنا 2,304 أقل لكل كتلة عند ؛ من أجل MLP؛ من أجل LayerNorms اثنين — ، زائد جدول token قدره ، وللمواضع المطلقة، . لشكل GPT-2 small — ، 12 كتلة، مفردات 50,257، سياق 1024، وطبقة الخرج تشارك أوزان embedding:
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وهذا هو الحجم المنشور لذلك النموذج. الصيغة ليست تقريبًا؛ إنها النموذج. لاحظ أيضًا أن قرابة ثلث النموذج الصغير هو جدول embedding، ولهذا يكون حجم المفردات قرارًا معماريًا لا قرار preprocessing — المقايضة التي أسسها الفصل 7.
إلى ماذا ينظر head فعليًا
رابط إلى القسم: إلى ماذا ينظر head فعليًاperplexity رقم عن متن. ما يفعله head واحد سؤال مختلف، ونموذج مدرّب على ميغابايت من شكسبير أداة خاطئة له: القول الصادق عن خريطة attention لنموذج 500,000 معلمة هو أنها في معظمها غير قابلة للتفسير. لذا: لغة يكون للسؤال فيها جواب صحيح.
المثال الكلاسيكي هو the animal did not cross the street because it was too tired، حيث it هي animal، مقابل …because it was too wet، حيث تنقل كلمة واحدة المرجع إلى street. هذه Winograd schemas14 — أزواج جمل متطابقة إلا في كلمة واحدة، وتلك الكلمة تقرر إلى ماذا يشير الضمير.
وهي أيضًا قابلة للحل بالغش، وهذا هو الجزء الذي تتخطاه الشروحات. إذا كان المرشحان animal ومكانًا، فإن tired وwet يحددان المرجع حسب الفئة، ونموذج لا يعرف إلا أي الكلمات موجودة يجيب صح من دون أن يعرف شيئًا عن الترتيب. مقاسًا على تلك النسخة من المهمة، مع أزواج animal/place محجوزة:
uniform causal average held-out referent accuracy 100.0 %
one transformer block held-out referent accuracy 91.7 %حقيبة الكلمات تهزم transformer. أي عرض مبني على تلك الجملة لا يثبت شيئًا عن attention.
لذا أغلق الثغرة: اسحب كلا المرشحين من حوض واحد من ستة عشر اسمًا، يمكن لأي منهما الظهور في أي خانة، واقسم الصفات حسب الدور بدل الفئة — أربع تجعل it هو العابر (tired, scared, slow, weak)، وأربع تجعله الشيء المعبر عليه (wet, wide, busy, steep).
the {x} did not cross the {y} because it was too {adj} , so the {ref} waited .درّب كمتنبئ عادي بـ next-token، وقيّم موضعًا واحدًا — الكلمة بعد so the — وابنِ المجموعة المحجوزة من أزواج أسماء كان ترتيبها المعكوس في التدريب، بحيث إن أي شيء يعرف أي اسمين موجودان لا أيهما جاء أولًا لا بد أن يجيب بالعكس.
| النموذج | المعلمات | المحجوز | يذكر الاسم الآخر |
|---|---|---|---|
| token الحالية فقط | 5,796 | 5.2 % | 5.2 % |
| متوسط سببي موحد | 5,796 | 27.9 % | 50.0 % |
| head واحد من learned attention | 18,084 | 35.4 % | 64.6 % |
| أربعة heads | 22,244 | 75.0 % | 15.6 % |
| كتلة transformer واحدة | 55,716 | 92.7 % | 4.2 % |
| كتلتان transformer | 105,508 | 100.0 % | 0.0 % |
الصدفة بين الاسمين الموجودين هي 50 %. المتوسط الموحد يقع عند 27.9 % ويجيب بـ الاسم الخطأ من الزوج نصف الوقت بالضبط — توقيع شيء يعرف أي الكلمات موجودة ولا يعرف شيئًا عن ترتيبها، كما تنبأ اختبار الخلط قبل ثلاثة أقسام.
والآن الخريطة: attention عند الموضع الذي يجب أن يسمّي المرجع، بمتوسط عبر heads الأربعة لكل كتلة، للجملتين اللتين تختلفان بكلمة واحدة. المتوسط الموحد سيضع 0.067 على كل token من الخمس عشرة المرئية.
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الكتلة 1 متطابقة في الجملتين — 0.70 على الاسم الأول، أيًا كانت الصفة. هذا ليس فشلًا بل برهان: في الطبقة الأولى تكون query عند موضع دالة في token ذلك الموضع وفهرسه، وthe عند الموضع 14 هي token نفسها في الجملتين. لا يستطيع head في الطبقة الأولى أن يشترط على كلمة لم يجلبها بعد. لذلك تفعل الكتلة 1 الشيء المفيد الوحيد المتاح لها وتسحب الاسم الأول إلى الأمام.
الكتلة 2 هي حيث تفترق الجملتان، والصف نفسه عبر الصفات الثماني يبيّن القاعدة التي وجدها النموذج:
| الصفة | الكتلة 2 على animal | على street | على الصفة | الإجابة |
|---|---|---|---|---|
| tired, scared, slow, weak | 0.000 | 0.000 | 1.000 | animal |
| wet, wide, busy, steep | 0.000 | 0.491 | 0.00–0.03 | street |
لصفة العابر تنفق الكتلة الثانية وزنها كله على الصفة، لأن الإجابة موجودة بالفعل في residual stream — وضعتها الكتلة 1 هناك — وكل ما تحتاج إليه هو التأكيد. ولصفة المعبر عليه تذهب وتجلب الاسم الآخر بدلًا من ذلك. هذه دائرة من قفزتين: head ينقل مرشحًا إلى الأمام، وhead في طبقة لاحقة يقرأ token تقرر هل يُبقيه. التركيب عبر الطبقات هو الآلية، ولهذا وصلت كتلة واحدة إلى 92.7 % وكتلتان إلى 100 %.
وهو أيضًا شكل أفضل دائرة موثقة في النماذج الحقيقية. Induction heads — head للـ previous-token يغذي head في الطبقة التالية يكمل النمط [A][B] … [A] → [B] — هي ما تحدده أعمال Anthropic في قابلية التفسير خلف جزء كبير من in-context learning، وهي تتشكل في لحظة قابلة للتحديد أثناء pretraining. لا يحاول هذا الفصل ذلك التحليل: يتركه، مع الورقتين في المراجع، لأن قراءة الدوائر من نموذج حقيقي مجال بحث لا قسمًا.
أخيرًا، التنفيذ. الأسطر الثلاثون أعلاه، مع أوزانها منسوخة من PyTorch نفسها:
ours vs nn.MultiheadAttention max |diff| = 1.7881393432617188e-07
ours vs F.scaled_dot_product_attention max |diff| = 1.7881393432617188e-07على مخرجات متوسط مقدارها 0.159: الحساب نفسه بترتيب مختلف، عند دقة float32.
إلى أين يذهب هذا بعد ذلك
رابط إلى القسم: إلى أين يذهب هذا بعد ذلكلديك الآن المعمارية التي يُبنى منها كل نموذج في بقية هذه الدورة، وهي أصغر من سمعتها: متوسط موزون بأوزان متعلّمة، وMLP لكل موضع تحمل ثلثي المعلمات، وتطبيعان وإضافتان، مكدسة.
ما لا تملكه هو نموذج يعرف أي شيء، والتكديس وحده لن يصلح ذلك. كتلتان على هذا المتن تصلان إلى training perplexity قدرها 14.49 وvalidation perplexity قدرها 40.57، مقابل 18.77 و38.07 لكتلة واحدة — سعة أكبر، أفضل على ما رآه، أسوأ على ما لم يره، وهذا جدول الفصل 6 وفيه transformer. المسافة بين هذا النموذج والنماذج التي تتحدث إليها الفصول 14 إلى 30 ليست معمارية. إنها الكتلة نفسها، مكررة مرات أكثر، فوق نص أكثر بكثير.
وهذا يجعله مسألة محاسبة، والمحاسبة أغرب مما تبدو. كم من النص، ومن أين يحصل عليه أي أحد؟ كم من الحساب، وكيف تقدّره قبل أن يُنفق المال؟ عند ميزانية ثابتة، هل الأفضل جعل النموذج أكبر أم عرضه على بيانات أكثر — وهل هناك جواب صحيح، أم مجرد موضة؟ يجيب الفصل 10 عن الثلاثة بالقياس، ويضع سعرًا لأرخص صيغة مفيدة من السؤال: كم يكلف اليوم تدريب نموذج مثل GPT-2 من الصفر؟
المصادر والمنهج
رابط إلى القسم: المصادر والمنهجثلاثة شروح لهذه المادة أفضل من هذا الشرح فيما صُممت له، وهذا الفصل مكتوب ليُقرأ بجانبها. عمل Jay Alammar، The Illustrated Transformer، هو أفضل صورة لتدفق البيانات رُسمت على الإطلاق. وThe Annotated Transformer من Harvard NLP هي ورقة 2017 مع كود عامل متداخل سطرًا بسطر. وLet's build GPT: from scratch, in code, spelled out لـ Andrej Karpathy يبني النموذج نفسه مباشرة خلال ساعتين، وسلم ablations أعلاه هو العمود نفسه مقاسًا على متن مختلف. أما سؤال قابلية التفسير الذي لا يلمسه هذا الفصل إلا قليلًا، فمصادره الأولية هي Elhage et al., A Mathematical Framework for Transformer Circuits (2021) وOlsson et al., In-context Learning and Induction Heads (2022)، وكلاهما من مجموعة قابلية التفسير في Anthropic.
المراجع
رابط إلى القسم: المراجع-
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 الذي يكون متجه السياق الواحد فيه هو الاختناق. ↩
-
Bahdanau, D., Cho, K. and Bengio, Y. Neural Machine Translation by Jointly Learning to Align and Translate. arXiv:1409.0473 (2014). attention، قبل transformer بثلاث سنوات. ↩
-
Perplexity هي أس متوسط cross-entropy لكل token، من الفصل 8. كل رقم هنا يستخدم tokenizer نفسه وقسم التحقق نفسه، وهذا هو الشرط الوحيد الذي يمكن عنده مقارنة قيمتي perplexity أصلًا. ↩
-
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). القسم 3.2.1 هو الجملة الوحيدة عن التي يقضي هذا الفصل قسمًا في قياسها. ↩
-
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). قُدّم وقيس في الفصل 6؛ ويُستخدم هنا بلا تغيير. ↩
-
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). تحليل gradient خلف pre-norm، والحجة أن warmup عرض لا علاج عام. ↩
-
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). نتيجة الاستقراء خارج النطاق المعاد إنتاجها أعلاه. ↩
-
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). البناء خلف جملة animal / street التي يستخدمها كل شرح لـ attention. ↩