العرض ينقسم عبر الرؤوس
رأس واحد يرى نمطًا واحدًا
غطت النشاطة 67 الانتباه بنقطة الضرب المقياسة: متجه استعلام Q، متجه مفتاح K، متجه قيمة V؛ احسب Q·Kᵀ/√d_k، قناع، softmax، وزن V. رأس واحد يتعلم نمط علاقة واحد: ربما توافق الفاعل والفعل، ربما مطابقة علامات الترقيم، ربما شيء غير مفيد.
الانتباه متعدد الرؤوس يشغل نفس العملية بالتوازي، عدة مرات، على شرائح مختلفة من تمثيل الرمز. اثنا عشر رأسًا متوازيًا. اثنا عشر نمط علاقة محتمل. الرؤوس تتخصص من خلال ضغط التدريب وحده؛ لا معماري يخبر الرأس 4 بالنظر إلى زمن الفعل.
علاقة التقسيم
يحدد ANDREA-120M d_model = 768 و n_head = 12. يقسم الاهتمام متعدد الرؤوس 768 إلى 12 قطعة بحجم 64 لكل منها:
head_dim = d_model / n_head
64 = 768 / 12
تعمل كل رأس على متجهات بـ 64 بعدًا. يتم تطبيق التقسيم بشكل نظيف: يجب أن يقسم d_model على n_head بدون باقٍ. الإعدادات التي تنتهك هذا تفشل في التحقق من صحة الإعداد، وليس أثناء التشغيل.
ثلاثة نماذج، ثلاثة تقسيمات
| Variant | d_model | n_head | head_dim |
|---|---|---|---|
| ANDREA-12M | 384 | 12 | 32 |
| ANDREA-120M | 768 | 12 | 64 |
| ANDREA-480M | 1536 | 24 | 64 |
ملاحظة: ANDREA-12M و ANDREA-120M يحافظان على n_head=12 ثابتًا؛ فقط d_model وبالتالي head_dim يتوسعان. ANDREA-480M يضاعف عدد الرؤوس إلى 24، مع الحفاظ على head_dim=64 متطابقًا مع ANDREA-120M.
حساب head_dim
ثلاث مصفوفات لكل رأس، أو مصفوفة كبيرة واحدة
منظور لكل رأس
يحتاج كل رأس إلى إسقاط استعلام خاص به، وإسقاط مفتاح، وإسقاط قيمة. بالنسبة لرأس h:
Q_h = X · W_Q^h حيث تكون W_Q^h بشكل [d_model, head_dim]
K_h = X · W_K^h حيث أن W_K^h لها شكل [d_model, head_dim]
V_h = X · W_V^h حيث أن W_V^h لها شكل [d_model, head_dim]
X تحمل شكل الإدخال [batch, seq_len, d_model]. بعد الإسقاط، تحمل Q_h وK_h وV_h كل منها شكل [batch, seq_len, head_dim].
عرض مدمج
مصفوفات الرأس الواحد تُوضع جنبًا إلى جنب في الذاكرة. مصفوفة مدمجة واحدة W_Q بشكل [d_model, d_model] تنتج جميع الرؤوس دفعة واحدة:
Q_fused = X · W_Q # [batch, seq_len, d_model]
Q_per_head = reshape(Q_fused) # [batch, n_head, seq_len, head_dim]
الضرب المصفوفي المدمج يرسل استدعاء BLAS واحد بدلاً من 12. وحدات التنسور CUDA تصل إلى أقصى إنتاجية في عمليات ضرب المصفوفات لهذا الحجم؛ عمليات ضرب المصفوفات لكل رأس ستستخدم الأجهزة بشكل غير كافٍ.
عدد المعاملات
ثلاث مصفوفات مدمجة W_Q، W_K، W_V، كل واحدة d_model × d_model. بالإضافة إلى مصفوفة الإخراج W_O، أيضًا d_model × d_model. لـ ANDREA-120M:
معاملات لكل طبقة انتباه = 4 × 768² = 2,359,296 ≈ 2.36M
معاملات عبر 12 طبقة = 12 × 2.36M ≈ 28.3M
تقريبًا ربع إجمالي معاملات ANDREA-120M يعيش في عمليات الإسقاط الانتبهية. الثلاثة أرباع المتبقية تعيش في طبقة MLP الفرعية & الترميزات.
تسمية عمليات الإسقاط
اثنا عشر متجهًا يصبحان واحدًا
بعد حساب كل رأس
يُنتج كل رأس تنسور إخراج بشكل [batch, seq_len, head_dim]. اثنا عشر رأسًا يُنتجان اثني عشر تنسورًا كهذا. الدمج على طول البعد الخاص بالميزات يُعيد تجميعهم معًا:
concat_output = concat(head_1, head_2, ..., head_12)
shape = [batch, seq_len, n_head × head_dim]
= [batch, seq_len, 768] # for ANDREA-120M
Concat يعكس عملية التقسيم. يعود البعد الإجمالي للميزات إلى d_model. لا يوجد فقدان للمعلومات في الأبعاد؛ الفرق يكمن في محتوى كل قطعة: قطعة head 1 تعكس نمط الاهتمام المتعلم لـ head 1.
إسقاط الإخراج W_O
الدمج وحده يترك الرؤوس معزولة: إخراج head 4 يجلس بجانب إخراج head 7، ولا وعي ببعضهما البعض. إسقاط الإخراج W_O ذو الشكل [d_model, d_model] يمزجهما:
attention_output = concat_output · W_O
shape = [batch, seq_len, d_model]
بعد W_O، كل بعد إخراجي يحمل تركيبة خطية متعلمة لجميع الرؤوس الاثني عشر. تتدفق المعلومات بحرية بين الرؤوس من خلال هذا الضرب المصفوفي الواحد.
لماذا تتخصص الرؤوس
لا يوجد شيء في الهندسة المعمارية يجبر الرأس 4 على تعلم زمن الفعل أو الرأس 9 على تعلم علامات الترقيم المزدوجة. تظهر التخصصية من ضغط التدرج: أثناء التدريب، تتلقى الرؤوس التي تساهم بشكل متكرر تدرجات أصغر من الرؤوس التي تساهم بشكل فريد. على مدى آلاف الخطوات، يستقر كل رأس في تخصص يقلل من الخسارة الإجمالية بأكثر فعالية.
تجريبيًا، تظهر المحولات المدربة رؤوسًا تتعامل مع: أنماط الموضع (الرأس ينظر إلى الرمز السابق)، أنماط التركيب (الرأس ينظر إلى قوس الإغلاق المتطابق)، أنماط الدلالة (الرأس ينظر إلى الكيان المسمى الأحدث). لا تدرب تسميات هذا التخصص. إشارة التدريب وحدها، المنتشرة عبر W_O، ترتب الرؤوس.
لماذا اثنا عشر رأسًا، لا رأس واحد أعرض
كيفية تخزين CUDA للرؤوس
تنسور واحد، معاد تشكيله
محرك تدريب ANDREA microgpt_cuda.cu لا يخصص اثني عشر مخزن مؤقت منفصلاً لاثنتي عشر رأساً. يخصص تنسوراً مدمجاً واحداً & يعامل بعد الرأس كنمط خطوة:
// بعد Q = X · W_Q (ضرب مصفوفة واحد، مدمج عبر الرؤوس)
// Q لديه شكل [batch, seq_len, d_model]
// إعادة تشكيل إلى [batch, seq_len, n_head, head_dim]
// نقل إلى [batch, n_head, seq_len, head_dim]
// كل رأس الآن متجاور في البعدين الداخليين
عملية النقل تضع n_head أمام seq_len. لماذا؟ لأن العملية التالية (Q_h · K_h^T) تحتاج إلى أن يكون شريحة seq_len × head_dim لكل رأس متجاورة في الذاكرة. عمليات ضرب المصفوفات في CUDA تعمل بشكل أسرع على التنسورات المتجاورة.
نواة واحدة، رؤوس كثيرة
يتم تشغيل نواة CUDA الواحدة للانتباه عبر جميع الرؤوس بالتوازي. يتعامل كل كتلة خيوط مع زوج (دفعة، رأس) واحد؛ تتعاون الخيوط داخل الكتلة على بلاطة seq_len × head_dim. لا تعرف النواة أبدًا أنها تعالج رؤوسًا متعددة؛ يتعامل شبكة الإطلاق مع التوازي.
التكوين يعكس الأجهزة
اختيار ANDREA-120M لـ n_head=12, head_dim=64 يتوافق مع نوى الـ tensor في RTX 4090، التي تفضل بلاطات matmul في مضاعفات 16. head_dim=64 = 4 × 16 يطابق شكل البلاطة تمامًا. head_dim=32 (ANDREA-12M) يطابق أيضًا لكنه يستخدم البلاطة بشكل غير كامل. head_dim=72 لن يطابق وسيجبر على نوى احتياطية.
الصورة النهائية
| الخطوة | العملية | شكل الإخراج |
|---|---|---|
| 1. المشروع | Q = X · W_Q (كذلك K, V) | [batch, seq, d_model] |
| 2. إعادة التشكيل والتبديل | تقسيم d_model → (n_head, head_dim) | [batch, n_head, seq, head_dim] |
| 3. الانتباه لكل رأس | ضرب نقطي مقياس على كل رأس | [batch, n_head, seq, head_dim] |
| 4. التبديل وإعادة التشكيل | دمج (n_head, head_dim) → d_model | [batch, seq, d_model] |
| 5. إسقاط الإخراج | output = concat · W_O | [batch, seq, d_model] |
خمس خطوات. ثلاث عمليات ضرب مصفوفي تلمس الإدخال (إسقاطات Q, K, V). عملية ضرب مصفوفي واحدة تلمس الرؤوس المدمجة (W_O). نواة انتباه واحدة تتعامل مع جميع الرؤوس بالتوازي. ANDREA-120M تقوم بتنفيذ جميع الخطوات الخمس مرة واحدة لكل طبقة، اثنتا عشرة طبقة عمقًا، في كل مرور أمامي.