تحليل البياناتتعلم الآلة

كيفية حساب MAPE في بايثون

دليل أكاديمي شامل يشرح كيفية حساب متوسط النسبة المئوية للخطأ المطلق (MAPE) في بايثون خطوة بخطوة باستخدام الدوال المخصصة والمكتبات الإحصائية المتقدمة.

تاريخ النشر

تُعد عملية تقييم النماذج التنبؤية إحدى الركائز الجوهرية في مسار علم البيانات وتعلم الآلة والإحصاء التطبيقي. فعند بناء نموذج تنبؤي أو خوارزمية لاستقراء السلاسل الزمنية، لا تتوقف المهمة عند استخراج النتائج الرقمية فحسب، بل تمتد إلى قياس مدى موثوقية هذه التقديرات ودقتها مقارنة بالقيم الحقيقية المرصودة في الواقع. تتعدد المقاييس الإحصائية المتاحة لاختبار جودة النماذج، إلا أن متوسط النسبة المئوية للخطأ المطلق (Mean Absolute Percentage Error – MAPE) يبرز كأحد أكثر هذه المقاييس شيوعاً واعتماداً في الأوساط الأكاديمية والتطبيقية، نظراً لقدرته الفريدة على تقديم تقييم بديهي ومجرد من وحدات القياس المباشرة.

تكمن قوة مقياس MAPE في كونه يعبر عن حجم الخطأ كنسبة مئوية من القيمة الفعلية، مما يتيح للمحللين والباحثين وأصحاب القرار فهم حجم الانحراف بشكل فوري دون الحاجة إلى الإلمام بالوحدات الهندسية أو المالية للبيانات المدروسة. سواء كنت تتنبأ بأحجام المبيعات بملايين الدولارات، أو باستهلاك الطاقة بالميغاواط، أو بدرجات الحرارة، فإن النتيجة المعبر عنها بنسبة مئوية تمنحك معياراً موحداً وقابلاً للمقارنة المباشرة عبر مختلف النطاقات والمجالات. ومع ذلك، فإن تطبيق هذا المقياس من الناحية الحسابية والبرمجية ينطوي على تعقيدات دقيقة، تتطلب فهماً عميقاً لبنيته الرياضية وكيفية تجنب الثغرات البرمجية والتحيزات الإحصائية المرتبطة به.

في هذا الدليل الأكاديمي والتقني الشامل، سنستعرض بعمق نظري وتطبيقي متكامل كيفية حساب مقياس MAPE باستخدام لغة بايثون (Python)، مستعرضين البنية الجبرية الكامنة وراءه، والخطوات البرمجية لبنائه يدوياً باستخدام مكتبة NumPy، مروراً بالاعتماد على المكتبات المتخصصة مثل Scikit-Learn وStatsmodels، وصولاً إلى استراتيجيات معالجة التحديات الحسابية المتقدمة كالقسمة على الصفر والانحياز الإحصائي، وتطوير أطر عمل برمجية متكاملة لتقييم النماذج التنبؤية بكفاءة عالية في بيئات الإنتاج والبحث العلمي.

1. مقدمة شاملة لمقياس متوسط النسبة المئوية للخطأ المطلق (MAPE)

1.1 التعريف النظري والرياضي لمقياس MAPE

يُعرف مقياس متوسط النسبة المئوية للخطأ المطلق (MAPE) بأنه مقياس إحصائي يقيس متوسط حجم الأخطاء المرتكبة في التنبؤ دون النظر إلى اتجاهها الإيجابي أو السلبي، معبراً عنها بنسبة مئوية من القيم الفعلية المرصودة. يعود التطور التاريخي لهذا المقياس إلى النصف الثاني من القرن العشرين، حيث برزت الحاجة في بحوث العمليات وإدارة سلاسل الإمداد إلى مقياس نسبي يتفوق على المقاييس المطلقة التي كانت تصعب المقارنة بين المنتجات ذات الأسعار أو الكميات المتباينة جذرياً.

يستند الأساس النظري لـ MAPE إلى حساب الخطأ الفردي لكل مشاهدة كنسبة مئوية من القيمة الفعلية لتلك المشاهدة، ومن ثم إيجاد الوسط الحسابي البسيط لمجموع هذه النسب المطلقة. هذه المنهجية تمنحه خاصية رياضية فريدة تتمثل في التجريد التام من وحدات القياس (Scale-Independency)، مما يجعله متميزاً عن مقاييس مثل متوسط الخطأ المطلق (MAE) أو الجذر التربيعي لمتوسط مربعات الأخطاء (RMSE) اللذين يحتفظان بنفس وحدة قياس المتغير التابع.

يرجع الاعتماد الواسع على هذا المقياس في مجتمعات الإحصاء وتعلم الآلة إلى سهولة فهمه الإدراكي؛ إذ إن إخبار مدير تنفيذي بأن النموذج يرتكب خطأ بمتوسط 5% يسهل اتخاذ القرار مقارنة بإخباره بأن الخطأ يبلغ 500 وحدة، خاصة إذا كان سياق حجم العمليات الكلي غير حاضر في الذهن. ومع ذلك، فإن هذه الخاصية الرياضية ذاتها تفرض شروطاً تقنية على نوعية البيانات المستخدمة، خصوصاً فيما يتعلق بتوزيع الأخطاء وطبيعة القيم القريبة من الصفر.

1.2 تفسير القيم المئوية لمقياس MAPE ودلالاتها التحليلية

يمثل تفسير قيم MAPE خطوة نقدية في تقييم النماذج الرياضية، حيث تضع الأدبيات الإحصائية والأكاديمية – لاسيما أبحاث لويس (Lewis, 1982) – معايير قياسية لتصنيف دقة النماذج التنبؤية بناءً على النطاقات المئوية الناتجة. فعندما تكون قيمة MAPE أقل من 10%، يُصنف النموذج عموماً بأنه يتمتع بـ “دقة تنبؤية عالية جداً” (Highly Accurate Forecasting)، ويعد ملائماً لاتخاذ القرارات الحساسة والتخطيط الاستراتيجي الدقيق.

إذا وقعت القيمة بين 10% و 20%، يُعتبر النموذج “جيداً” (Good Forecast) ويصلح للتطبيقات العملية التشغيلية التي تتقبل هامشاً معقولاً من التباين. أما القيم التي تتراوح بين 20% و 50%، فتشير إلى تنبؤ “معقول أو مقبول” (Reasonable Forecast)، لكنها تستدعي الحذر والتدقيق في العوامل الخارجية المؤثرة على دقة المتغير التابع. وفي حال تجاوزت قيمة MAPE عتبة الـ 50%، يُحكم على النموذج بأنه “غير دقيق” (Inaccurate Forecast)، وتعتبر مخرجاته غير صالحة للاستخدام التطبيقي وتتطلب إعادة هيكلة جذرية للميزات أو اختيار خوارزمية نمذجة مختلفة كلياً.

من الناحية التحليلية، يترجم الباحثون هذه النسب إلى قرارات إحصائية منهجية. فالنموذج الذي يحقق MAPE منخفضاً جداً قد يكون أحياناً عرضة لمشكلة فرط التخصيص (Overfitting)، خاصة إذا تم تقييمه على بيانات التدريب فقط بدلاً من بيانات اختبار مستقلة، في حين أن الارتفاع المفاجئ في MAPE قد يعود إلى وجود مشاهدات شاذة متناهية الصغر جعلت الخطأ النسبي يقفز إلى مستويات تضليلية، وهو ما يتطلب فحص التوزيع الاحتمالي للأخطاء جنباً إلى جنب مع القيمة الإجمالية للمقياس.

1.3 أهمية MAPE مقارنة بالمقاييس الإحصائية التقليدية

تتجلى الأهمية الاستثنائية لمقياس MAPE عند إجراء مقارنات معيارية (Benchmarking) بين نماذج متعددة تعمل على مجموعات بيانات ذات نطاقات عددية متفاوتة بشكل كبير. فعلى سبيل المثال، إذا أردنا مقارنة كفاءة خوارزمية تنبؤية واحدة في التنبؤ بمبيعات متجر تجزئة صغير يحقق مبيعات يومية تقدر بمئات الدولارات، ومتجر ضخم يحقق ملايين الدولارات، فإن استخدام المقاييس المطلقة مثل RMSE سيعطي بالضرورة قيماً هائلة للمتجر الكبير مقارنة بالصغير، مما يعطي انطباعاً زائفاً بتفوق النموذج في المتجر الأول، بينما يتيح MAPE مقارنة عادلة ومحايدة تعكس النسبة المئوية للكفاءة بغض النظر عن الحجم.

