38
13 марта 2026
LoRA файнтюнинг на GPU: полный гайд
Как дообучить LLM с помощью LoRA и QLoRA на потребительских GPU: от теории до практики
Файнтюнинг (дообучение) больших языковых моделей позволяет адаптировать модель под свою задачу: от чат-бота на корпоративных данных до генерации кода в вашем стеке. Но полный файнтюнинг модели на 7B параметров требует ~112 ГБ VRAM — это 2× A100.
LoRA (Low-Rank Adaptation) решает эту проблему: вместо обновления всех весов модели обучаются только маленькие адаптерные матрицы. Результат — файнтюнинг 7B модели на одной RTX 3090, а с QLoRA — даже на RTX 4060 с 8 ГБ VRAM.
Как работает LoRA
Проблема: полный файнтюнинг слишком дорог
При полном файнтюнинге с Adam-оптимизатором в FP32 нужно хранить в VRAM:
| Компонент | Байт/параметр | 7B модель |
|---|---|---|
| Веса модели | 4 | 28 ГБ |
| Градиенты | 4 | 28 ГБ |
| Adam states (m + v) | 8 | 56 ГБ |
| Итого (без активаций) | 16 | 112 ГБ |
Плюс активации — ещё 10–50 ГБ в зависимости от batch size и длины контекста.
Решение: обучаем только адаптеры
LoRA замораживает все оригинальные веса модели и добавляет пару маленьких матриц (A и B) к каждому целевому слою:
W_new = W_frozen + α × (B × A)
Где:
- W_frozen — оригинальные веса (заморожены, не обновляются)
- A — матрица [hidden_dim × r] (инициализируется случайно)
- B — матрица [r × hidden_dim] (инициализируется нулями)
- r — ранг адаптера (обычно 8–64)
- α — scaling factor
Пример: для слоя 4096×4096 с r=16:
- Оригинал: 16.7M параметров
- LoRA: 4096×16 + 16×4096 = 131K параметров (в 128× меньше)
Обучаемых параметров обычно 0.1–2% от общего числа. Вместо 112 ГБ для 7B модели нужно ~16 ГБ с LoRA и ~6 ГБ с QLoRA.
LoRA vs QLoRA
| Характеристика | LoRA | QLoRA |
|---|---|---|
| Веса базовой модели | FP16 | INT4 (NF4) |
| VRAM для 7B | ~16 ГБ | ~6 ГБ |
| VRAM для 13B | ~32 ГБ | ~10 ГБ |
| VRAM для 70B | ~150 ГБ | ~40 ГБ |
| Качество | Чуть лучше | ~99% качества LoRA |
| Скорость обучения | Быстрее | Медленнее (~1.5×) |
QLoRA = LoRA + квантизация базовой модели в 4-bit NF4. Модель загружается в INT4, а LoRA-адаптеры обучаются в FP16/BF16. При этом вычисления идут в BFloat16 через деквантизацию «на лету».
Рекомендация: если VRAM хватает — используйте LoRA (быстрее и чуть лучше). Если VRAM ограничен — QLoRA даёт почти то же качество.
Требования к VRAM
QLoRA (рекомендуемые конфигурации)
| Модель | r | batch | Контекст | VRAM | GPU |
|---|---|---|---|---|---|
| 7B (Qwen, Llama, Mistral) | 64 | 4 | 2048 | ~8 ГБ | RTX 4060, RTX 3070 |
| 7B | 64 | 4 | 4096 | ~12 ГБ | RTX 4070, RTX 3060 12GB |
| 13B | 32 | 2 | 2048 | ~12 ГБ | RTX 4070 |
| 13B | 64 | 4 | 2048 | ~16 ГБ | RTX 4080 |
| 32B (Qwen2.5-32B) | 16 | 1 | 2048 | ~20 ГБ | RTX 3090 |
| 32B | 32 | 2 | 2048 | ~24 ГБ | RTX 4090 |
| 70B (Llama 3.1) | 16 | 1 | 2048 | ~42 ГБ | 2× RTX 3090 |
Факторы, влияющие на VRAM
| Фактор | Влияние |
|---|---|
| Ранг (r) | r=16 → r=64 = +2–4 ГБ |
| Batch size | ×2 batch ≈ +30–50% VRAM |
| Длина контекста | 2048 → 4096 ≈ +30% VRAM |
| Gradient checkpointing | Включить = −30–50% VRAM (но −20% скорость) |
| Количество target_modules | Больше слоёв = больше VRAM |
Практика: файнтюнинг с Hugging Face
Установка
pip install transformers peft trl bitsandbytes datasets accelerate
QLoRA файнтюнинг Qwen2.5-7B-Instruct
import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments,
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from trl import SFTTrainer
from datasets import load_dataset
# 1. Конфигурация квантизации (QLoRA)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16, # Важно: bfloat16, НЕ float16
bnb_4bit_use_double_quant=True, # Экономит ещё ~0.4 бит/параметр
)
# 2. Загрузка модели
model_name = "Qwen/Qwen2.5-7B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto",
trust_remote_code=True,
)
model = prepare_model_for_kbit_training(model)
# 3. Конфигурация LoRA
lora_config = LoraConfig(
r=32, # Ранг адаптера
lora_alpha=64, # Scaling (обычно 2× r)
target_modules=[ # Какие слои адаптировать
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Пример вывода: trainable params: 41,943,040 || all params: 7,657,300,480 || 0.55%
# 4. Загрузка датасета
dataset = load_dataset("your-dataset", split="train")
# 5. Параметры обучения
training_args = TrainingArguments(
output_dir="./output",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4, # Эффективный batch = 16
gradient_checkpointing=True, # Экономит VRAM
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_ratio=0.05,
logging_steps=10,
save_strategy="epoch",
bf16=True, # BFloat16 обучение
optim="paged_adamw_8bit", # 8-bit Adam (экономит VRAM)
max_grad_norm=0.3,
report_to="none",
)
# 6. Запуск обучения
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
args=training_args,
max_seq_length=2048,
)
trainer.train()
# 7. Сохранение адаптера
model.save_pretrained("./lora-adapter")
tokenizer.save_pretrained("./lora-adapter")
Важные детали
bnb_4bit_compute_dtype=torch.bfloat16 — используйте bfloat16, не float16! Float16 вызывает NaN-ы при обучении на Ampere+ GPU (RTX 3000+, A100).
bnb_4bit_use_double_quant=True — двойная квантизация. Квантизует сами квантизационные константы, экономя ~0.4 бит/параметр без потери качества.
paged_adamw_8bit — 8-bit Adam оптимизатор с пейджингом в CPU RAM при нехватке VRAM. Экономит 4–8 ГБ на больших моделях.
Выбор гиперпараметров
Ранг (r)
| Задача | Рекомендуемый r |
|---|---|
| Простая классификация | 8 |
| Генерация в определённом стиле | 16–32 |
| Обучение на специализированном домене | 32–64 |
| Сложные задачи (код, математика) | 64–128 |
Общее правило: r=32 — хороший дефолт. Увеличивайте, если модель недообучается. Уменьшайте, если VRAM не хватает.
lora_alpha
Обычно lora_alpha = 2 × r. Это scaling factor: ΔW = (α/r) × B × A. При alpha=2r и r=32 scaling = 2.0.
target_modules
| Вариант | Обучаемые параметры | Качество | VRAM |
|---|---|---|---|
| Только attention (q, v) | 0.1–0.3% | Хорошее | Минимум |
| Все attention (q, k, v, o) | 0.3–0.5% | Лучше | Среднее |
| Attention + MLP (gate, up, down) | 0.5–1.5% | Лучшее | Больше |
Рекомендация: включайте все attention + MLP слои (как в примере выше). Разница в VRAM минимальна, а качество заметно лучше.
Learning rate
- QLoRA: 1e-4 — 3e-4 (выше, чем при полном файнтюнинге)
- LoRA (FP16 base): 5e-5 — 2e-4
- Используйте cosine scheduler с warmup 3–5%
Подготовка датасета
Формат для instruction tuning
[
{
"instruction": "Объясни что такое LoRA простыми словами",
"input": "",
"output": "LoRA — это метод дообучения нейросетей..."
},
{
"instruction": "Переведи на английский",
"input": "Привет, как дела?",
"output": "Hello, how are you?"
}
]
Формат chat (для чат-моделей)
[
{
"messages": [
{"role": "system", "content": "Ты помощник по Python."},
{"role": "user", "content": "Как отсортировать список?"},
{"role": "assistant", "content": "Используйте sorted() или list.sort()..."}
]
}
]
Сколько данных нужно?
| Задача | Примеров | Эпох |
|---|---|---|
| Стиль / тон | 100–500 | 3–5 |
| Доменные знания | 1 000–10 000 | 2–3 |
| Сложные навыки (код, математика) | 10 000–100 000 | 1–3 |
Лучше 500 качественных примеров, чем 50 000 шумных.
Использование обученного адаптера
Инференс
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
# Загружаем базовую модель
base_model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B-Instruct",
device_map="auto",
torch_dtype=torch.bfloat16,
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
# Накладываем LoRA-адаптер
model = PeftModel.from_pretrained(base_model, "./lora-adapter")
# Генерация
inputs = tokenizer("Ваш промпт", return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=512)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
Merge адаптера в базовую модель
Для продакшена можно слить адаптер с базой:
merged_model = model.merge_and_unload()
merged_model.save_pretrained("./merged-model")
tokenizer.save_pretrained("./merged-model")
После merge получается обычная модель, которую можно квантизовать в GGUF и запускать через llama.cpp.
Multi-GPU обучение
Для моделей, которые не помещаются на одну GPU:
# FSDP (рекомендуется для 2+ GPU)
accelerate launch --multi_gpu --num_processes 2 train.py
Или через DeepSpeed ZeRO Stage 2:
accelerate launch --config_file ds_config.yaml train.py
Частые ошибки
CUDA OOM при обучении
- Уменьшите
per_device_train_batch_size(до 1) - Увеличьте
gradient_accumulation_steps(компенсация) - Включите
gradient_checkpointing=True - Уменьшите
max_seq_length - Уменьшите ранг
r
NaN loss
- Убедитесь:
bnb_4bit_compute_dtype=torch.bfloat16(не float16!) - Уменьшите learning rate
- Добавьте
max_grad_norm=0.3(gradient clipping) - Проверьте датасет на пустые / битые примеры
Модель не учится (loss не падает)
- Увеличьте learning rate (попробуйте 3e-4)
- Увеличьте ранг
r(16 → 64) - Добавьте MLP-слои в
target_modules - Проверьте формат данных (должен совпадать с chat template модели)
- Убедитесь, что достаточно данных (минимум 100 примеров)
Выбор GPU для файнтюнинга
| Бюджет | GPU | Лучшая модель для QLoRA |
|---|---|---|
| ~$300 | RTX 4060 8GB | 7B (r=32, batch=2) |
| ~$400 | RTX 4060 Ti 16GB | 13B (r=32, batch=2) |
| ~$600 | Б/у RTX 3090 24GB | 32B (r=16, batch=1) |
| ~$1 800 | RTX 4090 24GB | 32B (r=32, batch=2) |
| ~$1 200 | 2× б/у RTX 3090 | 70B (r=16, batch=1) |
Для серьёзного файнтюнинга больших моделей (32B+) аренда GPU-сервера с A100 или RTX 4090 — самый экономичный вариант.
Итог
| Параметр | Рекомендация |
|---|---|
| Метод | QLoRA (экономит VRAM) |
| Ранг | r=32 (дефолт), r=64 для сложных задач |
| Target modules | Все attention + MLP слои |
| Learning rate | 2e-4 с cosine scheduler |
| Оптимизатор | paged_adamw_8bit |
| Compute dtype | bfloat16 (обязательно!) |
| Данные | 500+ качественных примеров |
LoRA/QLoRA демократизировали файнтюнинг — теперь дообучить 7B модель можно на GPU за $300, а 70B — на паре б/у RTX 3090.
Нужен мощный GPU для файнтюнинга? Арендуйте GPU-сервер в облаке Intelion — RTX 4090, A100, H100 с оплатой по минутам.
#GPU
#LLM
#VRAM
#LoRA
#QLoRA
#файнтюнинг
#PEFT
#обучение