انتقل إلى المحتوى الرئيسي

الوحدة 6 — QLoRA والتكميم بأربعة بتّات

LoRA خفّض معاملات التدريب، لكن أوزان النموذج الأصلي ما زالت تشغل الذاكرة بحجمها الكامل: 14 غيغا لنموذج بسبعة مليارات في FP16. لكي يعمل الضبط على بطاقة استهلاكية بسعة 24 غيغا، لا بدّ من ضغط هذه الأوزان أيضًا. هذا ما يفعله QLoRA، اقتراح 2023 من ورقة Dettmers وآخرين.

المبدأ العام

QLoRA يجمع تقنيتين:

  1. تكميم أوزان النموذج الأصلي إلى 4 بتّات بدل 16. الوزن يحفظ بأربعة بتّات بدل ستّة عشر، أي تقليل الحجم بأربعة.
  2. تدريب محوّلات LoRA بدقّة عادية فوق هذا النموذج المُكمَّم. المحوّلات تبقى في BF16 لكنّها صغيرة جدًّا.

النموذج بسبعة مليارات يشغل الآن 3.5 غيغا فقط (بدل 14)، مما يجعل بطاقة واحدة بسعة 24 غيغا كافية للتدريب مع دفعة معقولة.

صيغة NF4 (NormalFloat 4-bit)

التكميم البسيط إلى 4 بتّات (16 قيمة ممكنة موزَّعة بانتظام) يفقد جودة كبيرة. QLoRA يستعمل صيغة أذكى: NF4، صيغة مصمَّمة خصّيصًا لأوزان الشبكات العصبية.

الحدس: أوزان الشبكات العصبية تتوزَّع تقريبًا كتوزيع طبيعي مركَّز حول الصفر. NF4 يوزّع نقاطه الستّة عشر بحيث تكون مكافئة الاحتمال ضمن هذا التوزيع: كثيفة قرب الصفر، متفرّقة عند الأطراف. النتيجة: خطأ التكميم أقلّ بكثير من التكميم الخطّي.

هذا يعني عمليًّا أنّ نموذج مُكمَّم بـNF4 يفقد أقلّ من نقطتين مئويّتين من الأداء مقارنة بالنموذج الأصلي، وفي كثير من الحالات أقلّ من نقطة واحدة.

التكميم المزدوج (Double Quantization)

تفصيل ثانٍ: كلّ كتلة من أوزان النموذج المُكمَّم تحتاج إلى ثابت تحجيم (scale factor) خاصّ بها. هذه الثوابت نفسها تشغل ذاكرة. على نموذج بسبعة مليارات، ثوابت التحجيم في FP32 تشغل نحو 800 ميغا بايت.

الحلّ: كمِّم الثوابت نفسها بـ8 بتّات. هذا يوفّر نحو 600 ميغا إضافية، بلا أثر يُذكر على الجودة. اسمه الرسمي «التكميم المزدوج».

مُستمثِل الصفحات (Paged Optimizer)

المشكلة الثالثة: حتّى مع LoRA، بعض العمليات (تحديث الحالات، الانتشار الخلفي في الطبقات الكبيرة) تُنتج قممًا مؤقّتة في استهلاك الذاكرة تُفجّر البطاقة. مُستمثِل الصفحات يحلّها بإدارة ذكية للذاكرة: تُنقَل الحالات المؤقّتة إلى RAM النظام عند الحاجة، وتُعاد إلى GPU عند الاستعمال.

هذه الآلية مبنية في bitsandbytes وتُفعَّل تلقائيًّا حين تختار AdamW8bit أو PagedAdamW.

التهيئة الكاملة على 24 غيغا

الوصفة العملية لضبط Llama-3 8B على RTX 4090 (24 غيغا):

from transformers import AutoModelForCausalLM, BitsAndBytesConfig
import torch

bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16,
)

model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Meta-Llama-3-8B",
quantization_config=bnb_config,
device_map="auto",
)

