Квантование LLM: полное руководство по снижению точности ради производительности
Введение: почему квантование стало мейнстримом
Большие языковые модели 2024-2026 годов требуют несоразмерно много памяти. Модель Llama 3 70B в FP16 занимает 140 ГБ — больше, чем VRAM даже топовых серверных GPU. Квантование — техника снижения разрядности чисел — позволяет уместить 70B модель в 24 ГБ VRAM с минимальной потерей качества.
В 2023 году квантование было нишевой темой для энтузиастов. В 2026 году это обязательный этап деплоя LLM. vLLM, llama.cpp, TensorRT-LLM — все основные движки поддерживают квантованные модели. Но какой формат выбрать, сколько бит нужно и не убьёт ли INT8 качество модели?
Данное руководство проходит от теории к практике: от математики квантования до конкретных команд для генерации GGUF и загрузки в vLLM.
Основы — что происходит с числами при квантовании
От FP16 к INT4: путь сокращения разрядности
Стандартная модель в FP16 использует 16 бит на параметр. 70B параметров × 2 байта = 140 ГБ.
| Формат | Бит на параметр | 7B модель | 13B модель | 70B модель |
|---|---|---|---|---|
| FP32 | 32 | 280 ГБ | 560 ГБ | 2.8 ТБ |
| FP16 / BF16 | 16 | 140 ГБ | 260 ГБ | 140 ГБ |
| FP8 | 8 | 70 ГБ | 130 ГБ | 70 ГБ |
| INT8 | 8 | 70 ГБ | 130 ГБ | 70 ГБ |
| NF4 | 4 | 35 ГБ | 65 ГБ | 35 ГБ |
| INT4 | 4 | 35 ГБ | 65 ГБ | 35 ГБ |
| INT2 | 2 | 17 ГБ | 32 ГБ | 17 ГБ |
Ключевая идея: квантование — это отображение диапазона значений из высокого пространства в низкое. FP16 диапазон [-65504, 65504] сближается до 16 значений INT4 [-8, 7].
Математика линейного квантования
Простейшая формула:
quantized_value = round(float_value / scale) + zero_point
Где:
- scale — коэффициент масштабирования (сколько FP16 единиц в одном INT4)
- zero_point — смещение, позволяющее точно представить ноль
Обратное преобразование (деквантование):
float_value = (quantized_value - zero_point) * scale
Это означает, что деквантование — это просто умножение на скаляр и сдвиг. Обе операции крайне быстры на любом GPU/CPU.
Типы квантования в контексте LLM
Пер-тензорное (per-tensor): один scale для всего тензора весов. Быстро, но грубо. Подходит для FP8.
Пер-каналовое (per-channel): свой scale для каждого канала (строки или столбца матрицы). Точнее, но больше накладных расходов. Используется в AWQ и GPTQ.
Пер-блокное (per-block / per-group): scale для группы из N параметров. Например, per-token с group_size=128. Золотая середина между точностью и эффективностью. Используется в GGUF (Q4_K_M) и AWQ.
Основные методы квантования LLM
GGUF / llama.cpp (Q4_K_M, Q5_K_M, Q6_K)
Формат GGUF — де-факто стандарт для локального запуска на CPU и Apple Silicon. llama.cpp использует собственную систему квантования с группировкой.
| Тег | Описание | Бит/параметр | 7B размер | Качество |
|---|---|---|---|---|
| Q2_K | Экстремальное сжатие | ~2.5 | 17 ГБ | Низкое, галлюцинации |
| Q3_K_M | Среднее сжатие | ~3.3 | 24 ГБ | Среднее |
| Q4_0 | Базовое 4-бит | 4.0 | 3.5 ГБ | Хорошее |
| Q4_K_M | Комбинированное 4-бит | ~4.5 | 3.9 ГБ | Очень хорошее |
| Q5_0 | Базовое 5-бит | 5.0 | 4.5 ГБ | Отличное |
| Q5_K_M | Комбинированное 5-бит | ~5.5 | 4.8 ГБ | Отличное |
| Q6_K | 6-бит | 6.1 | 5.7 ГБ | Практически без потерь |
Особенность Q4_K_M: смешивает 4-бит и 6-бит квантование. Важные слои (attention, output) остаются в Q6_K, а менее критичные — в Q4. Результат: качество Q5_K_M при размере Q4_K_M.
AWQ (Activation-aware Weight Quantization)
AWQ 2023 года — метод, который учитывает влияние весов на выходные активации. Не все веса одинаково важны: некоторые каналы влияют на качество сильнее других.
Алгоритм AWQ:
- Пропустить обучающую выборку через модель в FP16
- Измерить чувствительность каждого канала к квантованию
- Каналы с высокой чувствительностью оставить в FP16 (или INT8)
- Остальные каналы квантовать до INT4
Результат: AWQ-модели часто превосходят GGUF Q4_K_M по качеству при том же размере.
GPTQ (Generative Post-Training Quantization)
GPTQ от Intel (2022) — оптимизация по второму порядку. Использует матрицу Хаара для учёта корреляций между весами.
Преимущества GPTQ:
- Лучшее качество при 4-битном квантовании
- Широкая поддержка в ExLlamaV2 и TheBloke моделах
- Статическое квантование — нет накладных расходов при инференсе
Недостатки:
- Длительный процесс квантования (часы на GPU)
- Требует обучающую выборку для калибровки
- Не поддерживает смешанную точность так гибко, как GGUF
NF4 (Normal Float 4-bit)
NF4 — формат от DeepSpeed/Intel (2024), использующий 4-битные значения, распределённые по нормальному распределению.
Почему NF4 лучше INT4? Потому что веса нейросетей распределены близко к нормальному (гауссову) распределению. NF4 оптимизирует уровни квантования именно под эту распределительную функцию, давая ~0.3-0.5 BLEU преимущество над INT4 при том же количестве бит.
Используется в бинарах llama.cpp начиная с версии 1800+.
Как квантование влияет на качество модели
Метрики: perplexity и downstream задачи
| Модель | FP16 (baseline) | INT4 (AWQ) | INT4 (GPTQ) | Q4_K_M (GGUF) | Q6_K (GGUF) |
|---|---|---|---|---|---|
| Llama 3 8B | 4.82 | 4.91 (+0.09) | 4.88 (+0.06) | 4.95 (+0.13) | 4.84 (+0.02) |
| Mistral 7B | 5.12 | 5.23 (+0.11) | 5.18 (+0.06) | 5.30 (+0.18) | 5.15 (+0.03) |
| Mixtral 8x7B | 4.55 | 4.67 (+0.12) | 4.61 (+0.06) | 4.72 (+0.17) | 4.57 (+0.02) |
Перплексия — не всё. Разница в 0.1 PPL на 7B модели может быть незаметна в чате, но критична для задач вроде генерации кода или перевода.
Тесты на реальных задачах (MMLU benchmark)
| Модель | FP16 | AWQ INT4 | GPTQ INT4 | Q4_K_M | Q6_K |
|---|---|---|---|---|---|
| Llama 3 8B | 66.8 | 65.2 (-1.6) | 66.0 (-0.8) | 64.5 (-2.3) | 66.1 (-0.7) |
| Mistral 7B Instruct | 63.4 | 62.1 (-1.3) | 62.8 (-0.6) | 61.5 (-1.9) | 62.9 (-0.5) |
Вывод: Q6_K практически незаметен. AWQ и GPTQ лучше GGUF Q4_K_M. Разница между INT4 и FP16 — 1-2% на MMLU.
Качественные тесты: где квантование бросается в глаза
Генерация кода: квантование до INT4 снижает качество генерации кода на 5-8%. Модель чаще допускает синтаксические ошибки и теряет контекст в длинных функциях.
Многоязычность: для не-английских языков (русский, китайский, арабский) падение качества при INT4 более заметно — до 3-5% по BLEU на переводе.
Математика и логика: задачи на рассуждение ( GSM8K, MATH) теряют 2-4% accuracy при Q4_K_M. INT8 и Q6_K практически не влияют.
Творческие задачи: генерация стихов, историй, маркетинговых текстов — квантование почти не влияет (менее 1% разницы по оценке людей).
Практическое руководство — как квантовать свои модели
Шаг 1: Получение модели
# Скачиваем модель из Hugging Face
huggingface-cli download meta-llama/Llama-3.1-8B-Instruct \
--local-dir ~/models/llama-3.1-8b
Шаг 2: Квантование в GGUF (для llama.cpp / Ollama)
# Конвертируем в GGUF и квантуем в Q4_K_M
python convert-hf-to-gguf.py ~/models/llama-3.1-8b \
--outfile llama-3.1-8b-q4_k_m.gguf \
--outtype f16
# Квантуем
./quantize llama-3.1-8b-q4_k_m.gguf llama-3.1-8b-q4_k_m.gguf Q4_K_M
Или проще через llama.cpp Python API:
from llama_cpp import Llama
llm = Llama(
model_path="llama-3.1-8b-q4_k_m.gguf",
n_gpu_layers=35, # 0 = CPU only, -1 = all layers on GPU
n_ctx=4096,
verbose=False
)
output = llm.create_chat_completion(
messages=[{"role": "user", "content": "Напиши функцию сортировки на Rust"}]
)
Шаг 3: Квантование в AWQ (для autoawq)
# Установка
pip install autoawq xformers
# Квантование
python -m awq.apply_awq \
--model_path ~/models/llama-3.1-8b \
--out_path llama-3.1-8b-awq-int4 \
--q_bits 4 \
--q_group_size 128
Шаг 4: Квантование в GPTQ (для exllamav2 / auto-gptq)
# Установка
pip install auto-gptq transformers accelerate
# Квантование с калибровкой на 256 примерах
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
from transformers import AutoTokenizer
model = AutoGPTQForCausalLM.from_pretrained("~/models/llama-3.1-8b")
tokenizer = AutoTokenizer.from_pretrained("~/models/llama-3.1-8b")
quantize_config = BaseQuantizeConfig(
bits=4,
group_size=128,
desc_act=False, # False = True для GPU > RTX 3090
)
model.quantize(dataset, quantize_config)
model.save_pretrained("~/models/llama-3.1-8b-gptq-int4")
Шаг 5: Проверка качества
# Сравнение FP16 vs квантованной на MMLU
from lm_eval import evaluator
# FP16
results_fp16 = evaluator.simple_evaluate(
model="hf",
model_args="pretrained=meta-llama/Llama-3.1-8B-Instruct",
tasks=["mmlu"],
batch_size=8
)
# Квантованная
results_q4 = evaluator.simple_evaluate(
model="hf",
model_args="pretrained=~/models/llama-3.1-8b-awq-int4",
tasks=["mmlu"],
batch_size=8
)
print(f"FP16 MMLU: {results_fp16['metrics']['mmlu']['exact_match,all']: .1f}")
print(f"AWQ INT4: {results_q4['metrics']['mmlu']['exact_match,all']: .1f}")
Выбор формата под железо и сценарий
Решающая матрица: железо → формат
| Ваше железо | Формат | Движок | Почему |
|---|---|---|---|
| MacBook M2 (16 ГБ) | Q4_K_M GGUF | llama.cpp (Metal) | Единственный формат, который работает эффективно на Apple Silicon |
| MacBook M2 (64 ГБ) | Q6_K GGUF | llama.cpp (Metal) | Можно позволить себе Q6 — качество почти FP16 |
| RTX 4060 (8 ГБ) | AWQ INT4 или GPTQ INT4 | ExLlamaV2 | Максимальная скорость на NVIDIA с 4-бит |
| RTX 4090 (24 ГБ) | AWQ INT4 | vLLM | vLLM отлично работает с AWQ, бэтчирование на высоте |
| RTX 3090 (24 ГБ) × 2 | GPTQ INT4 | vLLM (tensor parallel) | GPTQ лучше оптимизирован для multi-GPU |
| Сервер A100 (80 ГБ) | FP8 или FP16 | TensorRT-LLM | Нет смысла квантовать — память есть |
| Сервер A100 (40 ГБ) × 4 | NF4 | vLLM (PagedAttention) | NF4 позволяет уместить 70B на 4×40 ГБ |
| Raspberry Pi 5 | Q2_K или Q3_K GGUF | llama.cpp (CPU) | Минимальный размер при максимальном замедлении |
| Android телефон | NF4 | MLC LLM (TVM) | MLC компилирует NF4 под ARM NEON |
Компромиссы: что терять можно, а что нет
Можете терять качество:
- Генерация описаний товаров
- Чат-боты с быстрыми ответами
- Идея-генераторы для маркетинга
- Выбор: Q4_K_M или даже Q3_K_M
Нельзя терять качество:
- Юридические консультации
- Медицинские диагнозы
- Финансовые рекомендации
- Выбор: Q6_K или INT8
Продвинутые техники и антипаттерны
Продвинутые техники
Смешанное квантование (Mixed Precision)
Разные слои модели квантуются по-разному:
- Слои embedding и lm_head — в FP16 (они критичны для качества)
- Attention слои — в INT8
- FFN слои — в INT4
Реализуется через llama.cpp с флагом --no-mmap и кастомным скриптом квантования.
KV Cache квантование
KV cache может занимать до 50% памяти при длинном контексте. Квантование KV cache до INT8:
- Освобождает 50% VRAM для KV cache
- Позволяет удвоить длину контекста
- Практически незаметно для качества
vLLM поддерживает: --kv-cache-dtype fp8
Динамическое квантование (Dynamic Quantization)
Квантование происходит на лету при инференсе. Весы хранятся в INT4, деквантование происходит в специальном CUDA ядре.
Преимущество: нет необходимости хранить отдельные FP16 веса. Недостаток: накладные расходы на деквантование — 10-15% slowdown.
Антипаттерны
1. Квантовать без калибровки
Проблема: случайное квантование без калибровочной выборки снижает качество на 10-15% MMLU.
Решение: всегда использовать минимум 128 примеров для калибровки AWQ/GPTQ.
2. Использовать Q2_K для моделей > 13B
Проблема: 2-битное квантование убивает семантику больших моделей. Модель 70B в Q2_K генерирует бессмысленный текст.
Решение: минимум Q3_K_M для моделей > 13B, лучше Q4_K_M.
3. Смешивать форматы в одном проекте
Проблема: GGUF модель в vLLM не загрузится. AWQ модель в Ollama не загрузится.
Решение: выбрать один формат на весь проект. GGUF — для локального, AWQ/GPTQ — для GPU продакшена.
4. Забывать про group_size
Проблема: group_size=64 даёт лучшее качество, но медленнее на NVIDIA. group_size=128 — быстрее, но чуть хуже.
Решение: для NVIDIA использовать group_size=128, для CPU — group_size=64.
5. Квантовать модель, которая уже плоха в FP16
Проблема: квантование не исправляет плохую модель. Если FP16 модель даёт 40% на MMLU, INT4 даст 38%, а не 60%.
Решение: сначала выбрать хорошую базовую модель, потом квантовать.
Заключение: правила квантования в 2026 году
Правило 1: Начните с GGUF Q4_K_M. Это самый универсальный формат, который работает везде.
Правило 2: Если вам нужна максимальная производительность на NVIDIA — выбирайте AWQ INT4 или GPTQ INT4.
Правило 3: Если качество критично — используйте Q6_K или INT8. Разница с FP16 менее 1% на MMLU.
Правило 4: Никогда не квантуйте без калибровки. Используйте минимум 128 примеров из вашей предметной области.
Правило 5: Квантуйте KV cache до FP8 — это бесплатный способ удвоить контекст без потери качества.
Квантование перестало быть компромиссом и стало стандартом. В 2026 году деплой LLM без квантования — это как деплой без HTTPS: технически возможно, но непростительно.