Дообучение LLM методом QLoRA
QLoRA (Quantized Low-Rank Adaptation) — метод, объединяющий квантизацию базовой модели до 4-bit с обучением LoRA-адаптеров в bf16/fp32. Предложен Dettmers et al. в 2023 году (статья «QLoRA: Efficient Finetuning of Quantized LLMs»). Ключевое достижение: дообучение 65B модели на одном GPU A100 80GB с минимальной потерей качества по сравнению с Full Fine-Tuning в bf16.
Как работает QLoRA
Шаг 1: базовая модель загружается в 4-bit NormalFloat (NF4) — специальный формат квантизации, оптимальный для нормально распределённых весов нейросетей.
Шаг 2: для каждого квантизованного блока хранится отдельный масштабирующий коэффициент (Double Quantization — квантизация самих масштабов).
Шаг 3: при forward/backward pass веса деквантизируются в bf16 «на лету» для вычислений.
Шаг 4: LoRA-адаптеры хранятся и обновляются в полной точности (bf16/fp32).
Результат: потребление памяти снижается в ~4× по сравнению с bf16 LoRA, при этом качество практически не страдает благодаря NF4 квантизации.
Реализация QLoRA
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
import torch
# NF4 квантизация с Double Quantization
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # NF4 для весов
bnb_4bit_compute_dtype=torch.bfloat16, # bf16 для вычислений
bnb_4bit_use_double_quant=True, # Дополнительная экономия ~0.4 бит/параметр
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Meta-Llama-3.1-70B-Instruct",
quantization_config=bnb_config,
device_map="auto",
)
# Обязательная подготовка модели для kbit обучения
model = prepare_model_for_kbit_training(model)
lora_config = LoraConfig(
r=64,
lora_alpha=128,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
lora_dropout=0.05,
task_type="CAUSAL_LM",
bias="none",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable: 0.84% | all: 70B | memory: ~40 GB на 1×A100 80GB
Требования к памяти QLoRA vs LoRA vs Full FT
| Метод | 7B | 13B | 34B | 70B |
|---|---|---|---|---|
| Full FT (bf16) | 4×A100 40GB | 8×A100 40GB | N/A | 8×A100 80GB |
| LoRA (bf16) | 1×A100 40GB | 2×A100 40GB | 4×A100 40GB | 4×A100 80GB |
| QLoRA (NF4) | 1×A100 24GB | 1×A100 40GB | 2×A100 40GB | 1×A100 80GB |
QLoRA позволяет работать с 70B моделью на одной A100 80GB — это революционное снижение требований к инфраструктуре.
Gradient Checkpointing при QLoRA
При QLoRA активации занимают основную память. Gradient checkpointing критически важен:
from trl import SFTTrainer, SFTConfig
training_args = SFTConfig(
output_dir="./qlora-output",
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=16, # effective batch = 32
gradient_checkpointing=True, # обязательно
gradient_checkpointing_kwargs={"use_reentrant": False},
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_ratio=0.05,
bf16=True,
max_seq_length=4096,
logging_steps=25,
save_steps=100,
report_to="wandb",
)
Практический кейс: 70B модель на одном A100 80GB
Задача: специализация Llama 3.1 70B Instruct для анализа юридических договоров — классификация рисков, выявление нестандартных условий, сравнение с шаблоном.
Почему 70B, а не 8B: ранее тестировали Llama 3.1 8B — качество анализа сложных договоров неприемлемо (слишком много пропущенных нюансов). 70B даёт качество, сопоставимое с GPT-4o.
Инфраструктура: 1×A100 80GB. QLoRA NF4, r=64, alpha=128.
Датасет: 1400 договоров с разметкой (проведена практикующими юристами): каждый договор → список рисков с категорией и severity.
Время обучения: 3 эпохи, 22 часа на одной A100 80GB.
Результаты:
- Recall рисков (не пропускаем): 0.71 (8B fine-tuned) → 0.89 (70B QLoRA)
- Precision рисков: 0.79 → 0.87
- Качество формулировок (LLM-as-judge, 1–5): 3.6 → 4.5
- Стоимость инференса vs GPT-4o API: -71% (self-hosted vLLM)
Ограничения QLoRA
Скорость обучения: деквантизация на лету замедляет обучение на ~20% по сравнению с bf16 LoRA.
Тепловыделение: A100 при QLoRA работает на пределе — нужна адекватная система охлаждения.
Вариантность: результаты чуть менее воспроизводимы из-за квантизационных ошибок.
Сроки
- Подготовка данных: 2–5 недель
- Обучение (70B, QLoRA, 1×A100 80GB): 12–36 часов
- Итерации: 1–2 недели
- Итого: 4–8 недель