ثمّ إعداد PEFT كما في الوحدة السابقة:

from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model

model = prepare_model_for_kbit_training(model)

config = LoraConfig(
r=16,
lora_alpha=32,
target_modules="all-linear",
lora_dropout=0.05,
task_type="CAUSAL_LM",
)

model = get_peft_model(model, config)

الدالّة prepare_model_for_kbit_training تُفعّل تحديد التدرّج الاختياري (gradient checkpointing) وتعيّن الطبقات التي يجب أن تبقى في FP32 لأسباب عددية (مثل layer norms).

قياس ذاكرة الضبط الفعلي

على مثالنا (Llama-3 8B، r=16، دفعة 4، طول 2048):

العنصرذاكرة تقديرية
أوزان في NF44.2 غيغا
محوّلات LoRA0.2 غيغا
تدرّجات (LoRA فقط)0.2 غيغا
حالات المُستمثِل (Paged AdamW 8-bit)0.4 غيغا
تفعيلات (مع checkpointing)8-10 غيغا
هوامش وأنظمة CUDA2-3 غيغا
المجموع~18 غيغا

هامش 6 غيغا يسمح بزيادة الدفعة أو طول التسلسل قليلًا. النتيجة: التدريب ممكن على بطاقة بأقلّ من 2000 دولار في 2026.

الفجوة في الجودة مع LoRA

السؤال الطبيعي: كم نخسر مقارنة بـLoRA على أوزان BF16 كاملة؟ الأبحاث تُشير إلى فجوة ضيّقة جدًّا: بين 0.5 و2 نقطة على المقاييس الشائعة (MMLU، BBH). في مهامّ محدّدة الصيغة كحالتنا (محاضر منظّمة)، الفجوة عادة أقلّ من واحد بالمئة، وتختفي كلّيًّا مع بيانات كافية.

القاعدة: إذا كانت البطاقة تسمح بـLoRA عادي، فاستعمله. لكن حين الميزانية ضيّقة، QLoRA خيار ممتاز بفارق جودة مقبول جدًّا.

متى لا يعمل QLoRA؟

  • نماذج صغيرة جدًّا (أقلّ من مليار): مكسب الذاكرة لا يستحقّ فقدان الجودة، ويكفي LoRA عادي.
  • مهامّ حسّاسة للدقّة العددية: توليد كود دقيق أو حساب رياضي معقّد قد يعاني من التكميم.
  • عتاد قديم: بعض بطاقات ما قبل A100 لا تدعم عمليات bnb بكفاءة.
حِيلَة إضافية: FlashAttention-2

عند تفعيل attn_implementation="flash_attention_2" مع QLoRA، يمكن رفع طول التسلسل من 2048 إلى 4096 أو 8192 على البطاقة نفسها. للتفريغات الطويلة (اجتماعات ساعتين)، هذا فرق حاسم.

تحذير حول dtype المحوّل

احتفظ بـbnb_4bit_compute_dtype=torch.bfloat16 على بطاقات NVIDIA الحديثة. استعمال FP16 هنا يؤدّي إلى عدم استقرار عددي (خسارة NaN) في المشاريع الحقيقية.

الخلاصة

  • QLoRA يضغط أوزان النموذج الأصلي إلى 4 بتّات (NF4) ويدرّب محوّلات LoRA فوقها في BF16.
  • NF4 وتكميم مزدوج ومُستمثِل صفحات: ثلاث حِيَل تخفّض الفاتورة بأربعة أضعاف على الأقلّ.
  • التهيئة النموذجية تسمح بضبط Llama-3 8B على بطاقة 24 غيغا واحدة.
  • الفجوة في الجودة مع LoRA الكامل صغيرة (أقلّ من نقطتين) وتختفي غالبًا في المهامّ محدّدة الصيغة.

في الوحدة التالية: المعاملات الفائقة (معدّل التعلّم، الحقب، حجم الدفعة، طول التسلسل) وكيف تختار قيمًا افتتاحية معقولة.