إضافة إلى ذلك، يلعب MAPE دور جسر التواصل بين الفرق الفنية المتخصصة والجمهور غير التقني في المؤسسات الأكاديمية والتجارية. فالمصطلحات الرياضية مثل “التباين” و”الانحراف المعياري للمربعات” غالباً ما تكون غامضة بالنسبة للجهات المستفيدة من نتائج البحث، في حين أن التعبير عن الخطأ كنسبة مئوية يختزل التعقيد الإحصائي في رقم مفهوم عالمياً، مما يسهل بناء الثقة في النماذج الخوارزمية وتبرير الاستثمارات الموجهة لتطويرها.

علاوة على ذلك، يمتلك مقياس MAPE ميزة الاستقرار القياسي عند تغيير وحدات القياس؛ فإذا قمت بتحويل درجات الحرارة من مقياس كلفن إلى مقاييس متناسبة، أو تحويل العملة من الدولار إلى السنت، فإن قيمة MAPE تظل ثابتة ومستقرة، وهو ما لا يتحقق في المقاييس الأخرى دون إعادة تحجيم مصفوفات الأخطاء بشكل مسبق ومفصل.

2. الصيغة الرياضية الدقيقة لحساب MAPE ومكوناتها

2.1 التفكيك الجبري لمعادلة MAPE

تُصاغ المعادلة الرياضية القياسية لحساب متوسط النسبة المئوية للخطأ المطلق بالصيغة الجبرية التالية:

MAPE = (1 / n) * Σ (|y_i – ŷ_i| / |y_i|) * 100%

حيث يمثل n حجم العينة الكلي أو إجمالي عدد نقاط البيانات المرصودة في مصفوفة الاختبار. ويمثل رمز المجموع Σ إجراء عملية التجميع التراكمي لجميع الأخطاء النسبية الفردية عبر المشاهدات الممتدة من المشاهدة الأولى (i = 1) وحتى المشاهدة الأخيرة (i = n).

يمثل المتغير y_i القيمة الفعلية المرصودة (Actual Value) للنقطة الزمنية أو المشاهدة رقم i، بينما يمثل ŷ_i القيمة المتوقعة أو التنبؤية (Predicted Value) الناتجة عن النموذج لنفس النقطة. يكمن دور دالة القيمة المطلقة (Absolute Value) المحيطة بالبسط |y_i – ŷ_i| في إزالة الأثر الاتجاهي للأخطاء؛ فبدون القيمة المطلقة، يمكن للأخطاء الإيجابية الكبيرة (عندما يكون التوقع أقل من الفعلي) أن تلغي الأخطاء السلبية الكبيرة (عندما يكون التوقع أعلى من الفعلي)، مما يؤدي إلى الحصول على متوسط خطأ يقارب الصفر بشكل مضلل، رغم أن النموذج في حقيقته شديد الاضطراب والضعف.

أما معامل الضرب في 100، فهو مجرد عملية تحويل مقياسي لنقل الكسر العشري الناتج عن قسمة الخطأ المطلق على القيمة الفعلية إلى صيغة النسبة المئوية التقليدية المألوفة (مثلاً تحويل 0.05 إلى 5%)، مما يجعل قراءة النتيجة وتحليلها أكثر سلاسة في التقارير الإحصائية القياسية.

2.2 الخطوات الحسابية التراكمية للمعادلة

لتنفيذ الحساب الدقيق لصيغة MAPE، تمر الخوارزمية الرياضية بثلاث خطوات متسلسلة وصارمة منطقياً تضمن دقة المعالجة الحسابية عبر كامل مصفوفة البيانات:

  • الخطوة الأولى: حساب الخطأ المتبقي المطلق (Absolute Residual Calculation): يتم فيها طرح القيمة المتوقعة من القيمة الفعلية لكل زوج من البيانات في المصفوفة (y_i – ŷ_i)، ثم تطبيق عملية القيمة المطلقة لإلغاء أي إشارة سالبة، مما ينتج عنه مصفوفة من الفروق الإيجابية الصافية التي تمثل المسافة المكانية بين التوقع والحقيقة.
  • الخطوة الثانية: المعايرة النسبية للخطأ (Relative Error Scaling): يُقسم كل خطأ مطلق فردي تم حسابه في الخطوة السابقة على القيمة المطلقة للقيمة الفعلية المقابلة له (|y_i – ŷ_i| / |y_i|). تنتج هذه الخطوة مصفوفة من الكسور العشرية التي تمثل حجم الانحراف كجزء نسبي من حجم المشاهدة الأصلية.
  • الخطوة الثالثة: التجميع وإيجاد المتوسط والتحويل المئوي (Averaging and Percentage Conversion): تُجمع كافة الأخطاء النسبية الفردية الناتجة من الخطوة الثانية وتُقسم على إجمالي عدد المشاهدات (n) للحصول على الوسط الحسابي، وأخيراً يُضرب الناتج في 100 لإنتاج القيمة المئوية النهائية المعبرة عن المقياس ككل.

هذا التسلسل الحسابي الصارم يضمن أن كل نقطة بيانات تساهم في النتيجة النهائية بوزن نسبي متكافئ مع حجمها الخاص، مما يمنع هيمنة المشاهدات ذات القيم الضخمة على مجمل عملية التقييم الإحصائي، على عكس ما يحدث في المقاييس المعتمدة على التربيع مثل MSE.

2.3 الشروط والمحددات الرياضية لتطبيق الصيغة

على الرغم من الأناقة الرياضية لمعادلة MAPE، إلا أن تطبيقها مشروط بفرضيات صارمة في نظرية الأعداد والتحليل الإحصائي. الشرط الرياضي الأساسي والأكثر حساسية هو ضرورة ألا تحتوي مصفوفة القيم الفعلية y_i على أي قيمة تساوي الصفر المطلق. فمن الناحية الجبرية، تؤدي محاولة قسمة أي بسط على مقام يساوي صفراً إلى حالة عدم تعيين رياضي (Undefined Value)، وبرمجياً ينتج عنها استثناء القسمة على صفر (Division by Zero Exception) أو توليد قيم لا نهائية (Infinity) تفسد مجمل الحسابات التراكمية.

علاوة على ذلك، تعاني الصيغة من حساسية مفرطة وغير متماثلة تجاه القيم الفعلية القريبة جداً من الصفر (Values Close to Zero). فعندما تقترب y_i من الصفر، فإن أي خطأ بسيط في البسط، مهما كان ضئيلاً بالقيمة المطلقة، يؤدي إلى تضخيم النسبة المئوية بشكل هائل قد يتجاوز آلاف الأضعاف المئوية، مما يشوه مقياس MAPE الإجمالي للعينة ويجعله يعكس شذوذ نقطة واحدة بدلاً من التعبير عن الأداء العام للنموذج.

كما تفترض الصيغة ضمناً وجود توزيع متماثل للأخطاء النسبية؛ إلا أن التركيب الرياضي للنسب يجعل المقياس منحازاً هيكلياً ضد التنبؤات التي تزيد عن القيمة الفعلية مقارنة بالتنبؤات التي تقل عنها. فإذا كانت القيمة الفعلية 100 وتوقع النموذج 0، فإن الخطأ النسبي هو 100%، لكن إذا توقع النموذج 300، فإن الخطأ النسبي يصبح 200%، رغم أن الانحراف المطلق متطابق في الحالتين من منظور المسافة العددية، وهو ما يفرض قيوداً منهجية يجب مراعاتها عند تصميم التجارب.

3. تهيئة بيئة العمل البرمجية في لغة بايثون

3.1 تثبيت وضبط المكتبات الأساسية للحوسبة العلمية

يتطلب حساب مقياس MAPE في بيئة بايثون تهيئة حزمة من المكتبات القياسية المتخصصة في الحوسبة المتجهية والتحليل الإحصائي. في مقدمة هذه المكتبات تأتي مكتبة NumPy التي توفر هياكل مصفوفات عالية الكفاءة (N-dimensional Arrays) تسمح بتنفيذ العمليات الرياضية الجبرية على ملايين البيانات في أجزاء من الثانية بفضل بنيتها البرمجية المكتوبة بلغة C.

