چیت‌شیت

فاین‌تیونینگ با LoRA

Fine-Tuning with LoRA

افزودن تطبیق‌دهنده‌های LoRA، بارگذاری پایه‌ی 4-بیتی برای QLoRA، ماسک‌کردن لیبل‌های SFT، آموزش، merge و رفع اشکال. با PyTorch، PEFT و bitsandbytes.

  • ۱۲ بخش
  • ۴ درس مرتبط
  • کد و دستورها عیناً از دوره‌ی اصلی
فهرست مطالب
  1. وظایف
  2. مسیر LoRA در یک لایه
  3. LoRA از صفر
  4. QLoRA با PEFT
  5. یک گام آموزش SFT
  6. فرمول‌های کلیدی
  7. پیش‌فرض‌ها
  8. عیب‌یابی
  9. کوته‌نوشت‌ها
  10. پرسش‌ها
  11. نکات
  12. انتخاب روش

وظایف

کار و کد
وظیفهکد
افزودن LoRA به مدلmodel = get_peft_model(model, lora_config)
نمایش سهم پارامترهای آموزش‌پذیرmodel.print_trainable_parameters()
بارگذاری پایه‌ی 4-بیتیBitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4")
شمارش پارامترهای آموزش‌پذیرcount_parameters(model)
ذخیره‌ی فقط تطبیق‌دهندهmodel.save_pretrained("./lora-adapter")
merge کردن تطبیق‌دهنده در Wmerge_lora_weights(model)
نادیده‌گرفتن لیبل‌های ماسک‌شده در تابع زیان (loss)F.cross_entropy(..., ignore_index=ignore_index)
آموزش فقط-هدfreeze_body(model)

مسیر LoRA در یک لایه

معماری
mergeورودی xW منجمدout x inAr x in، مقداردهی گاوسیBout x r، مقداردهی صفرمقیاسalpha / rجمعWx + scaled BAxخروجی yW' مرج‌شدهW + (alpha/r) BA

LoRA از صفر

کد
python
class LoRALayer(nn.Module):
    def __init__(self, in_features, out_features, rank=8, alpha=16):
        super().__init__()
        self.scaling = alpha / rank                             # alpha / r
        self.A = nn.Parameter(torch.randn(in_features, rank) * (1 / math.sqrt(rank)))
        self.B = nn.Parameter(torch.zeros(rank, out_features))  # BA از صفر شروع می‌شود
    def forward(self, x):
        return (x @ self.A @ self.B) * self.scaling             # به‌روزرسانی کم‌رتبه با مقیاس

class LinearWithLoRA(nn.Module):
    # __init__ wraps linear and builds self.lora
        for param in self.linear.parameters():
            param.requires_grad = False                         # انجماد W
    def forward(self, x):
        return self.linear(x) + self.lora(x)                    # Wx + scaled BAx

QLoRA با PEFT

کد
python
bnb_config = BitsAndBytesConfig(load_in_4bit=True,  # پایه‌ی 4-بیتی
    bnb_4bit_quant_type="nf4",                      # سطوح NF4
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True)                 # کوانتیزه‌سازی مقیاس‌ها نیز
model = AutoModelForCausalLM.from_pretrained("<model>",
    quantization_config=bnb_config, device_map="auto")
lora_config = LoraConfig(task_type=TaskType.CAUSAL_LM, r=16,
    lora_alpha=32, lora_dropout=0.05,
    target_modules=["q_proj", "v_proj"])            # query و value
model = get_peft_model(model, lora_config)          # A و B را اضافه می‌کند
model.save_pretrained("./lora-adapter")             # تطبیق‌دهنده‌ی 10 تا 100 مگابایتی

یک گام آموزش SFT

گام‌به‌گام
  1. قالبهر جفت تبدیل می‌شود به <INST> instruction <RESP> response.
  2. توکنایزشناسه‌های بایتی به‌علاوه‌ی INST_ID = 256، RESP_ID = 257 و PAD_ID = 258.
  3. تجمیع (Collate)تابع sft_collate هر دسته را تا طولانی‌ترین توالی پد می‌کند.
  4. ماسکلیبل‌ها روی دستورالعمل، پدینگ و مرز مقدار -100 می‌گیرند.
  5. عبور مستقیم (Forward)مدل کل توالی، شامل دستورالعمل را می‌بیند.
  6. تابع زیان (Loss)تابع shifted_loss موقعیت i+1 را با ignore_index=-100 پیش‌بینی می‌کند.
  7. گامAdam بدنه را به‌روزرسانی می‌کند. ارزیابی تطابق دقیق هر پنج دوره اجرا می‌شود.

فرمول‌های کلیدی

مفهوم‌ها
عبور مستقیم LoRA
فرمول $y = Wx + BAx$ با منجمد بودن $W$.
به‌روزرسانی با مقیاس
$y = Wx + \frac{\alpha}{r} \cdot BAx$
تعداد پارامترها
رتبه‌ی $r$ به‌جای $d^2$ تعداد $2 \cdot r \cdot d$ پارامتر آموزش می‌دهد.
مثال
رتبه‌ی $r=16$ روی ابعاد 4096x4096 تعداد 131٬072 از 16٬777٬216 پارامتر را آموزش می‌دهد؛ یعنی 0.78%.
Merge
فرمول $W' = W + (\alpha/r) \cdot BA$. هم‌اندازه، بدون سربار در استنتاج.
حافظه‌ی فاین‌تیونینگ کامل
مدل 8B در fp16 حدود 56 گیگابایت با گرادیان‌ها و حالت‌های Adam مصرف می‌کند.

