24 / 37 · Адаптация и эффективные модели
Дообучение
Продолжить обучение предобученной модели на размеченной задаче: что обучать (всё или только новый выходной слой), с каким шагом обучения и чего это стоит по памяти. Модель GPT-2 на задаче тональности даёт 0.890, если обучать всё, 0.737 — только выходной слой, и 0.900, если сначала обучить выходной слой, а затем всё.
Перенос обучения в NLP · GPT и авторегрессионное языковое моделирование · Градиентный спуск
На этой странице 12
Заметка о переносе обучения показала, что обучение всего предобученного энкодера на задаче дало на AG News больше, чем считывание его замороженных признаков: 0.949 на отложенной десятой части обучающей выборки против 0.902 на тесте. Отсюда практические вопросы, на которые отвечает эта заметка: какие параметры обучать, с каким шагом обучения, в каком порядке и во что обходится выбор. Эксперименты переходят на модель из одного декодера и новую задачу, чтобы выводы не были привязаны к BERT.
Обозначения. Предобученные параметры (тело модели), выходной слой задачи с параметрами , инициализированными случайно; шаг обучения ; функция потерь — кросс-энтропия задачи.
Постановка#
Задача: бинарная тональность на Stanford Sentiment Treebank (SST-2), фразы из рецензий на фильмы с метками «положительная» или «отрицательная»; используются 50 000 из 67 349 обучающих фраз, а валидационная часть из 872 фраз служит тестом (официальные тестовые метки скрыты). На обучении 44% отрицательных и 56% положительных — близко к балансу, поэтому приводится доля правильных ответов.
Модель: GPT-2 small (124 млн параметров, из заметки о GPT) с линейным выходным слоем на скрытом состоянии последнего токена без паддинга. В каузальной модели только последняя позиция видела весь вход, поэтому только она может подытожить фразу; соглашение BERT с [CLS] читает первую позицию, потому что там каждая позиция видит всё. В токенизатор добавляется токен [PAD], и таблица эмбеддингов вырастает на одну строку.
Обучение: AdamW, размер батча 128, 1000 шагов (около 2.6 прохода по 50 000 фраз), смешанная точность, оценка каждые 250 шагов.
Отправная точка: обучать всё#
Полное дообучение обновляет и вместе одним оптимизатором:
Шаг обучения — , на три порядка меньше , с которым небольшой трансформер обучался с нуля в заметке об архитектуре. Предобученные веса уже кодируют то, что модель знает; большой шаг разрушает это прежде, чем выходной слой научится этим пользоваться, — такой провал называется катастрофическим забыванием (catastrophic forgetting). Маленькие шаги сдвигают тело модели ровно настолько, насколько требует задача.
Результат: 0.890 правильных ответов на валидации, функция потерь 0.277.
Цена: оптимизатор хранит две оценки моментов на параметр, а обратный проход — градиент на параметр. В 32-битных числах 124 млн весов занимают 0.5 ГБ, градиенты — ещё 0.5 ГБ, состояния AdamW — 1.0 ГБ, и это без активаций: примерно вчетверо больше памяти самой модели. Для модели на 7 млрд параметров та же арифметика даёт 112 ГБ — больше, чем вмещает один GPU, и именно это число берётся сократить заметка о PEFT.
Линейное зондирование: обучать только выходной слой#
Заморозить и обучать только с бо́льшим шагом (: выходной слой начинает со случайных значений, и забывать ему нечего). Выход тела модели — фиксированный признак, а выходной слой — логистическая регрессия поверх него, как в эксперименте с замороженными признаками из предыдущей заметки, только здесь признаки вычисляются на лету.
Результат: 0.737, функция потерь 0.541.
Отставание от полного дообучения — 15 пунктов. Скрытое состояние последнего токена языковой модели обучалось предсказывать следующий токен, а не разделять тональности, и линейное считывание находит лишь часть сигнала. Вектор [CLS] BERT на AG News в похожем режиме дал 0.902, но это сравнение меняет сразу модель, задачу, данные и обучение выходного слоя. По нему нельзя понять, присутствует ли тема в представлении линейнее, чем тональность, или двунаправленный итоговый токен — лучший признак, чем каузальное состояние последней позиции. Обе гипотезы правдоподобны; чтобы проверить любую из них, нужно сравнение, меняющее один фактор: например, одна и та же модель, зондируемая на обеих задачах, или энкодер и декодер близкого размера, зондируемые на SST-2. Линейное зондирование (linear probing) — это измерение того, что содержит представление, и дешёвый, но слабый классификатор.
По времени оно вышло примерно таким же, как полное дообучение (6.5 против 7.5 минуты): каждый шаг всё равно выполняет полный прямой проход, а обратный проход через замороженное тело пропускается, но при таком размере не был основной статьёй затрат. Зондирование экономит память, а не время.
LP-FT: сначала выходной слой, потом всё#
Kumar et al. (2022) показали, что такое двухэтапное расписание (линейное зондирование, затем дообучение) лучше сохраняет предобученные признаки, чем дообучение со случайным выходным слоем, причём сильнее всего выигрыш на данных, отличающихся от распределения дообучения. Здесь полное дообучение начинается с выходного слоя, обученного линейным зондированием выше, и идёт при .
Результат: 0.900, функция потерь 0.258 — на пункт выше дообучения с нуля при той же цене плюс один прогон зондирования.
| Режим | Обучается | Доля верных (валидация) | Потери (валидация) | |
|---|---|---|---|---|
| Полное дообучение | 124 млн | 0.890 | 0.277 | |
| Линейное зондирование | 1536 | 0.737 | 0.541 | |
| LP-FT | 1536, затем 124 млн | , затем | 0.900 | 0.258 |
Три режима дообучения: что и когда обучается
Разница в один пункт между первой и третьей строками — на пределе того, что могут различить 872 примера: это 9 фраз (один пример — 0.11%), а стандартная ошибка одной доли верных около 0.9 на 872 примерах равна , то есть одному пункту. Поэтому в этом прогоне наблюдалось 0.900 против 0.890: это согласуется с механизмом выше, но не упорядочивает два режима и не доказывает, что они равноценны.
Гиперпараметры, которые важны#
- Шаг обучения — главный: от до для энкодеров, меньше для больших декодеров. Слишком большой — модель забывает; слишком маленький — не сдвигается.
- Расписание. Линейный прогрев на первых нескольких сотнях шагов, затем затухание — выбор по умолчанию для моделей post-norm и безвредный для pre-norm.
- Эпохи. Два–четыре прохода по размеченной выборке; больше — переобучение на малых выборках.
- Затухание весов 0.01 и дропаут на уровне предобучения; оба регуляризуют модель, у которой параметров гораздо больше, чем примеров в задаче.
- Seed. На малых выборках запуски различаются на пункт и больше в зависимости от seed и порядка данных; решение требует нескольких запусков (Dodge et al., 2020).
Паддинг до длины батча, а не всего набора данных#
Батч — это тензор, поэтому у всех его последовательностей должна быть одна длина: короткие дополняются паддингом, а маска внимания скрывает его (заметка о токенизации). Вопрос в том, до какой длины. Дополнить весь набор данных до одного максимума просто, но вычисления тратятся на позиции, которые всё равно замаскированы. Динамический паддинг (dynamic padding) токенизирует каждый пример один раз, без паддинга, и дополняет только при формировании батча — до самой длинной последовательности этого батча. Батчи перемешиваются заново каждую эпоху, так что их длины заранее неизвестны; паддингу место в функции, которая собирает примеры в батч (collate function).
Разобранный пример (игрушечные длины). Батч из восьми фраз длиной 5, 9, 12, 7, 23, 4, 10 и 6 токенов содержит 76 настоящих токенов. Дополненный до 128, он занимает 1024 позиции, из которых настоящих 7.4%; дополненный до своей самой длинной фразы, 23, — 184 позиции, из которых настоящих 41.3%. Стоимость полносвязных блоков пропорциональна числу позиций — здесь она в 5.6 раза меньше. Self-attention сравнивает каждую пару позиций внутри последовательности: пар против , в 31 раз меньше.
Предсказания не меняются с точностью до округления: позиции паддинга исключены из внимания маской, а классификатор читает настоящий токен. Здесь это последний токен, не являющийся паддингом, найденный по маске внимания; такой выбор работает при любой длине дополнения, если паддинг стоит справа. Группировка примеров близкой длины в один батч убирает большую часть оставшегося паддинга ценой менее случайных батчей.
Что изменилось#
| Замороженные признаки + линейная модель | Дообучение | |
|---|---|---|
| Обновляемые параметры | Выходной слой | Выходной слой и тело |
| Шаг обучения | Большой (случайный слой) | Маленький (предобученное тело) |
| Память | Только выходной слой | ≈ 4 × размер модели в fp32 |
| Качество признаков | Зафиксировано предобучением | Подстроено под задачу |
| SST-2, GPT-2 small | 0.737 | 0.890 / 0.900 (LP-FT) |
Ограничения#
- Одна полная копия на задачу. Дообученные — новый артефакт на 124 млн параметров (или 7 млрд); десять задач — десять копий.
- Память растёт вместе с моделью: веса, градиенты и состояния оптимизатора.
- Забывание. Дообученная модель специализирована; её общие способности ухудшаются.
- Шум. Малые валидационные выборки не различают разницу в пункт.
- Признаки последнего токена слабы. Представление каузальной модели не предназначено для классификации; энкодер того же размера для этой задачи часто лучше и дешевле, хотя на SST-2 курс их не сравнивает.
Что нужно запомнить#
- Дообучение: обучать тело и выходной слой вместе с маленьким шагом (здесь порядка –); большие шаги стирают предобучение.
- Линейное зондирование: заморозить тело, обучать выходной слой с бо́льшим шагом; дёшево по памяти, ограничено тем, что представление уже кодирует (здесь 0.737).
- LP-FT: сначала зондирование, затем дообучение начиная с обученного выходного слоя; здесь 0.900 против 0.890, разница в пределах шума, так что довод в его пользу — механизм и результаты Kumar et al., и проверять его нужно на каждой задаче.
- Память при полном дообучении — примерно вчетверо больше весов модели в fp32.
- Каждая задача, дообученная так, даёт полную копию модели.
- Токенизировать один раз без паддинга и дополнять каждый батч до его собственной самой длинной последовательности; с маской внимания и паддингом справа предсказания не меняются, а вычисления сокращаются вместе с паддингом.
Ноутбук#
week10_PEFT.ipynb. Номера ячеек считают все ячейки, включая текстовые, начиная с 1. Приведённые числа взяты из прогона, сохранённого в курсе; у ячеек, изменённых с тех пор под текущие версии библиотек, сохранённого выхода нет.
- Ячейки 4–7 загружают SST-2 (
train[:50000]иvalidation); ячейка 19 печатает доли классов (0.442 / 0.558 на обучении, 0.491 / 0.509 на валидации). - Ячейки 10–14 загружают GPT-2 с выходным слоем для классификации последовательностей, добавляют
[PAD], расширяют эмбеддинги и печатают 124 442 112 параметров. МетодforwardобёрткиModelпрогоняет трансформер, выбирает скрытое состояние с индексомattention_mask.sum(-1) - 1(последний настоящий токен) и применяет слойscore. - Ячейка 23 определяет цикл обучения (AdamW, кросс-энтропия,
torch.autocastво float16, оценка каждые 250 из 1000 шагов с кривыми функции потерь и доли правильных ответов) иevaluate. - Ячейки 25–27: полное дообучение при , функция потерь на валидации 0.2772 и доля правильных ответов 0.8899.
- Ячейки 31–34: линейное зондирование (
AdamW(model.model.score.parameters(), lr=1e-4)), 0.5412 и 0.7374; выходной слой сохраняется вhead.pt. - Ячейки 56–60: LP-FT, загрузка
head.ptи дообучение всего при : 0.2580 и 0.9002. - Ячейки 62–64 печатают предсказания с вероятностями для десяти валидационных фраз.
Ячейки 35–54 (LoRA и настройка промпта в той же постановке) относятся к следующей заметке.
Ноутбук о LLM курса HSE-LAMBDA Deep Generative Models, Transformers-LangChain.ipynb, даёт рецепт с Trainer для задачи того же рода в текстовых ячейках 32–35, которые не запускаются (ячейки нумеруются так же). Он дообучает distilbert-base-uncased на предложениях из рецензий на фильмы Rotten Tomatoes с шагом обучения , размером батча 8, 2 эпохами и оценкой каждые 500 шагов (значение по умолчанию, когда выбрана стратегия "steps"). Набор данных токенизируется один раз через map(batched=True) без паддинга, а DataCollatorWithPadding(tokenizer=tokenizer) дополняет каждый батч до его самой длинной последовательности — это описанный выше динамический паддинг. Перед запуском нужно поменять две детали: текущие версии Transformers принимают только eval_strategy и отвергают evaluation_strategy, а оценка идёт на тестовой части, хотя в наборе данных есть валидационная — именно за ней следят во время обучения.
Дальше#
Полное дообучение даёт лучшую точность и стоит полной копии модели плюс вчетверо больше памяти при обучении. Следующая заметка оставляет тело замороженным и добавляет немного новых параметров в правильных местах, так что та же задача SST-2 выучивается до той же точности при обучении 0.24% весов.
Литература#
- A. Kumar, A. Raghunathan, R. Jones, T. Ma, P. Liang. Fine-Tuning can Distort Pretrained Features and Underperform Out-of-Distribution. ICLR, 2022. LP-FT.
- J. Howard, S. Ruder. Universal Language Model Fine-tuning for Text Classification. ACL, 2018. Разные шаги обучения для разных слоёв и постепенная разморозка.
- J. Dodge, G. Ilharco, R. Schwartz, A. Farhadi, H. Hajishirzi, N. Smith. Fine-Tuning Pretrained Language Models: Weight Initializations, Data Orders, and Early Stopping. arXiv, 2020.
- R. Socher et al. Recursive Deep Models for Semantic Compositionality Over a Sentiment Treebank. EMNLP, 2013. SST.
- A. Wang et al. GLUE: A Multi-Task Benchmark and Analysis Platform for Natural Language Understanding. BlackboxNLP, 2018. Использованное здесь разбиение SST-2.
- I. Loshchilov, F. Hutter. Decoupled Weight Decay Regularization. ICLR, 2019. AdamW.