الوحدة 4 — مهامّ التدريب والحاويات المدمجة
انتهت الوحدة السابقة بمجلّد S3 منظّم يحتوي بيانات التسرّب. هنا نُشغّل أوّل مهمّة تدريب فعليّة داخل SageMaker: بلا تركيب مكتبة على العتاد، وبلا تشغيل Docker يدويًّا. نستدعي المُقدِّر (Estimator)، وترتيب البقيّة يجري تلقائيًّا في الخلفيّة.
دورة حياة مهمّة التدريب
عندما تنادي estimator.fit()، تنطلق سلسلة عمليّات مُدارة بالكامل:
- SageMaker يوفّر آلة EC2 من النوع المطلوب.
- يسحب صورة Docker المناسبة (مدمجة أو مخصّصة) من مستودع ECR.
- ينسخ البيانات من S3 إلى
/opt/ml/input/data/<channel>/داخل الحاوية. - يُشغّل نقطة الدخول (سكربتك أو نقطة دخول الصورة المدمجة).
- عند الانتهاء، ينسخ محتوى
/opt/ml/model/إلى S3 كأرشيفmodel.tar.gz. - يُطفئ الآلة. لا يبقى شيء نشطًا، ولا فاتورة بعد الثانية الأخيرة.
هذه الدورة هي ما يميّز مهامّ التدريب من دفتر يُدرَّب فيه النموذج مباشرة: لا خطر بأن يُترَك العتاد يعمل ليلًا.
المُقدِّر (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.large | 0.115 | تدريب سريع، بيانات صغيرة |
ml.m5.xlarge | 0.230 | خيار افتراضيّ للجداول |
ml.m5.4xlarge | 0.922 | بيانات فوق 5 غيغابايت |
ml.c5.2xlarge | 0.408 | حساب مكثّف بلا حاجة لذاكرة كبيرة |
ml.g4dn.xlarge | 0.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 لا يستحقّ عبء إدارة التفتيش. ولمهامّ الإنتاج المرتبطة بموعد إطلاق، احتمال المقاطعة يعني تأخيرًا لا ينبغي قبوله.
الخلاصة
- مهمّة التدريب تنشئ عتادًا مؤقّتًا، وتنفّذ حاويةً، وتحفظ النموذج على S3، ثمّ تُطفئ الآلة.
- المُقدِّر يجمع في كائن واحد كلّ ما يلزم للتشغيل، وقنوات
train/validationتربطه ببيانات S3. - ابدأ بأصغر نوع مثيل معقول (
ml.m5.largeأوml.m5.xlargeللجداول)، ولا تُكبّر إلّا عند حاجة موثّقة. - نُسخ Spot توفّر حتّى 70٪، لكنّها تستلزم
max_wait ≥ max_runونقاط تفتيش لتدريب يدوم أكثر من دقائق.
الوحدة التالية: نجاوز الحاويات المدمجة ونكتب سكربت scikit-learn خاصّ بنا في «مود سكربت».