المحاذاة مع DPO
DPOTrainer عملياً
3 دقيقة للقراءة
لننفذ تدريب DPO باستخدام DPOTrainer من TRL. سنمر على سكريبت تدريب كامل.
تدريب DPO الأساسي
from unsloth import FastLanguageModel
from trl import DPOTrainer, DPOConfig
from datasets import load_dataset
# ============================================
# 1. تحميل النموذج
# ============================================
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/Llama-3.2-3B-Instruct",
max_seq_length=2048,
load_in_4bit=True,
)
# أضف LoRA
model = FastLanguageModel.get_peft_model(
model,
r=16,
lora_alpha=16,
lora_dropout=0,
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"
],
bias="none",
use_gradient_checkpointing="unsloth",
)
# ============================================
# 2. تحميل مجموعة البيانات
# ============================================
dataset = load_dataset("HuggingFaceH4/ultrafeedback_binarized", split="train_prefs")
dataset = dataset.select(range(1000)) # مجموعة فرعية للاختبار
# ============================================
# 3. تكوين DPO
# ============================================
dpo_config = DPOConfig(
output_dir="./outputs/dpo-model",
beta=0.1, # معامل عقوبة KL
learning_rate=5e-6, # أقل من SFT
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
num_train_epochs=1,
warmup_ratio=0.1,
logging_steps=10,
save_steps=500,
bf16=True,
optim="adamw_8bit",
max_length=1024,
max_prompt_length=512,
)
# ============================================
# 4. تهيئة المدرّب
# ============================================
trainer = DPOTrainer(
model=model,
args=dpo_config,
train_dataset=dataset,
processing_class=tokenizer,
)
# ============================================
# 5. درّب
# ============================================
trainer.train()
# ============================================
# 6. احفظ
# ============================================
trainer.save_model("./outputs/dpo-model/final")
معاملات DPO الرئيسية
بيتا (β)
تتحكم في مقدار انحراف النموذج عن المرجع:
# محافظ (ابق قريباً من المرجع)
beta = 0.05
# متوازن (افتراضي)
beta = 0.1
# عدواني (انحراف أكثر مسموح)
beta = 0.5
معدل التعلم
DPO عادة يستخدم معدلات تعلم أقل من SFT:
# معدل تعلم SFT
sft_lr = 2e-4
# معدل تعلم DPO (10-100x أقل)
dpo_lr = 5e-6 # إلى 5e-7
الأطوال القصوى
# الطول الأقصى الكلي للمختار/المرفوض
max_length = 1024
# الطول الأقصى لجزء المحث
max_prompt_length = 512
التكوين المتقدم
dpo_config = DPOConfig(
output_dir="./outputs/dpo-advanced",
# خاص بـ DPO
beta=0.1,
loss_type="sigmoid", # أو "hinge"، "ipo"
# التدريب
learning_rate=5e-6,
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
num_train_epochs=1,
# الأطوال
max_length=1024,
max_prompt_length=512,
truncation_mode="keep_start",
# التحسين
warmup_ratio=0.1,
lr_scheduler_type="cosine",
weight_decay=0.01,
optim="adamw_8bit",
bf16=True,
# التسجيل
logging_steps=10,
eval_strategy="steps",
eval_steps=100,
save_steps=500,
# التنظيم
max_grad_norm=1.0,
)
أنواع الخسارة
DPO يدعم دوال خسارة مختلفة:
# خسارة sigmoid القياسية (افتراضي)
loss_type = "sigmoid"
# خسارة hinge
loss_type = "hinge"
# IPO (Identity Preference Optimization)
loss_type = "ipo"
مع نموذج مرجعي
لـ DPO صحيح، تحتاج نموذج مرجعي (نسخة مجمدة من نموذج SFT):
from trl import DPOTrainer, DPOConfig
from peft import PeftModel
# حمّل نموذج SFT كمرجع (مجمد)
ref_model = AutoModelForCausalLM.from_pretrained(
"path/to/sft-model",
torch_dtype=torch.bfloat16,
device_map="auto"
)
# حمّل النموذج للتدريب
model = AutoModelForCausalLM.from_pretrained(
"path/to/sft-model",
torch_dtype=torch.bfloat16,
device_map="auto"
)
model = get_peft_model(model, lora_config)
trainer = DPOTrainer(
model=model,
ref_model=ref_model, # مرجع مجمد
args=dpo_config,
train_dataset=dataset,
processing_class=tokenizer,
)
مراقبة التدريب
المقاييس الرئيسية
# سجلات التدريب ستُظهر:
# - loss: خسارة DPO (يجب أن تتناقص)
# - rewards/chosen: مكافأة الاستجابات المختارة (يجب أن تزيد)
# - rewards/rejected: مكافأة الاستجابات المرفوضة (يجب أن تتناقص)
# - rewards/margins: المختار - المرفوض (يجب أن يزيد)
علامات التدريب الجيد
| المقياس | الاتجاه الجيد |
|---|---|
| loss | متناقص |
| rewards/margins | متزايد |
| rewards/chosen | مستقر أو متزايد |
| rewards/rejected | متناقص |
علامات التدريب السيء
- الخسارة تنفجر ← قلل معدل التعلم
- الهوامش تصبح سالبة ← تحقق من جودة البيانات
- لا تحسن ← زد beta أو epochs
مثال كامل مع التقييم
from unsloth import FastLanguageModel
from trl import DPOTrainer, DPOConfig
from datasets import load_dataset
# حمّل النموذج
model, tokenizer = FastLanguageModel.from_pretrained(
"unsloth/Llama-3.2-3B-Instruct",
max_seq_length=2048,
load_in_4bit=True,
)
model = FastLanguageModel.get_peft_model(
model,
r=16,
lora_alpha=16,
target_modules="all-linear",
use_gradient_checkpointing="unsloth",
)
# حمّل وقسّم مجموعة البيانات
dataset = load_dataset("HuggingFaceH4/ultrafeedback_binarized")
train_dataset = dataset["train_prefs"].select(range(5000))
eval_dataset = dataset["test_prefs"].select(range(500))
# كوّن
dpo_config = DPOConfig(
output_dir="./outputs/dpo-eval",
beta=0.1,
learning_rate=5e-6,
per_device_train_batch_size=2,
per_device_eval_batch_size=2,
gradient_accumulation_steps=4,
num_train_epochs=1,
eval_strategy="steps",
eval_steps=200,
logging_steps=20,
bf16=True,
optim="adamw_8bit",
)
# درّب مع التقييم
trainer = DPOTrainer(
model=model,
args=dpo_config,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
processing_class=tokenizer,
)
trainer.train()
trainer.save_model("./outputs/dpo-eval/final")
نصيحة: ابدأ بـ beta صغير (0.1) وزده إذا لم يتعلم النموذج التفضيلات جيداً. راقب هوامش المكافأة للتأكد أن النموذج يفضل فعلاً المختار على المرفوض.
بعد ذلك، لنتعلم كيفية دمج SFT و DPO لخط أنابيب تدريب كامل. :::