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

الوحدة 10 — المراقبة والتنبيهات والتحكّم في الفاتورة

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

Model Monitor: ما الذي يُراقب فعليًّا

يقدّم Model Monitor أربعة أنواع من الفحوصات، لا يُشغَّل الأربع في العادة:

  • Data Quality (الأشيع): يقارن توزيع كلّ متغيّر في الإنتاج بالتوزيع المرجعيّ الذي حُسب من بيانات التدريب. يكشف قيمًا شاذّة، وأعمدة فارغة، وحدودًا جديدة.
  • Model Quality: يقارن التوقّعات بالعلامات الفعليّة. يفترض توفّر التسميات، وهي نادرًا ما تصل فورًا (لخيطنا الأحمر، نعرف إن كان العميل تسرّب فعلًا بعد ثلاثة أشهر).
  • Bias Drift: يفحص إن كانت مقاييس الإنصاف قد اختلّت.
  • Feature Attribution Drift: يفحص إن تغيّرت أهمّيّة المتغيّرات.

في 80٪ من المشاريع، Data Quality وحده يعطي 80٪ من القيمة.

الحدّ المرجعيّ (Baseline)

خطوة إلزاميّة قبل أيّ مراقبة: توليد حدّ مرجعيّ من بيانات التدريب. مهمّة SageMaker مخصّصة تحسب لكلّ عمود: الإحصاءات (المتوسّط، الانحراف)، وقيود (نطاق مقبول، نسبة القيم المفقودة القصوى).

from sagemaker.model_monitor import DefaultModelMonitor
from sagemaker.model_monitor.dataset_format import DatasetFormat

monitor = DefaultModelMonitor(role=role, instance_type="ml.m5.xlarge", instance_count=1)
monitor.suggest_baseline(
baseline_dataset=f"s3://{bucket}/churn/processed/v1/train.csv",
dataset_format=DatasetFormat.csv(header=True),
output_s3_uri=f"s3://{bucket}/churn/monitor/baseline/",
)

النتيجة على S3: ملفّان JSON — statistics.json وconstraints.json. راجعهما يدويًّا قبل الإنتاج، فقد يفرض SageMaker قيدًا صارمًا زيادةً (مثلًا نطاق قيمة age بين 18 و95 بينما القاعدة الحقيقيّة 18-120). حذف قيد أو توسيعه أسهل الآن من مطاردة تنبيهات كاذبة كلّ يوم لاحقًا.

التقاط البيانات والجدولة

لكي يستطيع المراقب أن يقارن، يجب أن يلتقط الاستدلالات:

from sagemaker.model_monitor import DataCaptureConfig

data_capture = DataCaptureConfig(
enable_capture=True,
sampling_percentage=20, # يكفي 20٪ في الإنتاج
destination_s3_uri=f"s3://{bucket}/churn/capture/",
)

predictor = sk_model.deploy(
endpoint_name="churn-monitored",
instance_type="ml.m5.large",
initial_instance_count=1,
data_capture_config=data_capture,
)

ثمّ نجدول تحليلًا كلّ ساعة:

from sagemaker.model_monitor import CronExpressionGenerator

monitor.create_monitoring_schedule(
endpoint_input=predictor.endpoint_name,
output_s3_uri=f"s3://{bucket}/churn/monitor/reports/",
statistics=monitor.baseline_statistics(),
constraints=monitor.suggested_constraints(),
schedule_cron_expression=CronExpressionGenerator.hourly(),
enable_cloudwatch_metrics=True,
)

كلّ ساعة، مهمّة تحليل تُشغَّل وتنشئ تقريرًا. الانتباه: هذه المهمّة تكلّف نحو 0.05 دولار كلّ مرّة. ساعيًا ذلك 36 دولارًا شهريًّا. للحمولات المتوسّطة، الجدولة اليوميّة كافية (1.5 دولار في الشهر).

CloudWatch: التنبيه لا الرسم البيانيّ

كلّ خدمة SageMaker تنشر تلقائيًّا مقاييس في CloudWatch:

  • عدد الاستدعاءات (Invocations)، ونسبة الخطأ (Invocation4XXErrors, Invocation5XXErrors).
  • زمن الاستجابة (ModelLatency، OverheadLatency).
  • استعمال CPU/GPU/الذاكرة.
  • تنبيهات Model Monitor (عدد الانتهاكات لكلّ عمود).