إلى جانب NumPy، تلعب مكتبة Pandas دوراً محورياً في التعامل مع السلاسل الزمنية والجداول الإحصائية (DataFrames)، حيث تسهل قراءة البيانات من الملفات، وتنظيف الفهارس، ومواءمة مصفوفات التوقعات مع القيم الحقيقية. لتثبيت هذه الحزم في بيئة بايثون الخاصة بك، يمكن استخدام مدير الحزم القياسي (pip) عبر تنفيذ الأمر التالي في سطر الأوامر:

pip install numpy pandas scikit-learn matplotlib seaborn statsmodels

من الأهمية بمكان التأكد من توافق إصدار بايثون (يُفضل استخدام Python 3.9 فما فوق) مع إصدارات المكتبات المثبتة لتفادي أي سلوك غير متوقع في العمليات المتجهية (Vectorized Operations) أو في إدارة الذاكرة عند معالجة المصفوفات الكبيرة. بعد اكتمال التثبيت، يتم استيراد المكتبات الأساسية داخل بيئة العمل البرمجية كالتالي:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

3.2 هيكلة البيانات وتحويلها إلى مصفوفات مناسبة

قبل تمرير البيانات إلى أي خوارزمية لحساب MAPE، يجب ضمان هيكلة المدخلات بصورة رياضية متناسقة ومطابقة للمعايير المتجهية. غالباً ما تأتي البيانات الحقيقية في صورة قوائم قياسية (Python Lists) أو أعمدة داخل كائنات DataFrames، وتتطلب معالجة أولية لتحويلها إلى مصفوفات NumPy متجانسة النمط البياني (Homogeneous Data Types)، وعادة ما يُفضل استخدام النمط العشري عالي الدقة np.float64 لتجنب أخطاء التقريب الرقمي.

تتضمن عملية الهيكلة أيضاً التحقق الصارم من تطابق الأبعاد (Dimensionality Match) بين مصفوفة القيم الفعلية ومصفوفة القيم المتوقعة؛ إذ يجب أن تكون كلتا المصفوفتين أحادية البعد وبنفس الطول الحسابي (Shape Match). إذا كانت مصفوفة التوقعات ثنائية الأبعاد، كما هو شائع عند استخدام مخرجات بعض نماذج التعلم الآلي مثل Scikit-Learn التي ترجع مصفوفات بأبعاد (n, 1)، فإنه يلزم تسطيحها (Flattening) باستخدام الدالة ravel() أو reshape(-1) لتتطابق تماماً مع أبعاد القيم الفعلية.

تشمل مرحلة التنظيف المسبق فحص ومعالجة القيم المفقودة من نمط NaN (Not a Number) أو القيم غير المعرفة الناتجة عن انقطاع البيانات الحساسة. يجب استبعاد هذه القيم أو تعويضها بطرق إحصائية معتمدة (Imputation) قبل التمرير لدوال التقييم؛ حيث إن وجود قيمة NaN واحدة كفيل بإفساد ناتج دالة التجميع الرياضي بالكامل وجعل المخرجات غير قابلة للتحليل.

4. بناء دالة برمجية مخصصة لحساب MAPE باستخدام NumPy

4.1 الترميز الأساسي للدالة بلغة بايثون

يمثل بناء دالة مخصصة باستخدام مكتبة NumPy النهج الأكثر مرونة وفهماً لطبيعة عمل مقياس MAPE. تعتمد القوة البرمجية لـ NumPy على استبدال الحلقات التكرارية البطيئة بعمليات متجهية يتم تطبيقها بشكل متزامن على كافة عناصر المصفوفة دفعة واحدة، مما يعزز الأداء الحسابي لأقصى حد ممكن.

تتم كتابة الدالة البرمجية القياسية من خلال استقبال مصفوفتين، إحداهما تمثل القيم الفعلية والأخرى تمثل التوقعات، ثم تحويلهما تلقائياً إلى مصفوفات NumPy لضمان استقرار العمليات الرياضية بغض النظر عن النمط الأصلي للمدخلات. فيما يلي البناء البرمجي النموذجي لهذه الدالة:

def calculate_mape(actual, predicted):
    """
    حساب متوسط النسبة المئوية للخطأ المطلق (MAPE) باستخدام العمليات المتجهية.
    """
    actual = np.asarray(actual, dtype=np.float64)
    predicted = np.asarray(predicted, dtype=np.float64)
    
    # التحقق من تطابق الأبعاد
    if actual.shape != predicted.shape:
        raise ValueError("أبعاد مصفوفة القيم الفعلية لا تتطابق مع أبعاد التوقعات.")
    
    # حساب الخطأ النسبي المطلق وتطبيق الوسط الحسابي
    absolute_percentage_errors = np.abs((actual - predicted) / actual)
    mape_value = np.mean(absolute_percentage_errors) * 100.0
    
    return mape_value

تعتمد الدالة على np.asarray لتحويل القوائم أو أعمدة Pandas دون تكرار حجز الذاكرة إذا كانت البيانات في الأصل مصفوفة NumPy، ثم تستخدم np.abs() لحساب المسافات المطلقة، تليها عملية القسمة المتجهية، ثم np.mean() لتوليد المتوسط الحسابي، وأخيراً الضرب في 100 لتحقيق المعايرة المئوية الصحيحة.

4.2 تحليل الأداء الحسابي والسرعة التنفيذية للدالة

إن الفرق في الأداء الحسابي بين استخدام العمليات المتجهية في NumPy والحلقات التكرارية التقليدية في بايثون (مثل for loops) يُعد هائلاً من الناحية البرمجية، خاصة عند معالجة مجموعات البيانات الضخمة (Big Data) أو عند إجراء التحقق المتقاطع (Cross-Validation) الذي يتطلب تكرار حساب المقياس آلاف المرات.

في الحلقات التكرارية القياسية، تضطر بيئة تشغيل بايثون إلى فحص النمط البياني لكل عنصر على حدة في كل دورة تكرار (Dynamic Type Checking)، مما يرفع التعقيد الزمني ويسبب إهداراً كبيراً في دورات المعالج المركزي (CPU Cycles). في المقابل، تقوم دوال NumPy بتمرير العملية المتجهية مباشرة إلى روتينات C المجمعة مسبقاً (Compiled C Routines)، مما يقلل التعقيد الزمني للعملية إلى O(n) بأقل استهلاك ممكن للذاكرة المؤقتة (Cache Memory).

توضح التجارب المعيارية (Benchmarking) أن حساب MAPE باستخدام NumPy على مصفوفة تحتوي على 10 ملايين نقطة بيانات يستغرق بضعة أجزاء من المئة من الثانية، في حين قد يستغرق تنفيذ نفس الحساب باستخدام حلقة for عدة ثوانٍ، وهو فارق جوهري عند بناء خطوط أنابيب تعلم الآلة للإنتاج الفعلي (Machine Learning Production Pipelines).

4.3 أمثلة تطبيقية برمجية خطوة بخطوة

لتوضيح كيفية عمل الدالة المخصصة ومقارنة نواتجها الحسابية يدوياً، نستعرض المثال التطبيقي التالي الذي يحتوي على مصفوفة بيانات افتراضية صغيرة تمثل مبيعات أسبوعية متوقعة مقابل المبيعات الفعلية:

actual_sales = [150.0, 200.0, 250.0, 180.0, 300.0]
predicted_sales = [140.0, 210.0, 230.0, 190.0, 315.0]

mape_result = calculate_mape(actual_sales, predicted_sales)
print(f"قيمة MAPE المحسوبة: {mape_result:.2f}%")

عند تفكيك هذه الحسبة يدوياً للتحقق من المخرجات الإحصائية:

  • المشاهدة الأولى: |150 – 140| / 150 = 10 / 150 = 0.0667 (6.67%)
  • المشاهدة الثانية: |200 – 210| / 200 = 10 / 200 = 0.0500 (5.00%)
  • المشاهدة الثالثة: |250 – 230| / 250 = 20 / 250 = 0.0800 (8.00%)
  • المشاهدة الرابعة: |180 – 190| / 180 = 10 / 180 = 0.0556 (5.56%)
  • المشاهدة الخامسة: |300 – 315| / 300 = 15 / 300 = 0.0500 (5.00%)

مجموع الأخطاء النسبية = 0.0667 + 0.0500 + 0.0800 + 0.0556 + 0.0500 = 0.3023. بالقسمة على عدد المشاهدات (5)، نحصل على: 0.06046. وبالضرب في 100 تصبح النتيجة النهائية 6.05%. وهي النتيجة المتطابقة تماماً مع مخرجات الدالة البرمجية، مما يعكس دقة تطبيق النموذج في نطاق خطأ ضئيل جداً.

