الوحدة 2 — الاستعلام والمفتاح والقيمة
الوحدة السابقة أوضحت لماذا جاء الانتباه. هذه الوحدة تُعرّي ميكانيكيّته بالكامل: صيغة على مصفوفتين وشعاعَين لا تصمد أمام تحليل يستهلك خمسًا وأربعين ثانية بالورقة والقلم. وسنُحسبها بيدنا على ثلاث جتونات، ثمّ سنكتبها في بايتورش لأنّها أوّل لبنة من المشروع الموجّه الذي سيرافقنا حتى الوحدة 10.
ثلاثيّة تستعير من قاعدة بيانات
يُقدَّم الانتباه في الغالب بمعادلة مصفوفيّة، لكنّ التمثيل الأوضح مستعار من عالم قواعد البيانات:
- الاستعلام : ما أبحث عنه الآن. من منظور جتون معيّن، هو السؤال «ما الذي أحتاجه من الآخرين ليكتمل معناي؟».
- المفتاح : ما يعلن عنه كلّ جتون آخر. من منظوره هو، «هذا ما أعرضه على من يبحث».
- القيمة : ما يُقدّم فعلًا حين يُختار. من منظوره أيضًا، «إن اخترتَني فهذا ما آخذه لك».
آلية البحث بسيطة: نُقارن الاستعلام بكلّ المفاتيح، فيُنتج ذلك درجة تشابه لكلّ زوج؛ نُحوّل هذه الدرجات إلى أوزان بمجموع واحد؛ نأخذ متوسطًا موزونًا للقيم بهذه الأوزان. النتيجة هي متّجه واحد يُلخّص، من وجهة نظر الاستعلام، ما يهمّه في الآخرين.
الأناقة أنّ الجتون نفسه هو مصدر الاستعلام والمفتاح والقيمة في الآن ذاته. فكلّ جتون يبعث في التسلسل ثلاث نسخ من نفسه، لكلّ منها دور مختلف. وسنُطلق على هذا الترتيب اسم الانتباه الذاتي لأنّ التسلسل ينظر إلى نفسه.
الحساب بأيدينا على ثلاثة جتونات
خذ ثلاث كلمات: «القطّ»، «يأكل»، «سمكة». نرمز إلى تمثيلاتها الأوّلية بمتّجهين ، ثمّ نُنتج و و بضربها في ثلاث مصفوفات إسقاط مُتعلَّمة .
سنكتفي في هذا المثال المُبسَّط بضياع بسيط: ندَع لعرض الآلية. من أجل الجتون «القطّ»، ليكن:
ومن أجل «يأكل» و«سمكة»:
الخطوة الأولى: حساب درجات التشابه بجداء نقطي .
| الزوج | الجداء النقطي |
|---|---|
الخطوة الثانية: نقسم على . نحصل على و و.
الخطوة الثالثة: نُطبّق softmax:
عدديًّا: ، و، و. المجموع . فالأوزان هي على التقريب و و.
الخطوة الرابعة: نأخذ متوسطًا موزونًا للقيم:
هو تمثيل «القطّ» بعد الانتباه. يظهر أنّ الجتون احتفظ بنفسه أساسًا (0,51)، لكنّه أدخل جزءًا من «سمكة» (0,30) وأقلّ من ذلك من «يأكل» (0,19). لو غيّرنا الاستعلام إلى جتون «يأكل» لأنتجنا ولحصلنا على توزيع مختلف تمامًا.
لماذا القسمة على جذر البُعد
الخطوة الثانية أعلاه ليست تجميلية. فبِبُعد متزايد، ينمو الجداء النقطي بمعدّل ، ويصير softmax متطرّفًا: قيمة واحدة قريبة من 1، والباقي قريب من 0. هذا الاستقطاب يُفرغ الانتباه من فائدته، ويجعل التدرّج ينهار.
القسمة على تُبقي الدرجات في مجال معتدل، والتوزيع في مرحلة نشي طة يستطيع فيها التدريب أن يحرّك الأوزان. هذا الإصلاح البسيط هو ما جعل الانتباه قابلًا للتدريب على أبعاد أو أكثر، وهو ما ميّز صيغة Vaswani عن صيغة Luong الأولى.
هذه هي المعادلة المُشار إليها في كلّ ورقة عن Transformer. سبعة رموز، ووراءها كلّ ما سنبنيه.
إن كان مصفوفة حيث عدد الجتونات، فإنّ softmax يجب أن يُطبَّق على البُعد الثاني (المفاتيح)، لا الأوّل. الخطأ يُنتج توزيعًا يجمع الاستعلامات معًا بدلًا من المفاتيح، ويُعطي شبكة تتدرّب دون أن تتعلّم. راجع دائمًا dim=-1 في torch.softmax.
الكتلة الأولى ببايتورش
لنكتب هذه العملية في بايتورش، بلا استعمال nn.MultiheadAttention بعد. هذا هو الجدار الأوّل من المشروع الموجّه:
import torch
import torch.nn as nn
import torch.nn.functional as F
class SingleHeadAttention(nn.Module):
def __init__(self, d_model: int, d_k: int):
super().__init__()
self.d_k = d_k
self.W_q = nn.Linear(d_model, d_k, bias=False)
self.W_k = nn.Linear(d_model, d_k, bias=False)
self.W_v = nn.Linear(d_model, d_k, bias=False)
def forward(self, x: torch.Tensor) -> torch.Tensor:
# x : (batch, seq, d_model)
Q = self.W_q(x) # (batch, seq, d_k)
K = self.W_k(x)
V = self.W_v(x)
scores = Q @ K.transpose(-2, -1) # (batch, seq, seq)
scores = scores / (self.d_k ** 0.5)
weights = F.softmax(scores, dim=-1) # على محور المفاتيح
return weights @ V # (batch, seq, d_k)
if __name__ == "__main__":
torch.manual_seed(0)
x = torch.randn(1, 3, 8) # حزمة 1، 3 جتونات، بُعد 8
layer = SingleHeadAttention(d_model=8, d_k=4)
y = layer(x)
print(y.shape) # torch.Size([1, 3, 4])
يتّسع الأمر عندما نستبدل الساذجة بثلاث إسقاطات مختلفة . هذا الفصل هو ما يمنح النموذج حرّية الدور: يستطيع الجتون أن يعرض نفسه بطريقة (المفتاح) ويسأل عن الآخرين بطريقة أخرى تمامًا (الاستعلام). ولولا هذا الفصل، لتحوّل الانتباه إلى قناع تشابه شكلي بحت.
ما يفهمه النموذج من هذا
لِفهم ما يتعلّمه هذا المكوّن، فكّر في هذه المعادلة الجزئية: الاستعلام قابل للتعلّم، والمفتاح قابل للتعلّم، والقيمة قابلة للتعلّم. ثلاث مصفوفات إسقاط يُحسّنها التدريب حتى تنشأ خارطة انتباه ذات معنى. في اللغة، تُظهر خرائط الانتباه أنّ رأسًا قد يتعلّم البحث عن مرجع الضمائر، وآخر يبحث عن الموصوف الأقرب، وثالث يربط الفعل بفاعله. هذه الأنماط ليست مبرمجة: بل تنبثق من تدريب الشبكة على مهمّة مُحدَّدة.
هذا الانبثاق هو ما يجعل Transformer معمارية عامّة إلى هذا الحدّ. فهو لا يفرض شكلًا بعينه للتفاعل بين الجتونات: بل يترك للنموذج أن يكتشف الشكل المفيد. أمّا وظيفة المهندس فحصر ما تحتاجه المهمّة إلى و و، وحساب البُعد اللازم، والتأكّد من أنّ الدرجات لا تنفجر.
في الخلاصة
- الانتباه ثلاثيّة استعلام ومفتاح وقيمة، مُشتقّة من نفس التسلسل عبر ثلاث مصفوفات إسقاط قابلة للتعلّم؛ فيبعث كلّ جتون ثلاث نسخ من نفسه بأدوار مختلفة.
- الحساب في أربع خطوات: جداء نقطي، قسمة على ، softmax، ثمّ متوسط موزون للقيم. جوهر الأمر لا يتجاوز خمسة أسطر عدديّة.
- القسمة على جذر البُعد ضروريّة كي لا يستقرّ softmax عند القيم المتطرّفة عند الأبعاد الكبيرة؛ وهي الفرق العملي بين الانتباه القابل للتدريب والانتباه المشلول.
- الكتلة الأولى من المشروع الموجّه،
SingleHeadAttentionببايتورش، تُنجز كلّ ذلك في نحو عشرة أسطر ولا تستعمل أيّ طبقة انتباه جاهزة.
الوحدة التالية: نضاعف الرؤوس، فنرى لماذا لا تكفي رأسًا واحدة، وكيف نحسب أبعاد كلّ رأس بحيث تبقى الكلفة ثابتة.