الموضع
درس 5 من 8
5الموضع
الصورة الكبيرةالانتباه لا يرى الترتيب. «عضّ الكلبُ الرجلَ» و«عضّ الرجلُ الكلبَ» عنده نفس مجموعة الكلمات بالضبط. لهذا نحقن الموضع في المتّجهات بطريقة ما، والطريقة الأشيع اليوم اسمها RoPE: تدوير السؤال والمفتاح بزاوية تعتمد على موضع كل منهما.
ماذا تشاهد في الرسم: هذان عمودان حقيقيان من جدول الترميز الجيبي في الدرس: الأول يدور بسرعة كعقرب الثواني، والثاني يتغيّر ببطء كعقرب الساعات. معًا يعطيان كل موضع بصمة، والمواضع المتجاورة بصمات متقاربة.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
الانتباه وحده لا يعرف الترتيب: «أكل الولد التفاحة» و«أكلت التفاحة الولد» تبدوان له نفس الكيس من الكلمات. لهذا نضيف لكل كلمة رقم مقعدها، مثل تذكرة في مسرح، فيعرف النموذج من جاء قبل من.
الترميز الموضعي إما مطلق (جيبي أو متعلَّم يضاف إلى التضمين) أو نسبي. والأشيع اليوم RoPE الذي يدوّر متجهي Q وK بزاوية تتبع الموضع، فيعتمد حاصل ضربهما على المسافة بين الرمزين، ويسهل مدّ السياق لأطوال أكبر.
قبل أن تبدأ
👀الانتباه
تعرف أن الانتباه يقارن كل سؤال بكل مفتاح، ولا شيء في المعادلة يذكر ترتيب الكلمات.
🧱كتلة المحوّل
تعرف أين يدخل السؤال والمفتاح في الكتلة، لأن RoPE يعمل عليهما مباشرة.
الفكرة الجوهرية
في هذا الدرس تثبت أولًا أن الانتباه لا يرى الترتيب، ثم ترى ثلاث طرق لإضافة الموضع: متّجه مُضاف، ثم الترميز الجيبي، ثم RoPE.
1الانتباه لا يرى الترتيب
الانتباه يعامل الجملة كمجموعة كلمات لا كتسلسل. الجملتان في الرسم فيهما الكلمات نفسها بترتيب معكوس.
import numpy as np
rng = np.random.default_rng(0)
d = 4
Wq, Wk, Wv = (rng.normal(size=(d, d)) for _ in range(3))
def attend(x):
s = (x @ Wq) @ (x @ Wk).T / np.sqrt(d)
w = np.exp(s - s.max(1, keepdims=True))
w /= w.sum(1, keepdims=True)
return w @ (x @ Wv)
emb = {w: rng.normal(size=d) for w in ["dog", "bites", "man"]}
a = np.stack([emb[w] for w in ["dog", "bites", "man"]])
b = np.stack([emb[w] for w in ["man", "bites", "dog"]])
out_a, out_b = attend(a), attend(b)
print("output for 'dog' in sentence A equals 'dog' in sentence B:",
bool(np.allclose(out_a[0], out_b[2])))
print("same set of outputs, only reordered:",
bool(np.allclose(np.sort(out_a, 0), np.sort(out_b, 0))))
ناتج كلمة dog هو نفسه سواء كانت فاعلًا في أول الجملة أو مفعولًا في آخرها. الانتباه يعطي نفس النواتج، فقط بترتيب مختلف. أي أن النموذج لا يستطيع التمييز بين من عضّ ومن عُضّ. هذا ما يسمّى «التكافؤ مع التبديل».
2الحل الأول: أضف الموضع
المطلوب أن تبدو الكلمة نفسها مختلفة في موضعين مختلفين. انظر إلى الرسم: «كلب» في الموضع 0 تدخل الكتلة الأولى بمتّجه غير «كلب» في الموضع 2.
أبسط فكرة: متّجه لكل موضع (0، 1، 2، ...) يُضاف إلى تضمين الكلمة قبل الكتلة الأولى. إما أن نتعلّمه كجدول تضمين ثانٍ، كما في GPT-2 وفي المحوّل الذي سنبنيه، وإما أن نحسبه بدوال الجيب كما في المحوّل الأصلي.
3الترميز الجيبي
بدل جدول نتعلّمه، يمكن حساب متّجه كل موضع بدوال الجيب وجيب التمام بترددات مختلفة. لا معاملات فيه، واستعمله المحوّل الأصلي.
import numpy as np
def sinusoidal(T, d):
pos = np.arange(T)[:, None]
i = np.arange(0, d, 2)[None, :]
angle = pos / 10000 ** (i / d)
pe = np.zeros((T, d))
pe[:, 0::2] = np.sin(angle)
pe[:, 1::2] = np.cos(angle)
return pe
np.set_printoptions(precision=2, suppress=True)
pe = sinusoidal(T=6, d=8)
print(pe + 0.0)
near = float(pe[2] @ pe[3])
far = float(pe[2] @ pe[5])
print(f"position 2 vs 3: {near:.2f} position 2 vs 5: {far:.2f}")
كل صف موضع، والأعمدة الأولى تتغيّر بسرعة والأخيرة ببطء شديد، مثل عقارب الساعة: الثواني والدقائق والساعات. وتشابه الموضعين 2 و3 (3.54) أعلى من 2 و5 (1.96)، أي أن المواضع القريبة لها متّجهات متشابهة، فيستطيع النموذج تعلّم «القرب».
4RoPE: الدرجة تعتمد على المسافة
الموضع النسبي أنفع من المطلق: «قبلي بثلاث كلمات» أهم من «الموضع 7». RoPE يدير الاستعلام بزاوية موضعه، ويدير المفتاح بزاوية موضعه.
نفس السؤال ونفس المفتاح في مواضع مختلفة. ننظر إلى الدرجة حين تكون المسافة بينهما ثابتة.
import numpy as np
def rope(v, pos, base=10000):
d = len(v)
theta = pos / base ** (np.arange(0, d, 2) / d)
cos, sin = np.cos(theta), np.sin(theta)
x, y = v[0::2], v[1::2]
out = np.empty(d)
out[0::2] = x * cos - y * sin
out[1::2] = x * sin + y * cos
return out
q = np.array([1.0, 0.5, -0.3, 0.8])
k = np.array([0.2, -1.0, 0.7, 0.4])
for m, n in [(3, 1), (10, 8), (105, 103), (5, 1)]:
score = rope(q, m) @ rope(k, n)
print(f"query at {m:>3}, key at {n:>3}, gap {m - n}: score {score:+.4f}")
print("length unchanged by rotation:", bool(np.isclose(np.linalg.norm(rope(q, 50)), np.linalg.norm(q))))
الأزواج (3، 1) و(10، 8) و(105، 103) بينها مسافة 2، فأعطت نفس الدرجة بالضبط، رغم أن مواضعها المطلقة مختلفة تمامًا. والمسافة 4 أعطت درجة أخرى. هذه الخاصية هي سبب انتشار RoPE: النموذج يتعلّم علاقات نسبية تصلح في أي مكان من النص.
انظر إلى الرسم: الدوران لا يغيّر طول المتّجه، فلا يفسد ما يحمله من معلومات. والدرجة بينهما تعتمد على الزاوية بينهما فقط.
كيف يعمل، خطوة بخطوة: كيف يُدخل RoPE الموضع في الانتباه
تقسم أبعاد السؤال والمفتاح إلى أزواج، كل زوج نقطة في مستوى.
تدير كل زوج بزاوية تساوي الموضع مضروبًا في تردّد خاص بذلك الزوج، سريع للأزواج الأولى وبطيء للأخيرة.
تفعل ذلك للسؤال بموضعه m وللمفتاح بموضعه n، دون أن يتغيّر طول أي منهما.
عند الضرب النقطي تبقى فقط الزاوية m − n، فتصير الدرجة معتمدة على المسافة بين الكلمتين وحدها.
أعمق قليلًا
لهذا تبنّت أغلب النماذج المفتوحة الحديثة (Llama وQwen وMistral وغيرها) RoPE. ومع ذلك، حين ترى نموذجًا يعِد بسياق مليون رمز، تذكّر أن «يقبل» لا تعني «يستخدم جيدًا». الأبحاث وجدت أن النماذج تتذكّر أول السياق وآخره أفضل من وسطه، وهذا ما ستقيسه بنفسك في درس هندسة السياق.
مثال محلول
لنثبت أولًا أن المشكلة حقيقية. جملتان بنفس الكلمات بترتيب معكوس، وانتباه بلا أي معلومة موضع.
max_position_embeddings في ملف الإعدادات لا يعلّم النموذج مواضع جديدة. طرق التمديد الحقيقية (مثل تحجيم RoPE) تحتاج غالبًا ضبطًا إضافيًّا على نصوص طويلة، وتُقاس بعدها على مهمة استرجاع من وسط السياق.
جرّب بلا كود
خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| الانتباه يعرف الترتيب لأن الكلمات تدخل بالتسلسل. | كل الكلمات تُحسب معًا كضرب مصفوفات. في المثال أعطت «dog bites man» و«man bites dog» نفس المخرجات بترتيب مختلف فقط. |
رفع max_position_embeddings يمدّد سياق النموذج. | تغيير الإعداد لا يعلّم النموذج مواضع جديدة. التمديد الحقيقي يحتاج عادة تدريبًا إضافيًّا على نصوص طويلة، ثم قياسًا. |
| النموذج الذي يقبل مليون رمز يستخدمها كلها جيدًا. | «يقبل» لا تعني «يستخدم جيدًا». النماذج تتذكّر أول السياق وآخره أفضل من وسطه. |
جرّب بنفسك
ماذا يحدث لنواتج الانتباه (بلا ترميز موضع) إذا عكست ترتيب كلمات الجملة؟
كل كلمة ترى نفس المجموعة من الكلمات بغض النظر عن ترتيبها، فناتجها لا يتغيّر. لهذا نحتاج معلومة الموضع.
في RoPE، على ماذا تعتمد درجة الانتباه بين سؤال في الموضع m ومفتاح في الموضع n؟
الدوران بزاوية m ثم الضرب في مفتاح مدوَّر بزاوية n يساوي دورانًا بالفرق بينهما. هذا ما رأيته في المثال: نفس الدرجة لكل الأزواج بمسافة 2.
بطاقات مراجعة سريعة
تحقق من فهمك
لماذا لا يكفي جدول مواضع متعلَّم لنموذج تدرّب على 2048 رمزًا ثم يُعطى 4000؟
لأن الجدول فيه 2048 صفًّا فقط، فلا يوجد متّجه للموضع 2049 أصلًا. حتى لو مدّدناه، الصفوف الجديدة لم تتدرّب. RoPE يحسب الزاوية لأي موضع، فيعمل تقنيًّا بعد طول التدريب، وإن ساءت الجودة بلا تمديد.
في RoPE، لماذا لا يفسد التدوير المعلومات التي يحملها المتّجه؟
لأن التدوير يغيّر الاتجاه ولا يغيّر الطول، كما أكّد المثال بـTrue. والزاوية نفسها معروفة من الموضع، فلا يضيع شيء.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.