← Back to Transformer Overview | 🇬🇧 English Version
المثال اللي رح نمشي فيه طول الشرح:
ترجمة من إنجليزي لعربي:
Input: "I love learning"
Output: "أنا أحب التعلم"
أول خطوة: كل كلمة بتتحول لـ vector (قائمة أرقام). نفترض الـ embedding dimension = 4 (بالواقع 512).
"I" → [0.2, 0.5, 0.1, 0.8] "love" → [0.9, 0.3, 0.7, 0.2] "learning" → [0.4, 0.6, 0.5, 0.9]
هاي الأرقام الموديل بتعلمها وقت التدريب — كلمات بمعنى قريب بكون vectors قريبة من بعض.
الـ Transformer بعالج كل الكلمات بنفس الوقت (بالتوازي)، فما بعرف إنه "I" أول كلمة و"learning" ثالث كلمة.
نضيف vector خاص لكل موقع بالجملة باستخدام دوال sin و cos:
PE(pos, 2i) = sin(pos / 10000^(2i/d)) PE(pos, 2i+1) = cos(pos / 10000^(2i/d))
حيث: pos = موقع الكلمة (0, 1, 2, ...) | i = رقم البُعد | d = حجم الـ embedding (= 4)
الموقع 0 ("I"):
PE(0,0) = sin(0 / 10000^(0/4)) = sin(0) = 0.00 PE(0,1) = cos(0 / 10000^(0/4)) = cos(0) = 1.00 PE(0,2) = sin(0 / 10000^(2/4)) = sin(0) = 0.00 PE(0,3) = cos(0 / 10000^(2/4)) = cos(0) = 1.00 → PE₀ = [0.00, 1.00, 0.00, 1.00]
الموقع 1 ("love"):
PE(1,0) = sin(1) = 0.84 PE(1,1) = cos(1) = 0.54 PE(1,2) = sin(0.01) = 0.01 PE(1,3) = cos(0.01) = 1.00 → PE₁ = [0.84, 0.54, 0.01, 1.00]
الموقع 2 ("learning"):
PE(2,0) = sin(2) = 0.91 PE(2,1) = cos(2) = -0.42 PE(2,2) = sin(0.02) = 0.02 PE(2,3) = cos(0.02) = 1.00 → PE₂ = [0.91, -0.42, 0.02, 1.00]
"I" = [0.2, 0.5, 0.1, 0.8] + [0.00, 1.00, 0.00, 1.00] = [0.20, 1.50, 0.10, 1.80] "love" = [0.9, 0.3, 0.7, 0.2] + [0.84, 0.54, 0.01, 1.00] = [1.74, 0.84, 0.71, 1.20] "learning" = [0.4, 0.6, 0.5, 0.9] + [0.91,-0.42, 0.02, 1.00] = [1.31, 0.18, 0.52, 1.90]
كل كلمة بتسأل: "مين من الكلمات الثانية مهم إلي عشان أفهم معناي؟"
لكل كلمة بنضرب الـ vector بثلاث مصفوفات وزن:
Q = X × Wq (Query — شو عم بدور عليه؟) K = X × Wk (Key — شو عندي؟) V = X × Wv (Value — شو القيمة اللي بعطيها؟)
نفترض بعد الضرب (بحجم مبسط 3):
Q K V
"I" [1, 0, 1] [0, 1, 1] [1, 0, 0]
"love" [0, 1, 0] [1, 1, 0] [0, 1, 0]
"learn" [1, 1, 0] [0, 0, 1] [0, 0, 1]
أ) ضرب Q × Kᵀ (كل query مع كل key):
مثال: score لكلمة "I" مع كل الكلمات:
"I" مع "I": Q_I · K_I = [1,0,1]·[0,1,1] = 0+0+1 = 1 "I" مع "love": Q_I · K_love = [1,0,1]·[1,1,0] = 1+0+0 = 1 "I" مع "learn": Q_I · K_learn = [1,0,1]·[0,0,1] = 0+0+1 = 1
كل الـ scores:
"I" "love" "learn"
"I" → [ 1, 1, 1 ]
"love" → [ 1, 1, 0 ]
"learn" → [ 0, 2, 1 ]
ب) القسمة على √dₖ (scaling):
dₖ = 3 → √3 ≈ 1.73
"I" "love" "learn"
"I" → [0.58, 0.58, 0.58]
"love" → [0.58, 0.58, 0.00]
"learn" → [0.00, 1.15, 0.58]
ج) تطبيق Softmax (تحويل لاحتمالات):
softmax بحول كل صف لاحتمالات مجموعها = 1:
"I" "love" "learn"
"I" → [0.33, 0.33, 0.33] ← بنتبه لكل الكلمات بالتساوي
"love" → [0.39, 0.39, 0.22] ← بنتبه لـ "I" ونفسه أكتر
"learn" → [0.19, 0.59, 0.22] ← بنتبه لـ "love" أكتر!
د) الضرب بـ V (الحصول على المخرج):
output_I = 0.33×[1,0,0] + 0.33×[0,1,0] + 0.33×[0,0,1] = [0.33, 0.33, 0.33] output_love = 0.39×[1,0,0] + 0.39×[0,1,0] + 0.22×[0,0,1] = [0.39, 0.39, 0.22] output_learn = 0.19×[1,0,0] + 0.59×[0,1,0] + 0.22×[0,0,1] = [0.19, 0.59, 0.22]
بدل ما نعمل attention وحدة، نعمل 8 بالتوازي — كل وحدة اسمها head.
كل head بتعلم علاقة مختلفة:
1. لكل head: اعمل Self-Attention بشكل مستقل (بأوزان مختلفة) head₁ = Attention(Q×W₁ᵠ, K×W₁ᵏ, V×W₁ᵛ) head₂ = Attention(Q×W₂ᵠ, K×W₂ᵏ, V×W₂ᵛ) ... head₈ = Attention(Q×W₈ᵠ, K×W₈ᵏ, V×W₈ᵛ) 2. ادمج كل النتائج: MultiHead = Concat(head₁, head₂, ..., head₈) × Wᴼ
Head 1 output for "learn": [0.19, 0.59, 0.22] (تعلم علاقة المعنى) Head 2 output for "learn": [0.45, 0.10, 0.45] (تعلم علاقة الموقع) Concat: [0.19, 0.59, 0.22, 0.45, 0.10, 0.45] × Wᴼ → [0.30, 0.40, 0.30] (النتيجة النهائية)
output = x + Sublayer(x)
يعني: المدخل الأصلي بنجمعه مع مخرج الطبقة.
LayerNorm(x) = (x - μ) / √(σ² + ε) × γ + β
حيث: μ = المتوسط | σ² = التباين | γ, β = معاملات قابلة للتعلم
x (المدخل الأصلي لـ "learn"): [1.31, 0.18, 0.52]
attention output: [0.19, 0.59, 0.22]
بعد Residual: [1.31+0.19, 0.18+0.59, 0.52+0.22] = [1.50, 0.77, 0.74]
μ = (1.50 + 0.77 + 0.74) / 3 = 1.00
σ² = ((0.50)² + (-0.23)² + (-0.26)²) / 3 = 0.12
√(σ² + ε) ≈ 0.35
LayerNorm = [(1.50-1.00)/0.35, (0.77-1.00)/0.35, (0.74-1.00)/0.35]
= [1.43, -0.66, -0.74]
بعد الـ attention، كل كلمة بتمر بشبكة عصبية صغيرة:
FFN(x) = max(0, x×W₁ + b₁) × W₂ + b₂
input: [1.43, -0.66, -0.74] بعد W₁ + b₁: [2.1, -0.3, 1.5, -1.2] بعد ReLU (max 0): [2.1, 0.0, 1.5, 0.0] ← السالب صار 0 بعد W₂ + b₂: [0.8, 0.5, 0.3] ← رجع للحجم الأصلي
الـ Decoder بشتغل كلمة كلمة. نفترض وصلنا لمرحلة توليد الكلمة الثالثة وعندنا:
مدخلات الـ Decoder حتى الآن: ["أنا", "أحب", ???]
نفس Self-Attention بالزبط — بس مع قناع (mask):
Scores قبل الـ mask:
"أنا" "أحب" ???
"أنا" → [0.8, 0.5, 0.3]
"أحب" → [0.6, 0.9, 0.4]
??? → [0.3, 0.7, 0.8]
Mask (المثلث السفلي فقط):
"أنا" "أحب" ???
"أنا" → [0.8, -∞, -∞ ] ← "أنا" بشوف بس حاله
"أحب" → [0.6, 0.9, -∞ ] ← "أحب" بشوف "أنا" وحاله
??? → [0.3, 0.7, 0.8] ← ??? بشوف كل اللي قبله
بعد Softmax:
"أنا" → [1.00, 0.00, 0.00]
"أحب" → [0.43, 0.57, 0.00]
??? → [0.17, 0.37, 0.46]
هون الـ Decoder بشوف مخرجات الـ Encoder:
Q = من الـ Decoder (الكلمة اللي عم نولدها)
K = من الـ Encoder ("I", "love", "learning")
V = من الـ Encoder ("I", "love", "learning")
Q لـ ???: [0.5, 0.8, 0.3] Scores مع كل كلمة إنجليزية: ??? مع "I": 0.5×0.2 + 0.8×0.5 + 0.3×0.1 = 0.53 ??? مع "love": 0.5×0.9 + 0.8×0.3 + 0.3×0.7 = 0.90 ??? مع "learning": 0.5×0.4 + 0.8×0.6 + 0.3×0.5 = 0.83 بعد softmax: [0.22, 0.40, 0.38]
آخر خطوة — مخرج الـ Decoder بمر بـ:
1. Linear Layer: بحول الـ vector لحجم المفردات (مثلاً 50,000 كلمة) 2. Softmax: بحول لاحتمالات مخرج الـ Decoder لـ ???: [0.25, 0.60, 0.15] بعد Linear (نفترض 5 كلمات بس للتبسيط): ["أنا": 0.02, "أحب": 0.05, "التعلم": 0.85, "كتاب": 0.03, "بيت": 0.05] أعلى احتمال → "التعلم" (0.85) ✅
| المعلومة | القيمة |
|---|---|
| عدد طبقات الـ Encoder بالورقة الأصلية | 6 |
| عدد طبقات الـ Decoder | 6 |
| حجم الـ Embedding (d_model) | 512 |
| عدد الـ Heads | 8 |
| حجم كل Head (dₖ) | 512/8 = 64 |
| حجم الـ Feed-Forward الداخلي | 2048 |
| الورقة الأصلية | "Attention Is All You Need" (2017) |
| المؤلفين | Vaswani et al. (Google) |
| الـ Optimizer | Adam (مع learning rate متغير) |