← Back to Transformer Overview   |   🇬🇧 English Version

Transformer — شرح كامل بمثال واحد خطوة بخطوة

المثال اللي رح نمشي فيه طول الشرح:
ترجمة من إنجليزي لعربي:
Input: "I love learning"
Output: "أنا أحب التعلم"

1. Input Embedding (تحويل الكلمات لأرقام)

أول خطوة: كل كلمة بتتحول لـ 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 قريبة من بعض.


2. Positional Encoding (ترميز الموقع)

المشكلة:

الـ 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]

الجمع (Embedding + Position):

"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]
هلأ كل كلمة بتعرف شو هي (embedding) ووين هي (position). ✅

3. Self-Attention (آلية الانتباه الذاتي)

الفكرة:

كل كلمة بتسأل: "مين من الكلمات الثانية مهم إلي عشان أفهم معناي؟"

الخطوة الأولى: إنشاء Q, K, V

لكل كلمة بنضرب الـ 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]

الخطوة الثانية: حساب Attention Scores

المعادلة الأساسية:
Attention(Q, K, V) = softmax(Q × Kᵀ / √dₖ) × V

أ) ضرب 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 بصير يعطي 0 و 1 بس (مش تدرجات) → الموديل ما بتعلم منيح.

ج) تطبيق 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" أكتر!
ملاحظة: "learning" بنتبه أكتر لـ "love" — منطقي! "love learning" مرتبطين.

د) الضرب بـ 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]
هلأ كل كلمة صارت تحمل معلومات من الكلمات اللي مهمة إلها. ✅

4. Multi-Head Attention (انتباه متعدد الرؤوس)

الفكرة:

بدل ما نعمل 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ᴼ

بمثالنا (بنبسط لـ 2 heads):

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]  (النتيجة النهائية)

5. Residual Connection + Layer Normalization

Residual (Skip) Connection:

output = x + Sublayer(x)

يعني: المدخل الأصلي بنجمعه مع مخرج الطبقة.

ليش؟ بمنع مشكلة Vanishing Gradients (التدرجات بتختفي بالشبكات العميقة) وبضمن إنه المعلومات الأصلية ما تضيع.

Layer Normalization:

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]

6. Feed-Forward Network (شبكة أمامية)

بعد الـ 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]           ← رجع للحجم الأصلي
+ Residual + LayerNorm مرة ثانية ← مخرج الـ Encoder جاهز!

7. Decoder — الجزء اللي بولّد الترجمة

الـ Decoder بشتغل كلمة كلمة. نفترض وصلنا لمرحلة توليد الكلمة الثالثة وعندنا:

مدخلات الـ Decoder حتى الآن: ["أنا", "أحب", ???]

7.1 Masked Self-Attention (انتباه مقنّع)

نفس 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]
ليش الـ Mask؟ لأن وقت التوليد ما لازم الموديل يغش ويشوف الكلمات اللي لسه ما ولّدها!

7.2 Cross-Attention (انتباه متقاطع)

هون الـ 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]
يعني الكلمة الثالثة بالعربي بتنتبه أكتر لـ "love" و "learning" — منطقي لأن "التعلم" ترجمة "learning"! ✅

8. Linear + Softmax (التنبؤ بالكلمة)

آخر خطوة — مخرج الـ 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) ✅
النتيجة: "أنا أحب التعلم" 🎉

9. ملخص العملية الكاملة

┌──────────────────────── ENCODER ────────────────────────┐ │ │ │ "I love learning" │ │ ↓ │ │ [Input Embedding] → vectors لكل كلمة │ │ ↓ │ │ [+ Positional Encoding] → إضافة معلومات الموقع │ │ ↓ │ │ [Multi-Head Self-Attention] → كل كلمة تنتبه للباقي │ │ ↓ │ │ [+ Residual + LayerNorm] │ │ ↓ │ │ [Feed-Forward Network] → شبكة عصبية لكل كلمة │ │ ↓ │ │ [+ Residual + LayerNorm] │ │ ↓ │ │ ══► مخرجات الـ Encoder (تُرسل للـ Decoder) │ │ │ └──────────────────────────────────────────────────────────┘ ┌──────────────────────── DECODER ────────────────────────┐ │ │ │ "أنا أحب" (الكلمات اللي ولّدناها لحد هلأ) │ │ ↓ │ │ [Output Embedding + Positional Encoding] │ │ ↓ │ │ [Masked Multi-Head Self-Attention] → ما بشوف المستقبل │ │ ↓ │ │ [+ Residual + LayerNorm] │ │ ↓ │ │ [Cross-Attention] → Q من هون، K+V من الـ Encoder │ │ ↓ │ │ [+ Residual + LayerNorm] │ │ ↓ │ │ [Feed-Forward Network] │ │ ↓ │ │ [+ Residual + LayerNorm] │ │ ↓ │ │ [Linear → Softmax] → احتمال كل كلمة بالقاموس │ │ ↓ │ │ ══► "التعلم" ← الكلمة اللي احتمالها أعلى │ │ │ └──────────────────────────────────────────────────────────┘

10. معلومات أساسية للامتحان

المعلومةالقيمة
عدد طبقات الـ Encoder بالورقة الأصلية6
عدد طبقات الـ Decoder6
حجم الـ Embedding (d_model)512
عدد الـ Heads8
حجم كل Head (dₖ)512/8 = 64
حجم الـ Feed-Forward الداخلي2048
الورقة الأصلية"Attention Is All You Need" (2017)
المؤلفينVaswani et al. (Google)
الـ OptimizerAdam (مع learning rate متغير)