PEFT documentation
التكميم
التكميم
تمثل الكمية (Quantization) البيانات بعدد أقل من البتات، مما يجعلها تقنية مفيدة لتقليل استهلاك الذاكرة وتسريع الاستدلال (Inference)، لا سيما عند التعامل مع نماذج اللغة الكبيرة (LLMs). هناك عدة طرق لكمّية النموذج، بما في ذلك:
- تحسين الأوزان النموذجية التي يتم تكميمها باستخدام خوارزمية AWQ
- كمّ كل صف من مصفوفة الأوزان بشكل مستقل باستخدام خوارزمية GPTQ
- الكمّ إلى دقة 8 بت و4 بت باستخدام مكتبة bitsandbytes
- تكميم الدقة حتى 2 بت باستخدام خوارزمية AQLM
ومع ذلك، بعد تكميم النموذج، لا يتم تدريبه عادةً بشكل إضافي للمهام اللاحقة لأن التدريب قد يكون غير مستقر بسبب الدقة المنخفضة للأوزان والتفعيلات. لكن نظرًا لأن طرق PEFT تضيف فقط معلمات قابلة للتدريب إضافية، فإن هذا يتيح لك تدريب نموذج مكمّم مع مُكيّف PEFT فوقه! يمكن أن يكون دمج التكميم مع PEFT استراتيجية جيدة لتدريب حتى أكبر النماذج على وحدة معالجة رسومية واحدة. على سبيل المثال، QLoRA هي طريقة تكمّم النموذج إلى 4 بتات ثم تدربه باستخدام LoRA. تتيح لك هذه الطريقة ضبط نموذج يحتوي على 65 مليار معلمة على وحدة معالجة رسومية واحدة بسعة 48 جيجابايت!
في هذا الدليل، ستتعلم كيفية تكميم نموذج إلى 4 بتات وتدريبه باستخدام LoRA.
تكميم نموذج
bitsandbytes هو مكتبة للكمّية (Quantization) تتضمن تكاملاً مع Transformers. من خلال هذا التكامل، يمكنك كمّية النموذج إلى 8 أو 4 بتات، وتمكين العديد من الخيارات الأخرى عن طريق تكوين فئة BitsAndBytesConfig. على سبيل المثال، يمكنك:
- اضبط
load_in_4bit=Trueلتكميم النموذج إلى 4 بتات عند تحميله - اضبط
bnb_4bit_quant_type="nf4"لاستخدام نوع بيانات رباعي البت خاص للأوزان المُهيّأة من توزيع طبيعي - اضبط
bnb_4bit_use_double_quant=Trueلاستخدام مخطط تكميم متداخل لتكميم الأوزان المُكمَّمة مسبقًا - اضبط
bnb_4bit_compute_dtype=torch.bfloat16لاستخدام bfloat16 لحساب أسرع
import torch
from transformers import BitsAndBytesConfig
config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16,
)مرّر config إلى طريقة from_pretrained.
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1", quantization_config=config)في الخطوة التالية، يجب عليك استدعاء دالة prepare_model_for_kbit_training() لمعالجة النموذج المُكمَّم مسبقاً قبل التدريب.
from peft import prepare_model_for_kbit_training
model = prepare_model_for_kbit_training(model)الآن، وبما أن النموذج المُكمَّم جاهز، لنقم بإعداد تكوين.
LoraConfig
أنشئ LoraConfig بالباراميترات التالية (أو اختر ما يناسبك):
from peft import LoraConfig
config = LoraConfig(
r=16,
lora_alpha=8,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)ثم استخدم دالة get_peft_model() لإنشاء PeftModel من النموذج المُكمَّم والإعدادات.
from peft import get_peft_model
model = get_peft_model(model, config)لقد أصبحتَ مستعدًا تمامًا للتدريب باستخدام أي طريقة تدريب تفضلها!
تهيئة LoftQ
يُهيّئ LoftQ أوزان LoRA بحيث يتم تقليل خطأ التكميم، ويمكنه تحسين الأداء عند تدريب النماذج المكمّمة. للبدء، اتبع هذه التعليمات.
يُطبَّق LoftQ على طبقات الخطية فقط، بما في ذلك تلك المستهدفة عبر target_parameters. لا تُدعَم طبقات التضمين والطبقات التلافيفية، بل تُستخدم بدلاً من ذلك تهيئة LoRA الافتراضية. كما لا تُدعَم طبقات nn.MultiheadAttention وتُطلق خطأً.
بشكل عام، للحصول على أفضل أداء لـ LoftQ، يُوصى باستهداف أكبر عدد ممكن من الطبقات باستخدام LoRA، حيث لا يمكن تطبيق LoftQ على الطبقات غير المستهدفة. وهذا يعني أن تمرير LoraConfig(..., target_modules="all-linear") سيُحقق على الأرجح أفضل النتائج. كما ينبغي استخدام nf4 كنوع للتكميم في إعدادات التكميم الخاصة بك عند استخدام تكميم 4 بت، أي BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4").
بشكل عام، للحصول على أفضل أداء لـ LoftQ، يُوصى باستهداف أكبر عدد ممكن من الطبقات باستخدام LoRA، حيث لا يمكن تطبيق LoftQ على الطبقات غير المستهدفة. وهذا يعني أن تمرير LoraConfig(..., target_modules="all-linear") سيُحقق على الأرجح أفضل النتائج. كما ينبغي استخدام nf4 كنوع للتكميم في إعدادات التكميم الخاصة بك عند استخدام تكميم 4 بت، أي BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4").
هناك طريقتان مقصودتان حاليًا لتطبيق LoftQ:
- حمّل النموذج الأساسي غير المُكمَّم، وطبّق LoftQ بمستوى الكمّات المقصود (مثلًا
bits=4لـ nf4) ثم احفظ المُكيّف الناتج. بعد ذلك، قم بكمّ النموذج الأساسي باستخدام، على سبيل المثال،BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4")ثم حمّل المُكيّف المُهيّأ بواسطة LoftQ فوقه - تحميل النموذج الأساسي المُكمَّم، وتهيئة نموذج PEFT باستخدام LoRA (بدون loftq)، واستخدام
replace_lora_weights_loftqلتطبيق تهيئة LoftQ عن طريق بث أوزان المرجع للنموذج الأساسي غير المُكمَّم من ملف الأوزان (يُشرح ذلك بالتفصيل في القسم التالي)
استخدام replace_lora_weights_loftq لتطبيق LoftQ أثناء التشغيل
طريقة أسهل لكنها أكثر محدودية لتطبيق تهيئة LoftQ هي استخدام الدالة الميسّرة replace_lora_weights_loftq. تستقبل هذه الدالة نموذج PEFT المُكمَّم كمدخل، وتستبدل أوزان LoRA في مكانها بنظيراتها المُهيّأة بواسطة LoftQ.
from peft import replace_lora_weights_loftq
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(load_in_4bit=True, ...)
base_model = AutoModelForCausalLM.from_pretrained(..., quantization_config=bnb_config)
# note: don't pass init_lora_weights="loftq" or loftq_config!
lora_config = LoraConfig(task_type="CAUSAL_LM")
peft_model = get_peft_model(base_model, lora_config)
replace_lora_weights_loftq(peft_model)replace_lora_weights_loftq يتيح لك أيضًا تمرير معامل callback لمنحك مزيدًا من التحكم في الطبقات التي يجب تعديلها أو عدم تعديلها، وهو ما يمكن أن يحسّن النتائج بشكل كبير عمليًا. للاطلاع على مثال أكثر تفصيلًا حول ذلك، راجع هذا الدفتر.
replace_lora_weights_loftq ينفّذ خطوة تكرار واحدة فقط من LoftQ. وهذا يعني أن أوزان LoRA هي التي تُحدَّث فقط، بدلاً من التحديث التكراري لأوزان LoRA وأوزان النموذج الأساسي المُكمَّم. قد يؤدي ذلك إلى أداء أدنى، لكنه يحمل ميزة وهي إمكانية استخدام الأوزان المُكمَّمة الأصلية المشتقة من النموذج الأساسي، بدلاً من الحاجة إلى الاحتفاظ بنسخة إضافية من الأوزان المُكمَّمة المعدَّلة. يعتمد ما إذا كان هذا التنازل يستحق أم لا على حالة الاستخدام.
في الوقت الحالي، replace_lora_weights_loftq لديها هذه القيود الإضافية:
- يجب تخزين ملفات النموذج كملف
safetensors. - يُؤمَّن فقط تكميم 4 بت من قِبل مكتبة bitsandbytes.
التدريب بأسلوب QLoRA
تضيف QLoRA أوزانًا قابلة للتدريب إلى جميع الطبقات الخطية في بنية الترانسفورمر. نظرًا لأن أسماء الخصائص لهذه الطبقات الخطية قد تختلف بين البنى المعمارية، اضبط target_modules على "all-linear" لإضافة LoRA إلى جميع الطبقات الخطية:
config = LoraConfig(target_modules="all-linear", ...)كمّية GPTQ
يمكنك معرفة المزيد حول التكميم بعدد بتات [2, 3, 4, 8] القائم على GPTQ في GPT-QModel وفي وثائق GPTQ الخاصة بـ Transformers. يدعم PEFT التدريب اللاحق باستخدام GPTQ من خلال GPT-QModel.
# GPT-QModel install
pip install "gptqmodel>=7.0.0"from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_id = "facebook/opt-125m"
tokenizer = AutoTokenizer.from_pretrained(model_id)
gptq_config = GPTQConfig(bits=4, group_size=128, dataset="wikitext2", tokenizer=tokenizer)
quantized_model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=gptq_config)
# save quantized model
quantized_model.save_pretrained("./opt-125m-gptq")
tokenizer.save_pretrained("./opt-125m-gptq")بمجرد إجراء التكميم، يمكنك تدريب نماذج GPTQ ما بعد التدريب باستخدام واجهات PEFT البرمجية.
كمّية AQLM
تُعدّ الكمية الإضافية لنماذج اللغة (AQLM) طريقة لضغط نماذج اللغة الكبيرة. فهي تُكمّم أوزانًا متعددة معًا وتستفيد من التبعيات المتبادلة بينها. يُمثّل AQLM مجموعات من 8 إلى 16 وزنًا كمجموع لرموز متجهات متعددة. وهذا يتيح له ضغط النماذج حتى مستوى منخفض يبلغ 2 بت مع خسائر دقة منخفضة بشكل ملحوظ.
نظرًا لأن عملية تكميم AQLM مكلفة من الناحية الحسابية، يُوصى باستخدام النماذج المُكمَّمة مسبقًا. يمكن العثور على قائمة جزئية بالنماذج المتاحة في مستودع aqlm الرسمي repository.
تدعم النماذج ضبط مُكيّفات LoRA. لضبط النموذج المُكمَّم، ستحتاج إلى تثبيت مكتبة الاستدلال aqlm: pip install aqlm>=1.0.2. يجب حفظ مُكيّفات LoRA المُحسَّنة بشكل منفصل، إذ لا يمكن دمجها مع الأوزان المُكمَّمة بواسطة AQLM.
quantized_model = AutoModelForCausalLM.from_pretrained(
"BlackSamorez/Mixtral-8x7b-AQLM-2Bit-1x16-hf-test-dispatch",
dtype="auto", device_map="auto", low_cpu_mem_usage=True,
)
peft_config = LoraConfig(...)
quantized_model = get_peft_model(quantized_model, peft_config)يمكنك الرجوع إلى مثال Google Colab للحصول على نظرة عامة على ضبط النموذج باستخدام AQLM+LoRA.
كمّية EETQ
يمكنك أيضًا إجراء الضبط الدقيق باستخدام LoRA على النماذج المُكمّاة بتقنية EETQ. يوفر حزمة EETQ طريقة بسيطة وفعّالة لإجراء التكميم بدقة 8 بت، ويُزعم أنها أسرع من خوارزمية LLM.int8(). أولاً، تأكد من أنك تستخدم إصدارًا من transformers متوافقًا مع EETQ (مثلًا عن طريق تثبيته من أحدث إصدار على pypi أو من المصدر).
import torch
from transformers import EetqConfig
config = EetqConfig("int8")مرّر config إلى طريقة from_pretrained.
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1", quantization_config=config)وانشئ LoraConfig وقم بتمريره إلى get_peft_model:
from peft import LoraConfig, get_peft_model
config = LoraConfig(
r=16,
lora_alpha=8,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
model = get_peft_model(model, config)كمّية HQQ
تدعم النماذج المُكمّمة باستخدام كمّية نصف تربيعية لنماذج التعلم الآلي الكبيرة (HQQ) ضبط مُكيّفات LoRA. لضبط النموذج المُكمّم، ستحتاج إلى تثبيت مكتبة hqq باستخدام الأمر: pip install hqq.
from hqq.engine.hf import HQQModelForCausalLM
device = torch.accelerator.current_accelerator().type if hasattr(torch, "accelerator") else "cuda"
quantized_model = HQQModelForCausalLM.from_quantized(save_dir_or_hfhub, device=device)
peft_config = LoraConfig(...)
quantized_model = get_peft_model(quantized_model, peft_config)أو باستخدام إصدار من transformers متوافق مع HQQ (على سبيل المثال، عن طريق تثبيته من أحدث إصدار على pypi أو من المصدر).
from transformers import HqqConfig, AutoModelForCausalLM
quant_config = HqqConfig(nbits=4, group_size=64)
quantized_model = AutoModelForCausalLM.from_pretrained(save_dir_or_hfhub, device_map=device_map, quantization_config=quant_config)
peft_config = LoraConfig(...)
quantized_model = get_peft_model(quantized_model, peft_config)torchao (تحسين بنية PyTorch)
يدعم PEFT النماذج المُكمّمة باستخدام torchao (“ao”) لتكميم int8.
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM, TorchAoConfig
from torchao.quantization import Int8WeightOnlyConfig
model_id = ...
quantization_config = TorchAoConfig(quant_type=Int8WeightOnlyConfig())
base_model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=quantization_config)
peft_config = LoraConfig(...)
model = get_peft_model(base_model, peft_config)ملاحظات:
- استخدم أحدث إصدارات من torchao (>= v0.4.0) و transformers (> 4.42).
- يتم حاليًا دعم الطبقات الخطية فقط.
quant_type = "int4_weight_only"غير مدعوم حاليًا.- لم يتم تنفيذ
NF4في مكتبة transformers بعد، وبالتالي لا يُدعَم. - يعمل DoRA حاليًا فقط مع
quant_type = "int8_weight_only". - يوجد دعم صريح لـ torchao عند استخدامه مع LoRA. ومع ذلك، عندما يقوم torchao بتكميم طبقة، فإن فئتها لا تتغير، بل يتغير فقط نوع المصفوفة الأساسية. لهذا السبب، ستعمل بشكل عام طرق PEFT الأخرى غير LoRA مع torchao، حتى لو لم يكن هناك دعم صريح لها. لكن انتبه إلى أن الدمج يعمل بشكل صحيح فقط مع LoRA ومع
quant_type = "int8_weight_only". إذا استخدمت طريقة PEFT مختلفة أو نوع بيانات مختلف، فمن المرجح أن يؤدي الدمج إلى خطأ، وحتى لو لم يحدث خطأ، فستظل النتائج غير صحيحة.
تكميم INC
يتيح Intel Neural Compressor (INC) تكميم النماذج لأجهزة مختلفة، بما في ذلك معجلات Intel Gaudi (المعروفة أيضًا بأجهزة HPU). يمكنك إجراء ضبط دقيق باستخدام LoRA على النماذج التي تم تكميمها باستخدام INC. لاستخدام INC مع نماذج PyTorch، قم بتثبيت المكتبة عبر الأمر: pip install neural-compressor[pt]. يمكن تكميم النموذج بدقة FP8 لأجهزة HPU من خلال سير عمل التكميم بخطوة واحدة التالي:
import torch
from neural_compressor.torch.quantization import FP8Config, convert, finalize_calibration, prepare
quant_configs = {
...
}
config = FP8Config(**quant_configs)مرّر الإعداد إلى طريقة prepare، ثم نفّذ الاستدلال لجمع إحصاءات المعايرة، واستدعِ طريقتي finalize_calibration وconvert لتكميم النموذج بدقة FP8:
model = prepare(model, config)
# Run inference to collect calibration statistics
...
# Finalize calibration and convert the model to FP8 precision
finalize_calibration(model)
model = convert(model)
# Load PEFT LoRA adapter as usual
...يُقدَّم مثال يُظهر كيفية تحميل مُكيّف PEFT LoRA في نموذج FLUX لتوليد الصور من النص المُكمَّم بتقنية INC لأجهزة HPU هنا.
ملاحظات:
- لا يتم دعم طريقتي
merge()وunmerge()حاليًا للنماذج المُكمّاة بطريقة INC. - حاليًا، يتم دعم طبقات Linear المُكمّاة بطريقة INC فقط عند تحميل محولات PEFT.
طرق PEFT المدعومة الأخرى
بالإضافة إلى LoRA، تدعم طرق PEFT التالية التكميم:
- VeRA (يدعم تكميم bitsandbytes)
- AdaLoRA (يدعم كلًا من كميّات bitsandbytes وGPTQ)
- (IA)³ (يدعم تكميم bitsandbytes)
لورا لمحرك الترانسفورمر
يدعم PEFT مُكيّفات LoRA فوق طبقات NVIDIA Transformer Engine (te.pytorch.Linear، te.pytorch.LayerNormLinear، وte.pytorch.LayerNormMLP). تستخدم طبقات TE تنسيق FP8 والأنوية المدمجة لتسريع تدريب نماذج التحويل، وتتيح إرفاق مُكيّفات LoRA ضبطًا دقيقًا فعّالًا من حيث المعاملات للنماذج المُسرَّعة بواسطة TE.
from peft import LoraConfig, get_peft_model
config = LoraConfig(
r=8,
lora_alpha=16,
target_modules=["q_proj", "v_proj"],
task_type="TOKEN_CLS",
)
model = get_peft_model(te_model, config)عند تثبيت Transformer Engine، يقوم PEFT تلقائيًا بتوجيه الطبقات المطابقة إلى مُكيّف TeLinear — دون الحاجة إلى أي إعداد إضافي.
ملاحظات
merge()وunmerge()غير مدعومين بعدًا لطبقات TE.- لا يُدعم DoRA مع طبقات TE.
يتوفر مثال كامل لتصنيف الرموز لـ ESM2 تحت examples/lora_finetuning_transformer_engine/.
دمج المُكيِّفات في الأوزان المُكمَّمة
بالنسبة لأي طريقة تكميم تدعم ذلك، يقوم merge_adapter() بإلغاء تكميم الوزن الأساسي، وإضافة أوزان المُكيّف، ثم إعادة تكميم النتيجة. يقوم unmerge_adapter() بالشيء نفسه في الاتجاه المعاكس، لذا فهو لا يستعيد الأوزان المكمّمة الأصلية، كما أن تكرار دورات الدمج وإلغاء الدمج يمكن أن يؤدي إلى تراكم خطأ التقريب. لاستعادة الأوزان الأصلية، أعد تحميل النموذج الأساسي. للتبديل بين النموذج الأساسي والمُكيّف دون دمج، استخدم مدير السياق disable_adapter().
الخطوات التالية
إذا كنت مهتمًا بمعرفة المزيد حول التكميم، فقد تكون العناصر التالية مفيدة:
- تعرّف على مزيد من التفاصيل حول QLoRA واستعرض بعض المعايير المرجعية لتأثيره في منشور المدونة Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA.
- اقرأ المزيد حول مخططات التكميم المختلفة في دليل Quantization الخاص بـ Transformers.