المستوى: محترف.
لو بتحاول تشغّل Llama 70B على GPU واحد بـ 24GB VRAM، الـ vanilla model مش هيتحمّل أصلاً. الموديل في FP16 محتاج 140GB ذاكرة. Quantization بيخلّيه يدخل في 22GB بفقد دقة 1.2% بس على MMLU. الفرق بين 4 × A100 (80GB) على AWS و RTX 4090 واحد على vast.ai هو 280 ألف دولار في السنة بدل 4 آلاف.
الفكرة باختصار
Quantization مش حذف معلومات. هو إعادة تمثيل الأوزان بدقة أقل. بدل ما الـ weight يتخزّن كـ float 16-bit، بيتخزّن كـ integer 4-bit مع scale factor صغير. النتيجة: 4× تقليل في الذاكرة، 2-3× زيادة في سرعة الاستنتاج، فقد دقة محدود لو استخدمت technique مناسب.
مثال للمبتدئ: ضغط الصور
تخيّل عندك صورة RAW حجمها 50MB. لو حفظتها JPEG عالية الجودة، بقت 5MB، والعين البشرية مش هتفرّق. لو حفظتها JPEG منخفضة، بقت 500KB لكن فيها تشويه واضح. Quantization نفس المنطق بالظبط: بتختار النقطة اللي بين توفير الذاكرة وفقد الدقة. INT8 زي JPEG عالية الجودة، INT4 زي JPEG متوسطة، INT2 زي JPEG رديئة. الفرق إن في الموديل الذكي، الجودة بتُقاس بـ MMLU وHellaSwag، مش بالعين.
التعريف العلمي الدقيق
Quantization هو mapping من تمثيل عالي الدقة (FP16) إلى تمثيل منخفض الدقة (INT8, INT4, INT2) باستخدام معادلة linear تقريبية:
# w_quantized = round(w / scale) + zero_point
# w_dequantized = (w_quantized - zero_point) * scale
# scale = (w_max - w_min) / (q_max - q_min)
# zero_point = round(q_min - w_min / scale)
الفكرة: لكل block من الأوزان (مثلاً 64 weight)، احسب min و max، ثم اعمل scale يخلّيهم يتمثّلوا في 4-bit (16 قيمة بس). الورقة الأصلية لـ GPTQ من Frantar وزملاؤه (ICLR 2023) أظهرت إن INT4 quantization على Llama-13B بيخلي accuracy على MMLU ينزل من 50.3% لـ 49.1% فقط — ده فقد 1.2 نقطة مقابل تقليل ذاكرة 4×.
المثال التنفيذي: Llama 70B على RTX 4090
هنستخدم bitsandbytes مع NF4 quantization من Hugging Face. الكود ده بيشتغل فعلاً على RTX 4090 (24GB) من غير modifications:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
quant_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_quant_type="nf4", # NormalFloat 4-bit, Dettmers 2023
bnb_4bit_use_double_quant=True, # quantize scale factors too
)
model_id = "meta-llama/Llama-3.1-70B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=quant_config,
device_map="auto",
torch_dtype=torch.bfloat16,
)
prompt = "اكتب function في Python بتحسب factorial بـ recursion"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
out = model.generate(**inputs, max_new_tokens=256, do_sample=False)
print(tokenizer.decode(out[0], skip_special_tokens=True))