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

الوحدة 4 — مهامّ التدريب والحاويات المدمجة

انتهت الوحدة السابقة بمجلّد S3 منظّم يحتوي بيانات التسرّب. هنا نُشغّل أوّل مهمّة تدريب فعليّة داخل SageMaker: بلا تركيب مكتبة على العتاد، وبلا تشغيل Docker يدويًّا. نستدعي المُقدِّر (Estimator)، وترتيب البقيّة يجري تلقائيًّا في الخلفيّة.

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

عندما تنادي estimator.fit()، تنطلق سلسلة عمليّات مُدارة بالكامل:

  1. SageMaker يوفّر آلة EC2 من النوع المطلوب.
  2. يسحب صورة Docker المناسبة (مدمجة أو مخصّصة) من مستودع ECR.
  3. ينسخ البيانات من S3 إلى /opt/ml/input/data/<channel>/ داخل الحاوية.
  4. يُشغّل نقطة الدخول (سكربتك أو نقطة دخول الصورة المدمجة).
  5. عند الانتهاء، ينسخ محتوى /opt/ml/model/ إلى S3 كأرشيف model.tar.gz.
  6. يُطفئ الآلة. لا يبقى شيء نشطًا، ولا فاتورة بعد الثانية الأخيرة.

هذه الدورة هي ما يميّز مهامّ التدريب من دفتر يُدرَّب فيه النموذج مباشرة: لا خطر بأن يُترَك العتاد يعمل ليلًا.

المُقدِّر (Estimator)

الفكرة المركزيّة في SDK. المُقدِّر يجمع في كائن واحد كلّ ما يلزم لتشغيل تدريب: الحاوية، والعتاد، والمعاملات الفائقة، ودور IAM، ومسار المخرَج.

from sagemaker import image_uris
from sagemaker.estimator import Estimator

region = session.boto_region_name
xgb_image = image_uris.retrieve("xgboost", region=region, version="1.7-1")

estimator = Estimator(
image_uri=xgb_image,
role=role,
instance_type="ml.m5.xlarge",
instance_count=1,
output_path=f"s3://{bucket}/churn/models/",
hyperparameters={
"objective": "binary:logistic",
"eval_metric": "auc",
"num_round": 200,
"max_depth": 5,
"eta": 0.1,
"subsample": 0.8,
},
)

image_uris.retrieve يبني هويّة الصورة الرسميّة لخوارزميّة مدمجة في المنطقة المستهدفة. لا تكتب هذا الرابط يدويًّا: قد يختلف من منطقة إلى أخرى.

القنوات، أو كيف تدخل البيانات

يقبل XGBoost المدمج قناة train وقناة validation. يتوقّع الصيغة text/csv مع العمود المستهدف في المكان الأوّل، بلا رأس. إعادة صياغة بسيطة قبل تشغيل المهمّة:

train_df = pd.read_parquet(f"s3://{bucket}/churn/processed/v1/train.parquet")
cols = ["churn"] + [c for c in train_df.columns if c != "churn"]
train_df = train_df[cols]
train_df.to_csv(
f"s3://{bucket}/churn/xgb-input/train.csv", header=False, index=False,
)

ثمّ نشغّل المهمّة:

from sagemaker.inputs import TrainingInput

train_ch = TrainingInput(f"s3://{bucket}/churn/xgb-input/train.csv", content_type="text/csv")
valid_ch = TrainingInput(f"s3://{bucket}/churn/xgb-input/valid.csv", content_type="text/csv")

estimator.fit({"train": train_ch, "validation": valid_ch})

يُطبع سجلّ التدريب مباشرةً في الدفتر، ويستمرّ في CloudWatch حتّى بعد إغلاق الدفتر. لكلّ جولة تتراكم القيم:

[0]     train-auc:0.72814       validation-auc:0.71203
[50] train-auc:0.89117 validation-auc:0.83422
[199] train-auc:0.96442 validation-auc:0.84019

