الانتباه
درس 3 من 8
3الانتباه
الصورة الكبيرةالانتباه يجيب عن سؤال واحد لكل كلمة: «أي الكلمات الأخرى في الجملة تهمّني الآن، وبكم؟». كل كلمة تسأل (Query)، وكل كلمة تعرض ما عندها (Key)، والإجابة خليط من قيمها (Value) بنسب تحدّدها المطابقة. هذه الفكرة وحدها هي قلب كل نموذج لغوي حديث.
ماذا تشاهد في الرسم: هذه أوزان صفّ واحد من المثال: «sat» تعطي نفسها 51% لأن مفتاحها [1, 2] يطابق سؤالها [1, 1] أكثر من غيره. لاحظ أن المجموع 100%، فالمخرج متوسط موزون للقيم لا أكثر.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
حين تقرأ «سقط الكوب من على الطاولة لأنه كان على الحافة»، تعرف فورًا أن «هو» تعني الكوب. الانتباه يعطي النموذج هذه القدرة: كل كلمة تسأل بقية الكلمات «من منكم يهمّني؟» ثم تأخذ من كل واحدة بقدر أهميتها.
لكل رمز ثلاثة متجهات: الاستعلام Q والمفتاح K والقيمة V. الأوزان softmax(Q·Kᵀ / √d) تحدد كم يأخذ كل رمز من قيم الآخرين، والناتج مجموع موزون للقيم. والقناع السببي يمنع الرمز من رؤية ما بعده في النماذج التوليدية.
قبل أن تبدأ
🧭التضمينات
تعرف أن كل كلمة متّجه، وأن الضرب النقطي بين متّجهين يقيس تشابههما.
🎲الاحتمال عمليًا
تعرف softmax: تحوّل أي درجات إلى نسب موجبة مجموعها 1.
الفكرة الجوهرية
في هذا الدرس تبني الانتباه خطوة خطوة: الاستعلام والمفتاح والقيمة، ثم الدرجات والخلط، ثم سبب القسمة على √d، ثم القناع، وأخيرًا ثمنه.
1الاستعلام والمفتاح والقيمة
كل كلمة تُضرب في ثلاث مصفوفات فتخرج منها ثلاثة متّجهات. الاستعلام يقول ماذا تبحث عنه، والمفتاح يقول ماذا تعرض، والقيمة هي ما تسلّمه إن اختارها أحد.
انظر إلى الرسم: الكلمة نفسها تلعب ثلاثة أدوار. حين تسأل تستعمل استعلامها، وحين تُسأل يُقارَن مفتاحها، وحين تُختار تعطي قيمتها.
2الدرجات ثم softmax ثم الخلط
نضرب كل استعلام في كل مفتاح فنحصل على جدول درجات حجمه الكلمات في الكلمات. ثم يحوّل softmax كل صف إلى نسب مجموعها 1، ونخلط القيم بهذه النسب.
import numpy as np
words = ["the", "cat", "sat", "down"]
x = np.array([[1, 0, 0],
[0, 1, 0],
[0, 1, 1],
[0, 0, 1]], dtype=float) # one 3-number vector per word
Wq = np.array([[0, 1], [1, 0], [0, 1]], dtype=float)
Wk = np.array([[1, 0], [1, 1], [0, 1]], dtype=float)
Wv = np.array([[1, 0], [0, 1], [1, 1]], dtype=float)
Q, K, V = x @ Wq, x @ Wk, x @ Wv
scores = Q @ K.T / np.sqrt(2)
weights = np.exp(scores) / np.exp(scores).sum(axis=1, keepdims=True)
out = weights @ V
np.set_printoptions(precision=2, suppress=True)
print("Q:\n", Q)
print("K:\n", K)
print("scores = Q K^T / sqrt(2):\n", scores)
print("weights (softmax of each row):\n", weights)
print("output = weights V:\n", out)
اقرأ الصف الثالث، كلمة sat: سؤالها [1, 1]، ومفتاح sat نفسها [1, 2]، فالضرب 3 وبعد القسمة على √2 يصير 2.12، أعلى رقم في الصف. بعد softmax تأخذ 51% من انتباهها، والباقي يتوزّع. ناتجها خليط من القيم الأربع بهذه النسب. احسب الصف الأول بيدك وتأكّد أنه يطابق.
3لماذا نقسم على √d
في الجدول السابق قسمنا على √2 لأن العرض 2. هذه القسمة الصغيرة تصير مهمة جدًّا حين يكبر العرض.
مع عرض 128 أو أكثر، يصير الضرب النقطي أرقامًا كبيرة، فيعطي softmax كل الوزن لكلمة واحدة تقريبًا وتختفي التدرّجات للباقي. القسمة على الجذر التربيعي للعرض تعيد الأرقام إلى مدى معقول.
4القناع السببي
النموذج الذي يولّد النص يجب ألّا يرى الكلمات التي بعده. لذلك نضع −∞ فوق القطر قبل softmax، فيصير وزن المستقبل صفرًا.
نجعل كل الدرجات متساوية حتى نرى أثر القناع وحده.
import numpy as np np.set_printoptions(precision=2, suppress=True) T = 4 scores = np.zeros((T, T)) # equal scores, to see the mask alone mask = np.triu(np.ones((T, T), dtype=bool), k=1) # True above the diagonal = the future scores[mask] = -np.inf weights = np.exp(scores) / np.exp(scores).sum(axis=1, keepdims=True) print(weights)
الكلمة الأولى لا ترى إلا نفسها، والثانية تقسم انتباهها بين نفسها والأولى، وهكذا. بدون هذا القناع، يتعلّم النموذج أثناء التدريب أن «يقرأ» الكلمة التالية من المدخلات بدل أن يتنبّأ بها، فتنخفض الخسارة بشكل مذهل ثم يفشل تمامًا عند التوليد.
انظر إلى الرسم: الكلمة الأولى لا ترى إلا نفسها، والرابعة ترى الأربع كلها. كل كلمة ترى نفسها وما قبلها فقط.
5الثمن التربيعي
كل رمز يُقارَن بكل رمز، فمضاعفة طول السياق تعني أربعة أضعاف الحساب والذاكرة في الانتباه.
for n in [512, 2048, 8192, 32768, 131072]:
pairs = n * n
mb = pairs * 2 / 1e6 # one fp16 score per pair, one head, one layer
print(f"{n:>7} tokens {pairs:>17,} pairs {mb:>10,.0f} MB per head per layer")
من 8 آلاف إلى 32 ألف رمز، أربعة أضعاف الطول، والذاكرة من 134 إلى 2147 ميغابايت، ستة عشر ضعفًا، لرأس واحد في طبقة واحدة. النماذج الحديثة لا تخزّن هذه المصفوفة كاملة بفضل خوارزميات مثل FlashAttention التي تحسبها على قطع، لكن الحساب نفسه يبقى تربيعيًّا. لهذا السياق الطويل بطيء ومكلف حتى حين يكون متاحًا.
كيف يعمل، خطوة بخطوة: كيف يُحسب الانتباه لجملة واحدة
تضرب متّجه كل كلمة في ثلاث مصفوفات Wq وWk وWv فتحصل على سؤالها ومفتاحها وقيمتها.
تضرب كل سؤال في كل مفتاح وتقسم على √d، فتحصل على جدول درجات بحجم الكلمات في الكلمات.
في النماذج المولِّدة تضع −∞ فوق القطر، ثم تطبّق softmax على كل صف فيصير مجموعه 1.
تضرب الأوزان في القيم، فيصير مخرج كل كلمة خليطًا من قيم الكلمات بنسب انتباهها.
مثال محلول
سنحسب الانتباه لجملة من أربع كلمات بأرقام صغيرة صحيحة تستطيع حسابها على الورق. كل كلمة متّجه من ثلاثة أرقام، وثلاث مصفوفات أوزان تحوّلها إلى سؤال ومفتاح وقيمة بعرض 2.
مثال: نفس الشيء في PyTorch
في الكود الحقيقي لا تكتب softmax بنفسك. PyTorch فيه دالة واحدة تختار أسرع تنفيذ لجهازك.
import torch import torch.nn.functional as F q = torch.randn(1, 4, 16) # (batch, tokens, width) k = torch.randn(1, 4, 16) v = torch.randn(1, 4, 16) out = F.scaled_dot_product_attention(q, k, v, is_causal=True) print(out.shape) # torch.Size([1, 4, 16])
is_causal=True يطبّق القناع نفسه الذي كتبناه. نفس المعادلة، لكن بتنفيذ يستخدم FlashAttention حين يتوفّر.
جرّب بلا كود
خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| خريطة الانتباه تشرح لماذا قال النموذج ما قاله. | هي نسب خلط في طبقة واحدة ورأس واحد من عشرات. لا تثبت سببًا وحدها. |
| القسمة على √d تفصيل تجميلي. | بدونها تكبر الدرجات مع العرض، فتعطي softmax كل الوزن لكلمة واحدة وتتلاشى التدرّجات للباقي. |
| السياق الأطول يكلّف أكثر بنسبة طوله فقط. | الانتباه يقارن كل رمز بكل رمز، فمضاعفة الطول تضاعف الحساب أربع مرات: من 8 آلاف إلى 32 ألف رمز قفزت الذاكرة من 134 إلى 2,147 ميغابايت للرأس الواحد. |
جرّب بنفسك
ماذا يحدث لمجموع كل صف في مصفوفة أوزان الانتباه؟
softmax يحوّل كل صف إلى نسب مجموعها 1، فالناتج متوسط موزون للقيم. حتى مع القناع، الكلمات المحجوبة تأخذ صفرًا والباقي مجموعه 1.
مضاعفة طول السياق من 4 آلاف إلى 8 آلاف رمز تضاعف حساب الانتباه بكم؟
عدد الأزواج n²، فمضاعفة n تضرب الأزواج في 4. باقي النموذج (الطبقات الخطية) يتضاعف مرتين فقط، ولهذا يغلب الانتباه على التكلفة في السياقات الطويلة.
بطاقات مراجعة سريعة
softmax(Q Kᵀ / √d) V: تشابه كل سؤال مع كل مفتاح، ثم تحويله لنسب مجموعها 1، ثم خلط القيم بها.−∞ فوق القطر قبل softmax، فيصير وزن المستقبل صفرًا.تحقق من فهمك
في مثالنا، لماذا الصف الأول والأخير متطابقان؟
لأن the وdown لهما نفس السؤال [0, 1] (انظر Q)، فتطابقان المفاتيح بنفس الدرجات، فتأخذان نفس الأوزان ونفس الناتج. في الانتباه، كلمتان بنفس السؤال ترى الجملة بنفس الطريقة بالضبط، وهذا أحد أسباب حاجتنا لترميز الموضع.
لماذا كان وزن «down» في الصف الثاني 0.14 فقط، أقل من الثلاث الأخرى؟
سؤال «cat» هو [1, 0]، ومفتاح «down» هو [0, 1]، فضربهما صفر، وهي أدنى درجة في الصف. باقي المفاتيح تبدأ بـ1 فأخذت كل منها 0.71 بعد القسمة على √2.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
توثيق رسمي2
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.