Главная / Статьи / LoRA и QLoRA простыми словами: дообучение 7B-модели без 100 ГБ видеопамяти

LoRA и QLoRA простыми словами: дообучение 7B-модели без 100 ГБ видеопамяти

Почему полное дообучение требует 80–100 ГБ, как низкоранговые адаптеры сокращают обучаемые веса до 1,6%, как выбрать ранг и целевые слои и что добавляет QLoRA.

1064 слов

LoRA становится понятной, только когда видно, где она находится между предобучением и дообучением, так что начнём с этого.

Предобучение и дообучение

Предобучение происходит, когда модель создают впервые. Она сама учится на последовательностях текста, без всякой разметки: обучающий текст сам даёт и входы, и цели, а в результате получается универсальная базовая модель.

Знаний у такой базовой модели много, но определённому формату, шаблону или инструкции она не следует. Довольно часто она просто продолжает то, что вы набрали, и дописывает в конец ещё слов. Это исправляет дообучение. Вы обучаете модель на размеченных примерах из инструкции, входных данных и желаемого ответа, и она узнаёт, как выглядят хорошие ответы.

Допустим, вам нужна модель для юридических запросов. Обучать с нуля незачем, если уже есть предобученная модель с большим запасом знаний о предметной области. Вы дообучаете её, чтобы она отвечала по делу.

Почему полное дообучение так тяжело

Обновление всех параметров съедает память. Возьмём 7B-модель Llama с такой конфигурацией:

Model size: 7 billion parameters
Training dtype: BF16 / FP16
Optimizer: AdamW
Sequence length: 2048

Одна только загрузка базовой модели занимает 14 ГБ. При полном дообучении обучается каждый параметр, значит, каждому нужен градиент, и если хранить градиенты в BF16 или FP16, это ещё 14 ГБ. Оптимизатор AdamW просит сверху примерно 56 ГБ и может держать копию параметров в FP32, а это ещё около 28 ГБ. Часть уходит и на активации. В сумме выходит 80–100 ГБ — слишком много для узкой прикладной задачи, которая к тому же не так уж сложна.

Что делает LoRA

LoRA расшифровывается как Low-Rank Adaptation, низкоранговая адаптация. Она дообучает модель, не обновляя каждый вес по отдельности. Все исходные веса заморожены, а учится пара небольших матриц.

Как маленькие матрицы могут управлять большой моделью? Подумайте, что предобученная модель уже знает: английский, грамматику, шаблоны рассуждений, программирование, факты. Если теперь нужно, чтобы она отвечала на юридические вопросы в определённом стиле, заново учить язык ей не надо. Достаточно направить то, что уже есть. LoRA делает ставку на то, что такое изменение обычно укладывается в структуру меньшей размерности:

ΔW = AB

Миллиарды выученных моделью весов остаются нетронутыми. LoRA не трогает W и добавляет поправку поверх:

W_new = W + ΔW

Разбираем на числах

Представьте трансформер с одним линейным слоем:

X -> W -> Output

Пусть W имеет размер 1000 на 1000. Тогда в ней:

1000 x 1000 = 1,000,000 parameters

Полное дообучение обучает все эти параметры, а в настоящих LLM такие матрицы повсюду, поэтому у 7B-модели обучать нужно около 7 млрд параметров.

С LoRA вы создаёте две узкие матрицы, A и B, и выбираете ранг, например r = 8:

A = [1000 x 8]
b = [8 x 1000]

Их произведение имеет ту же форму, что и W, поэтому сумма корректна:

W_new = W + AB

[1000×1000] + [1000×1000]

Экономия возникает из того, как мало параметров в двух узких матрицах:

A: 1000 × 8 = 8,000
B: 8 × 1000 = 8,000

Total = 16,000 parameters

Сравним два подхода:

Full fine-tuning:
1,000,000 parameters

LoRA:
16,000 parameters

Для этого слоя обучаемых параметров всего 1,6% от исходного числа.

Что значит ранг

Ранг — один из главных гиперпараметров LoRA, и он задаёт ёмкость адаптера. Низкий ранг, например 4 или 8, даёт адаптер поменьше: он расходует меньше памяти, но менее гибок. Сложным задачам может понадобиться 32, 64 или 128. Более высокий ранг стоит больше памяти и не означает автоматически лучшее качество, ведь он может добавлять шум. Попробуйте несколько рангов и оставьте тот, что работает лучше.

Куда ставить адаптеры

LoRA прикрепляет небольшие обучаемые матрицы к замороженному трансформеру, но матриц в трансформере много. В упрощённом блоке decoder-only их несколько, а модель может повторять этот блок 32, 40, 80 и более раз. Вопрос LoRA в том, каким из этих матриц W нужна обучаемая поправка BA. Три распространённые стратегии:

Стратегия 1: только q_proj и v_proj. Адаптер на q_proj может менять то, как представления формируют запросы к релевантному контексту, а адаптер на v_proj меняет информацию, которую передают токены, на которые направлено внимание.

Стратегия 2: все проекции внимания. Добавьте адаптеры на q_proj, k_proj, v_proj и o_proj, и LoRA сможет менять все основные обучаемые линейные преобразования во внимании. Гибкости больше, но и обучаемых параметров тоже.

Стратегия 3: проекции внимания плюс слои MLP. Это более крупная и сильная универсальная конфигурация:

ATTENTION

q_proj       ✅
k_proj       ✅
v_proj       ✅
o_proj       ✅


MLP

gate_proj    ✅
up_proj      ✅
down_proj    ✅

Трансформер — это не только внимание. MLP выполняет огромную часть обучаемых преобразований признаков, так что, охватив и его, вы заметно расширяете свободу дообучения.

Решила ли LoRA проблему с памятью?

Нет, не полностью. Она сокращает число обучаемых параметров примерно на 99%, но видеопамять на 99% не уменьшается: базовую модель всё равно нужно загрузить, прямой проход всё равно выполняется, да ещё с небольшими дополнительными вычислениями. Настоящий выигрыш — в градиентах и состояниях оптимизатора. Хранить градиенты для 7 млрд параметров больше не нужно.

QLoRA

QLoRA, квантованная низкоранговая адаптация, развивает идею ещё на шаг. Раз базовые веса всё равно заморожены, их можно квантовать до 4 бит. 7B-модель, которой в BF16 нужно 14 ГБ, сжимается примерно до 3,5–5 ГБ. Поэтому 7B-модель можно дообучить через QLoRA на одной игровой видеокарте, тогда как обычное полное дообучение потребовало бы нескольких GPU с большим объёмом памяти.