الاستعلام، المفتاح، القيمة
ثلاثة خرائط خطية من نفس الإدخال
بعد التضمين (النشاط 4)، يحمل كل موضع متجهًا ثلاثي الأبعاد 768 x_t. يبدأ الانتباه بإنتاج ثلاثة إسقاطات متميزة لـ x:
Q (الاستعلام): ما الذي يريد هذا الموضع معرفته؟
K (key): ما الذي يقدمه هذا الموقع للمواقع الأخرى؟
V (value): ما هو المحتوى الذي يقدمه هذا الموقع إذا تم الانتباه إليه؟
كل إسقاط يأتي من مصفوفة وزن متعلمة:
Q = x · W_Q # شكل W_Q: (d_model, d_k)
K = x · W_K # شكل W_K: (d_model, d_k)
V = x · W_V # شكل W_V: (d_model, d_k)
ثلاث مصفوفات، جميعها تُدرَّب عبر الانتشار العكسي. يتعلم النموذج: في هذا الموقع، أي استعلام يسترجع أفضل السياقات الماضية المفيدة؟ أي مفتاح يعلن محتوى هذا الموقع بشكل جيد؟ أي قيمة تُقدَّم إذا تم اختيارها؟
تشبيه المكتبة
تخيّل كتالوج بطاقات المكتبة. تدخل وأنت تفكر في موضوع معيّن (استعلامك query). كل بطاقة تسرد كلمات مفتاحية (مفتاح key). عندما يتطابق موضوعك مع كلمات مفتاحية البطاقة، تأخذ محتويات الكتاب (قيمة value). الـ Attention يقوم بهذا لكل رمز بالتوازي: كل موضع يستعلم كل موضع آخر، يرتب التوافق، ويسترجع تركيبة مرجحة من متجهات القيم.
أبعاد ANDREA-120M
| الكمية | القيمة | الملاحظات |
|---|---|---|
| d_model | 768 | حجم المتجه في كل موضع |
| n_head | 12 | رؤوس الاهتمام المتوازية |
| d_k | 64 | البعد لكل رأس (= d_model / n_head) |
| T | 1024 | طول السياق |
d_k = d_model / n_head = 768 / 12 = 64. كل رأس يرى شريحة ثنائية الأبعاد 64 من الفضاء الكامل 768 الأبعاد. النشاط 6 (grow_a_language_model_multi_head) يغطي التقسيم لكل رأس بالتفصيل.
احسب d_k
لماذا نقسم على sqrt(d_k)
مصفوفة النتيجة
بمجرد وجود Q & K (كل شكل (T, d_k))، يحسب الاهتمام مصفوفة نتيجة:
scores = Q · K^T # shape: (T, T)
scores[i, j] = مدى قوة توافق استعلام الموضع i مع مفتاح الموضع j. كل زوج (i, j) يحصل على درجة واحدة: 1024 × 1024 = 1,048,576 درجة لكل رأس انتباه في كل مرور أمامي.
لماذا نقسم
ناتج نقطي لمتجهين عشوائيين للناحية الوحدية في بعد d له قيمة كبيرة بنظام sqrt(d). بدون التوسيع، تنمو الدرجات مع d_k:
- d_k = 64: الضرب الداخلي النموذجي من الدرجة 8.
- d_k = 256: الضرب الداخلي النموذجي من الدرجة 16.
- d_k = 4096: الضرب الداخلي النموذجي من الدرجة 64.
النتائج الكبيرة تنتج softmax حاد القمة (موقع واحد يسيطر، تختفي التدرجات في أماكن أخرى). يتوقف التدريب. التمويه يصلح مقدارًا:
scaled_scores = (Q · K^T) / sqrt(d_k)
بالنسبة لـ ANDREA-120M، sqrt(d_k) = sqrt(64) = 8. يتم قسمة كل درجة على 8. تبقى الأحجام تقريبًا على مقياس الوحدة بغض النظر عن d_k. يبقى softmax سلسًا في سلوكه. تتدفق التدرجات.
تبرير Vaswani الأصلي
من Attention Is All You Need (2017): 'بالنسبة للقيم الكبيرة من d_k، تنمو الضربات النقطية كبيرة في الحجم، مما يدفع دالة softmax إلى مناطق حيث تكون التدرجات لديها صغيرة للغاية.' مقسوم sqrt(d_k) يقاوم هذا النمو.
عرض بالكود
داخل microgpt_cuda.cu، يظهر هذا التوسيع كقسمة حرفية:
scores[i][j] = dot(Q[i], K[j]) * (1.0f / sqrtf(d_k));
ضربة float واحدة لكل درجة. رخيصة. حاسمة.
التوسيع عند d_model = 4096
لماذا لا يمكن للموضع i رؤية الموضع j > i
قيد ولد من الإنتاج
تولد ANDREA رمزًا واحدًا في كل مرة. أثناء الاستدلال، تنتج الموضع 0 رمزًا أوليًا، ثم يرى الموضع 1 إخراج الموضع 0 وينتج رمزًا ثانيًا، وهكذا. لا يملك النموذج أبدًا وصولًا إلى الرموز المستقبلية أثناء التوليد.
يجب أن يعكس التدريب هذا. إذا كان بإمكان الموضع 5 أثناء التدريب الالتفات إلى الموضع 6، فسيتعلم النموذج اختصارًا: "تنبؤ الرمز 6 بقراءة الرمز 6". أثناء الاستدلال، يختفي هذا الاختصار (الرمز 6 غير موجود بعد). سيتفرق سلوك النموذج بين التدريب والاستدلال بشكل كارثي.
قناع سببي
يقوم القناع السببي بحظر الالتفات من أي موضع i إلى أي موضع j > i. التنفيذ: تعيين scaled_scores[i][j] = -infinity حيث j > i. بعد الـsoftmax، تصبح تلك المدخلات exp(-inf) = 0. يصفي القناع الالتفات إلى المواضع المستقبلية بشكل نظيف.
لـ i في range(T):
لـ j في range(T):
إذا j > i:
scaled_scores[i][j] = -1e9 # فعليًا -inf
بعد softmax (على مستوى الصفوف)، يصبح مجموع كل صف 1، لكن فقط المدخلات [0, i] تحمل كتلة الاحتمال. الموضع i يمزج المعلومات فقط من المواضع السابقة.
تصور القناع
مصفوفة الدرجات بشكل (T, T) مع تطبيق القناع تبدو كبنية مثلثية سفلية:
scaled_scores بعد القناع، تطبيق softmax سطرًا بسطر:
السطر 0: [1.0, 0, 0, 0, ...] # يرى نفسه فقط
السطر 1: [0.4, 0.6, 0, 0, ...] # يرى المواضع 0، 1
الصف 2: [0.2, 0.3, 0.5, 0, ...] # يرى 0, 1, 2
الصف 3: [0.1, 0.2, 0.3, 0.4, ...] # يرى 0, 1, 2, 3
...
توزيع احتمالي صارم للجزء السفلي الثلاثي الزوايا لكل صف. المستقبل يبقى غير مرئي.
لماذا يحتاج محول Decoder-Only إلى هذا
نموذج الـ Decoder فقط مثل ANDREA و GPT و LLaMA لديها جميعها هدف واحد: التنبؤ بالرمز التالي من الماضي. قناع سببي (causal mask) يجعل هذا الهدف قابلاً للتدريب بالتوازي: كل موضع يحسب تنبؤه بالرمز التالي الخاص به في وقت واحد، ولا يخدع أي موضع بالنظر إلى الأمام.
القناع والنكهة
من الدرجات إلى الإخراج
الـ Softmax: من الدرجات إلى الاحتمالات
الدرجات المقنّعة والمُقياسة لا تزال تتراوح على الأعداد الحقيقية. يحوّل الـ Softmax كل صف إلى توزيع احتمالي:
A[i][j] = exp(scaled_scores[i][j]) / sum_k exp(scaled_scores[i][k])
تنتج ثلاث خصائص:
الإجابة المباشرة
- المحتوى مُترجم بدقة: تم ترجمة النصوص إلى العربية الفصحى مع الحفاظ على المصطلحات التقنية مثل "Softmax" و"scaled_scores". - التنسيق محفوظ: بقيت العناوين (###)، الأسطر الفارغة، والكود كما هو. - المكان الحافظ: جميع البلوكات (- A[i][j] >= 0 لكل (i, j).
- sum_j A[i][j] = 1 لكل صف i.
- القيم الخام الأكبر تنتج احتماليات أكبر (تزايدية).
تخبر متجه الاحتمالات للصف i النموذج: كم يجب على الموضع i الانتباه إلى كل موضع سابق عند حساب مخرجاته؟
مجموع V الموزون
الإخراج النهائي للانتباه للموضع i:
output[i] = sum_j A[i][j] · V[j]
يتم وزن كل متجه قيمة V[j] باحتمالية الانتباه A[i][j]، ثم يتم جمعه. إخراج الموضع i يجمع متجهات القيم من كل موضع سابق، مرجحة بدرجة الصلة.
في الصيغة المصفوفية، جميع المواضع دفعة واحدة:
Attention(Q, K, V) = softmax(mask(Q · K^T / sqrt(d_k))) · V
سطر واحد. آلية انتباه كاملة. كتبها Vaswani et al. في عام 2017؛ لم تتغير الـtransformers بشكل جوهري منذ ذلك الحين.
شكل إخراج الرأس الواحد
إخراج رأس انتباه واحد: الشكل (T, d_k). بالنسبة لـ ANDREA-120M: (1024, 64). جميع الـ 12 رأسًا يحسبون بالتوازي؛ تُدمج مخرجاتهم إلى (1024, 768) & تُغذى إلى إسقاط خطي نهائي (W_O)، ثم إلى MLP لكتلة الـ transformer.
النشاط 6 (grow_a_language_model_multi_head) يغطي تقسيم متعدد الرؤوس. النشاط 7 (grow_a_language_model_transformer_block) يغطي كل ما يحيط بالانتباه: الاتصالات المتبقية، تطبيع الطبقة، MLP.