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

الفصل 1: نهج التخصيص الدقيق التقليدي

تحديث جميع معلمات النموذج​

يتضمن التخصيص الدقيق التقليدي تحديث كل معلمة قابلة للتدريب في النموذج أثناء التدريب. يوفر هذا أقصى قدر من المرونة لتكييف النماذج مع المهام الجديدة.


كيف يعمل التخصيص الدقيق الكامل​

حلقة التدريب​

  1. التمرير الأمامي: يتدفق البيانات عبر النموذج بأكمله
  2. حساب الخسارة: مقارنة التنبؤ بالهدف
  3. التمرير الخلفي: حساب التدرجات لجميع المعلمات
  4. تحديث الأوزان: تطبيق التدرجات لتحديث جميع الأوزان
  5. التكرار: الاستمرار حتى التقارب

مثال تدريب كامل​

import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
TrainingArguments,
Trainer,
DataCollatorForLanguageModeling,
)
from datasets import load_dataset

# تحميل النموذج والمحول
model_name = "meta-llama/Llama-3.1-8B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token

# تحميل النموذج - جميع المعلمات قابلة للتدريب افتراضيًا
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16, # استخدام bf16 لكفاءة الذاكرة
device_map="auto",
)

# التحقق من أن جميع المعلمات قابلة للتدريب
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in model.parameters())
print(f"Trainable: {trainable_params:,} / {total_params:,} = 100%")

# إعداد مجموعة البيانات
dataset = load_dataset("databricks/dolly-15k", split="train[:1000]")

def format_instruction(example):
return {
"text": f"### Instruction:\n{example['instruction']}\n\n### Response:\n{example['response']}"
}

dataset = dataset.map(format_instruction)

def tokenize(example):
return tokenizer(
example["text"],
truncation=True,
max_length=512,
padding="max_length",
)

tokenized_dataset = dataset.map(tokenize, remove_columns=dataset.column_names)

# تكوين التدريب
training_args = TrainingArguments(
output_dir="./llama-full-ft",
num_train_epochs=3,
per_device_train_batch_size=1, # محدود بالذاكرة
gradient_accumulation_steps=16, # محاكاة حجم الدفعة 16
learning_rate=2e-5,
weight_decay=0.01,
warmup_ratio=0.03,
logging_steps=10,
save_strategy="epoch",
bf16=True, # استخدام bfloat16
gradient_checkpointing=True, # توفير الذاكرة
optim="adamw_torch_fused", # محسن فعال
)

# إنشاء المدرب
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset,
data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False),
)

# تدريب
trainer.train()

# حفظ
model.save_pretrained("./llama-full-ft-final")
tokenizer.save_pretrained("./llama-full-ft-final")

شرح المكونات الرئيسية​

معدل التعلم​

learning_rate = 2e-5 # النطاق الشائع: 1e-5 إلى 5e-5

للتخصيص الدقيق الكامل، استخدم معدلات تعلم أقل من PEFT:

  • مرتفع جدًا: يتباعد النموذج أو ينسى التدريب المسبق
  • منخفض جدًا: التدريب بطيء، قد لا يتكيف بشكل كافٍ

اضمحلال الوزن​

weight_decay = 0.01 # تنظيم لمنع الإفراط في التخصيص

يمنع اضمحلال الوزن النموذج من الإفراط في التخصيص عن طريق معاقبة الأوزان الكبيرة.

التسخين​

warmup_ratio = 0.03 # 3% من خطوات التدريب

زيادة معدل التعلم تدريجيًا في البداية لتحقيق استقرار التدريب.

التحقق من التدرج​

gradient_checkpointing = True # مبادلة الحساب بالذاكرة

إعادة حساب التنشيطات أثناء التمرير الخلفي بدلاً من تخزينها—يوفر حوالي 30% من الذاكرة.


اختيارات المحسن​

المحسنالذاكرةالسرعةالجودة
AdamWعاليةسريعالأفضل
Adam 8-bitمتوسطةمتوسطةجيدة
SGDمنخفضةبطيءيتطلب ضبط
Adafactorمنخفضةمتوسطةجيدة
# AdamW القياسي
optim = "adamw_torch"

# AdamW المدمج (أسرع)
optim = "adamw_torch_fused"

# Adam 8-bit (ذاكرة أقل)
optim = "adamw_8bit"

# Adafactor (بدون حالات زخم)
optim = "adafactor"

ديناميكيات التدريب​