5. حساب MAPE باستخدام مكتبة Scikit-Learn والمكتبات المتقدمة

5.1 استخدام الدالة المدمجة mean_absolute_percentage_error

بدءاً من الإصدار 0.24، وفرت مكتبة Scikit-Learn دالة قياسية جاهزة لحساب MAPE تحت وحدة التقييم sklearn.metrics باسم mean_absolute_percentage_error. تمتاز هذه الدالة بالتكامل السلس مع أدوات التحقق وضبط المعلمات الفائقة مثل GridSearchCV وcross_val_score.

ومع ذلك، يجب الانتباه إلى فارق جوهري وتصميمي دقيق عند استخدام دالة Scikit-Learn: الدالة المدمجة لا تضرب الناتج في 100 بصورة افتراضية، بل تُرجع الخطأ ككسر عشري عائم (Float Decimal). لذلك، إذا كانت نسبة الخطأ هي 5%، فإن الدالة سترجع القيمة 0.05. فيما يلي كيفية استدعاء واستخدام الدالة وتعديل الناتج للتمثيل المئوي القياسي:

from sklearn.metrics import mean_absolute_percentage_error

actual = [100.0, 150.0, 200.0]
predicted = [110.0, 140.0, 190.0]

# الدالة ترجع كسر عشري
raw_mape = mean_absolute_percentage_error(actual, predicted)
# تحويله إلى نسبة مئوية
percentage_mape = raw_mape * 100.0

print(f"الخطأ النسبي العشري: {raw_mape:.4f}")
print(f"النسبة المئوية الحقيقية لـ MAPE: {percentage_mape:.2f}%")

هذا الفارق التصميمي قد يسبب ارتباكاً شائعاً بين المطورين عند توثيق النتائج الإحصائية، حيث يتم أحياناً تسجيل الأرقام العشرية بالخطأ على أنها نسب مئوية جاهزة، مما يجعل النموذج يبدو أفضل بمئة ضعف من واقعه الفعلي.

5.2 تطبيق MAPE عبر مكتبات السلاسل الزمنية المتخصصة

في مجال التنبؤ بالسلاسل الزمنية والتعلم العميق، توفر المكتبات المتقدمة مثل Darts ومكتبة Statsmodels بيئات مخصصة لتقييم النماذج الإحصائية مثل ARIMA وSARIMAX وشبكات RNN/LSTM باستخدام MAPE كمعيار خسارة أو دقة متقدم.

في مكتبة Darts على سبيل المثال، يتم استيراد مقياس MAPE مباشرة لتطبيقه على كائنات السلاسل الزمنية TimeSeries، حيث تتولى المكتبة محاذاة التواريخ الزمنية بشكل آلي وتطبيق التقييم عبر نوافذ زمنية مختلفة كالتالي:

from darts.metrics import mape
# حساب MAPE بين سلسلة البيانات الفعلية وسلسلة التنبؤ
# series_actual و series_forecast يمثلان كائنات TimeSeries في Darts
error = mape(series_actual, series_forecast)
print(f"Darts MAPE: {error:.2f}%")

أما في بيئات التعلم العميق مثل PyTorch أو TensorFlow/Keras، يتم كتابة MAPE كدالة خسارة (Loss Function) مخصصة لحساب التدرجات العكسية (Backpropagation)، مع مراعاة الحسابات المتجهية على وحدات معالجة الرسومات (GPU Tensors):

import tensorflow as tf

# دالة MAPE المدمجة في Keras كمعيار خسارة
mape_keras = tf.keras.losses.MeanAbsolutePercentageError()
loss = mape_keras(actual, predicted)
print(f"TensorFlow MAPE Loss: {loss.numpy():.2f}%")

6. معالجة التحديات الرياضية والبرمجية في حساب MAPE

6.1 مشكلة القسمة على الصفر والحلول البرمجية المقترحة

تُعد مشكلة وجود قيم صفرية في مصفوفة القيم الفعلية (Zero Division) الخلل التقني الأكبر الذي يهدد استقرار مقياس MAPE. فبمجرد وجود قيمة فعلية y_i = 0، فإن عملية القسمة في بايثون ستثير استثناء ZeroDivisionError أو تولد قيمة inf عند استخدام NumPy، مما يؤدي إلى فشل الخوارزمية كلياً.

للتعامل مع هذه المعضلة برمجياً، يعتمد مهندسو البيانات على استراتيجيتين رئيسيتين:

  • استراتيجية الإزاحة برقم متناهي الصغر (Epsilon Addition): يتم فيها إضافة قيمة رقمية دقيقة جداً (تسمى إبسيلون ε، مثل 1e-8) إلى المقام لمنع وصوله إلى الصفر المطلق دون التأثير بشكل ملحوظ على دقة القيم الأخرى غير الصفرية.
  • استراتيجية التصفية والاستبعاد (Masking & Filtering): يتم فيها استبعاد نقاط البيانات التي تساوي قيمتها الفعلية صفراً من حسابات المقياس، مع توثيق نسبة البيانات المستبعدة في التقرير الإحصائي.

فيما يلي كود برمجي يطبق استراتيجية الإزاحة بأمان لحماية الحسابات من الانهيار:

def safe_mape_epsilon(actual, predicted, epsilon=1e-8):
    actual = np.asarray(actual, dtype=np.float64)
    predicted = np.asarray(predicted, dtype=np.float64)
    # إضافة إبسيلون إلى القيم الصفرية فقط أو المقام ككل
    denominator = np.where(actual == 0, epsilon, actual)
    return np.mean(np.abs((actual - predicted) / denominator)) * 100.0

6.2 التعامل مع القيم الشاذة والمتطرفة (Outliers)

تتسبب القيم الفعلية القريبة جداً من الصفر (مثلاً y_i = 0.001) في تشويه جسيم لمقياس MAPE؛ فإذا كان التوقع مساوياً 0.05، فإن الفرق المطلق ضئيل للغاية (0.049)، ولكن الخطأ النسبي سيتجاوز 4900%. وجود نقطة واحدة من هذا النوع كفيل برفع MAPE الإجمالي للنموذج من 5% إلى 500%، مما يقود إلى استنتاجات مضللة حول كفاءة النموذج الحقيقية.

لمعالجة هذا التضخيم غير المنطقي، يُنصح بتطبيق تقنية تقليم الخطأ (Error Clipping)، والتي تفرض حداً أقصى للخطأ النسبي لكل نقطة مفردة (مثلاً قصر الحد الأقصى للخطأ على 100% أو 200%) قبل حساب المتوسط العام، مما يحمي المقياس من تأثير القيم المتطرفة الشاذة:

def clipped_mape(actual, predicted, max_threshold=1.0):
    actual = np.asarray(actual, dtype=np.float64)
    predicted = np.asarray(predicted, dtype=np.float64)
    raw_errors = np.abs((actual - predicted) / actual)
    # تقليم الأخطاء بحيث لا تتجاوز العتبة القصوى
    clipped_errors = np.clip(raw_errors, 0, max_threshold)
    return np.mean(clipped_errors) * 100.0

إذا كانت طبيعة البيانات تحتوي على نسبة عالية من القيم المتناهية الصغر، يصبح الانتقال إلى مقاييس إحصائية بديلة مثل WAPE أو MASE واجباً منهجياً لضمان سلامة التقييم الأكاديمي.

6.3 معالجة مشكلة عدم التماثل والانحياز الرياضي (Asymmetry Issue)

يتميز مقياس MAPE بانحياز هيكلي أصيل يفضل النماذج التي تميل إلى التقليل من التقدير (Under-forecasting) على النماذج التي تفرط في التقدير (Over-forecasting). هذا الانحياز ينبع من البنية الرياضية للمقام؛ فإذا كانت القيمة الفعلية 100، وكان التوقع 50 (نقص في التقدير بمقدار 50 وحدة)، فإن الخطأ النسبي هو:

|100 - 50| / 100 = 50%

أما إذا كان التوقع 150 (زيادة في التقدير بنفس المقدار المطلق 50 وحدة)، فإن الخطأ النسبي يظل 50%. لكن إذا قفز التوقع إلى 250 (زيادة بمقدار 150 وحدة)، فإن الخطأ النسبي يصبح 150%، بينما إذا هبط التوقع إلى الصفر (نقص بأقصى حد ممكن وهو 100 وحدة)، فإن الخطأ النسبي لا يمكن أن يتجاوز أبداً 100%. وبالتالي، فإن العقوبة الرياضية على الإفراط في التنبؤ لا سقف لها، بينما تقتصر عقوبة التقليل في التنبؤ على حد أقصى هو 100%.

