الوحدة 8 — المقاربات العميقة: LSTM والمحوّلات الزمنية
بعد الطرائق الإحصائيّة، وProphet، والتعزيز التدرّجي، ندخل عالم التعلّم العميق للسلاسل الزمنيّة. الوعد كبير: تعلّم تلقائيّ لتمثيلات معقّدة، ومعالجة متزامنة لآلاف السلاسل، وإدماج بيانات متعدّدة الوسائط (نصّ، صورة، سلسلة). الواقع أدقّ: التعلّم العميق يفوز في حالات محدّدة ويخسر في أخرى، وهذه الوحدة تُوضح المفصلين معًا.
من سلسلة إلى موتّرات: النافذة الزمنيّة
الشبكات العصبيّة تنتظر موتّرات ذات شكل محدّد. لتحويل سلسلتنا إلى مُدخَل قابل لـLSTM، نُنشئ نوافذ منزلقة: نافذة إدخال (نظرة إلى الوراء) وأفق إخراج (إلى الأمام).
import numpy as np
import torch
def creer_fenetres(serie, L=60, H=28):
"""
serie : تسلسل NumPy ذو بعد واحد.
L : طول نافذة الإدخال.
H : أفق التنبّؤ.
"""
X, y = [], []
for i in range(len(serie) - L - H + 1):
X.append(serie[i:i+L])
y.append(serie[i+L:i+L+H])
return np.array(X), np.array(y)
serie = df["ventes_totales"].values.astype(np.float32)
# التسوية على التدريب وحده (قاعدة الوحدة 1).
n_tr = int(len(serie) * 0.85)
mu, sigma = serie[:n_tr].mean(), serie[:n_tr].std()
serie_n = (serie - mu) / sigma
X_tr, y_tr = creer_fenetres(serie_n[:n_tr], L=60, H=28)
X_te, y_te = creer_fenetres(serie_n[n_tr:], L=60, H=28)
# tenseurs بشكل (نافذة، طول، سمات) = (N, L, 1).
X_tr_t = torch.tensor(X_tr).unsqueeze(-1)
y_tr_t = torch.tensor(y_tr)
X_te_t = torch.tensor(X_te).unsqueeze(-1)
y_te_t = torch.tensor(y_te)
اختيار هو قرار جوهريّ. قاعدة عمليّة: يجب أن يغطّي على الأقلّ دورتين موسميّتين كاملتين. على تردّد يوميّ بموسميّة أسبوعيّة، يعني ذلك . لدمج الموسميّة السنويّة يجب ، وهو مُكلف حسابيًا؛ الحلّ المعتاد إدماج متغيّرات تقويم كسمات إضافيّة، بدلًا من إعطاء الشبكة الأمر بإعادة اكتشاف السنة من التدفّق الخام.
LSTM كنموذج مرجعيّ عميق
LSTM (شرح مفصّل في الدورة 11) هي شبكة متكرّرة قادرة على حفظ حالة عبر خطوات زمنيّة طويلة. على السلاسل الزمنية تكوّن الحدّ الأدنى المعقول للنموذج العميق.
import torch.nn as nn
class LSTMPrevision(nn.Module):
def __init__(self, n_entrees=1, largeur=64, n_couches=2, H=28, abandon=0.2):
super().__init__()
self.lstm = nn.LSTM(
input_size=n_entrees,
hidden_size=largeur,
num_layers=n_couches,
batch_first=True,
dropout=abandon,
)
# تنبّؤ H قيمة دفعة واحدة (مسار مباشر).
self.sortie = nn.Linear(largeur, H)
def forward(self, x):
# x بشكل (N, L, sensat).
sortie_lstm, _ = self.lstm(x)
# نأخذ آخر خطوة زمنيّة فقط لأنّها تُلخّص التاريخ كلّه.
derniere = sortie_lstm[:, -1, :]
return self.sortie(derniere)
appareil = "cuda" if torch.cuda.is_available() else "cpu"
modele = LSTMPrevision(n_entrees=1, largeur=64, H=28).to(appareil)
حلقة تدريب معياريّة (تُذكِّر بالدورة 07):
critere = nn.MSELoss()
optimiseur = torch.optim.AdamW(modele.parameters(), lr=1e-3, weight_decay=0.01)
X_tr_t, y_tr_t = X_tr_t.to(appareil), y_tr_t.to(appareil)
X_te_t, y_te_t = X_te_t.to(appareil), y_te_t.to(appareil)
for epoque in range(100):
modele.train()
optimiseur.zero_grad()
prev = modele(X_tr_t)
perte = critere(prev, y_tr_t)
perte.backward()
torch.nn.utils.clip_grad_norm_(modele.parameters(), 1.0)
optimiseur.step()
if epoque % 10 == 0:
modele.eval()
with torch.no_grad():
perte_te = critere(modele(X_te_t), y_te_t).item()
print(f"epoque {epoque:3d} | tr {perte.item():.4f} | te {perte_te:.4f}")
نقاط انتباه ثلاث. الأولى: التنبّؤ المباشر لكامل الأفق (الطبقة الأخيرة تُخرِج قيمة) أفضل من التكرار المتسلسل الذي يُراكم الأخطاء. الثانية: clip_grad_norm_ يحدّ من انفجار التدرّج، مشكلة كلاسيكيّة في LSTM على السلاسل الطويلة. الثالثة: التسوية على التدريب وحده (المتوسّط والانحراف) وليس على كامل السلسلة — نفس قاعدة الوحدة 1.
المحوّلات الزمنيّة
المحوّلات (Transformers) هيمنت على معالجة اللغة والصورة، ودخلت التنبّؤ الزمنيّ بقوّة منذ 2020. النماذج البارزة: Temporal Fusion Transformer (TFT) من Google، وInformer، وPatchTST. الفكرة العامّة: بدل معالجة السلسلة تسلسليًا كـLSTM، تُقسَّم السلسلة إلى رقع (patches) وتُمرَّر عبر آليّة الانتباه الذاتيّ التي تتقاط الاعتماديّات الطويلة المدى بلا مراكمة أخطاء.
مزايا المحوّلات: التوازي في التدريب (أسرع من LSTM على بطاقات رسوميّة)، التقاط أفضل للاعتماديّات البعيدة، ودعم طبيعيّ لمتغيّرات مخلوطة (تأخّرات + متنبّئات معروفة + متغيّرات فئويّة). لكنّها جوعى للبيانات: على سلسلة وحيدة بأربع سنوات (سلسلتنا) نادرًا ما تتفوّق على LightGBM، بينما على آلاف السلاسل معًا (كلّ صيدليّة فرد) تص بح خيارًا جدّيًا.
نماذج التأسيس الزمنيّة (2024-2026)
الجيل الجديد الأشدّ ابتكارًا هو نماذج التأسيس الزمنيّة: TimeGPT (Nixtla)، وMoirai (Salesforce)، وTimeFM (Google). دُرِّبت مسبقًا على مئات آلاف السلاسل من مجالات متنوّعة، وتُقدّم تنبّؤًا بلا تدريب (zero-shot) على سلسلة جديدة. الاختبار السريع أصبح مباشرًا:
# مثال مفهومي (API قد يتغيّر).
from nixtla import NixtlaClient
client = NixtlaClient(api_key="...")
prev = client.forecast(df, h=28, freq="D", model="timegpt-1")
في 2026 هذه النماذج مغرية للنماذج الأوّلية السريعة لكنّها ليست دائمًا أفضل من نموذج مُصمَّم للحالة. الاستعمال العمليّ الأفضل: خطّ أساس فوريّ لبيانات جديدة قبل بناء نموذج مخصّص.
متى يفوز العميق ومتى يخسر
بلا لفّ ولا دوران: على سلسلة يوميّة وحيدة بأربع سنوات، LightGBM من الوحدة 7 يهزم LSTM ذي 64 وحدة في 8 حالات من 10. الجواب الأمين على السؤال «متى نستخدم التعلّم العميق؟» هو:
عندما يفوز التعلّم العميق:
- عدد كبير من السلاسل (آلاف) نتعلّم عليها معًا: كلّ صيدليّة أو منتج سلسلة، فيتعلّم النموذج تمثيلًا مشتركًا.
- متغيّرات متعدّدة الوسائط: نصّ (تعليقات العملاء)، أو صور (مخزون مصوَّر)، أو سلسلة أخرى مرافقة.
- آفاق طويلة جدًّا (شهور، سنة) على تردّد ساعيّ حيث الاعتماديّات البعيدة مركزيّة.
- بيانات كثيفة جدًّا (ملايين النقاط) حيث تعمّم الأشجار تعميمًا رديئًا.
عندما ي خسر:
- سلسلة وحيدة قصيرة أو متوسّطة (أقلّ من 10 سنوات يوميّ).
- موسميّة قويّة قابلة للتفكيك بلا نموّ للتعقيد.
- بيانات جدوليّة مصمَّمة جيّدًا: هنا يبقى LightGBM الحاكم في 2026.
كثيرًا ما يُبنى LSTM على سلسلة صغيرة ويُقاس MAE = 90 فيبدو مذهلًا. قارن قبل الاحتفال: naïf saisonnier قد يعطي 145، وSARIMA 118، وLightGBM 98، وLSTM بلا ضبط 90. الفرق مع LightGBM 8٪ في تحسين، مقابل ساعات تدريب وتعقيد صيانة. يجب أن يبرّر الفارق التكلفة. غياب مقارنة صريحة هو أشيع خطأ في مشاريع «التعلّم العميق للتنبّؤ».
تحديث الجدول
| النموذج | MAE (28 يومًا) | MASE |
|---|---|---|
| naïf saisonnier | 145 | 1.00 |
| SARIMA(1,1,1)(0,1,1) | 118 | 0.81 |
| Prophet + fêtes | 112 | 0.77 |
| LightGBM + calendrier | 98 | 0.68 |
| LSTM (64, L=60) | 95 | 0.66 |
تحسّن هامشيّ من LSTM على مبيعاتنا. الاختيار النهائيّ للوحدة 10 سيعتمد على مقايضة الأداء ↔ الصيانة، لا على الرقم وحده.
الخلاصة
- تُبنى نافذة الإدخال لتغطّي دورتين موسميّتين؛ متغيّرات التقويم تُغني عن نوافذ ضخمة لاستيعاب الموسميّة السنويّة.
- LSTM بسيط وقابل للتدريب، لكنّه يتطلّب
clip_grad_norm_والتنبّؤ المباشر لكلّ الأفق، وتسوية على التدريب وحده. - المحوّلات الزمنيّة ونماذج التأسيس تتفوّق مع كثرة السلاسل أو البيانات متعدّدة الوسائط؛ على سلسلة وحيدة قصيرة تخسر أمام LightGBM.
- حكم مباشر لعام 2026: LightGBM لسلسلة وحيدة، وشبكة عميقة لمجموعة سلاسل؛ ضع خطّ مرجعيّ قبل قرار التعقيد.
الوحدة التالية: التحقّق المتدرّج والمقاييس الملائمة، ومفصّل ما ينبغي مراقبته لتقييم أمين.