پیش‌فرض‌ها

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
r16شروع مطمئن برای اغلب وظایف
lora_alpha322 برابر رتبه؛ alpha = rank محافظه‌کارانه است
lora_dropout0.050.1 برای کمتر از 5K نمونه
target_modulesq_proj, v_projافزودن بیشتر فقط در صورت پایین بودن کیفیت
QLoRA learning rate2e-4بالاتر از فاین‌تیونینگ کامل
LoRA fp16 learning rate5e-5پایین‌تر از QLoRA
Full SFT learning rate2e-5مدل Llama 2 Chat، 15 برابر کمتر از پیش‌آموزش
Epochs1-3مقادیر بیشتر خطر بیش‌برازش دارد

عیب‌یابی

عیب‌یابی
  • مقادیر NaN در تابع زیان مدل‌های Llama

    علت
    توکن پد تعیین نشده است
    راه‌حل
    توکن پد را تنظیم کنید
  • تابع زیان (loss) کاهش نمی‌یابد

    علت
    نرخ یادگیری برای LoRA بسیار پایین است
    راه‌حل
    مقدار 2e-4 را امتحان کنید
  • کاهش تابع زیان اما کیفیت ارزیابی ضعیف

    علت
    بیش‌برازش
    راه‌حل
    دوره‌های کمتر، دراپ‌اوت بیشتر، داده‌های بیشتر
  • عملکرد ضعیف در وظایف پیچیده

    علت
    رتبه بسیار پایین است یا لایه‌های هدف نامناسب‌اند
    راه‌حل
    امتحان r=32 یا افزودن لایه‌های MLP
  • افت مهارت‌های عمومی پس از SFT

    علت
    نرخ یادگیری بسیار بالا است
    راه‌حل
    استفاده از 1e-5 تا 5e-5 و 1 تا 3 دوره آموزش
  • مدل دستورالعمل را پیش‌بینی می‌کند

    علت
    ماسک تابع زیان اعمال نشده
    راه‌حل
    تنظیم مقدار -100 روی دستورالعمل و پدینگ
  • خطای کمبود حافظه (OOM) روی توالی‌های طولانی

    علت
    حالت‌های بهینه‌ساز بیش از حافظه‌ی گرافیکی است
    راه‌حل
    استفاده از optim="paged_adamw_8bit"

کوته‌نوشت‌ها

اصطلاح‌ها
LoRA
انطباق کم‌رتبه (Low-Rank Adaptation). منجمد کردن W و آموزش A و B.
QLoRA
نسخه‌ی کوانتیزه‌شده‌ی LoRA. پایه‌ی 4-بیتی NF4 با تطبیق‌دهنده‌های fp16.
NF4
فرمت Normal Float 4. شانزده سطح در چندک‌های نرمال.
PEFT
کتابخانه‌ی هاگینگ‌فیس برای LoRA، QLoRA، DoRA و IA3.
TRL
ترینرهای هاگینگ‌فیس برای SFT، DPO، GRPO، PPO و ORPO.
SFT
فاین‌تیونینگ تحت نظارت روی جفت‌های دستورالعمل و پاسخ.
ChatML
قالب نقش‌ها با توکن‌های <|im_start|> و <|im_end|>.
کوانتیزه‌سازی دوگانه
کوانتیزه‌کردن مقیاس‌های هر بلوک به fp8.

پرسش‌ها

پرسش و پاسخ
چرا B در ابتدا صفر است؟
ضرب BA از صفر شروع می‌شود؛ آموزش از رفتار مدل اصلی آغاز می‌گردد.
کاربرد alpha چیست؟
فارغ از نرخ یادگیری پایه، به‌روزرسانی را با نسبت alpha / r مقیاس‌دهی می‌کند.
Merge یا نگهداری مجزا؟
مجزا برای سرویس‌دهی به چندین وظیفه؛ merge برای یک مدل واحد.
چرا دستورالعمل ماسک می‌شود؟
بدون ماسک، مدل پیش‌بینی دستورالعمل را می‌آموزد و سیگنال پاسخ تضعیف می‌شود.
چه زمانی فاین‌تیون نکنیم؟
وقتی مهندسی پرامپت جواب می‌دهد، داده‌های دانشی لازم است (استفاده از RAG) یا کمتر از 500 نمونه دارید.

نکات

نکته‌ها
  • ابتدا مهندسی پرامپت را امتحان کنید، سپس RAG و در نهایت فاین‌تیونینگ.
  • هر 100 گام روی مجموعه‌ی نگه‌داشته‌شده ارزیابی کنید. بهترین چک‌پوینت را نگه دارید.
  • مدل پایه با پرامپت را در برابر مدل پایه با LoRA روی بیش از 200 نمونه‌ی نگه‌داشته‌شده مقایسه کنید.
  • با 800 نمونه، فقط هد را با بدنه‌ی منجمد آموزش دهید.
  • تابع زیان متن خام را رصد کنید؛ افزایش بیش از 10 تا 15 درصد نشانه‌ی شدت بیش‌ازحد SFT است.

انتخاب روش

دستورها
Choiceکاربرد در شرایط
Full fine-tune, about 56GB for 7Bحافظه‌ی گرافیکی >= 2 برابر حجم مدل در fp16
LoRA on fp16 base, about 18GBحافظه‌ی گرافیکی >= حجم مدل در fp16
QLoRA on 4-bit base, about 6GBحافظه‌ی گرافیکی >= یک‌چهارم حجم مدل
r=16وظایف چندحوزه‌ای، پیروی از دستورالعمل، چت
r=32تولید کد، استدلال پیچیده، ریاضیات