هذا الانحياز يجعل خوارزميات التحسين التي تستخدم MAPE كدالة خسارة تميل تلقائياً إلى إنتاج تنبؤات منخفضة بشكل منهجي لتجنب العقوبات اللانهائية، وهو ما يجب أن ينتبه له مطورو النماذج التنبؤية عند تفسير سلوك خوارزمياتهم وتحسينها.

7. مقارنة معيارية بين MAPE ومقاييس تقييم النماذج الأخرى

7.1 المقارنة مع MAE و MSE و RMSE

لتحديد متى يجب استخدام MAPE مقارنة بالمقاييس الإحصائية التقليدية الأخرى، يستعرض الجدول والتحليل المنهجي التالي الفروق الجوهرية بين أشهر مقاييس تقييم النماذج التنبؤية في بيئات تعلم الآلة:

  • متوسط الخطأ المطلق (MAE): يقيس متوسط الفروق المطلقة بنفس وحدة قياس البيانات الأصلية. يُعد مقياساً خطياً قوياً ومقاوماً للقيم الشاذة، ولكنه غير مستقل عن المقياس، مما يجعل مقارنة أداء النماذج عبر سياقات وبيانات مختلفة أمراً غير ممكن.
  • متوسط مربعات الأخطاء (MSE): يقوم بتربيع الفروق، مما يمنحه حساسية قصوى للأخطاء الكبيرة. يُستخدم على نطاق واسع في تدريب النماذج كدالة خسارة قابلة للاشتقاق، ولكنه يتأثر بشكل فادح بالقيم المتطرفة وتكون وحدته مربعة يصعب تفسيرها.
  • جذر متوسط مربعات الأخطاء (RMSE): يعيد تربيع MSE إلى الوحدة الأصلية للبيانات. يظل حساساً للأخطاء الجسيمة ويعاقب الانحرافات الكبيرة بقوة، لكنه يشترك مع MAE في ارتباطه الوثيق بمقياس البيانات المحدد.
  • متوسط النسبة المئوية للخطأ المطلق (MAPE): يتميز باستقلاله التام عن المقياس وسهولة تفسيره كنسبة مئوية، ولكنه يعاني من مشكلة الأصفار والانحياز نحو التنبؤات المنخفضة.

من الناحية العملية، يُفضل استخدام MAE وRMSE عندما تكون وحدات القياس ثابتة والبيانات خالية من المقارنات المتعددة، بينما يُلجأ إلى MAPE لتقييم النماذج الشاملة عبر محافظ المنتجات الواسعة أو التقارير التنفيذية متعددة المستويات.

7.2 المقارنة مع مقياس SMAPE البديل وتطبيقه في بايثون

استجابة للانحياز الرياضي ومشكلات الأصفار في مقياس MAPE التقليدي، تم تطوير مقياس النسبة المئوية المتماثل للخطأ المطلق (Symmetric Mean Absolute Percentage Error – SMAPE). يحل هذا المقياس مشكلة عدم التماثل من خلال قسمة الخطأ المطلق على متوسط مجموع القيمة الفعلية والقيمة المتوقعة معاً في المقام.

تُصاغ معادلة SMAPE رياضياً كالتالي:

SMAPE = (100% / n) * Σ [ |y_i – ŷ_i| / ((|y_i| + |ŷ_i|) / 2) ]

تتراوح قيمة هذا المقياس دائماً بين 0% و 200%، مما يضع سقفاً محدداً للأخطاء ويجعله يعامل التنبؤات الزائدة والناقصة بعدالة متكافئة. وفيما يلي كود بناء دالة SMAPE في بايثون:

def calculate_smape(actual, predicted):
    actual = np.asarray(actual, dtype=np.float64)
    predicted = np.asarray(predicted, dtype=np.float64)
    denominator = (np.abs(actual) + np.abs(predicted)) / 2.0
    # تفادي القسمة على صفر إذا كانت القيمة الفعلية والمتوقعة كلاهما صفر
    zeros_mask = (actual == 0) & (predicted == 0)
    smape_elements = np.where(zeros_mask, 0.0, np.abs(actual - predicted) / denominator)
    return np.mean(smape_elements) * 100.0

وعلى الرغم من مزايا SMAPE، إلا أنه يتعرض لانتقادات بسبب عدم وضوح تفسيره البديهي مقارنة بـ MAPE، إضافة إلى حساسيته عندما يقترب كل من الفعلي والمتوقع معاً من الصفر.

7.3 المقارنة مع مقياس WAPE والمقاييس الوزنية

يُعد مقياس النسبة المئوية المرجح للخطأ المطلق (Weighted Absolute Percentage Error – WAPE)، والذي يُعرف أحياناً باسم مقياس MAD/Mean Ratio، البديل الأكثر اعتماداً وموثوقية في سلاسل الإمداد وتجارة التجزئة عند التعامل مع بيانات تحتوي على أصفار متكررة وقيم متقطعة.

بدلاً من حساب متوسط النسب الفردية، يقوم WAPE بقسمة مجموع كافة الأخطاء المطلقة على مجموع كافة القيم الفعلية، مما يمنحه الصيغة الرياضية التالية:

WAPE = ( Σ |y_i – ŷ_i| ) / ( Σ |y_i| ) * 100%

هذا التركيب الرياضي يزيل مشكلة القسمة على صفر الفردية نهائياً (طالما أن إجمالي مبيعات الفترة ككل أكبر من صفر)، كما يمنح المشاهدات الكبيرة ذات التأثير الحقيقي وزناً أكبر في تقييم دقة النموذج. فيما يلي تطبيق دالة WAPE في بايثون:

def calculate_wape(actual, predicted):
    actual = np.asarray(actual, dtype=np.float64)
    predicted = np.asarray(predicted, dtype=np.float64)
    total_actual = np.sum(actual)
    if total_actual == 0:
        raise ValueError("إجمالي مجموع القيم الفعلية يساوي صفراً، لا يمكن حساب WAPE.")
    return (np.sum(np.abs(actual - predicted)) / total_actual) * 100.0

8. التطبيق العملي: حساب MAPE في نماذج السلاسل الزمنية والتنبؤ

8.1 بناء سيناريو تنبؤي متكامل في بايثون

لفهم كيفية توظيف مقياس MAPE في سيناريو واقعي لتحليل السلاسل الزمنية، سنقوم ببناء خط أنابيب تنبؤي متكامل يولد سلسلة زمنية ذات اتجاه وموسمية، ثم نطبق نموذج الانحدار الذاتي والمتوسطات المتحركة التكاملي (ARIMA) ونقيم دقته باستخدام مكتبات بايثون القياسية.

فيما يلي الكود البرمجي الكامل لإعداد البيانات، تدريب النموذج، واستخراج التنبؤات:

import numpy as np
import pandas as pd
from statsmodels.tsa.arima.model import ARIMA
from sklearn.metrics import mean_absolute_percentage_error

# توليد سلسلة زمنية تجريبية تحتوي على 100 نقطة بيانات
np.random.seed(42)
time_index = pd.date_range(start='2023-01-01', periods=100, freq='D')
trend = np.linspace(50, 150, 100)
seasonality = 15 * np.sin(np.linspace(0, 8 * np.pi, 100))
noise = np.random.normal(0, 3, 100)
data_values = trend + seasonality + noise

ts_data = pd.Series(data_values, index=time_index)

# تقسيم البيانات إلى تدريب (80%) واختبار (20%)
train_size = int(len(ts_data) * 0.8)
train_data = ts_data.iloc[:train_size]
test_data = ts_data.iloc[train_size:]

# بناء وتدريب نموذج ARIMA(2, 1, 2)
model = ARIMA(train_data, order=(2, 1, 2))
fitted_model = model.fit()

# توليد التوقعات لفترة الاختبار
predictions = fitted_model.forecast(steps=len(test_data))

# حساب MAPE لفترة الاختبار
mape_score = mean_absolute_percentage_error(test_data, predictions) * 100.0
print(f"قيمة MAPE للنموذج التنبؤي ARIMA: {mape_score:.2f}%")

يوضح هذا التطبيق كيفية تحويل النظرية إلى ممارسة برمجية متكاملة، حيث يتم تقسيم السلسلة زمنياً دون خلط البيانات لضمان واقعية التقييم، ومن ثم حساب الخطأ النسبي لمصفوفة الاختبار بدقة عالية.

8.2 تقييم أداء النموذج عبر نوافذ زمنية متعددة (Rolling Forecast)