منحنى الخسارة​

Epoch 1: انخفاض سريع في خسارة التدريب
(النموذج يتكيف مع البيانات الجديدة)

Epoch 2: استقرار خسارة التدريب
(مراقبة خسارة التحقق من الإفراط في التخصيص)

Epoch 3: احتمال الإفراط في التخصيص
(خسارة التدريب لا تزال تنخفض، قد تزيد خسارة التحقق)

مراقبة التدريب​

# استخدام Weights & Biases
training_args = TrainingArguments(
# ... معلمات أخرى ...
report_to="wandb",
run_name="llama-full-ft-experiment-1",
)

المقاييس الرئيسية للمراقبة:

  • خسارة التدريب: يجب أن تنخفض
  • خسارة التحقق: يجب أن تنخفض ولكن راقب التباعد عن خسارة التدريب
  • معيار التدرج: قد تشير الارتفاعات إلى عدم استقرار
  • معدل التعلم: تحقق من عمل التسخين والانخفاض

التدريب بدقة مختلطة​

لماذا استخدام الدقة المختلطة؟​

# نصف الذاكرة، غالبًا تدريب أسرع
bf16 = True # مفضل للبطاقات الرسومية الأحدث (Ampere+)
# أو
fp16 = True # للبطاقات الرسومية الأقدم
الدقةالذاكرةالنطاقالاستقرار
float324 بايتكاملالأعلى
bfloat162 بايتكاملعالي
float162 بايتمحدودمتوسط
استقرار Float16

لدى Float16 نطاق أضيق ويمكن أن يسبب تجاوز/تحت التدفق. يحافظ BFloat16 على نطاق float32 مع تقليل الدقة، مما يجعله أكثر استقرارًا.


الحفظ والتحميل​

أثناء التدريب (نقاط التحقق)​

training_args = TrainingArguments(
save_strategy="steps",
save_steps=500,
save_total_limit=3, # الاحتفاظ بآخر 3 نقاط تحقق فقط
)

بعد التدريب​

# حفظ النموذج الكامل
model.save_pretrained("./final-model")
tokenizer.save_pretrained("./final-model")

# لاحقًا، تحميله
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("./final-model")

مزايا التخصيص الدقيق الكامل​

أقصى تخصيص​

يمكن تعديل جميع المعلمات لمهمتك.

جودة محتملة أعلى​

لا توجد قيود من الأوزان المجمدة.

البساطة​

لا حاجة لتكوين محولات.

إخراج مدمج​

ملف نموذج واحد، لا يوجد عبء محول في الاستدلال.


العيوب​

متطلبات ذاكرة عالية​

الحاجة إلى تخزين النموذج، التدرجات، وحالات المحسن.

خطر النسيان الكارثي​

يمكن أن يفقد المعرفة المدربة مسبقًا.

مكلف​

يتطلب موارد GPU كبيرة.

تدريب بطيء​

يجب تحديث كل معلمة.


متى يجب استخدام التخصيص الدقيق الكامل​

حالة الاستخدامالتوصية
الحاجة إلى جودة قصوى✅ تخصيص دقيق كامل
محدودية الموارد❌ استخدم PEFT
التجريب السريع❌ استخدم PEFT
الإنتاج على نطاق واسع⚠️ النظر في التوازنات
البحث/المقارنة✅ تخصيص دقيق كامل

النقاط الرئيسية​

✅ التخصيص الدقيق الكامل يحدث لكل معلمات النموذج

✅ يتطلب ذاكرة GPU كبيرة (النموذج + التدرجات + المحسن)

✅ استخدم الدقة المختلطة والتحقق من التدرج لتقليل الذاكرة

✅ معدلات تعلم أقل من PEFT (1e-5 إلى 5e-5)

✅ مراقبة الإفراط في التخصيص مع خسارة التحقق

✅ الأفضل لأقصى تخصيص عندما تسمح الموارد


الخطوات التالية​

تابع إلى الفصل 2: متطلبات الحوسبة لفهم الاحتياجات الدقيقة للذاكرة والحوسبة.


تحقق سريع​

قبل المتابعة، تأكد من أنك تستطيع الإجابة على:

  1. ما هي المكونات الأربعة الرئيسية المخزنة في ذاكرة GPU أثناء التدريب؟
  2. لماذا يفضل bfloat16 غالبًا على float16؟
  3. ما هو نطاق معدل التعلم النموذجي للتخصيص الدقيق الكامل؟