الوحدة 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"],
)
قاعدة عمل: كلّ تنبيه ينشر يجب أن يكون قابلًا للتصرّف. تنبيهات لا يُفهم كيف تعالج تولّد تعبًا للفريق، ثمّ إغلاقًا آليًّا للسجلّ. أفضل أن يكون هناك ثلاث تنبيهات محترمة من خمس عشرة تنبيهة تُهمَل.