في البيئات الإنتاجية الديناميكية، لا يكفي حساب قيمة MAPE ثابتة لنقطة زمنية واحدة؛ إذ قد تتدهور كفاءة النماذج التنبؤية بمرور الوقت بسبب التغير الهيكلي في سلوك البيانات (Concept Drift). هنا تبرز أهمية استخدام أسلوب التنبؤ المتدحرج عبر النوافذ الزمنية المتتالية (Rolling or Expanding Forecast Origin).

يتيح تتبع مقياس MAPE المتحرك عبر النوافذ مراقبة استقرار النموذج الزمني واكتشاف اللحظات التي يبدأ فيها أداء النموذج بالتراجع، مما يوفر إنذاراً مبكراً لإعادة تدريب الخوارزمية. يوضح الكود التالي كيفية تنفيذ ذلك برمجياً:

rolling_mapes = []
window_size = 5

for i in range(len(test_data) - window_size + 1):
    actual_window = test_data.iloc[i : i + window_size]
    pred_window = predictions.iloc[i : i + window_size]
    window_mape = mean_absolute_percentage_error(actual_window, pred_window) * 100.0
    rolling_mapes.append(window_mape)

rolling_mape_series = pd.Series(rolling_mapes, index=test_data.index[window_size - 1:])
print("متوسط MAPE عبر النوافذ المتحركة:", np.mean(rolling_mapes))

يمكن تمثيل هذه السلسلة بيانياً باستخدام مكتبة matplotlib لرسم منحنى الخطأ عبر الزمن، مما يسهل على الفرق الهندسية تحديد الفترات التي شهدت صدمات خارجية أو تغيرات موسمية حادة غير مشمولة في ميزات التدريب.

8.3 تحليل الأخطاء المتبقية (Residuals Analysis) بالتزامن مع MAPE

على الرغم من أن مقياس MAPE يعطي رقماً إجمالياً ملخصاً لدقة التنبؤ، إلا أنه لا يكشف عن الطبيعة الإحصائية للأخطاء المرتكبة. لذلك، يجب دائماً مرافقة حساب MAPE بتحليل تشخيصي للأخطاء المتبقية (Residuals = Actual – Predicted).

يتضمن تحليل البواقي التحقق من فرضيتين إحصائيتين أساسيتين:

  • استقلال البواقي وانعدام الارتباط الذاتي (Autocorrelation-Free): يجب ألا تظهر البواقي أي نمط زمني دوري متبقٍ، وهو ما يتم اختباره عبر دالة الارتباط الذاتي (ACF) أو اختبار Ljung-Box. فإذا كان MAPE مرتفعاً مع وجود ارتباط ذاتي، فهذا يعني أن النموذج قد فشل في استخلاص نمط موسمي واضح من البيانات.
  • التوزيع الطبيعي للبواقي (Normality of Residuals): فحص ما إذا كانت الأخطاء تتوزع بشكل متماثل حول الصفر باستخدام المخططات الاحتمالية (Q-Q Plots) واختبار Shapiro-Wilk، لضمان عدم وجود تحيز اتجاهي منهجي في التوقعات.

إن الربط بين انخفاض قيمة MAPE وغياب الأنماط في البواقي يمثل الدليل الأكاديمي القاطع على أن النموذج التنبؤي قد استنفد كامل المعلومات المتاحة في السلسلة الزمنية ووصل إلى الكفاءة المثلى.

9. تطبيق MAPE في النمذجة الإحصائية والقياسات التجريبية

9.1 استخدام MAPE في تقييم نماذج القياس السلوكي والكمي

يمتد تطبيق مقياس MAPE إلى مجالات القياس النفسي (Psychometrics)، وتحليل السلوك الاقتصادي، والنماذج الكمية في العلوم الاجتماعية، حيث تبرز الحاجة إلى قياس مدى دقة النماذج الرياضية في محاكاة الاستجابات البشرية وتقدير المتغيرات الكامنة (Latent Variables).

في التجارب السلوكية، تتفاوت مقاييس الاستجابة (مثل أزمنة الاستجابة بالمللي ثانية، أو درجات الاستبيانات المركبة) من مشارك لآخر بناءً على الفروق الفردية. يوفر حساب MAPE للباحثين مؤشراً نسبياً موحداً يتيح مقارنة قدرة الخوارزمية على محاكاة سلوك مجموعات سكانية متباينة بدقة، دون أن تتأثر النتيجة باختلاف المتوسطات العامة لكل فئة تجريبية.

كما يُستخدم المقياس لتقييم استقرار الأدوات القياسية عبر الزمن (Test-Retest Reliability Analysis)، حيث يُحسب الخطأ النسبي المطلق بين درجات التطبيق الأول والتطبيق الثاني للمقاييس المقننة، مما يعطي تقديراً كمياً مباشراً لمدى اتساق الأداة وخلوها من الأخطاء العشوائية في القياس.

9.2 تقييم نماذج الانحدار في البيانات التجريبية

عند بناء نماذج الانحدار الخطي المتعدد (Multiple Linear Regression) أو الانحدار غير الخطي على بيانات تجريبية معملية، يُعد MAPE مؤشراً رئيسياً يتم تضمينه في الجداول الإحصائية للأوراق العلمية المحكمة إلى جانب معامل التحديد (R-squared) ومقاييس الخطأ المعياري.

تكمن فائدة دمج MAPE في التقارير الإحصائية في تقديم فهم بديهي لجودة الملاءمة (Goodness of Fit) يصعب استخراجه من معامل R² بمفرده؛ إذ يمكن لنموذج انحدار أن يحقق معامل R² مرتفعاً جداً (مثل 0.95) نتيجة لنطاق البيانات الواسع، في حين أن متوسط الخطأ النسبي للنقاط الفردية قد يكون مرتفعاً وغير مقبول عملياً في السياقات الدقيقة، وهو ما يظهره مقياس MAPE بوضوح وتجرد.

في الأبحاث الطبية والحيوية، يُطبق مقياس MAPE لتقييم نماذج الحرائك الدوائية (Pharmacokinetics)، حيث يتم قياس النسبة المئوية لانحراف تركيز الدواء المتوقع في الدم مقارنة بالقياسات المعملية الحقيقية عبر فترات زمنية متباعدة، مما يسهم في ضبط الجرعات العلاجية بأمان وموثوقية.

10. استراتيجيات برمجية لتقليل قيمة MAPE وتحسين أداء النماذج

10.1 التحويلات الرياضية للمتغير التابع في بايثون

تُعد التحويلات الرياضية للمتغير التابع إحدى أكثر الطرق فاعلية لتحسين أداء النماذج وتقليل قيمة MAPE الناتجة، خاصة عندما تظهر البيانات تبايناً غير متجانس (Heteroscedasticity) أو توزيعاً ملتوياً نحو اليمين (Right-Skewed Distribution).

أبرز هذه التحويلات هو التحويل اللوغاريتمي np.log1p() (الذي يضيف 1 لتفادي لوغاريتم الصفر) أو تحويلات Box-Cox المتاحة في مكتبة SciPy. يؤدي التحويل اللوغاريتمي إلى تقليص الفروق النسبية وتثبيت التباين عبر مختلف نطاقات البيانات، مما يجعل خوارزمية التحسين تركز على تقليل الخطأ النسبي بشكل طبيعي.

فيما يلي كود يوضح تدريب نموذج انحدار باستخدام التحويل اللوغاريتمي وعكسه عند التقييم لحساب MAPE بدقة:

from sklearn.linear_model import Ridge
from sklearn.metrics import mean_absolute_percentage_error

# تطبيق التحويل اللوغاريتمي على بيانات التدريب
y_train_log = np.log1p(train_data)

# بناء وتدريب النموذج على البيانات المحولة
regressor = Ridge()
regressor.fit(X_train, y_train_log)

# توليد التوقعات واستعادتها إلى المقياس الأصلي عبر الدالة الأسية
log_predictions = regressor.predict(X_test)
final_predictions = np.expm1(log_predictions)

# حساب MAPE على المقياس الأصلي الحقيقي
optimized_mape = mean_absolute_percentage_error(test_data, final_predictions) * 100.0
print(f"قيمة MAPE بعد التحويل اللوغاريتمي: {optimized_mape:.2f}%")

10.2 استخدام دوال الخسارة المخصصة (Custom Loss Functions)

