خلية LSTM: بوابات الإدخال والنسيان والإخراج
سيرسم المتعلمون مخطط خلية LSTM، ويتتبعون تدفق المعلومات عبر كل بوابة، وينفّذون مصنّفًا نصيًا باستخدام nn.LSTM.
خلية LSTM: بوابات الإدخال والنسيان والإخراج درس مجاني في Machine Learning Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Machine Learning Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Machine Learning Academy 4 دروس في المجموع.
لماذا تحتاج شبكات RNN إلى آليات البوابات
تواجه Vanilla RNNs صعوبة في التعامل مع الاعتماديات بعيدة المدى لأن التدرجات تتلاشى أثناء الانتشار العكسي عبر الزمن. وتستبدل الحالة المخفية h_t = tanh(W_h * h_{t-1} + W_x * x_t) السياق السابق مع كل مدخل جديد، مما يجعل الشبكة تنسى المعلومات التي تعود إلى خطوات زمنية عديدة.
صمّم Hochreiter وSchmidhuber تقنية Long Short-Term Memory (LSTM) عام 1997 لحل هذه المشكلة. وهي تقدّم حالة خلية — حزامًا ناقلًا منفصلًا للذاكرة — إلى جانب آليات بوابات تتحكم صراحةً في المعلومات التي تُضاف أو تُزال أو تُمرّر إلى الأمام.
مفهوم حالة خلية LSTM
تحتوي LSTM على حالتين داخليتين: حالة الخلية C_t والحالة المخفية h_t. وتمتد حالة الخلية مثل حزام ناقل عبر التسلسل بأكمله، مع بوابات تتحكم في تفاعلات خطية صغيرة. ويسهّل ذلك تدفق التدرجات عبر الزمن.
الحالة المخفية h_t هي الخرج عند كل خطوة زمنية، وتُحسب من حالة الخلية. فكّروا في C_t بوصفها ذاكرة طويلة المدى، وفي h_t بوصفها ذاكرة عاملة تُمرّر إلى الطبقة التالية وتُعاد كخرج.
import torch
import torch.nn as nn
# An LSTM processes sequences and returns (output, (h_n, c_n))
lstm = nn.LSTM(input_size=10, hidden_size=32, batch_first=True)
print('LSTM parameters:', sum(p.numel() for p in lstm.parameters()))بوابة النسيان
تُعد بوابة النسيان أول بوابة يمر عبرها المدخل. فهي تقرأ الحالة المخفية السابقة h_{t-1} والمدخل الحالي x_t، وتنتج قيمة بين 0 و1 لكل عنصر في حالة الخلية.
تعني القيمة 1 «الاحتفاظ بكل شيء»، بينما تعني القيمة 0 «النسيان بالكامل». والصيغة هي: f_t = sigmoid(W_f · [h_{t-1}, x_t] + b_f). فعلى سبيل المثال، عند معالجة جملة جديدة في مهمة من مهام NLP، تعيد بوابة النسيان ضبط أي معلومات مخزنة عن الفاعل من الجملة السابقة.
import torch
import torch.nn as nn
# Manual forget gate illustration
batch_size, hidden_size, input_size = 1, 4, 3
h_prev = torch.zeros(batch_size, hidden_size)
x_t = torch.randn(batch_size, input_size)
W_f = torch.randn(hidden_size, hidden_size + input_size)
b_f = torch.zeros(hidden_size)
combined = torch.cat([h_prev, x_t], dim=1)
f_t = torch.sigmoid(combined @ W_f.T + b_f)
print('Forget gate output:', f_t) # Values between 0 and 1بوابة الإدخال وخلية المرشح
تحدد بوابة الإدخال القيم الجديدة التي يجب تخزينها في حالة الخلية. وتتكون من جزأين يعملان معًا: تحدد بوابة الإدخال i_t = sigmoid(W_i · [h_{t-1}, x_t] + b_i) مقدار التحديث، بينما تنشئ الخلية المرشحة g_t = tanh(W_g · [h_{t-1}, x_t] + b_g) قيمًا مرشحة يمكن إضافتها.
تتحكم sigmoid في البوابة (0 = مغلقة، 1 = مفتوحة)، بينما تنشئ tanh قيمًا ضمن النطاق [-1, 1]. والمعلومات الجديدة التي تُضاف إلى حالة الخلية هي i_t * g_t — أي البوابة بعد ترشيحها باستخدام القيم المرشحة.
# Input gate and candidate values
W_i = torch.randn(hidden_size, hidden_size + input_size)
b_i = torch.zeros(hidden_size)
W_g = torch.randn(hidden_size, hidden_size + input_size)
b_g = torch.zeros(hidden_size)
i_t = torch.sigmoid(combined @ W_i.T + b_i) # Input gate: what to update
g_t = torch.tanh(combined @ W_g.T + b_g) # Candidate values to add
print('Input gate:', i_t.detach())
print('Candidate cell:', g_t.detach())تحديث حالة الخلية
بعد الحصول على بوابة النسيان f_t وبوابة الإدخال i_t والخلية المرشحة g_t، يصبح تحديث حالة الخلية مباشرًا: C_t = f_t * C_{t-1} + i_t * g_t.
يطبّق الحد الأول f_t * C_{t-1} بوابة النسيان، فيمحو معلومات محددة انتقائيًا من حالة الخلية السابقة. ويضيف الحد الثاني i_t * g_t معلومات جديدة بصورة انتقائية. وتسمح هذه البنية الإضافية للتدرجات بالانتقال عبر العديد من الخطوات الزمنية دون تلاشيها، لأن التدرج يمر مباشرة عبر عملية الجمع.
# Update cell state
C_prev = torch.zeros(batch_size, hidden_size) # Previous cell state
C_t = f_t * C_prev + i_t * g_t # Element-wise operations
print('Updated cell state C_t:', C_t.detach())
# The additive update is key: gradients flow through + easily
# Compare to vanilla RNN: h_t = tanh(W * h_{t-1} + U * x_t)
# where gradients must flow through the tanh compression each stepبوابة الإخراج
تتحكم بوابة الإخراج في الجزء من حالة الخلية الذي يظهر بوصفه مخرج الحالة المخفية h_t. أولًا، تحدد بوابة الإخراج أجزاء حالة الخلية التي يجب إخراجها: o_t = sigmoid(W_o · [h_{t-1}, x_t] + b_o).
بعد ذلك، تمرر حالة الخلية عبر tanh (لدفع القيم إلى النطاق بين -1 و1)، ثم تُضرب في بوابة الإخراج: h_t = o_t * tanh(C_t). وتعمل الحالة المخفية h_t بوصفها المخرج في هذه الخطوة الزمنية، وكذلك المدخل إلى خطوة LSTM التالية إلى جانب حالة الخلية الجديدة.
# Output gate and hidden state
W_o = torch.randn(hidden_size, hidden_size + input_size)
b_o = torch.zeros(hidden_size)
o_t = torch.sigmoid(combined @ W_o.T + b_o) # Output gate
h_t = o_t * torch.tanh(C_t) # New hidden state
print('Output gate:', o_t.detach())
print('New hidden state h_t:', h_t.detach())عدد معاملات LSTM ومصفوفات الأوزان
يحتوي LSTM على أربع مصفوفات أوزان (النسيان، والإدخال، والمرشحة، والإخراج)، ويكون حجم كل منها (hidden_size, hidden_size + input_size)، بالإضافة إلى الانحياز. ويبلغ العدد الإجمالي للمعاملات 4 * hidden_size * (hidden_size + input_size) + 4 * hidden_size.
تجمع nn.LSTM في PyTorch البوابات الأربع كلها في مصفوفتَي أوزان مدمجتين هما weight_ih_l0 وweight_hh_l0 لزيادة الكفاءة. ولهذا قد يكون تدريب LSTM أبطأ من تدريب GRU (Gated Recurrent Unit)، الذي يستخدم بوابتين فقط وعددًا أقل من المعاملات.
import torch.nn as nn
hidden = 64
input_s = 32
lstm = nn.LSTM(input_size=input_s, hidden_size=hidden, batch_first=True)
# PyTorch stores weight_ih (input-hidden) and weight_hh (hidden-hidden)
print('weight_ih_l0 shape:', lstm.weight_ih_l0.shape) # (4*hidden, input)
print('weight_hh_l0 shape:', lstm.weight_hh_l0.shape) # (4*hidden, hidden)
print('Total params:', sum(p.numel() for p in lstm.parameters()))استخدام nn.LSTM في PyTorch
تقبل nn.LSTM في PyTorch موترًا لتسلسل ذي الشكل (batch, seq_len, input_size) عند ضبط batch_first=True، كما تقبل اختياريًا صفيف الحالة الأولية (h_0, c_0). وتعيد موتر المخرجات (أي جميع الحالات المخفية) وصفيفًا من الحالات النهائية.
في تصنيف التسلسلات، تحتاجون عادةً إلى الحالة المخفية الأخيرة h_n من الخطوة الزمنية النهائية فقط. أما في مهام وسم التسلسلات (مثل التعرف على الكيانات المسماة)، فتستخدمون مخرجات جميع الخطوات الزمنية. احرصوا دائمًا على تهيئة الحالات المخفية إلى الصفر، ما لم يكن لديكم سبب لتمرير السياق بين الدفعات.
import torch
import torch.nn as nn
batch_size, seq_len, input_size = 16, 20, 32
hidden_size = 64
lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size, batch_first=True)
x = torch.randn(batch_size, seq_len, input_size)
# Forward pass
output, (h_n, c_n) = lstm(x)
print('Output shape (all timesteps):', output.shape) # (16, 20, 64)
print('h_n shape (final hidden):', h_n.shape) # (1, 16, 64)
print('c_n shape (final cell):', c_n.shape) # (1, 16, 64)شبكات LSTM متعددة الطبقات وثنائية الاتجاه
تمرر شبكة LSTM مكدسة مخرج طبقة LSTM إلى الطبقة التالية بوصفه مدخلًا، مما يتيح للشبكة تعلم تمثيلات زمنية هرمية. اضبطوا num_layers=2 أو قيمة أكبر في nn.LSTM.
تشغّل شبكة LSTM ثنائية الاتجاه شبكة LSTM واحدة إلى الأمام عبر التسلسل وأخرى إلى الخلف، ثم تدمج حالتيهما المخفيتين. ويمنح ذلك كل خطوة زمنية سياقًا من الماضي والمستقبل معًا. اضبطوا bidirectional=True؛ فتصبح أبعاد المخرج 2 * hidden_size. وتتميز شبكات LSTM ثنائية الاتجاه بفاعلية كبيرة في مهام معالجة اللغة الطبيعية التي يكون فيها السياق من الجهتين اليسرى واليمنى مهمًا.
import torch
import torch.nn as nn
# Bidirectional stacked LSTM
lstm = nn.LSTM(
input_size=32,
hidden_size=64,
num_layers=2,
batch_first=True,
bidirectional=True,
dropout=0.3 # Dropout between layers
)
x = torch.randn(16, 20, 32)
output, (h_n, c_n) = lstm(x)
print('Bidirectional output shape:', output.shape) # (16, 20, 128)
print('h_n shape:', h_n.shape) # (4, 16, 64): 2 layers * 2 directionsGRU: بديل أبسط لـ LSTM
تُبسّط الوحدة التكرارية ذات البوابات (GRU) بنية LSTM من خلال دمج بوابتي النسيان والإدخال في بوابة تحديث واحدة، ودمج حالتي الخلية والحالة المخفية. وهي تستخدم بوابتين فقط: بوابة إعادة الضبط (مقدار ما يجب نسيانه من الماضي) وبوابة التحديث (مقدار التحديث المطلوب).
تحتوي GRU على معاملات أقل وتتدرب أسرع من LSTM، مع تحقيق أداء مماثل غالبًا. استخدموا LSTM عندما تحتاجون إلى أقصى قدرة تعبيرية للتعامل مع التسلسلات المعقدة، واستخدموا GRU عندما تكون السرعة والبساطة مهمتين. وعمليًا، تحدد الاختبارات التجريبية على مهمتكم الخاصة الخيار الأفضل.
import torch
import torch.nn as nn
# GRU is simpler: only 3 weight matrices instead of 4
gru = nn.GRU(input_size=32, hidden_size=64, batch_first=True)
lstm = nn.LSTM(input_size=32, hidden_size=64, batch_first=True)
print('GRU params:', sum(p.numel() for p in gru.parameters()))
print('LSTM params:', sum(p.numel() for p in lstm.parameters()))
# GRU has 25% fewer parameters than LSTM for same hidden sizeفهم LSTM من خلال مثال لغوي
تأملوا الجملة: 'The author, who lived in Paris for many years, wrote a novel.' يجب أن تتذكر شبكة LSTM كلمة 'author' (المفرد) عندما تصل إلى كلمة 'wrote' بعد مرور كلمات عديدة.
تحافظ بوابة النسيان على كلمة 'author' في حالة الخلية طوال جملة الصلة الطويلة. وتضيف بوابة الإدخال معلومات جديدة ذات صلة، مثل 'wrote'، إلى حالة الخلية. وتستخدم بوابة الإخراج حالة الخلية في اللحظة المناسبة لإنتاج الحالة المخفية الصحيحة لمهام لاحقة مثل التنبؤ بالكلمة التالية أو تصنيف الجملة.
- بوابة النسيان: الحفاظ على الفاعل طوال جملة الصلة
- بوابة الإدخال: تخزين معلومات الفعل عند الوصول إليه
- بوابة الإخراج: استخدام المعلومات المخزنة وقت التنبؤ
تحقق سريع
اختبروا مدى فهمكم لبوابات LSTM في هذا الدرس.
مراجعة الدرس
تعلمتم في هذا الدرس أن حالة خلية LSTM تعمل بوصفها ذاكرة طويلة الأمد تنتقل عبر التسلسل مع أقل قدر من التعديل، وأن ثلاث آليات للبوابات (النسيان، والإدخال، والإخراج) تتحكم في تدفق المعلومات باستخدام الضرب المتحكم فيه بواسطة sigmoid، وأن تحديث حالة الخلية الإضافي C_t = f_t * C_{t-1} + i_t * g_t يسمح للتدرجات بالانتقال دون تلاشيها. في الخطوة التالية، سنطبق شبكات LSTM على مهمة حقيقية لتحليل المشاعر، ونبني مصنفًا نصيًا متكاملًا من البداية إلى النهاية.
تعلم Python مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 30
- الدروس
- 120
الأسئلة الشائعة
هل درس «خلية LSTM: بوابات الإدخال والنسيان والإخراج» مجاني؟
نعم — نص درس «خلية LSTM: بوابات الإدخال والنسيان والإخراج» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Machine Learning Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Machine Learning Academy 4 دروس في المجموع.
ماذا ستتعلم في «خلية LSTM: بوابات الإدخال والنسيان والإخراج»؟
سيرسم المتعلمون مخطط خلية LSTM، ويتتبعون تدفق المعلومات عبر كل بوابة، وينفّذون مصنّفًا نصيًا باستخدام nn.LSTM. تتمرن على Machine Learning Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Machine Learning Academy؟
لا تُشترط خبرة سابقة. Machine Learning Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «خلية LSTM: بوابات الإدخال والنسيان والإخراج»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Machine Learning Academy هذا؟
نعم. كل درس في Machine Learning Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- شبكات RNN التقليدية: الحالة المخفية وفك تسلسل الخطوات
- مشكلة تلاشي التدرجات في الخطوات الزمنية العميقة
- خلية LSTM: بوابات الإدخال والنسيان والإخراج
- من تسلسل إلى واحد: تحليل المشاعر باستخدام LSTM