الوحدة 8 — التحويل بالدفعات للأحجام الكبيرة
الوحدة السابقة اختصّت بالتنبّؤ في الوقت الحقيقيّ. لكن نصف مشاريع تعلّم الآلة لا تحتاج ميليثوانٍ، بل تحتاج إلى معالجة مليون سطر مرّة في الشهر. لخيطنا الأحمر: التسويق يريد فاتورة تسرّب شهريّة لكلّ عميل، مسبَّقة الحساب في ملفّ Parquet يقرأه CRM. هذه هي الحالة الطبيعيّة لـBatch Transform.
متى نفضّل الدفعة على نقطة النهاية
قاعدة القرار بسيطة، لكنّها تُنسى كثيرًا:
| المعيار | نقطة نهاية دائمة | Batch Transform |
|---|---|---|
| زمن الاستجابة المطلوب | ميليثوانٍ | دقائق أو ساعات |
| تكرار الاستعمال | مستمرّ | دفعة كلّ فترة (يوم، أسبوع، شهر) |
| الحجم لكلّ استدعاء | سطر أو بضعة سطور | آلاف إلى ملايين السطور |
| المستهلك | تطبيق ويب، جوّال | جدول قاعدة بيانات، CRM |
| الفاتورة الشهريّة النمطيّة | 74 دولارًا لآلة صغيرة | 1-5 دولارات لتشغيل واحد |
الفرق العمليّ: نقطة النهاية تدفع فيها ساعات الفراغ، أمّا الدفعة فتدفع فقط الدقائق التي عمل فيها العتاد فعلًا.
لخيطنا الأحمر: 500 ألف عميل، تسجيل شهريّ، لا حاجة لبيانات فوريّة قبل الحملة → دفعة.
أوّل Batch Transform
الفكرة نفسها: Transformer بدل Predictor. من نموذج مدرَّب:
transformer = sk_estimator.transformer(
instance_count=1,
instance_type="ml.m5.xlarge",
output_path=f"s3://{bucket}/churn/predictions/2024-07/",
strategy="MultiRecord", # نرسل عدّة سطور في نداء واحد
max_payload=6, # ميغابايت لكلّ نداء داخليّ
accept="text/csv",
)
transformer.transform(
data=f"s3://{bucket}/churn/scoring-input/2024-07/customers.csv",
content_type="text/csv",
split_type="Line",
join_source="Input", # الأصل مع المُخرَج (مفتاح للربط)
input_filter="$[1:]", # نتجاهل العمود الأوّل (المعرّف) عند الحساب
output_filter="$[0,-1]", # في المُخرَج: المعرّف والتوقّع فقط
)
transformer.wait()
النتيجة على S3: customers.csv.out يحتوي المعرّف والتوقّع، وشيء لا شيء غير ذلك.