انتقل إلى المحتوى الرئيسي

الوحدة 1 — ما تحلّه MLOps وتتجاهله البرمجة التقليدية

نبدأ الدورة بمشهد مألوف: عالِمة بيانات لدى مشغّل اتّصالات كتبت دفتر Jupyter يتوقّع تسرّب المشتركين، ويُظهر مؤشّر AUC بقيمة 0,86 على بيانات الاختبار. المدير يريد نشره غدًا. ما الذي يعنيه «نشره»؟ وأين تبدأ MLOps؟

ما لا تحلّه البرمجة التقليدية

يفترض تطوير البرمجيات الكلاسيكي أنّ الشفرة هي المصدر الوحيد للسلوك. تُعدّل السطر، تُشغّل الاختبارات، تنشر البناء الجديد. إن كان الاختبار أخضر فالسلوك محفوظ.

في التعلّم الآلي ينهار هذا الافتراض. سلوك النموذج ينتج من ثلاثة أشياء متزامنة: الشفرة (خوارزمية التدريب، تحضير البيانات، معلمات الضبط)، والبيانات (اللقطة المُستعملة لحظة التدريب)، والبيئة (نسخة scikit-learn، numpy، مكتبة النظام). فتغيّر أيّ منها يغيّر النموذج، والاختبار الوحداني على الشفرة لا يلتقط شيئًا من ذلك.

نتيجة عملية: دفتر Jupyter الذي كتبته الزميلة قبل ستّة أشهر لا يعيد إنتاج نفس النموذج اليوم، حتّى على نفس الجهاز. لأنّ pandas رُقّي، ولأنّ ملفّ CSV تغيّر بصمت، ولأنّ البذرة العشوائية لم تُثبَّت في مكان ما.

البيانات تتغيّر، والنموذج يتدهور

نموذج التسرّب الذي نشرناه في يناير يتوقّع اليوم تسرّبًا أعلى من الواقع بنسبة 8 نقاط مئوية. لم يتغيّر شيء في الشفرة، لكنّ المشغّل أطلق عرضًا جديدًا في مارس، وسلوك المشتركين تغيّر. هذا ما يُسمّى انحراف المفهوم (concept drift): العلاقة بين المتغيّرات والهدف لم تعد كما كانت.

هذا لا يحدث في مشروع برمجي كلاسيكي: عندما تكتب دالّة لحساب الفاتورة الشهرية، فإنّها تظلّ صحيحة إلى أجل غير مسمّى. أمّا نموذج التعلّم الآلي فيَبلَى مع مرور الوقت، حتّى وإن لم يتغيّر سطر واحد من الشفرة. ومن هنا الحاجة إلى مراقبة مستمرّة وإعادة تدريب دورية، وهما لا يوجدان في هندسة البرمجيات التقليدية.

التجربة كأداة عمل يومية

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

من دون أداة تتبّع، تصبح هذه التجارب فوضى غير قابلة للاسترجاع. أي نموذج حصل على AUC 0,86؟ وأي مجموعة معلمات استعملها؟ وأي نسخة من البيانات؟ MLOps تحلّ هذا بأداة تتبّع التجارب (MLflow في هذه الدورة) تحفظ كلّ ذلك تلقائيًا.

مستويات النضج

اقترحت Google تصنيفًا ذا ثلاثة مستويات لنضج فِرَق MLOps، وهو مرجع مفيد لتحديد الموقع:

  • المستوى 0: كلّ شيء يدوي. عالِمة البيانات تُدرّب في دفترها، وترسل ملفّ .pkl بالبريد إلى مهندس النشر. لا تتبّع، ولا اختبارات، ولا إعادة تدريب. يعمل حتّى يفشل.
  • المستوى 1: أتمتة خطّ التدريب. نصّ برمجي (script) يعيد التدريب على البيانات الجديدة، ولكنّ النشر لا يزال يدويًا.
  • المستوى 2: أتمتة كاملة لخطّ CI/CD. يُفعّل تغييرُ الشفرة اختباراتٍ، ثم تدريبًا، ثم اختبار جودة النموذج، ثم نشرًا. تراقب المنصّة الأداء وتُعيد التدريب تلقائيًا عند الحاجة.

معظم الفِرَق التي بدأت مشاريع التعلّم الآلي دون خبرة تشغيلية تجد نفسها في المستوى 0. الهدف من هذه الدورة الوصول إلى المستوى 2 على مثال واقعي.

الدفتر الأصلي وما ينقصه

في نهاية هذه الوحدة نفتح الدفتر الذي كتبته الزميلة. الشفرة تعمل، والنموذج مدرّب، والنتائج مطبوعة. لكنّ الملاحظات التالية تعبر الذهن فورًا:

  • لا توجد بذرة عشوائية مثبَّتة، فإعادة التشغيل تُنتج نموذجًا مختلفًا قليلًا.
  • ملفّ requirements.txt غائب، فلا نعرف نسخ المكتبات.
  • بيانات التدريب هي «الملفّ الذي كان على القرص في ذلك اليوم»، دون رقم إصدار.
  • لا اختبار يتحقّق أنّ النموذج لا يقهقر بالنسبة لعملية سابقة.
  • لا آلية للنشر، ولا مراقبة، ولا خطّة لإعادة التدريب.

كلّ الوحدات القادمة تعالج نقطة من هذه القائمة. الوحدة 2 تُثبّت البذور والبيئات، والوحدة 3 تتتبّع التجارب، وهكذا حتى الوحدة 10 التي تُغلق الحلقة بإعادة تدريب آليّة.

المسار الذي نبنيه

لا نُعيد كتابة الدفتر من الصفر. ننقله كما هو إلى مستودع Git، ثم نُضيف طبقةً MLOps فوقه، وحدةً بعد وحدة. في نهاية الدورة، الشفرة الأصلية لا تزال موجودة، لكنّها محاطة بإطار تشغيلي كامل.

في الخلاصة

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