Квантизация нейросетей: как уменьшить модель без потери качества

Что такое квантизация LLM: GPTQ, GGUF, AWQ. Как сжать модель в 4 раза и запустить на потребительском GPU без заметной потери качества.

Квантизация нейросетей: как уменьшить модель без потери качества

Модель на 70 миллиардов параметров в полной точности (fp16) весит 140 ГБ. Ни один потребительский GPU не вместит её целиком. Квантизация — способ сжать модель в 2–4 раза, заменив 16-битные числа на 8-, 4- или даже 2-битные, сохранив при этом большую часть качества. Благодаря квантизации модели, требовавшие серверных кластеров, запускаются на ноутбуках.

Зачем нужна квантизация

Каждый параметр нейросети — число с плавающей запятой. В формате float16 одно число занимает 2 байта. Модель Llama 3 70B содержит 70 миллиардов таких чисел — итого 140 ГБ. Для инференса нужна видеопамять (VRAM), сопоставимая с размером модели. Даже NVIDIA A100 с 80 ГБ VRAM не вместит такую модель без оптимизаций.

Квантизация до 4 бит (0.5 байта на параметр) сжимает ту же модель до ~35 ГБ. Это влезает в два GPU RTX 4090 (по 24 ГБ) или один серверный A100. Модели на 7–13 млрд параметров после квантизации занимают 4–8 ГБ — работают на обычных игровых видеокартах.

Дополнительный бонус — скорость. Меньше данных для загрузки из памяти при каждом шаге вычислений — быстрее инференс. На GPU, ограниченных пропускной способностью памяти (memory-bandwidth-bound), ускорение от квантизации достигает 2–3 раз.

Типы точности: от fp32 до int4

Понимание форматов чисел помогает оценить компромиссы:

  • fp32 (32 бита) — полная точность. Используется при обучении. Для инференса избыточна.
  • fp16 / bf16 (16 бит) — стандарт для инференса. bf16 (brain float 16) предпочтительнее: больший динамический диапазон при той же разрядности.
  • int8 (8 бит) — целочисленное представление. Размер модели уменьшается вдвое по сравнению с fp16. Потеря качества минимальна — обычно менее 1% на бенчмарках.
  • int4 (4 бита) — четвертьбитная квантизация. Размер — четверть от fp16. Потери качества: 1–5% на бенчмарках в зависимости от метода и модели.
  • int2–int3 — экстремальная квантизация. Потери заметны, но модель всё ещё функциональна для простых задач.

Методы квантизации

GGUF (llama.cpp)

GGUF — формат квантизации, разработанный в проекте llama.cpp Георгием Гергановым. Это доминирующий формат для локального запуска моделей через Ollama и llama.cpp.

Особенности GGUF:

  • Поддерживает квантизацию от Q2 до Q8 с различными вариантами (Q4_0, Q4_K_M, Q5_K_S и т.д.)
  • Суффикс K обозначает «k-quants» — улучшенный метод, где разные слои квантизуются с разной точностью. Критические слои получают больше бит, менее важные — меньше.
  • Работает на CPU и GPU, поддерживает частичную загрузку на GPU (offloading)
  • Единый файл — модель и метаданные упакованы вместе

Популярные варианты:

  • Q4_K_M — оптимальный баланс размера и качества. Стандартный выбор для большинства задач.
  • Q5_K_M — чуть крупнее, но ближе к fp16 по качеству. Для задач, где точность критична.
  • Q8_0 — минимальные потери, но размер вдвое больше Q4.
  • Q2_K — максимальное сжатие, заметная деградация. Для экспериментов на слабом железе.

GPTQ

GPTQ (GPT Quantization) — метод пост-тренировочной квантизации, основанный на работе Frantar et al. (2022). Использует небольшую калибровочную выборку (обычно 128–512 примеров) для оптимизации весов при квантизации.

Принцип: квантизация идёт послойно, и ошибка каждого квантизованного веса компенсируется корректировкой оставшихся. Математически это решение задачи оптимизации для минимизации ошибки аппроксимации.

GPTQ работает только на GPU (через библиотеку AutoGPTQ или exllama). Скорость инференса обычно выше, чем у GGUF на GPU, но нет поддержки CPU.

AWQ

Activation-Aware Weight Quantization (2023) — метод, который учитывает не только веса, но и типичные активации модели. Идея: некоторые веса важнее других — те, которые обрабатывают часто встречающиеся паттерны. AWQ сохраняет эти критические веса с большей точностью.

По бенчмаркам AWQ часто превосходит GPTQ при том же уровне квантизации, особенно при 4-битном сжатии. Поддерживается в vLLM, TGI и других фреймворках для продакшн-инференса.

Практика: квантизация модели

