中文翻译暂不可用,显示俄语原文。

QLoRA vs LoRA — в чем разница и когда QLoRA лучше?

Краткий тезис

QLoRA — это техника адаптации больших языковых моделей, объединяющая LoRA с 4-битной квантизацией (4‑bit NormalFloat). Она позволяет fine-tune модели размером до 70B параметров на одной 24GB GPU, жертвуя 1–2% качества и 20–30% скорости обучения. QLoRA оптимальна при дефиците GPU и работе с моделями от 30B; LoRA предпочтительна для моделей до 13B, когда критичны точность и скорость.


1. Термины: LoRA, квантование, QLoRA

LoRA (Low‑Rank Adaptation) — метод параметро-эффективного fine-tuning. Вместо обновления весов W модели вводит для каждого слоя две небольшие матрицы A и B (ранг r), так что ∆W = BA. Обучаются только эти матрицы, что снижает число обучаемых параметров в тысячи раз.

Квантование (quantization) — снижение точности чисел (например, с 16‑bit float до 4‑bit), уменьшающее размер модели и скорость инференса. Для fine-tuning требуется, чтобы градиенты проходили через квантованные веса, что обычно делается с помощью QLoRA.

QLoRA (Quantized Low‑Rank Adaptation)LoRA поверх 4‑битной квантованной модели. Веса базовой модели заморожены и хранятся в 4‑битном формате; адаптеры LoRA обучаются в полной точности (float32 или bfloat16). Использует специальные техники: NormalFloat4, Double Quantization, Paged Optimizers, чтобы минимизировать потерю качества при квантовании.


2. Как работает LoRA

LoRA вводит для каждого весового слоя (например, линейного) две низкоранговые матрицы A ∈ R^(d × r) и B ∈ R^(r × k), где r — ранг (обычно 8–64). Прямой проход: h = W₀x + BAx. Обучаются только A и B, исходные веса W₀ заморожены.

  • Преимущества
    • Число обучаемых параметров ↓ в 10 000 раз (для модели 7B c r=8 ~ 0.1% от полных весов).
    • Не требует хранения полных градиентов базовой модели.
    • Можно комбинировать несколько LoRA-адаптеров («переключать» их).
  • Недостатки Базовая модель хранится в 16‑bit (или 32‑bit), что занимает много памяти (для 70B ~ 140 GB в float16).

Код (PEFT + Hugging Face Transformers):

from peft import LoraConfig, get_peft_model

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.05
)
model = get_peft_model(base_model_16bit, lora_config)

3. Как работает QLoRA

QLoRA использует три ключевые инновации:

  1. 4‑bit NormalFloat (NF4) — специальный тип квантования, оптимально распределяющий значения по гауссовскому распределению весов. Сохраняет больше информации, чем обычный int4.
  2. Double Quantization — повторное квантование констант квантования (scale‑факторов) в 8‑битный формат, снижающее дополнительный расход памяти.
  3. Paged Optimizer — при нехватке GPU‑памяти автоматически выгружает градиенты в CPU (page‑out) и подгружает обратно, подобно swap.

Схема работы

  • Базовая модель загружается в 4‑bit NF4 (например, модель 70B занимает ~35 GB).
  • Для обратного прохода градиенты вычисляются в полной точности (float32 или bfloat16) с помощью параметризованных квантованных весов — веса на лету деквантуются до 16‑bit, применяется LoRA, градиент считается.
  • Адаптеры LoRA хранятся и обучаются в full‑precision.

Код

from transformers import BitsAndBytesConfig, AutoModelForCausalLM
from peft import LoraConfig, get_peft_model

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(model_id, quantization_config=bnb_config)
model = get_peft_model(model, lora_config)

4. Сравнение QLoRA vs LoRA

ПараметрLoRA (16‑bit)QLoRA (4‑bit NF4)
Память для базовой модели (7B)~14 GB (float16)~3.5 GB (4‑bit)
Память для градиентов / оптимизатора~0.1% от модели (дополнительно ~0.3 GB)~0.1% + overhead от деквантования
Максимальный размер модели на 24GB GPU~7‑13B~70B
Качество (точность на бенчмарках)ЭталонНиже на 1–2% (в среднем)
Скорость обученияБыстрее (нет деквантования)Медленнее на 20–30%
Скорость инференсаВысокая (‑bit)Медленнее из‑за деквантования при каждом forward
Совместимость с переключением адаптеровДа (хранить один адаптер)Да (но базовая модель 4‑bit занимает мало места)
Когда использоватьМодели до 13B, достаточно GPU, важно качествоМодели 30B+, ограниченная память, эксперименты

5. Когда QLoRA лучше

QLoRA — выбор для сценариев с жёсткими ограничениями по памяти:

  • Модели от 30B до 70B на одной 24GB GPU можно обучать Llama‑3‑70B, что невозможно с LoRA (требует >140 GB).
  • Экспериментирование с несколькими моделями можно быстро загружать разные 4‑bit модели и накатывать адаптеры.
  • Прототипирование и исследование не критично падение качества на 1‑2%, но критично время и ресурсы.
  • Сценарии с ограниченным бюджетом облачные GPU стоят дорого — QLoRA позволяет fine‑tune большие модели на дешёвых инстансах (T4, L4).

Пример: тонкий fine‑tune Llama‑3‑70B для задачи перевода на одном NVIDIA RTX 3090 (24 GB). С QLoRA это занимает ~2 дня, с LoRA невозможно.


