الوحدة 4 — النماذج المرجعية التي لا يجب إغفالها
قبل أن نُدخل ARIMA أو Prophet أو LSTM إلى الحلقة، نحتاج إلى معيار نُحاكم به أيّ نموذج قادم. هذه هي وظيفة النماذج المرجعيّة. أربع منها كافية لتغطية كلّ الحالات تقريبًا، وكلّها تُكتب في سطور قليلة من pandas. غياب هذه الخطوة هو أشيع خطأ منهجيّ في مشاريع التنبّؤ الحقيقيّة: مشروع يُنفَق فيه شهر على تعديل LSTM لا يهزم نسخة موسميّة ساذجة بأكثر من 3٪.
لماذا نبدأ من هنا
النماذج المرجعيّة تخدم أربع وظائف يخطئ من يخلطها بمرحلة استكشاف بسيطة:
- تُقدّم رقمًا يجب أن يهزمه كلّ نموذج مقترح؛ إن لم يفعل، النموذج لا يستحقّ النشر أيًّا كان تعقيده.
- تُبطئ عمليّة الاعتماد على المُقيَّم: هي أسرع تنفيذًا (ثوانٍ) من نموذج متقدّم (دقائق أو ساعات)، فتُتيح التكرار السريع على تصميم البيانات.
- تكشف تسرّب المستقبل من الوحدة 1: إن هزم النموذج المرجعيّ السقفَ النظريّ، فأنت أمام تسرّب.
- تُشكّل خيار طوارئ في الإنتاج: إن انهار النموذج المتقدّم أثناء التدريب أو الاستدلال، النموذج الساذج يُبقي النظام يعمل بدل أن يعود إلى الصفر.
النموذج الساذج: التوقّع الأبسط الممكن
نموذج naive يتوقّع لكلّ زمن آخر قيمة معلومة . صوريًا: لكلّ أفق . يبدو تافهًا، وهو كذلك، لكنّه أساس نظريّ متين: يُعطي تحديدًا أدنى مطلقًا يجب هزمه على أيّ سلسلة تحتوي أدنى قدر من البنية.
النموذج الساذج الموسميّ: عدوّ الطموحين
النسخة الموسميّة تتوقّع بتكرار قيمة من موسم سابق: ، حيث فترة الموسميّة (7 لدينا). على مبيعاتنا اليوميّة يعني هذا تكرار مبيعات نفس اليوم من الأسبوع السابق. مذهل بساطة، ومذهل قوّة: على السلاسل ذات الموسميّة الأسبوعيّة القويّة (شركات الخدمات، والبيع بالتجزئة، والنقل)، يهزم هذا النموذج ثلاثة أرباع المحاولات الأولى غير المُصمّمة جيّدًا بـLSTM.
المتوسّط المتحرّك ونموذج الدريفت
المتوسّط المتحرّك يتوقّع بمتوسّط النافذة الأخيرة من طول : . يُنعّم الضجيج قصير المدى ويعطي مرجعًا للسلاسل بلا اتّجاه ولا موسميّة قويّة. نموذج الدريفت يمدّ الخطّ المستقيم بين أوّل وآخر مشاهدتين: . يفيد للسلاسل ذات الاتّجاه الواضح بلا موسميّة، وهو مرجع طبيعيّ لمقارنة نموذج ARIMA(0, 1, 0) الذي يُنتج نتيجة مطابقة تقريبًا.
التنفيذ الموحَّد
نُطبّق الأربعة على مجموعة اختبار بأفق 28 يومًا، ونحسب MAE (متوسّط الخطأ المطلق) لكلّ منها:
import numpy as np
import pandas as pd
df = pd.read_csv("ventes_pharmacies.csv", parse_dates=["date"])
serie = df.set_index("date")["ventes_totales"].asfreq("D")
# التقسيم بلا خلط: قاعدة الوحدة 1.
train = serie[:"2027-08-31"]
test = serie["2027-09-01":"2027-09-28"] # 28 يومًا للاختبار
H = len(test)
def naif(train, H):
return np.repeat(train.iloc[-1], H)
def naif_saisonnier(train, H, s=7):
# نكرّر آخر s قيم بشكل دوري.
dernier_cycle = train.iloc[-s:].values
return np.tile(dernier_cycle, int(np.ceil(H / s)))[:H]
def moyenne_mobile(train, H, k=14):
m = train.iloc[-k:].mean()
return np.repeat(m, H)
def derive(train, H):
n = len(train)
pente = (train.iloc[-1] - train.iloc[0]) / (n - 1)
return train.iloc[-1] + pente * np.arange(1, H + 1)
predictions = {
"naïf": naif(train, H),
"naïf saisonnier": naif_saisonnier(train, H, s=7),
"moyenne mobile": moyenne_mobile(train, H, k=14),
"dérive": derive(train, H),
}
for nom, pred in predictions.items():
mae = np.mean(np.abs(pred - test.values))
print(f"{nom:20s} | MAE = {mae:8.1f}")
مثال مخرجات نموذجيّة على بياناتنا: naïf ≈ 380، naïf saisonnier ≈ 145، moyenne mobile ≈ 260، d érive ≈ 355. يظهر بوضوح أنّ الطبيعة الأسبوعيّة للسلسلة تجعل naïf saisonnier المرجع الحقيقيّ الذي يجب على SARIMA وProphet وLSTM أن يهزموه.
جدول المقارنة: النطق الأوّل
هذا الجدول سيُرافقنا حتى الوحدة 10، ويمتلئ من نموذج إلى آخر:
| النموذج | MAE (28 يومًا) | MASE | فارق مقابل المرجع |
|---|---|---|---|
| naïf (يوم واحد) | 380 | 2.62 | +162% |
| naïf saisonnier (7 أيّام) | 145 | 1.00 | المرجع |
| moyenne mobile (k=14) | 260 | 1.79 | +79% |
| dérive | 355 | 2.45 | +145% |
| SARIMA(1,1,1)(0,1,1) | — | — | (وحدة 5) |
| Prophet | — | — | (وحدة 6) |
| LightGBM + calendrier | — | — | (وحدة 7) |
| LSTM | — | — | (وحدة 8) |
مقياس MASE (سنعود إليه بالتفصيل في الوحدة 9) هو MAE مقسومًا على MAE للنموذج الساذج الموسميّ على التدريب. قيمة أقلّ من 1 = أفضل من المرجع؛ قيمة أكبر من 1 = أسوأ. الاصطلاح جميل: نموذج بـMASE = 0.7 يُقرأ فورًا «أخطأ بنسبة 70% ممّا يخطئ به المرجع»، أي 30% تحسّن حقيقيّ.
قبل قبول نموذج متقدّم في الإنتاج، اطلب منه على الأقلّ 15% تحسّنًا في MAE على المرجع الساذج الموسميّ، مقاسًا على تحقّق متدرّج (وحدة 9). أقلّ من ذلك، وتكلفة الصيانة والحوسبة لا تُبرَّر مقابل نسخة بسطر واحد من كود.
احرص على أن يكون آخر قيمة في التدريب من نفس يوم الأسبوع الذي يبدأ به الاختبار حين تُقارن. الالتباس بين أوّل يوم أفق وأوّل يوم أسبوع يمكن أن يجعل ساذجًا موسميًّا يبدو أسوأ ممّا هو عليه، أو أفضل، بضربة حظّ في التقسيم.
الخلاصة
- النماذج المرجعيّة ليست خيارًا استعراضيًا؛ هي الحدّ الأدنى النظريّ الذي يُبرّر أيّ نموذج قادم.
- naïf saisonnier بفترة هو أشرس منافس لسلاسلنا؛ يُهزم أكثر النماذج غير المصمَّمة جيّدًا.
- التنفيذ يأخذ دزينة أسطر؛ لا عذر في تخطّي هذه الخطوة.
- جدول المقارنة يمتلئ من الوحدة 5 إلى 8؛ سنقرأه في الوحدة 10 لاختيار النموذج النهائيّ بأدلّة، لا بذوق.
الوحدة التالية: نُدخل ARIMA وSARIMA ونطلب منهما هزم naïf saisonnier، مع اختيار الرتب من ACF/PACF الوحدة السابقة.