الفارق بين train-auc وvalidation-auc يشي بإفراط في التعلّم يجب أن يعالجه ضبط المعاملات (الوحدة 6).

اختيار نوع المثيل ونمط التوزيع

قاعدة أوّليّة: ابدأ بالأصغر. لو تدرَّب النموذج في دقيقتين على ml.m5.large، لا فائدة من ml.m5.4xlarge. تُدفع الفاتورة على قدر الوقت وعلى قدر الحجم:

نوع المثيلالتكلفة تقريبًا (دولار/ساعة)متى يُختار
ml.m5.large0.115تدريب سريع، بيانات صغيرة
ml.m5.xlarge0.230خيار افتراضيّ للجداول
ml.m5.4xlarge0.922بيانات فوق 5 غيغابايت
ml.c5.2xlarge0.408حساب مكثّف بلا حاجة لذاكرة كبيرة
ml.g4dn.xlarge0.736أوّل تدريب على GPU

للنموذج الجدوليّ (XGBoost)، ml.m5.xlarge هو نقطة الانطلاق الطبيعيّة. instance_count > 1 مفيد لخوارزميّات موزّعة، لكن XGBoost لا يستفيد منه إلّا فوق ملايين السطور — ابقَ على 1.

نُسخ Spot: خصم قد يبلغ 70٪

نُسخ Spot هي عتاد يبيعه AWS بسعر مخفَّض من مخزون غير مستعمَل، مقابل حقّ سحبه في أيّ لحظة. الخصم يكون بين 50٪ و90٪. لخيطنا الأحمر:

estimator = Estimator(
image_uri=xgb_image,
role=role,
instance_type="ml.m5.xlarge",
instance_count=1,
output_path=f"s3://{bucket}/churn/models/",
use_spot_instances=True,
max_wait=3600, # الحدّ الأقصى للانتظار قبل التخلّي (بالثواني)
max_run=1800, # الحدّ الأقصى للتدريب الفعليّ
checkpoint_s3_uri=f"s3://{bucket}/churn/checkpoints/",
hyperparameters={...},
)

قاعدتان لا نقاش فيهما:

  • max_wait ≥ max_run. max_wait يشمل زمن الانتظار و التدريب. جعله أصغر يعني أنّ المهمّة تفشل قبل أن تبدأ.
  • لا نُسخ Spot دون نقاط تفتيش (checkpoints) لمهمّة تدوم أكثر من دقائق. إذا انقطعت النسخة في الدقيقة 40 من تدريب لساعة، وبلا تفتيش، فقدت كلّ شيء.

XGBoost المدمج يعرف كتابة نقاط تفتيش تلقائيًّا عند تحديد checkpoint_s3_uri. للسكربتات المخصّصة (الوحدة 5) عليك كتابة منطق التفتيش يدويًّا.

Spot ليس دائمًا الخيار الأصحّ

لتدريب قصير جدًّا (تحت دقيقتَين) فرق سعر Spot لا يستحقّ عبء إدارة التفتيش. ولمهامّ الإنتاج المرتبطة بموعد إطلاق، احتمال المقاطعة يعني تأخيرًا لا ينبغي قبوله.

الخلاصة

  • مهمّة التدريب تنشئ عتادًا مؤقّتًا، وتنفّذ حاويةً، وتحفظ النموذج على S3، ثمّ تُطفئ الآلة.
  • المُقدِّر يجمع في كائن واحد كلّ ما يلزم للتشغيل، وقنوات train/validation تربطه ببيانات S3.
  • ابدأ بأصغر نوع مثيل معقول (ml.m5.large أو ml.m5.xlarge للجداول)، ولا تُكبّر إلّا عند حاجة موثّقة.
  • نُسخ Spot توفّر حتّى 70٪، لكنّها تستلزم max_wait ≥ max_run ونقاط تفتيش لتدريب يدوم أكثر من دقائق.

الوحدة التالية: نجاوز الحاويات المدمجة ونكتب سكربت scikit-learn خاصّ بنا في «مود سكربت».