Для большинства пользователей квантизировать модель самостоятельно не нужно — на Hugging Face доступны готовые квантизованные версии практически каждой популярной модели. TheBloke (один из самых активных контрибьюторов) опубликовал тысячи квантизованных моделей в форматах GGUF и GPTQ.

Если нужно квантизировать самостоятельно:

# Квантизация через llama.cpp в GGUF
# 1. Конвертация из Hugging Face формата
python convert_hf_to_gguf.py ./model-dir --outtype f16 --outfile model.f16.gguf

# 2. Квантизация
./llama-quantize model.f16.gguf model.Q4_K_M.gguf Q4_K_M
# Квантизация через AutoGPTQ
from auto_gptq import AutoGPTQForCausalLM
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3-8B")
model = AutoGPTQForCausalLM.from_pretrained(
    "meta-llama/Llama-3-8B",
    quantize_config={"bits": 4, "group_size": 128}
)
model.quantize(calibration_dataset)
model.save_quantized("./llama-3-8b-gptq-4bit")

Как квантизация влияет на качество

Исследования показывают устойчивую закономерность:

  • 8-бит — потери менее 0.5% на большинстве бенчмарков. Практически незаметно.
  • 4-бит (Q4_K_M) — потери 1–3%. Для большинства задач (суммаризация, перевод, генерация кода) результат неотличим от fp16.
  • 3-бит — потери 3–8%. Заметно при сложных рассуждениях и точных вычислениях.
  • 2-бит — потери 10–20%. Модель функциональна, но качество значительно ниже.

Важный нюанс: крупные модели переносят квантизацию лучше. Llama 3 70B в Q4 обычно умнее, чем Llama 3 8B в fp16. Лучше взять крупную модель с агрессивной квантизацией, чем маленькую в полной точности.

Что выбрать

Для локального запуска через Ollama или llama.cpp — GGUF Q4_K_M. Универсальный формат, работает на любом железе, оптимальный баланс размера и качества.

Для серверного инференса на GPU — AWQ или GPTQ. Быстрее на GPU, поддерживается в vLLM и TGI для production-деплоев.

Для максимального качества при ограниченной памяти — GGUF Q5_K_M или Q6_K. Чуть больше памяти, но ближе к полной точности.

Квантизация: что это и зачем нужна

Квантизация — уменьшение точности весов нейросети (float32 → float16 → int8 → int4). Результат: в 2–8 раз меньше памяти, быстрее inference, незначительная потеря качества. Без квантизации Llama 3.1 70B требует 140GB VRAM (fp32) — недоступно для большинства. В INT4 та же модель помещается в 35GB — запускается на двух потребительских GPU.

Форматы квантизации: сравнение

ФорматБиты/весПотеря качестваСкоростьРазмер (70B)
FP32 (float32)32Нет (эталон)★★☆☆☆~140GB
BF16 (bfloat16)16Минимальная★★★★☆~70GB
FP16 (float16)16Минимальная★★★★☆~70GB
GPTQ INT88Незначительная★★★★☆~35GB
GPTQ INT44Заметная на краях★★★★★~18GB
GGUF Q4_K_M~4.5Минимальная★★★★☆~20GB
GGUF Q2_K~2.5Существенная★★★★★~11GB

GGUF: стандарт для llama.cpp и Ollama

GGUF (GPT-Generated Unified Format) — формат квантизованных моделей, оптимизированный для CPU-инференса. Разработан командой llama.cpp. Все модели в Ollama хранятся в GGUF. Поддерживает смешанную квантизацию: разные слои модели квантизуются с разной точностью. Рекомендуемые варианты: Q4_K_M (лучший баланс размер/качество), Q5_K_M (чуть лучше качество), Q8_0 (почти без потерь, требует больше RAM).

GPTQ и AWQ: квантизация для GPU

GPTQ (Generative Pre-trained Transformers Quantization) — post-training квантизация с калибровочным датасетом. Хорошее качество при INT4. Поддерживается AutoGPTQ библиотекой и HuggingFace.

AWQ (Activation-aware Weight Quantization) — более новый метод, сохраняет важные веса в FP16. Лучше качество чем GPTQ при том же размере. Рекомендуется для production GPU-деплойментов через vLLM.

Практика: как выбрать квантизацию

Консьюмерский GPU (8–12GB VRAM) → GGUF Q4_K_M через Ollama для 7B–13B моделей
Профессиональный GPU (24GB) → GPTQ INT4 или GGUF Q5_K_M для до 30B
Server GPU (80GB A100) → BF16 для максимального качества или AWQ INT4 для 70B+
CPU-only (MacBook, сервер без GPU) → GGUF Q4_K_M, llama.cpp оптимизирован под Apple Metal


Читайте также

Подробнее: Как настроить локальную языковую модель