استخدام LoRA و QLoRA لتخفيف استهلاك كرت الشاشة أثناء تدريب النماذج
استخدام LoRA و QLoRA لتخفيف استهلاك كرت الشاشة أثناء تدريب النماذج
عند الوصول إلى مرحلة الضبط الدقيق للنماذج اللغوية الكبيرة، تظهر المشكلة الهندسية الأهم: استهلاك ذاكرة كرت الشاشة VRAM. فالتدريب الكامل Full Fine-Tuning يعني تحديث جميع أوزان النموذج، وهذا يرفع تكلفة الذاكرة بسبب تحميل المعاملات الأصلية، وتخزين التدرجات Gradients، وحالات المحسن Optimizer States. هنا ظهرت تقنيات مثل LoRA ونسختها الأكثر كفاءة QLoRA لتجعل تدريب النماذج الكبيرة ممكناً حتى على بطاقات متوسطة.
إذا كنت قد قرأت سابقاً مقال تجهيز مجموعة بيانات (Dataset) لتدريب نموذج مخصص لخدمة عملاء شركتك، فهذه المرحلة هي الامتداد العملي المباشر: كيف نستخدم البيانات مع أقل ضغط ممكن على العتاد.
ما المشكلة الفعلية في استهلاك الذاكرة أثناء التدريب؟
في أي نموذج Transformer، كل طبقة تحتوي مصفوفات أوزان ضخمة داخل وحدات مثل Attention و Feed Forward. عند التدريب الكامل، لا يكفي تخزين الأوزان فقط، بل يجب أيضاً حفظ:
- نسخة الأوزان المستخدمة في المرور الأمامي
Forward Pass. - التدرجات لكل وزن أثناء
Backward Pass. - حالات المحسن مثل المتوسطات المتحركة في
AdamW. - الـ
Activationsالوسيطة اللازمة لحساب الاشتقاقات.
لهذا قد يتطلب نموذج بحجم 7 مليار معلمة عشرات الجيجابايت من VRAM إذا تم تدريبه تقليدياً. هندسياً، هذا غير مناسب لمعظم المطورين، خصوصاً عند بناء حلول محلية مرتبطة بـ النماذج مفتوحة المصدر أو عند تشغيل النماذج مع Llama 3 أو Mistral محلياً.
ما هي فكرة LoRA هندسياً؟
LoRA اختصار Low-Rank Adaptation. الفكرة الأساسية ليست تحديث المصفوفة الضخمة الأصلية W مباشرة، بل تجميدها بالكامل، ثم إضافة تصحيح صغير قابل للتدريب يمثل فرق التخصيص المطلوب.
بدلاً من تعلم تحديث كامل ΔW بحجم ضخم، يتم تقريب هذا التحديث إلى حاصل ضرب مصفوفتين صغيرتين منخفضتي الرتبة:
ΔW = A × B
حيث تكون قيمة rank r صغيرة مثل 8 أو 16 أو 32. هذا يعني أننا لا ندرّب إلا عدداً قليلاً جداً من المعاملات مقارنة بالنموذج الكامل.
كيف يمر تدفق البيانات داخل الطبقة؟
في الوضع التقليدي، الطبقة تحسب:
y = W x
مع LoRA تصبح:
y = W x + (A × B) x
الأوزان الأصلية تبقى ثابتة، بينما التحديث يحدث فقط داخل المصفوفتين الصغيرتين. النتيجة: انخفاض كبير في الذاكرة المطلوبة للتدريب، مع الحفاظ على جودة جيدة جداً في مهام التخصيص مثل المحادثة، التصنيف، إعادة الصياغة، أو توليد أسلوب كتابي خاص.
ما الذي يضيفه QLoRA فوق LoRA؟
QLoRA يذهب خطوة أبعد: لا يكتفي بتجميد الأوزان الأساسية، بل يقوم أيضاً بتحميل النموذج نفسه بشكل مكمم Quantized عادة بدقة 4-bit عبر مكتبة bitsandbytes. ثم يضيف طبقات LoRA القابلة للتدريب فوق هذا الأساس المضغوط.
معمارياً، التسلسل يكون كالتالي:
- تحميل الأوزان الأساسية بصيغة مكممة لتقليل استهلاك الذاكرة.
- إبقاء هذه الأوزان مجمدة.
- حقن وحدات
LoRAفي طبقات مستهدفة مثلq_projوv_proj. - تدريب هذه الإضافات الصغيرة فقط.
لهذا أصبح بالإمكان ضبط نماذج كانت تتطلب سابقاً عتاداً احترافياً باستخدام بطاقات مثل 16GB أو 24GB في كثير من الحالات.
متى أستخدم LoRA ومتى أستخدم QLoRA؟
- استخدم
LoRAإذا كانت لديك ذاكرة جيدة وتريد بساطة أعلى في التدريب. - استخدم
QLoRAإذا كان هدفك الأقصى هو تقليلVRAMمع الاحتفاظ بأداء قوي. - في مشاريع الشركات الصغيرة أو المختبرات الفردية، غالباً يكون
QLoRAالخيار العملي الأول.
خطوات تنفيذ QLoRA باستخدام transformers و peft
قبل التنفيذ، من المفيد مراجعة مقال إعداد بيئة العمل الذكية لأن نجاح التدريب يعتمد على توافق الإصدارات والمكتبات.
1) تثبيت المكتبات
pip install transformers datasets peft accelerate bitsandbytes trl
2) تحميل النموذج مع التكميم
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
model_name = "mistralai/Mistral-7B-v0.1"
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype="bfloat16"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto"
)
3) حقن إعدادات LoRA
from peft import LoraConfig, get_peft_model
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
4) مثال تهيئة بيانات التدريب
from datasets import Dataset
data = {
"text": [
"السؤال: ما هي سياسة الإرجاع؟\nالإجابة: يمكن الإرجاع خلال 14 يوماً مع الفاتورة.",
"السؤال: هل يوجد شحن دولي؟\nالإجابة: نعم، الشحن الدولي متاح لعدد محدد من الدول."
]
}
dataset = Dataset.from_dict(data)
5) صياغة نمط التعليمات
أنت مساعد متخصص في الردود المؤسسية. أجب بدقة وبأسلوب مهني مختصر، واعتمد فقط على نبرة خدمة العملاء المحددة داخل بيانات التدريب.
هذا النوع من التعليمات يرتبط بما شرحناه سابقاً في هندسة الأوامر داخل الكود، لكن هنا يتم ترسيخ السلوك عبر التدريب نفسه لا عبر البرومبت فقط.
6) إعداد التدريب
from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
output_dir="./qlora-output",
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
num_train_epochs=3,
learning_rate=2e-4,
fp16=True,
logging_steps=10,
save_strategy="epoch",
optim="paged_adamw_8bit"
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset
)
trainer.train()
كيف نقلل الذاكرة أكثر أثناء التدريب؟
- تقليل
batch sizeمع استخدامgradient_accumulation_steps. - استهداف طبقات أقل داخل
LoRAلتقليل المعاملات القابلة للتدريب. - استخدام
sequence lengthمناسب، لأن طول السياق يرفع الذاكرة بشكل مباشر. - تفعيل
gradient checkpointingإذا دعمه النموذج.
هل LoRA بديل عن RAG؟
ليس دائماً. إذا كانت المشكلة هي حقن معرفة متغيرة باستمرار، فغالباً يكون دمج المعلومات المسترجعة مع الـ LLM أفضل من تدريب النموذج على كل تحديث. أما إذا كنت تريد تعديل الأسلوب، النبرة، شكل الإجابة، أو تكييف النموذج مع تعليمات متكررة في مجال ضيق، فـ LoRA و QLoRA أكثر منطقية.
أخطاء شائعة يجب تجنبها
- الاعتقاد أن
QLoRAيلغي الحاجة إلى بيانات نظيفة؛ الحقيقة أن جودةDatasetما زالت العامل الحاسم. - اختيار قيمة
rankكبيرة جداً دون داعٍ، ما يرفع الذاكرة ويزيد خطرoverfitting. - تدريب النموذج على نصوص غير متجانسة في الأسلوب أو المهمة.
- عدم اختبار النموذج بعد التدريب باستخدام عينات تقييم منفصلة.
الخلاصة الهندسية
LoRA يقلل تكلفة الضبط الدقيق عبر تجميد الأوزان الأساسية وتدريب تحديثات منخفضة الرتبة فقط. أما QLoRA فيضيف فوق ذلك تكميم النموذج إلى 4-bit، ما يجعل تدريب نماذج كبيرة ممكناً على عتاد أقل بكثير. لهذه الأسباب أصبحت هاتان التقنيتان من أهم أدوات مهندس LLM الحديث، خصوصاً عند بناء أنظمة مخصصة أو نماذج محلية مرتبطة بتطبيقات LangChain، أو خطوط الذكاء الاصطناعي المحلية الخاصة، أو حلول هجينة تجمع بين التخصيص وEmbeddings وVector Databases.