الدرس 15 من 24

التدريب مع Unsloth

التدريب مع Unsloth

3 دقيقة للقراءة

الآن لنشغّل مهمة تدريب كاملة باستخدام Unsloth مع SFTTrainer من TRL. سترى كم هو مشابه للتدريب القياسي، لكن أسرع بكثير.

سكريبت التدريب الكامل

from unsloth import FastLanguageModel
from trl import SFTTrainer
from transformers import TrainingArguments
from datasets import load_dataset

# ============================================
# 1. حمّل النموذج مع Unsloth
# ============================================
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/Llama-3.2-3B-Instruct",
    max_seq_length=2048,
    load_in_4bit=True,
    dtype=None,
)

# ============================================
# 2. أضف محولات 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",
    random_state=42,
)

# ============================================
# 3. جهّز مجموعة البيانات
# ============================================
dataset = load_dataset("tatsu-lab/alpaca", split="train")

def format_prompt(example):
    """نسّق بأسلوب Alpaca."""
    if example.get("input", ""):
        text = f"""### التعليمة:
{example['instruction']}

### المدخل:
{example['input']}

### الاستجابة:
{example['output']}<|eot_id|>"""
    else:
        text = f"""### التعليمة:
{example['instruction']}

### الاستجابة:
{example['output']}<|eot_id|>"""
    return {"text": text}

dataset = dataset.map(format_prompt)

# ============================================
# 4. إعداد المُرمّز
# ============================================
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

# ============================================
# 5. معاملات التدريب
# ============================================
training_args = TrainingArguments(
    output_dir="./outputs/unsloth-finetune",
    num_train_epochs=1,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    learning_rate=2e-4,
    weight_decay=0.01,
    warmup_steps=10,
    lr_scheduler_type="linear",
    logging_steps=10,
    save_steps=500,
    bf16=True,
    optim="adamw_8bit",  # محسّن 8-bit لتوفير الذاكرة
    seed=42,
)

# ============================================
# 6. تهيئة المدرّب
# ============================================
trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
    processing_class=tokenizer,
    max_seq_length=2048,
    dataset_text_field="text",
    packing=False,
)

# ============================================
# 7. درّب!
# ============================================
print("بدء تدريب Unsloth...")
trainer.train()

# ============================================
# 8. احفظ
# ============================================
trainer.save_model("./outputs/unsloth-finetune/final")
print("اكتمل التدريب!")

الاختلافات الرئيسية عن التدريب القياسي

1. تحميل النموذج

# قياسي
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(...)

# Unsloth
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(...)

2. إضافة LoRA

# قياسي
from peft import get_peft_model, LoraConfig
model = get_peft_model(model, LoraConfig(...))

# Unsloth
model = FastLanguageModel.get_peft_model(model, ...)

3. Gradient Checkpointing

# قياسي
model.gradient_checkpointing_enable()

# Unsloth (إصدار محسّن)
use_gradient_checkpointing="unsloth"

معاملات التدريب المحسّنة

لـ Unsloth، هذه المعاملات تعمل جيداً:

training_args = TrainingArguments(
    # الإعدادات الأساسية
    num_train_epochs=3,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,

    # المحسّن (8-bit يوفر الذاكرة)
    optim="adamw_8bit",
    learning_rate=2e-4,
    weight_decay=0.01,

    # المجدول
    warmup_ratio=0.03,
    lr_scheduler_type="linear",

    # الدقة
    bf16=True,

    # التسجيل
    logging_steps=10,
    save_steps=500,
)

استخدام قوالب المحادثة

لنماذج Instruct، استخدم قالب محادثة المُرمّز:

def format_chat(example):
    """نسّق باستخدام قالب محادثة النموذج."""
    messages = [
        {"role": "user", "content": example["instruction"]},
        {"role": "assistant", "content": example["output"]}
    ]
    text = tokenizer.apply_chat_template(messages, tokenize=False)
    return {"text": text}

dataset = dataset.map(format_chat)

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

مع Weights & Biases

import wandb
wandb.login()

training_args = TrainingArguments(
    ...
    report_to="wandb",
    run_name="unsloth-llama-finetune",
)

التسجيل اليدوي

# التدريب سيُظهر تقدم مثل:
# Step 10: loss=2.345
# Step 20: loss=1.987
# Step 30: loss=1.654
# ...

تحسين حجم الدفعة

اعثر على حجم الدفعة الأمثل لـ GPU:

# ابدأ صغيراً وزد
batch_sizes = [1, 2, 4, 8]

for bs in batch_sizes:
    try:
        # اختبر بخطوة واحدة
        trainer = SFTTrainer(
            model=model,
            args=TrainingArguments(
                per_device_train_batch_size=bs,
                max_steps=1,
                ...
            ),
            ...
        )
        trainer.train()
        print(f"حجم الدفعة {bs}: OK")
    except RuntimeError as e:
        if "out of memory" in str(e):
            print(f"حجم الدفعة {bs}: OOM")
            break

الأداء المتوقع

تدريب Llama 3.2 3B على 10K مثال:

المقياس قياسي Unsloth
الوقت لكل epoch 60 دقيقة 30 دقيقة
استخدام VRAM 12 GB 4 GB
خطوات/ثانية 2.5 5.0

استكشاف الأخطاء

الخسارة لا تتناقص

# تحقق من معدل التعلم
learning_rate = 2e-4  # جرّب 1e-4 أو 5e-5

# أضف إحماء
warmup_steps = 100

نفاد الذاكرة

# قلل حجم الدفعة
per_device_train_batch_size = 1
gradient_accumulation_steps = 16

# استخدم محسّن 8-bit
optim = "adamw_8bit"

تدريب بطيء

# عطّل التقييم أثناء التدريب
eval_strategy = "no"

# قلل تكرار التسجيل
logging_steps = 50

نصيحة: مع Unsloth، يمكنك تدريب نفس النموذج في نصف الوقت على نفس العتاد. هذا يعني تجارب أكثر وتكرار أسرع!

بعد ذلك، لنتعلم كيفية تصدير وتحويل نموذجنا المضبوط للنشر. :::

اختبار

الوحدة 4: التدريب مع Unsloth

خذ الاختبار