Как дообучить открытую LLM с помощью LoRA и QLoRA
Продвинутое3 минРедакция Innovialabs
Коротко
LoRA обучает небольшие адаптеры поверх замороженной модели, а QLoRA делает то же на 4-битной базе, поэтому дообучение помещается на одну GPU. Успех определяют чистый датасет и честное сравнение с базовой моделью.
Коротко: что такое LoRA и QLoRA
LoRA (Low-Rank Adaptation) не меняет веса исходной модели. Вместо этого к выбранным слоям добавляются маленькие матрицы низкого ранга, и обучаются только они. Итоговый адаптер весит мало, его легко хранить отдельно и подключать к базовой модели.
QLoRA — тот же подход, но базовая модель загружается в 4-битной квантизации. Это резко снижает потребление видеопамяти: модели, которые раньше требовали нескольких GPU, становятся доступны на одной.
Дообучение нужно, когда вы хотите изменить стиль, формат ответа или поведение модели. Если задача — дать модели новые факты, обычно лучше подходит RAG.
Шаг 1. Подготовьте датасет
Качество данных важнее любых гиперпараметров. Типичный формат — диалоги в JSONL:
{"messages": [{"role": "system", "content": "Вы помощник службы поддержки."}, {"role": "user", "content": "Как вернуть товар?"}, {"role": "assistant", "content": "Оформите возврат в личном кабинете..."}]}
Что проверить:
- Шаблон чата должен совпадать с тем, на котором обучалась модель. Используйте встроенный chat template токенизатора.
- Дубликаты и противоречия удалите — модель выучит их так же старательно, как правильные примеры.
- Отложите тестовую выборку заранее и не используйте её при обучении.
- Разнообразие важнее количества: сотни хороших примеров часто дают больше, чем тысячи однотипных.
Шаг 2. Настройте обучение
Распространённый стек — Hugging Face transformers, peft и trl. Минимальная конфигурация QLoRA:
from transformers import BitsAndBytesConfig
from peft import LoraConfig
import torch
bnb = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
)
lora = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
target_modules="all-linear",
task_type="CAUSAL_LM",
)
Дальше модель загружается с quantization_config=bnb, а SFTTrainer из trl получает датасет и конфиг LoRA. Подробности — в документации PEFT.
Шаг 3. Гиперпараметры, которые важны
| Параметр | Что делает | С чего начать |
|---|---|---|
r (ранг) | Ёмкость адаптера | 8–16, выше — если модель недоучивается |
lora_alpha | Масштаб обновлений | Часто ставят 2×r |
| learning rate | Скорость обучения | Выше, чем при полном fine-tuning; подбирайте по валидационному loss |
| эпохи | Проходы по данным | 1–3; больше — риск переобучения |
target_modules | Какие слои адаптировать | Все линейные слои обычно дают лучший результат |
Следите за validation loss: если он растёт, а training loss падает — модель переобучается.
Шаг 4. Требования к GPU
Точные цифры зависят от модели, длины контекста и размера батча, поэтому ориентируйтесь на факторы:
- Размер модели — главный фактор. QLoRA уменьшает память под веса примерно в четыре раза по сравнению с 16-битной загрузкой.
- Длина последовательности — длинные примеры увеличивают память под активации.
- Gradient checkpointing экономит память ценой скорости.
- Gradient accumulation позволяет эмулировать большой батч на маленькой GPU.
Начните с короткого прогона на малой части данных, чтобы проверить, что всё помещается в память.
Шаг 5. Оцените результат против базовой модели
Без сравнения с базой нельзя сказать, что дообучение помогло.
- Прогоните одну и ту же тестовую выборку через базовую и дообученную модель.
- Используйте метрики задачи: точность классификации, соответствие формату, долю корректных JSON.
- Добавьте слепую экспертную оценку или LLM-as-a-judge с чёткими критериями.
- Проверьте регрессии: не разучилась ли модель общим навыкам.
Частые ошибки
- Неверный chat template — модель отвечает странно или не останавливается.
- Обучение на «грязных» данных, собранных без проверки.
- Слишком много эпох на маленьком датасете.
- Оценка только по loss без проверки реальных ответов.