6. Когда LoRA лучше

  • Модели до 13B память позволяет хранить 16‑bit веса (7B ~14 GB, 13B ~26 GB). LoRA быстрее и точнее.
  • Продакшн с требованием высокой точности даже 1% ухудшения недопустимы (например, финансовые задачи, медицинские рекомендации).
  • Высокая скорость обучения если нужно много итераций (десятки тысяч шагов), QLoRA будет в 1.2‑1.3 раза медленнее.
  • Когда базовая модель уже в 16‑bit и нет желания переквантовывать: LoRA работает «как есть».
  • Сервинг с несколькими LoRA можно объединять адаптеры в производственном инференсе (через merge_and_unload), после чего QLoRA может дать прирост скорости за счёт меньшего размера модели? (обычно после merge модель остаётся 16‑bit, поэтому LoRA выигрывает).

7. Практические рекомендации по выбору ранга и настройкам

  • Rank (r): для QLoRA и LoRA ранг обычно 8–64. Для маленьких моделей (7B) r=16, для больших (70B) r=64 (больше ~ больше качество, но больше параметров). QLoRA не требует менять r из‑за квантования.
  • Target modules: чаще всего q_proj, v_proj (при LoRA), но в QLoRA можно добавлять k_proj, o_proj, gate_proj. Не рекомендуется трогать embedding и lm_head (требуют полной точности).
  • Batch size: из‑за ограниченной памяти QLoRA использует gradient accumulation; обычный batch size = 1–2.
  • Learning rate: для QLoRA чуть выше (2e‑4 vs 1e‑4 для LoRA), чтобы компенсировать шум квантования.
  • double_quant: всегда включать (экономит ~0.5 GB без потерь).

8. Производительность: оценочные цифры для разных размеров моделей

МодельМетодПамять (GPU)Время обучения на 1000 шагов (bs=1)Качество (на датасете GSM8K)
Llama‑2‑7BLoRA (16‑bit)~16 GB~6 часов45%
Llama‑2‑7BQLoRA (4‑bit)~5 GB~8 часов43%
Llama‑2‑13BLoRA~28 GB~10 часов53%
Llama‑2‑13BQLoRA~8 GB~13 часов51%
Llama‑2‑70BQLoRA~35 GB- (на 2×A100)68%
Llama‑3‑70BQLoRA~45 GB (с пагинацией)на 24 GB T4 невозможен, на 48 GB ~3 дня80%+

Цифры приблизительные, зависят от датасета, ранга, реализации.


9. Влияние на качество: доказательства из литературы

В оригинальной статье QLoRA (Dettmers et al., 2023) показано, что при сохранении всех гиперпараметров, QLoRA уступает LoRA менее 1% на большинстве бенчмарков (MMLU, TruthfulQA, GSM8K). Лучший результат достигается при использовании NF4 + Double Quantization + Paged Optimizer. Если пренебречь Double Quantization, просадка увеличивается до 2–3%.

Пример поведения на MMLU (5‑shot):

МетодMMLU (accuracy)
Full fine‑tune (16‑bit)68.0
LoRA (16‑bit)67.5
QLoRA (NF4)66.8

Разница 0.7% — допустима для экспериментов, но может быть существенной в продакшне.


10. Инструменты и реализация

Основные библиотеки:

Типичный workflow:

from transformers import AutoTokenizer, TrainingArguments, Trainer
import torch

# 1. Load quantized model
bnb_config = BitsAndBytesConfig(load_in_4bit=True, ...)
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-70b", quantization_config=bnb_config)

# 2. Wrap with LoRA
lora_config = LoraConfig(r=64, ...)
model = get_peft_model(model, lora_config)

# 3. Train
training_args = TrainingArguments(per_device_train_batch_size=1, gradient_accumulation_steps=16, ...)
trainer = Trainer(model=model, args=training_args, train_dataset=...)
trainer.train()

Пет-проект для закрепления

Задача Сравнить LoRA и QLoRA на одной модели (Llama‑2‑7B или Mistral‑7B) на задаче классификации сентиментов (датасет IMDB). Измерить время обучения, пиковую память, accuracy на тесте.

Инструменты

Шаги:

  1. Загрузить токенизатор и базовую модель (Mistral‑7B) в 16‑bit.
  2. Применить LoraConfig (r=8, target_modules= ["q_proj", "v_proj"], lora_alpha=16).
  3. Обучить модель на 1000 примерах IMDB (fine‑tune на последовательность). Замерить время и память (с помощью nvidia-smi или библиотеки pynvml).
  4. Сохранить адаптер, протестировать accuracy.
  5. Повторить шаги 1–4, но загружая модель с BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4", ...).
  6. Сравнить: accuracy, время, пиковую память.

Ожидаемый результат

  • QLoRA использует в 2–3 раза меньше памяти (например, 4.5 GB вместо 15 GB), но обучение длится на 20–30% дольше.
  • Accuracy будет в пределах 1–2% от LoRA (например, 88% vs 89%).
  • Вывод: на маленьких моделях LoRA предпочтительнее, но QLoRA позволяет работать с более сложными моделями на том же железе.

Связь с другими вопросами

ВопросТема
26LoRA — принцип работы, отличие от full fine‑tuning
28PEFT (Parameter‑Efficient Fine‑Tuning) — обзор методов
29Quantization — виды (INT8, FP4, NF4), как влияет на точность
30Как выбирать ранг LoRA / target modules
31Fine‑tuning vs RLHF — когда какой подход
32Memory optimization — Gradient Checkpointing, ZeRO, Paged Optimizer

Навигация