تقوم معظم خوارزميات تعلم الآلة القياسية، مثل الانحدار الخطي وشبكات الغابات العشوائية، بتحسين دوال خسارة مبنية على متوسط مربعات الأخطاء (MSE). وبالتالي، فإن النموذج يتم تدريبه رياضياً لتقليل الانحرافات المطلقة التربيعية وليس لتقليل النسبة المئوية، مما ينتج عنه قيم MAPE دون المستوى الأمثل.

لتحقيق أدنى قيمة ممكنة لـ MAPE، يجب إعادة صياغة دالة الهدف (Objective Function) في نماذج تعزيز التدرج المتقدمة مثل XGBoost أو LightGBM لتقوم بتحسين مقياس MAPE أو تقريب قابل للاشتقاق منه مباشرة أثناء عملية التدريب التكراري.

في مكتبة LightGBM، تتوفر دالة خسارة مدمجة باسم mape يمكن تمريرها مباشرة كمعامل تدريب:

import lightgbm as lgb

# إعداد معلمات التدريب لتحسين MAPE مباشرة
params = {
    'objective': 'mape',
    'metric': 'mape',
    'learning_rate': 0.05,
    'verbose': -1
}

train_dataset = lgb.Dataset(X_train, label=y_train)
lgb_model = lgb.train(params, train_dataset, num_boost_round=100)
lgb_preds = lgb_model.predict(X_test)
print("MAPE المحسن عبر LightGBM:", mean_absolute_percentage_error(y_test, lgb_preds) * 100.0)

10.3 هندسة الميزات وضبط المعلمات الفائقة (Hyperparameter Tuning)

تلعب هندسة الميزات الموجهة نحو النسب دوراً حاسماً في تقليص أخطاء MAPE. يتضمن ذلك إنشاء ميزات التأخير الزمني (Lagged Features)، وميزات النسب المئوية للتغير عبر الفترات السابقة (Percentage Growth Rates)، بالإضافة إلى المتوسطات المتحركة النسبية (Rolling Ratios).

علاوة على ذلك، يجب ضبط المعلمات الفائقة للخوارزميات بالاعتماد المباشر على معيار MAPE كدالة تقييم داخل أطر البحث مثل GridSearchCV أو التحسين البايزي (Bayesian Optimization) عبر مكتبة Optuna. يتم ذلك في Scikit-Learn باستخدام دالة make_scorer مع ضبط معامل العكس (greater_is_better=False):

from sklearn.model_selection import GridSearchCV
from sklearn.metrics import make_scorer, mean_absolute_percentage_error
from sklearn.ensemble import RandomForestRegressor

# إنشاء مقيم مخصص لـ MAPE لـ Scikit-Learn
mape_scorer = make_scorer(mean_absolute_percentage_error, greater_is_better=False)

param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [5, 10, None]
}

grid_search = GridSearchCV(
    estimator=RandomForestRegressor(random_state=42),
    param_grid=param_grid,
    scoring=mape_scorer,
    cv=5
)
grid_search.fit(X_train, y_train)
print("أفضل المعلمات المحققة لأدنى MAPE:", grid_search.best_params_)

11. استكشاف الأخطاء البرمجية الشائعة وإصلاحها عند حساب MAPE

11.1 أخطاء مطابقة الأبعاد وتوافق هياكل البيانات

أحد أكثر الأخطاء البرمجية شيوعاً وإرباكاً عند حساب مقاييس الأخطاء في بايثون هو مشكلة عدم تطابق الأبعاد (Shape Mismatch) وسلوك البث في NumPy (Broadcasting). فعند طرح مصفوفة ذات أبعاد (n, 1) من مصفوفة ذات أبعاد (n,)، لا تقوم بايثون بإصدار خطأ برمجي مباشر، بل تطبق عملية البث لتنتج مصفوفة ثنائية الأبعاد بحجم (n, n)، مما يؤدي إلى نتائج كارثية واستهلاك هائل للذاكرة.

لتفادي هذا الخطأ الصامت، يجب دائماً تسطيح وتوحيد أبعاد المداخل قبل تمريرها للحساب كالتالي:

def check_and_reshape(y_true, y_pred):
    y_true = np.asarray(y_true)
    y_pred = np.asarray(y_pred)
    
    # إعادة تشكيل المصفوفات لتكون أحادية البعد بشكل صارم
    if y_true.ndim != 1:
        y_true = y_true.reshape(-1)
    if y_pred.ndim != 1:
        y_pred = y_pred.reshape(-1)
        
    if len(y_true) != len(y_pred):
        raise ValueError(f"اختلاف عدد العناصر: الفعلي ({len(y_true)}) مقابل المتوقع ({len(y_pred)})")
    
    return y_true, y_pred

كما يجب الانتباه إلى عدم تطابق فهارس السلاسل الزمنية في كائنات Pandas؛ فإذا كانت الفهارس غير مرتبة بنفس التسلسل الزمني الدقيق، فإن عملية الطرح المباشر بين سلسلتين ستنتج مصفوفة مليئة بقيم NaN بسبب محاولة Pandas مطابقة الفهارس الاسمية بدلاً من المواقع الترتيبية.

11.2 التعامل مع أنواع البيانات غير الرقمية والمفقودة

عند استيراد مجموعات البيانات الكبيرة من ملفات CSV أو قواعد البيانات، قد تحتوي بعض الأعمدة الرقمية على نصوص غير مقصودة (مثل مسافات فارغة، أو رموز خاصة مثل "?" أو "NULL"). تمرير هذه الأعمدة إلى دوال NumPy يثير أخطاء نمطية TypeError: ufunc 'subtract' not supported for the input types.

تتم المعالجة الاحترافية لهذه المشكلة عبر تحويل الأنواع قسرياً باستخدام دالة pd.to_numeric مع تفعيل معامل errors='coerce' الذي يحول أي قيمة غير صالحة إلى NaN، ثم استخدام np.nanmean لحساب MAPE مع استبعاد القيم التالفة بأمان دون توقف النظام الإنتاجي:

def robust_nan_mape(actual_series, predicted_series):
    # تحويل آمن للأنماط الرقمية
    y_true = pd.to_numeric(actual_series, errors='coerce').to_numpy()
    y_pred = pd.to_numeric(predicted_series, errors='coerce').to_numpy()
    
    relative_errors = np.abs((y_true - y_pred) / y_true)
    # حساب المتوسط مع استبعاد NaN وقيم inf
    valid_mask = np.isfinite(relative_errors)
    if not np.any(valid_mask):
        return np.nan
    return np.mean(relative_errors[valid_mask]) * 100.0

11.3 أخطاء التفسير المنطقي والحسابي الشائعة

تشمل أخطاء التفسير الشائعة في الأوساط التحليلية تطبيق دالة MAPE على متغيرات تحتوي على قيم سالبة بطبيعتها (مثل درجات الحرارة بمقياس مئوي، أو معدلات الأرباح والخسائر المالية). من الناحية الرياضية، فإن إشارة القيمة السالبة في المقام تجعل تفسير النسبة المئوية فاقداً للمعنى الدلالي؛ إذ يمكن لقيمتين سالبة وموجبة أن تنتجا نفس النسبة المطلقة بسلوكيات فيزيائية متناقضة تماماً.

ولضمان جودة البرمجيات الإحصائية، يجب كتابة اختبارات الوحدة (Unit Testing) باستخدام إطار عمل pytest للتأكد المستمر من سلامة سلوك دوال التقييم ضد الحالات الحافة (Edge Cases):

import pytest
import numpy as np

def test_mape_perfect_prediction():
    y = [10.0, 20.0, 30.0]
    assert calculate_mape(y, y) == pytest.approx(0.0)

def test_mape_known_value():
    y_true = [100.0, 200.0]
    y_pred = [110.0, 180.0]
    # 10% + 10% / 2 = 10%
    assert calculate_mape(y_true, y_pred) == pytest.approx(10.0)

def test_mape_dimension_mismatch():
    with pytest.raises(ValueError):
        calculate_mape([1, 2], [1, 2, 3])

12. أفضل الممارسات المتقدمة وبناء حزم برمجية متكاملة لـ MAPE

12.1 تصميم دالة MAPE قوية وقابلة لإعادة الاستخدام في بيئات الإنتاج

يتطلب نقل الشيفرة البرمجية من النطاق التجريبي إلى بيئات الإنتاج الفعلية بناء دالة هندسية محكمة تدعم مختلف الإعدادات، وتتضمن آليات مرنة لمعالجة الأصفار، وتدعم توثيق النوع الصارم (Type Hinting) بما يتوافق مع معايير هندسة البرمجيات الحديثة (PEP 8).

