الوحدة 8 — متابعة التدريب والتوقّف في الوقت المناسب
بمجرّد أن ينطلق التدريب، تصبح المتابعة اليقظة أهمّ من إعداد أي معامل فائق. المنحنيات هي مصدرك الوحيد للحقيقة، والفشل في قراءتها يكلّف ساعات GPU لا نتائج معها. هذه الوحدة تُعطيك القراءات الأربع الأساسية وكيف تُفسَّر.
القراءتان الأساسيتان: خسارة التدريب والتحقّق
خسارة التدريب (train_loss) تُقاس على الدفعة الحالية. تنخفض عادةً بشكل
منتظم مع كلّ خطوة. لكنّها مضلّلة: نموذج يحفظ أمثلة التدريب حرفيًّا
يُنتج خسارة تدريب صفرًا تقريبًا مع نتيجة كارثية في الإنتاج.
خسارة التحقّق (eval_loss) تُقاس على مجموعة التحقّق التي لم يرها النموذج
أثناء التدريب. هي الحكم الحقيقي. تُحسَب دوريًّا (eval_steps=100
مثلًا) وتُرسم مع خسارة التدريب على المخطّط نفسه.
المنحنيات النموذجية وقراءتها
السيناريو المثالي: كلا المنحنيَين ينخفضان معًا، مع فجوة صغيرة بينهما تنمو ببطء. هذا يعني أنّ النموذج يتعلّم ويعمّم في الوقت نفسه.
فرط التخصيص الكلاسيكي: خسارة التدريب تستمرّ في الانخفاض، لكن خسارة التحقّق تستقرّ ثمّ ترتفع. هذه النقطة (حيث تنعطف خسارة التحقّق نحو الأعلى) هي لحظة التوقّف المثلى. نقاط التفتيش السابقة لهذه اللحظة هي التي يجب استعمالها.
نقص التخصيص: كلا المنحنيَين مستقرّان عند قيمة عالية، بلا انخفاض واضح. علامة على معدّل تعلّم منخفض جدًّا، أو رتبة LoRA صغيرة جدًّا، أو بيانات ضعيفة.
عدم استقرار: خسارة التدريب تقفز أو تُنتج NaN. معدّل تعلّم مرتفع
جدًّا، أو مشكلة في القالب، أو دقّة عددية خاطئة (FP16 بدل BF16).
اختبار «فرط التخصيص على عشرة أمثلة»
قبل التدريب الكامل، اختبار بسيط يوفّر ساعات. خذ عشرة أمثلة فقط من مجموعة التدريب، وشغّل التدريب عليها لمدّة 100-200 خطوة. الهدف: أن يحفظ النموذج هذه العشرة حرفيًّا.
النتيجة المتوقّعة: خسارة التدريب تنزل إلى قرب الصفر (0.01 مثلًا). إن لم يحدث ذلك، فهناك مشكلة أساسية في الإعداد: قالب خاطئ، أو خسارة غير مُقنَّعة صحيحًا، أو معدّل تعلّم مُعطَّل. الحلقة لا تستطيع أن تتعلّم على عشرة أمثلة، فلن تتعلّم على ألفَين.
هذا الاختبار يكشف 90% من مشكلات الإعداد في عشر دقائق، بدل اكتشافها بعد ثلاث ساعات من التدريب الكامل.
العيّنات المولَّدة في كلّ حقبة
الخسارة رقم بارد. لتقييم نوعية فعلية، ولِّد جوابًا على مثال ثابت من مجموعة التحقّق في نهاية كلّ حقبة، وسجّله. هذه العادة تكشف:
- تحسّن الأسلوب: هل يقترب الجواب من الأسلوب المستهدف؟
- الهلوسة: هل يخترع النموذج معلومات؟
- الانهيار الأسلوبي: هل يبدأ بتكرار الجملة نفسها، أو الوصول إلى صفة فقيرة من الكلمات؟
مقتطف عملي مع TrainerCallback:
from transformers import TrainerCallback
class SampleGenerationCallback(TrainerCallback):
def __init__(self, tokenizer, sample_input):
self.tokenizer = tokenizer
self.sample = sample_input
def on_epoch_end(self, args, state, control, model, **kwargs):
model.eval()
inputs = self.tokenizer(self.sample, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=300, do_sample=False)
text = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
print(f"\n=== Epoch {state.epoch} ===\n{text}\n")
model.train()
نقاط التفتيش (Checkpoints)
transformers يحفظ نقاط تفتيش دورية. الإعدادات المفيدة:
save_steps=100, # حفظ كلّ 100 خطوة
save_total_limit=3, # الاحتفاظ بـ3 نقاط فقط (توفير قرص)
load_best_model_at_end=True, # تحميل الأفضل عند النهاية
metric_for_best_model="eval_loss",
greater_is_better=False,
load_best_model_at_end=True هو ما ينقذك من فرط التخصيص: حتّى لو انتهى
التدريب متأخّرًا، يحمَّل تلقائيًّا النموذج ذو أدنى خسارة تحقّق.
أدوا ت المتابعة الحيّة
عرض المنحنيات في وقت التدريب يجعل التشخيص أسهل بمراحل من قراءة الأرقام. خياران رئيسيّان:
- TensorBoard: مدمج في
transformersبـreport_to="tensorboard". محلّي، بسيط، بلا اتّصال. - Weights & Biases:
report_to="wandb". أقوى، مقارنة بين التجارب، لكن يتطلّب حسابًا.
كلاهما يعرض خسارة التدريب والتحقّق في الوقت الحيّ، وأيّ قيمة أخرى تُسجّلها.
التوقّف المبكر (Early Stopping)
transformers يدعمه عبر EarlyStoppingCallback:
from transformers import EarlyStoppingCallback
trainer.add_callback(EarlyStoppingCallback(
early_stopping_patience=3,
early_stopping_threshold=0.001,
))
هذا يوقف التدريب إذا لم تتحسّن خسارة التحقّق لثلاث تقييمات متتالية بمقدار أقلّ من 0.001. يُوفّر ساعات GPU على تدريبات متأخّرة الفرط.
علامة تحذير أساسية
في القرار الأخير، إذا كانت خسارة التحقّق منخفضة جدًّا، أقلّ من التدريب، فهذه علامة تسريب في القسمة (كما نبّهت الوحدة 2). راجع تقسيم بياناتك قبل الاحتفال.
في المقابل، إذا كانت خسارة التدريب تنزل والتحقّق يرتفع بحدّة بعد حقبتين،
جرّب: تقليل الحقب، تقليل معدّل التعلّم، أو زيادة lora_dropout إلى 0.1.
راقب خسارة التحقّق كلّ 100 خطوة، والعيّنة المولَّدة كلّ حقبة. الأولى تُخبرك بالسلوك الإحصائي، والثانية تُخبرك بالنوعية المُدرَكة. تحتاج الاثنتين، ليس واحدة فقط.
خسارة تحقّق 0.5 على مهمّة توليد لا تعني «جيّد جدًّا»؛ خسارة 0.5 على تصنيف ثنائي تعني «كارثة». المقياس نسبي إلى المهمّة. قارن دائمًا بنقاط تفتيش سابقة على المهمّة نفسها.
الخلاصة
- خسارة التدريب تنخفض دائمًا؛ خسارة التحقّق هي الحكم الحقيقي.
- فرط تخصيص عشرة أمثلة يكشف مشكلات الإعداد قبل ضياع ساعات التدريب.
- ولِّد عيّنة في كلّ حقبة على مثال ثابت لرؤية النوعية لا الأرقام فقط.
- نقاط التفتيش مع
load_best_model_at_end=Trueتحميك من فرط التخصيص المتأخّر تلقائيًّا.
في الوحدة التالية: دمج المحوّلا ت في الأوزان وتصدير النموذج إلى صيغة GGUF للاستدلال المحلّي على CPU.