ریزتنظیم یک مدل زبانی زمانی تنها با خوشه‌های پردازشی پرهزینه ممکن بود. امروز با روشی به نام QLoRA می‌توان یک مدل کوچک را روی همان کارت گرافیک رایگانی که در Colab در دسترس است تنظیم کرد. در این راهنما، کل این مسیر را در حدود چهل خط کد مرور می‌کنیم.

چرا QLoRA این کار را ممکن می‌سازد

ریزتنظیم کامل یک مدل هفت‌میلیاردی به حدود ۱۴۰ گیگابایت حافظه نیاز دارد؛ کاری که مستلزم به‌کارگیری چندین کارت گرافیک در کنار یکدیگر است. روش LoRA این رقم را به حدود ۱۶ گیگابایت کاهش می‌دهد، چرا که به‌جای آموزش کل مدل، تنها چند ماتریس کوچک را آموزش می‌دهد و بدنه اصلی را ثابت نگه می‌دارد. روش QLoRA یک گام فراتر می‌رود: بدنه اصلی مدل را در دقت چهاربیتی فشرده می‌کند و همان ماتریس‌های کوچک را روی آن آموزش می‌دهد. در نتیجه، حافظه موردنیاز برای همان مدل هفت‌میلیاردی به حدود ۶ گیگابایت می‌رسد؛ حجمی که به‌راحتی روی یک کارت گرافیک معمولی و رایگان جا می‌شود. بهای این صرفه‌جویی نیز ناچیز است: سرعت آموزش کمی کاهش می‌یابد و کیفیت اندکی پایین‌تر می‌آید که برای بیشتر کاربردها کاملاً پذیرفتنی است.

مراحل گام‌به‌گام

کل این کار در چند مرحله خلاصه می‌شود: بارگذاری مدل پایه به‌صورت چهاربیتی، افزودن آداپتورهای LoRA، آماده‌سازی یک مجموعه داده کوچک، اعمال چند تنظیم کلیدی، و در نهایت آموزش.

from transformers import (AutoModelForCausalLM, AutoTokenizer,
                          BitsAndBytesConfig, TrainingArguments)
from peft import LoraConfig, get_peft_model
from trl import SFTTrainer
from datasets import load_dataset
import torch

model_name = "your-base-model"

# ۱. بارگذاری مدل پایه به‌صورت چهاربیتی (QLoRA)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_use_double_quant=True,
)
model = AutoModelForCausalLM.from_pretrained(
    model_name, quantization_config=bnb_config, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token

# ۲. افزودن بافت‌های LoRA
lora_config = LoraConfig(
    r=16, lora_alpha=32, target_modules="all-linear",
    lora_dropout=0.05, bias="none", task_type="CAUSAL_LM")
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()

# ۳. بارگذاری داده‌ها (داده خودتان را اینجا بگذارید)
dataset = load_dataset("your_dataset", split="train")

# ۴. تنظیمات آموزش
args = TrainingArguments(
    num_train_epochs=1,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=16,
    learning_rate=2e-4,
    lr_scheduler_type="cosine",
    warmup_ratio=0.03,
    fp16=True,
    gradient_checkpointing=True,
    logging_steps=10,
    output_dir="./out")

# ۵. آموزش و ذخیره
trainer = SFTTrainer(model=model, args=args,
                     train_dataset=dataset, max_seq_length=2048)
trainer.train()
model.save_pretrained("./my-lora-adapter")

تنظیمات کلیدی که باید بشناسید

در این کد، چند مقدار بیش از بقیه اهمیت دارند. رتبه (r) ابعاد ماتریس‌های آموزش‌دیده را مشخص می‌کند؛ مقدار r=16 نقطه شروع خوبی برای این کار است. مقدار آلفا (lora_alpha) معمولاً دو برابر رتبه در نظر گرفته می‌شود (یعنی 32). گزینه target_modules=“all-linear” بدین معناست که آداپتورها روی تمامی لایه‌های خطی اعمال شوند؛ رویکردی که امروزه به رویه‌ای متداول تبدیل شده است. نرخ یادگیری 2e-4 برای QLoRA مناسب است. همچنین در خصوص تعداد دوره‌های آموزش محتاط باشید: در بیشتر مواقع یک دوره کافی است و افزایش آن می‌تواند خطر بیش‌برازش را افزایش دهد.

ادغام و استنتاج

پس از آموزش، دو راه پیش رو دارید. می‌توانید آداپتور کوچک خود را که تنها چند ده مگابایت حجم دارد به‌صورت مجزا نگه دارید و در کنار مدل پایه بارگذاری کنید؛ این روش برای زمانی مناسب است که می‌خواهید چندین وظیفه مختلف را مدیریت کنید. همچنین می‌توانید آداپتور را با مدل پایه ادغام کنید تا مدلی یکپارچه با حداکثر سرعت اجرا به دست آید؛ این شیوه برای استقرار نهایی مناسب‌تر است. برای سنجش خروجی نیز کافی است مدل را در حالت ارزیابی قرار دهید، با یک پرامپت نمونه از آن خروجی بگیرید و نتیجه را با مدل پایه مقایسه کنید.

عیب‌یابی و رفع مشکلات رایج

سه مشکل رایج و راه‌حل آن‌ها به این شرح است: اگر با کمبود حافظه مواجه شدید، این مراحل را به ترتیب امتحان کنید: فعال‌سازی gradient checkpointing، کاهش اندازه دسته به یک و جبران آن با انباشت گرادیان، استفاده از حالت چهاربیتی، و در نهایت کوتاه‌تر کردن طول توالی. اگر مقدار خطا کاهش نمی‌یابد، نرخ یادگیری را کمی افزایش دهید و مطمئن شوید که آداپتورها به درستی اعمال شده‌اند. در نهایت، اگر خروجی مدل بی‌معنی شد، معمولاً علت آن بالا بودن بیش از حد نرخ یادگیری یا تعداد زیاد دوره‌های آموزش است. با تنظیم دقیق همین چند پارامتر، تقریباً تمامی مشکلات اولیه برطرف خواهند شد.