يوضح النموذج التالي صياغة برمجية كاملة تجمع كافة الممارسات الدفاعية المتقدمة:

from typing import Union, List, Optional
import numpy as np
import pandas as pd

def production_mape(
    y_true: Union[List[float], np.ndarray, pd.Series],
    y_pred: Union[List[float], np.ndarray, pd.Series],
    handle_zeros: str = 'eps',
    epsilon: float = 1e-8,
    clip_threshold: Optional[float] = None
) -> float:
    """
    حساب MAPE متقدم للبيئات الإنتاجية مع خيارات لمعالجة القيم الصفرية والشاذة.
    
    :param y_true: القيم الفعلية الحقيقية.
    :param y_pred: القيم التنبؤية.
    :param handle_zeros: خيار معالجة الأصفار ('eps', 'drop', 'raise').
    :param epsilon: القيمة المضافة لتفادي القسمة على صفر عند اختيار 'eps'.
    :param clip_threshold: حد تقليم الخطأ النسبي لمنع التضخيم الشاذ.
    :return: قيمة MAPE كنسبة مئوية دقيقة.
    """
    actual = np.asarray(y_true, dtype=np.float64).ravel()
    predicted = np.asarray(y_pred, dtype=np.float64).ravel()
    
    if actual.shape != predicted.shape:
        raise ValueError("أبعاد المصفوفات المدخلة غير متطابقة.")
    if len(actual) == 0:
        return 0.0
        
    if handle_zeros == 'raise' and np.any(actual == 0):
        raise ZeroDivisionError("تحتوي مصفوفة القيم الفعلية على أصفار.")
    elif handle_zeros == 'drop':
        mask = actual != 0
        if not np.any(mask):
            return np.nan
        actual = actual[mask]
        predicted = predicted[mask]
        denominator = actual
    else: # خيار إبسيلون الافتراضي
        denominator = np.where(actual == 0, epsilon, actual)
        
    ape = np.abs((actual - predicted) / denominator)
    
    if clip_threshold is not None:
        ape = np.clip(ape, 0, clip_threshold)
        
    return float(np.mean(ape) * 100.0)

12.2 بناء تقارير تقييم شاملة تتضمن MAPE مع مقاييس مكملة

في الممارسات الإحصائية الرصينة، يُحظر الاعتماد على مقياس تقييم أحادي الجانب للحكم على جودة النماذج التنبؤية. بدلاً من ذلك، يتم بناء فئات برمجية (Evaluation Classes) متكاملة تقوم بحساب حزمة من المقاييس المترابطة وتوليد تقارير إحصائية ولوحات معلومات بصرية متكاملة.

يقوم الكائن البرمجي التالي بحساب MAPE إلى جانب MAE وRMSE وWAPE ومعامل التحديد R²، وتصدير النتائج مباشرة كجدول بيانات DataFrame منسق:

class ModelEvaluator:
    def __init__(self, y_true, y_pred):
        self.y_true = np.asarray(y_true, dtype=np.float64).ravel()
        self.y_pred = np.asarray(y_pred, dtype=np.float64).ravel()
        
    def generate_report(self) -> pd.DataFrame:
        mae = np.mean(np.abs(self.y_true - self.y_pred))
        rmse = np.sqrt(np.mean((self.y_true - self.y_pred)**2))
        wape = (np.sum(np.abs(self.y_true - self.y_pred)) / np.sum(self.y_true)) * 100.0
        
        # حساب MAPE الآمن باستبعاد الأصفار
        mask = self.y_true != 0
        mape = np.mean(np.abs((self.y_true[mask] - self.y_pred[mask]) / self.y_true[mask])) * 100.0 if np.any(mask) else np.nan
        
        ss_res = np.sum((self.y_true - self.y_pred)**2)
        ss_tot = np.sum((self.y_true - np.mean(self.y_true))**2)
        r2 = 1.0 - (ss_res / ss_tot) if ss_tot != 0 else np.nan
        
        metrics = {
            "Metric": ["MAPE (%)", "WAPE (%)", "MAE", "RMSE", "R-Squared"],
            "Value": [round(mape, 2), round(wape, 2), round(mae, 4), round(rmse, 4), round(r2, 4)]
        }
        return pd.DataFrame(metrics)

12.3 الخلاصة والتوصيات المنهجية للباحثين والمطورين

في الختام، يظل مقياس متوسط النسبة المئوية للخطأ المطلق (MAPE) أحد أكثر الأدوات التحليلية إشراقاً وأهمية في ترسانة مهندس البيانات والباحث الإحصائي بفضل قدرته الفائقة على تبسيط تقييم النماذج التنبؤية وتجريدها من قيود الوحدات الفيزيائية والمالية. ومع ذلك، فإن نجاح تطبيقه العملي في لغة بايثون يرتبط بالالتزام الصارم بالتوصيات المنهجية التالية:

  • التحقق المسبق من طبيعة البيانات: تجنب استخدام MAPE تماماً إذا كانت البيانات تحتوي على قيم سالبة، أو إذا كانت نسبة القيم الصفرية والقريبة من الصفر مرتفعة، واستبداله في هذه الحالات بمقياسي WAPE أو SMAPE.
  • الانتباه لتحويل النسبة المئوية: تذكر دائماً أن الدوال القياسية مثل تلك الموجودة في Scikit-Learn تُرجع النتيجة ككسر عشري وتتطلب الضرب الصريح في 100 للحصول على القيمة المئوية الحقيقية.
  • استخدام التحسين الموجه: عند الرغبة في خفض قيمة MAPE، يجب مواءمة تدريب الخوارزميات عبر دوال خسارة مخصصة تعتمد على الخطأ النسبي بدلاً من الاعتماد على دوال المربعات التقليدية (MSE).
  • التقييم الشامل والمتعدد: عدم الاكتفاء بـ MAPE منفرداً في التقارير العلمية، وتدعيمه دائماً بمقاييس المسافة المطلقة (MAE, RMSE) وتحليلات البواقي الدقيقة لضمان سلامة النماذج التنبؤية وقوتها التعميمية.

المراجع الأكاديمية والمصادر (References)

  • Armstrong, J. S., & Collopy, F. (1992). Error measures for generalizing about forecasting methods: Empirical comparisons. International Journal of Forecasting, 8(1), 69–80. https://doi.org/10.1016/0169-2070(92)90008-W
  • Harris, C. R., Millman, K. J., van der Walt, S. J., Gommers, R., Virtanen, P., Cournapeau, D., … & Oliphant, T. E. (2020). Array programming with NumPy. Nature, 585(7825), 357–362. https://doi.org/10.1038/s41586-020-2649-2
  • Hyndman, R. J., & Athanasopoulos, G. (2021). Forecasting: principles and practice (3rd ed.). OTexts: Melbourne, Australia. https://otexts.com/fpp3/
  • Hyndman, R. J., & Koehler, A. B. (2006). Another look at measures of forecast accuracy. International Journal of Forecasting, 22(4), 679–688. https://doi.org/10.1016/j.ijforecast.2006.03.001
  • Lewis, C. D. (1982). Industrial and business forecasting methods: A radical guide to exponential smoothing and curve fitting. Butterworth-Heinemann.
  • Makridakis, S. (1993). Accuracy measures: Theoretical and practical concerns. International Journal of Forecasting, 9(4), 527–529. https://doi.org/10.1016/0169-2070(93)90079-3
  • Pedregosa, F., Varoquaux, G., Gramfort, A., Michel, V., Thirion, B., Grisel, O., … & Duchesnay, É. (2011). Scikit-learn: Machine learning in Python. Journal of Machine Learning Research, 12, 2825–2830. https://scikit-learn.org/
  • Seabold, S., & Perktold, J. (2010). Statsmodels: Econometric and statistical modeling with python. In Proceedings of the 9th Python in Science Conference (Vol. 57, pp. 61–65). https://www.statsmodels.org/

اقتباس هذا المقال

looti, M. (2026, أغسطس 26). كيفية حساب MAPE في بايثون. عرب سايكلوجي. https://arabpsychology.com/statistics/how-to-calculate-mape-in-python/
looti, Mohammed. “كيفية حساب MAPE في بايثون.” عرب سايكلوجي, 26 أغسطس 2026, https://arabpsychology.com/statistics/how-to-calculate-mape-in-python/.
looti, Mohammed. “كيفية حساب MAPE في بايثون.” عرب سايكلوجي. أغسطس 26, 2026. https://arabpsychology.com/statistics/how-to-calculate-mape-in-python/.