الفخّ: بناء لوحة قيادة جميلة لا يفتحها أحد يوميًّا. الاختيار الصحيح: تنبيهات (Alarms) ترسل رسالة إلى Slack أو بريد الفريق حين تجاوز عتبة.

import boto3
cw = boto3.client("cloudwatch")

cw.put_metric_alarm(
AlarmName="churn-endpoint-5xx",
MetricName="Invocation5XXErrors",
Namespace="AWS/SageMaker",
Statistic="Sum",
Period=60,
EvaluationPeriods=5,
Threshold=5,
ComparisonOperator="GreaterThanThreshold",
Dimensions=[
{"Name": "EndpointName", "Value": "churn-monitored"},
{"Name": "VariantName", "Value": "AllTraffic"},
],
AlarmActions=["arn:aws:sns:us-east-1:...:oncall-topic"],
)

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

الميزانيّة: التنبيه الذي يُنقذ الشركة

قبل النموذج، قبل التدريب، قبل نقطة النهاية، اضبط AWS Budget بأمر واحد:

budgets = boto3.client("budgets")
budgets.create_budget(
AccountId="<account-id>",
Budget={
"BudgetName": "sagemaker-monthly",
"BudgetLimit": {"Amount": "300", "Unit": "USD"},
"TimeUnit": "MONTHLY",
"BudgetType": "COST",
"CostFilters": {"Service": ["Amazon SageMaker"]},
},
NotificationsWithSubscribers=[{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80.0,
},
"Subscribers": [{"SubscriptionType": "EMAIL", "Address": "oncall@example.com"}],
}],
)

الفكرة: تلقّي إشعار عند بلوغ 80٪ من الحدّ، لا بعد التجاوز. القاعدة العمليّة: حدّ ميزانيّة نصف ضِعف الميزانيّة المتوقّعة. لخيطنا الأحمر بميزانيّة متوقّعة 150 دولارًا، حدّ 300 دولار يعطي هامشًا دون أن يكون مفتوحًا للخطأ الكبير.

الأسباب الخمسة للفواتير المفاجئة

كلّ فاتورة صدمة على SageMaker تنتمي إلى أحد هذه الأصناف:

  1. نقطة نهاية نُسيت مفتوحة (الأشيع). حلّ: قاعدة حذف تلقائيّ لكلّ نقطة dev-* بعد 12 ساعة.
  2. دفتر لم يُطفأ في الليل. حلّ: إغلاق تلقائيّ على مستوى المجال (الوحدة 2).
  3. مهمّة ضبط تلقائيّ على ml.g4dn.*xlarge بلا early_stopping. حلّ: early_stopping_type="Auto" دائمًا (الوحدة 6).
  4. إعادة تشغيل خطّ إنتاج كلّ ساعة بلا داعٍ. حلّ: مراجعة schedule_cron_expression، والتساؤل: هل تتغيّر البيانات فعلًا كلّ ساعة؟
  5. جدولة Model Monitor ساعيّة على عشرين نقطة نهاية. حلّ: يوميّة تكفي لأغلب الحالات، والساعيّة تُحفظ للنماذج ذات الأثر الحرج.
الوثيقة التي تكتب مرّة وحدها

اطبع في نهاية كلّ سبرنت جدولًا صغيرًا: أسماء نقاط النهاية النشطة، والعتاد، والفاتورة المرتقبة. عشر دقائق شهريًّا توفّر مئات الدولارات. هذا التمرين البسيط يفعل ما لا تفعله أيّ أداة مراقبة تلقائيّة.

الخلاصة

  • Model Monitor Data Quality يوفّر 80٪ من القيمة بـ20٪ من الجهد؛ الأنواع الأخرى تُضاف عند حاجة موثّقة.
  • الحدّ المرجعيّ يُراجع يدويًّا قبل الإنتاج؛ قيود صارمة زيادةً تولّد تنبيهات كاذبة كثيرة.
  • CloudWatch للتنبيهات لا للوحات؛ كلّ تنبيه قابل للتصرّف أو يُحذف.
  • الأسباب الخمسة للفواتير المفاجئة كلّها معروفة سلفًا؛ ضبط ميزانيّة وتفعيل حذف تلقائيّ يعالجانها بلا استثناء.

الوحدة التالية: مراجعة كاملة للدورة، ثمّ الاختبار النهائيّ من 40 سؤالًا.