2.97K subscribers
201 photos
6 files
400 links
Квантование & Прунинг & Дистилляция

Блог про сжатие сетей и не только.
От древнейших времен по настоящее время.
Download Telegram
Channel created
Channel photo updated
QLoRA: Efficient Finetuning of Quantized LLMs

Первый пост будет посвящен работе, относительно свежей по меркам Deep Learning, где, как известно, статьи отличаются небольшим сроком годности.

В последние несколько лет мы стали свидетелями бешеного прогресса глубокого обучения во всех его ипостасях, проявлениях и приложениях, и флагманом прогресса выступает область NLP (Natural Language Processing). Разрастающиеся в ширину и глубину модели, обученные на колосалльных обьемах данных, дополненные современными плюшками и прибамбасами в виде instruction finetuning, RLHF (reinforcement learning on human feedback) и прочими другими, демонстируют способности, которые еще не так давно казались бы чем-то из разряда научной фантастики.

Однако выдающиеся возможности языковых моделей не даются за бесплатно, всему есть цена. Характерный размер современных языковых моделей используемых в новомодных чатботах по типу Alpaca, Vicuna и прочих представителей животного мира исчисляется порядка десятков миллиардов параметров, что делает традиционный инференс на пользовательских GPU и любимом колабе затруднительным 😔.

Отсюда возникает естественный вопрос на сжатие таких моделей, и квантизация (представление чисел в более низкой точности) на текущий момент, по всей видимости, является наиболее ходовым решением.

Но если хочется пользоваться не просто готовой моделькой, а еще дообучить на какую-то специфичную задачу? Как бы много данных не видела сеть в процессе своего обучения, для достижения хорошего качества в конкретном приложении обыкновенно требуется дообучать модель, и существует множество способов и вариантов эффективного по памяти и вычислительным ресурсам техник по дообучению большихх сетей - различные адаптеры (среди них наиболее популярна LoRA, заслуживающая отдельного разбора), prompt tuning, in context learning и иже с ними.

И в статье, которой посвящен сегодняшний выпуск, предложили эффективный алгоритм квантования весов и последующую процедуру дообучения модели под чатбота, в результате которой получается весьма годный ассистент Guanaco, который, как утверждается, бьет всех open-source конкурентов.

Если перечислить списком основные результаты статьи, выходит что-то такое:

1. Новый тип для хранения весов 4-bit NormalFloat (NF4).
2. Двойное квантование (Double quantization).
3. Paged отпимизаторы
4. Экстенстивная валидация модели на разных бенчмарках и исследование самих бенчмарков
Теперь пройдемся по каждому из пунктов подробнее.

1) При квантовании весов, каждый параметр принимает одно из небольшого количества возможных значений. Скажем, если квантование в 4 бита, то у нас 2^4 = 16 вариантов. Но, как выбрать эти значения? Самая очевидная и по существу используемая на практике стратегия - задать максимальное и минимальное значение, которое может принимать вес, и разбить интервал на одинаковые промежутки. И если точки распределены равномерно, то это и правда оптимальный выбор. Однако на практике веса скорее распределены в соотвествии с нормальным распределением, имеющим колоколообразную форму. То есть веса обычно кучкуются ближе к центру интервала и вероятность их встретить убывает к краям интервала. Отсюда возникает идея выбрать интервалы таким образом, чтобы в каждый интервал попадала примерно одна и та же доля весов.

На языке высокой науки значения, которые случайная величина не превышает с заданной вероятностью называется квантилями распределения. Например, 10% квантиль - такой значение, что слева от него лежит 10% массы распределения. Для некоторых случайных величин квантили ищутся легко, как для равномерного распределения, но для нормального распределения это табличные значения, которые приходится получать численными методами.
Авторы наглядно демонстрируют, что NormalFloat4 дает заметно большее качество по сравнению с обычным Float4.
2) Следующее ноу-хау данной работы - Double quantization (двойное квантование из квантовой механики здесь не причем!). При квантовании группы значений каждое число представляется в виде целого числа, домноженного на некоторое вещественное, называемое масштабом (scale). со сдвигом от некоторого значения (zero point) в случае ассиметричной квантизации (в данной статье рассматривается симметричная квантизация).
Вот так мы квантуем (получаем целые числа)
А вот так получаем значения с плавающей точкой из квантованных
Группы для квантования могут быть различного размера - можно зафиксировать один масштаб на весь тензор, но так как разные измерения тензора могут сильно отличаться масштабом, то шаг квантования (разность между ближайшими возможными значениями) может быть слишком велик для точного представления весов, посему выгодно брать меньшие группы, фиксируя масштаб для одной размености, скажем, либо даже для меньшей группы соседних весов. Однако, если брать слишком маленькие группы - то память, выделяемая на хранение scale, cтановится довольно существенной. Скажем, если хранить scale в fp32, то для при квантовании в группы из 64 весов, скейлы уже будут давать дополнительные 32 / 64 = 0.5 бита в среднем.

Возникает идея - а почему бы и не заквантовать сами скейлы (и так до бесконечности, но авторы решили ограничиться двумя квантованиями). В данной работе scale квантуется группами по 256 весов в 8 бит, что снижает накладные расходы на их использование до 8 / 64 + 32 / (64 * 256) = 0.127 бит в среднем на параметр. Данная процедура не приводит к просадке качества, но дает существенную экономию по памяти.
3) И еще одно нововведение - так называемые paged optimizers. У Нвидиевских GPU есть опция автоматической перекачки памяти с GPU на CPU RAM, если память видеокарты забивается. Причем данная перекачка не приводит к заметному замедлению процесса обучения. Весьма полезная фича, учитывая сколько нейронов в голове программистов и исследователей убивает ежесекудно сообщение CUDA error: out of memory. ☠️

Низкоранговый Адаптер (LoRA, заслуживающая отдельного выпуска) не квантуется и хранится в bf16. Но учитывая его мизерный вес по сравнению со всей моделью - это и не требуется. Итого, в конечном виде обученный на целевой задаче имеет следующий вид:
Где первый член - это дважды квантованный вес, а второй - низкоранговая добавка. Double dequant - расквантование скейлов с последующим расквантованием весов.
4) Отдельного упоминания и уважения заслуживает валидация их модели и конкуретных на ряде бенчмарков.

Сначала авторы демонстрируют, что при finetuning, QLoRA имеет примерно такое же качество, как и дообучение всей модели и LoRA для модели с весами с плавающей точкой (без квантования).
Далее авторы дообучают квантованную сеть на различных датасетах, и замеряют качество работы на бенчмарках, тестирующих language understanding и качество ответов модели на чатбот-бенчмарках, замеренное с помощью GPT-4 и человеками. Среди датасетов берутся доступные публично данные:

- Self-Instruct
- Longform
- Chip2
- HH-RLHF
- Unnatural Instruct
- OASST1 (и конечная модель Guanaco обучается именно на нем)
- Alpaca
- Flan v2
Для замеров способности модели понимать языки используется стандартный MMLU бенчмарк. При обучении на датасете FLAN v2 (здоровенная смесь из множества разнообразных задач на инструкции) конечная модель выдает наилучшее качество (вероятно из-за количества данных и их структуры).