Перейти к содержимому
ПереводыDatawhale и китайские курсы

«Большие языковые модели», главы 7–9: инструктивное дообучение, выравнивание, декодирование и сжатие

Конспект глав 7–9 учебника RUC AI Box: как собирают и смешивают инструкции, эксперименты авторов по SFT и LoRA на LLaMA-2, расчёт памяти для LoRA и QLoRA; RLHF от модели награды до PPO, LLaMA-2, RLAIF и DPO, сравнение SFT и RLHF; стратегии декодирования, почему генерация упирается в память, FlashAttention, PagedAttention, спекулятивное декодирование, квантование, дистилляция и прунинг.

  • Глава 7 — SFT. Откуда брать инструкции (NLP-наборы, реальные диалоги, синтетика), как их улучшать (сложность, разнообразие, отбор), как смешивать и учить. Самое ценное — собственные эксперименты авторов на LLaMA-2 и расчёт памяти для LoRA: 108 ГБ против 14 ГБ для модели 7B.
  • Глава 8 — выравнивание. Критерии 3H, RLHF по шагам (данные, модель награды, PPO с выводом из policy gradient), опыт InstructGPT и LLaMA-2, RLAIF, DPO и другие методы без RL, и честное сравнение SFT и RLHF.
  • Глава 9 — использование. Стратегии декодирования и их типичные настройки; количественный анализ, почему генерация токенов упирается в пропускную способность памяти («стена памяти»); системные и алгоритмические ускорения; квантование с практическими выводами; дистилляция и прунинг.
Раздел книгиУрок курсаЧто даёт книга сверх урока
§7.1–7.2 данные и обучение SFT6.1.2 SFTобзор способов собрать инструкции, пропорции FLAN v2, эксперименты на LLaMA-2
§7.3 LoRA и PEFT6.2.1 LoRA, 6.2.2 Практикаформула памяти 2P+16PLoRA2P + 16P_{\text{LoRA}}, время дообучения 7B–65B
§8.2 RLHF и PPO6.3.2 RLHF и PPO, 6.0.3 Actor-critic и PPOтри способа учить модель награды, приёмы LLaMA-2
§8.3 DPO и др.6.3.3 DPOобзор «выравнивания без RL» до DPO
§9.1 декодирование4.1.3 Сэмплированиештрафы за повтор, контрастное декодирование, настройки известных моделей
§9.2 эффективность7.1.1 Префилл и декодирование, 7.1.2 Сервингтаблицы арифметической интенсивности для каждой операции
§9.3–9.4 сжатие7.2.1 Квантование, 7.2.2 Локальные LLMсобственные замеры авторов: качество и память FP16/INT8/INT4
  1. Из готовых NLP-наборов. К паре «вход–выход» дописывают описание задачи («переведи это предложение на английский»). Без описания качество заметно падает — именно описание учит следовать инструкциям. Трюк: «перевернуть» пример (по ответу сгенерировать вопрос) и получить новую задачу. Итог этой линии — FLAN v2, около 20 млн примеров.
  2. Из реальных диалогов. InstructGPT брала настоящие запросы к API OpenAI и дописывала ответы силами разметчиков (данные не открыты); открытые аналоги — Dolly, OpenAssistant, многоходовые диалоги ShareGPT.
  3. Синтетика. Self-Instruct: 175 написанных людьми примеров → модель по образцам придумывает новые задачи и ответы → фильтр отсекает похожие, слишком короткие/длинные и неразрешимые. Так получены Self-Instruct-52K и Alpaca-52K. Evol-Instruct (WizardLM) «выращивает» сложность: углубление пятью способами (добавить ограничение, углубить, конкретизировать, добавить шаги рассуждения, усложнить вход) и расширение — новая задача той же области, но реже встречающаяся. Ещё есть обратный перевод инструкций: взять хороший человеческий текст как ответ и сгенерировать к нему вопрос.
  • Формат. Смесь примеров с демонстрациями и без них, с цепочками рассуждений и без улучшает и zero-shot, и few-shot. Но «больше текста в инструкции» не всегда лучше: советы и оговорки могут даже навредить.
  • Количество. На FLAN-T5 рост числа инструкций 0,18M → 5,55M → 7,2M → 17,26M давал прирост, который после 7,2M почти остановился. Для диалога хватает гораздо меньшего: Alpaca — 52K синтетических примеров, LIMA — всего 1000 отборных для LLaMA-65B; но малым набором трудно покрыть и диалог, и классические NLP-задачи (Orca решала это 5M ответами GPT-4 и ChatGPT с пошаговыми объяснениями).
  • Переписывание и отбор. YuLan-Chat-3 переписывала инструкции под 293 темы, собранные с Чжиху («перепиши для темы „образование“»); AlpaGasus оставила 9K из 52K примеров Alpaca с лучшей оценкой GPT-4 и не потеряла в качестве; YuLan-Chat-3 ещё и выкидывала слишком лёгкие и слишком трудные примеры по перплексии модели.
  • Главный вывод авторов: качество важнее количества; человеческие разнообразные данные — лучше всего; синтетикой от сильных моделей количество компенсирует недостаток качества.

Что даёт SFT. Выигрывают модели от 77M до 540B параметров, и дообученная маленькая может обойти недообученную большую; стоимость — порядка одной десятитысячной от предобучения. SFT на чисто английских задачах (P3) улучшила многоязычную BLOOM в задаче дополнения предложений больше чем на 50% (BLOOMZ-P3). Для областей — Med-PaLM, китайская медицинская модель BenTsao поверх LLaMA.

  • Потерю считают только по ответу, не по инструкции.
  • Батч и скорость обучения малы: InstructGPT (175B) — батч 8 и постоянная скорость около 5⋅10−65\cdot10^{-6}; Alpaca (7B) — батч 128, разогрев до 2⋅10−52\cdot10^{-5} и косинус.
  • Многоходовый диалог подают целиком одной последовательностью и маскируют потерю на репликах пользователя — вместо того чтобы резать диалог на много примеров с повторяющимися префиксами.
  • Смешивание наборов: брать вперемешку NLP-задачи, диалоги и синтетику; ограничивать вклад огромных наборов «потолком». В FLAN v2 смесь — 46% FLAN, 27,9% T0, 24,2% NIV2, 1,8% CoT, а потолки — 30 000, 20 000, 5 000 и 100 000 примеров на задачу соответственно.
  • Многоэтапность и регуляризация. YuLan-Chat-3: сначала массовые NLP-инструкции, потом диалоги и синтетика (с подмесью NLP против забывания). OPT-IML подмешивала 5% данных предобучения в SFT, GLM-130B — наоборот, 5% инструкций в предобучение, а MiniCPM вставляет между этапами «отжиг» на смеси качественного предобучающего текста и инструкций.

Авторы дообучили LLaMA-2 7B и 13B на пяти наборах примерно одного размера (по 50–70K примеров: выборка FLAN v2, ShareGPT, Alpaca, Alpaca после Evol-Instruct, Alpaca после переписывания под темы; батч 128, постоянная скорость 10−510^{-5}, 3 эпохи, сервер 8×A800). Оценка — доля побед над text-davinci-003 на вопросах AlpacaFarm (судья ChatGPT) и точность на MMLU и BBH. Выводы:

  • Формат данных должен совпадать с задачей. FLAN v2 лучше всех на MMLU и BBH, но в диалоге проваливается: у 7B доля побед 12,4% против 55,5% у ShareGPT.
  • Сложность и разнообразие помогают. Переписывание Alpaca под темы подняло диалоговую метрику 13B с 48,5 до 58,2 — почти до уровня ShareGPT.
  • Больше модель — лучше следование инструкциям: 13B впереди 7B во всех вариантах; на ShareGPT MMLU растёт с 49,7 до 56,8.

W=W0+ΔWW = W_0 + \Delta W, где ΔW=AB⊤\Delta W = AB^\top, A,B∈RH×RA, B \in \mathbb R^{H\times R}, R≪HR \ll H; W0W_0 заморожена, после обучения AB⊤AB^\top вливают обратно, и при выводе накладных расходов нет.

Подсчёт памяти книги (без ZeRO, только веса и оптимизатор): замороженные веса FP16 — 2P2P байт; у обучаемых PLoRAP_{\text{LoRA}} параметров те же 16 байт на параметр, что при полном обучении. Итого

MLoRA≈2P+16 PLoRA,PLoRA=4⋅2⋅L⋅H⋅RM_{\text{LoRA}} \approx 2P + 16\,P_{\text{LoRA}}, \qquad P_{\text{LoRA}} = 4\cdot 2\cdot L\cdot H\cdot R

(LoRA на четырёх матрицах внимания). Для LLaMA-7B и R=8R=8: PLoRA=8 388 608P_{\text{LoRA}} = 8\,388\,608, память ≈ 13,6 млрд байт («14 ГБ») против 16P≈10816P \approx 108 ГБ при полном обучении. QLoRA хранит замороженные веса в 4 битах — ≈0,5P\approx 0{,}5P, что позволяет дообучать 65B на одной карте 48 ГБ.

Замер авторов (LoRA R=16R=16, длина 512, 3 эпохи Alpaca, A800 80G): 7B — одна карта, 2,3 ч; 13B — одна карта, 3,8 ч; 30B — одна карта, 10,2 ч; 65B — две карты, 26 ч. Для полного дообучения тех же моделей им понадобилось 2, 4, 8 и 16 карт. Обратная сторона: у 30B и 65B память почти целиком занята весами, батч падает до 1, и обучение сильно замедляется.

Другие методы PEFT — адаптеры (узкое «горлышко» внутри блока), prefix tuning и prompt tuning — книга описывает для полноты и отмечает, что для больших моделей их используют заметно реже LoRA. Из вариантов LoRA упомянута AdaLoRA (ранг распределяется по матрицам по их важности).

Три критерия 3H: полезность (helpful), честность (honest — в том числе выражать неуверенность), безвредность (harmless). Их трудно формализовать, отсюда идея учиться на человеческих предпочтениях. Конвейер RLHF: SFT → сбор сравнений → модель награды → RL (обычно PPO) с KL-штрафом за уход от исходной модели. Важная практика — отбор разметчиков: InstructGPT проверяла согласие кандидатов с разметкой самих исследователей (в проекте работали 40 разметчиков), Sparrow брала носителей британского английского с высшим образованием.

Языковая модель с линейной «головой», выдающей скаляр. Три способа обучения:

  1. Оценка по шкале — регрессия на человеческие баллы; страдает от разных строгостей разметчиков.
  2. Попарное сравнение — L=−E log⁡σ(rθ(x,y+)−rθ(x,y−))\mathcal L = -\mathbb E\,\log\sigma\big(r_\theta(x,y^+) - r_\theta(x,y^-)\big); сравнивать проще и согласованнее, чем ставить баллы.
  3. Ранжирование KK ответов — та же потеря по всем парам.

Приёмы: добавлять к попарной потере обычную LM-потерю на лучшем ответе (против переобучения); модель награды не меньше обучаемой (InstructGPT обходилась RM на 6B, LLaMA-2 инициализировала RM из того же чекпоинта, чтобы у них были одинаковые знания); при нескольких критериях — несколько моделей награды и взвешенная сумма r=∑iλirir = \sum_i \lambda_i r_i (например, строже к вредности, мягче к полезности). В книге есть и код модели награды поверх LlamaForCausalLM.

Книга выводит PPO по шагам: цель J(θ)=Eτ∼PθR(τ)J(\theta) = \mathbb E_{\tau\sim P_\theta}R(\tau) → policy gradient ∇J≈1N∑τR(τ)∇log⁡Pθ(τ)\nabla J \approx \frac1N\sum_\tau R(\tau)\nabla\log P_\theta(\tau) → преимущество A^t=Q(st,at)−V(st)\hat A_t = Q(s_t,a_t) - V(s_t) вместо сырой награды (иначе, как в примере книги, случайно выпавшее плохое действие с положительной наградой усиливается) → importance sampling с отношением rt(θ)=πθ(at∣st)/πθold(at∣st)r_t(\theta) = \pi_\theta(a_t|s_t)/\pi_{\theta_{\text{old}}}(a_t|s_t), чтобы несколько раз учиться на одной выборке → обрезка min⁡(rtA^t, clip(rt,1−ϵ,1+ϵ)A^t)\min\big(r_t\hat A_t,\ \mathrm{clip}(r_t, 1-\epsilon, 1+\epsilon)\hat A_t\big) или KL-штраф с адаптивным β\beta. Всего в работе четыре модели: политика, референс, критик (оценивает VV, инициализируется из модели награды) и модель награды.

Практика из книги: перед RL полезна выборка с отклонением (best-of-NN по модели награды и SFT на лучших ответах); LLaMA-2 прошла пять итераций RLHF — в первых четырёх только rejection sampling, затем PPO, — и каждый раз заново собирала предпочтения под текущую модель. LLaMA-2 учила две модели награды (полезность и безопасность), использовала около 1,5M открытых пар предпочтений из семи наборов и добавляла в попарную потерю зазор m(y+,y−)m(y^+, y^-) по степени предпочтения. Инженерный совет: держать обучаемые политику и критика на одном сервере, а замороженные модель награды и референс — на другом, обмениваясь по сети.

  • RLAIF: предпочтения ставит модель (Constitutional AI); по приведённым в книге результатам RLAIF сопоставим с RLHF, а в части задач лучше. Вариант Meta и NYU — модель сама оценивает свои ответы и учится на собственных парах через DPO; LLaMA-2 70B после таких итераций обошла на AlpacaEval 2.0 Claude 2, Gemini Pro и GPT-4 0613.
  • DPO: из KL-регуляризованной RL-задачи выражается оптимальная политика, и награда «сокращается»:
LDPO=−E log⁡σ ⁣(βlog⁡πθ(y+∣x)πref(y+∣x)−βlog⁡πθ(y−∣x)πref(y−∣x)).\mathcal L_{\text{DPO}} = -\mathbb E\,\log\sigma\!\left(\beta\log\frac{\pi_\theta(y^+|x)}{\pi_{\text{ref}}(y^+|x)} - \beta\log\frac{\pi_\theta(y^-|x)}{\pi_{\text{ref}}(y^-|x)}\right).
  • Другие «надзорные» методы — обычная SFT-потеря на хорошем ответе плюс вспомогательная: метки качества в префиксе («хороший ответ:», «ответ на 5 баллов:»), ранжирующие потери между хорошими и плохими ответами, контраст с ответами на другие вопросы (чтобы модель не отвечала всем одинаково).

SFT — клонирование поведения с потерей на уровне токенов («локальная» оптимизация по образцу учителя); RLHF — оптимизация на уровне всего ответа («глобальная»). Сводка книги: SFT простая и гибкая, но склонна к галлюцинациям, если учить модель вещам за пределами её знаний (особенно при дистилляции ответов сильной модели), и чувствительна к разнобою разметчиков. RLHF дополнительно повышает полезность, снижает вредность и галлюцинации, а сравнивать ответы людям легче, чем писать их; минусы — низкая эффективность использования выборки, нестабильность, чувствительность к гиперпараметрам и зависимость от хорошей SFT-модели на старте.

  • Жадный поиск и лучевой (обычно 3–6 лучей) с нормировкой на длину (делим логарифм вероятности на длину в степени α≈0,6\alpha \approx 0{,}6–0,70{,}7, иначе выигрывают короткие ответы).
  • Против повторов: запрет повторять nn-граммы (n=3n = 3–55), «мягкие» штрафы за присутствие и частоту (вычесть α\alpha или α⋅\alpha\cdotчисло повторов из логита; α≈0,1\alpha \approx 0{,}1–11).
  • Сэмплирование: температура, top-kk, top-pp и контрастное декодирование — брать разность логарифмов вероятностей большой и маленькой модели, чтобы поднять «содержательные» токены, которые большая модель знает, а маленькая — нет.
  • Настройки в известных работах: T5 и GPT-3 — 4 луча и штраф длины 0,6; Alpaca — top-kk 50, top-pp 0,9, температура 0,7; LLaMA на коде — температура 0,1 для pass@1 и 0,8 для pass@100.

Генерация делится на префилл (весь промпт за один проход, заполняем KV-кэш) и пошаговое декодирование (один новый токен, чтение всего кэша). Инструмент анализа — арифметическая интенсивность II = FLOPs / прочитанные байты. Если II меньше предела видеокарты Imax⁡I_{\max} = пиковые FLOPs / пропускная способность памяти, мы упираемся в память.

Числа книги для LLaMA-7B (H=4096H = 4096, D=128D = 128) при B=8B = 8, T=1024T = 1024: в префилле интенсивность линейных слоёв ≈2731\approx 2731, внимания ≈115\approx 115 — это упор в вычисления; при пошаговом декодировании у линейных слоёв I≤8I \le 8 — в десятки раз ниже предела A100. Это и есть «стена памяти»: каждый новый токен требует прочитать все веса.

def intensity_linear(H, tokens): # линейный слой: 1 / (1/H + 1/(B*T))
return 1 / (1 / H + 1 / tokens)
def intensity_attn(D, T): # внимание при префилле
return (1 + 1 / D) / (1 / D + 1 / T)
H, D, B, T = 4096, 128, 8, 1024 # LLaMA-7B, пример книги
print("префилл: линейные", round(intensity_linear(H, B * T), 2),
"| внимание", round(intensity_attn(D, T), 2)) # 2730.67 | 114.67
print("декодирование: линейные", round(intensity_linear(H, B), 2)) # 7.98
print("предел A100 ≈", round(312e12 / 2039e9)) # 153
P = 6.74e9 # параметров LLaMA-7B
for name, bw in [("A100", 2039e9), ("RTX 4090", 1008e9)]:
for bits in (16, 8, 4): # каждый токен = прочитать все веса
print(f"{name}, {bits} бит: не быстрее {bw / (P * bits / 8):.0f} ток/с при B=1")
# A100: 151 / 303 / 605 ток/с; RTX 4090: 75 / 150 / 299 ток/с

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

  • Системно: FlashAttention — блочное вычисление внимания без записи промежуточных матриц в видеопамять (в примере книги внимание LLaMA-2 7B при длине 2048 и батче 8 в десять раз быстрее); PagedAttention — KV-кэш страницами, как виртуальная память в ОС, без копирования при росте и без фрагментации; непрерывный батчинг (vLLM) — новые запросы подсаживаются в батч по мере освобождения мест, а не ждут самого длинного ответа.
  • Алгоритмически: спекулятивное декодирование — маленькая модель черновиком пишет несколько токенов, большая проверяет их за один проход (качество не меняется, ускорение около 2×); каскад (FrugalGPT) — сначала дешёвая модель, к дорогой — только если классификатор не доверяет ответу; полу-авторегрессия (Medusa: две дополнительные головы предсказывают 2-й и 3-й токены, а исходная модель проверяет); ранний выход из слоёв, когда распределение уже уверенное (низкая энтропия).

Пример спекулятивного декодирования в книге построен на первой фразе эссе Чжу Цзыцина «Вид со спины» (1925) — хрестоматийного текста, который знает каждый китайский школьник: «Мы с отцом не виделись больше двух лет, и больше всего я не могу забыть его спину» (перевод наш; в книге — китайский оригинал). Восемь слов продолжения большая модель получает за три проверки вместо восьми шагов.

xq=R(x/S)−Zx_q = R(x/S) - Z, обратно x~=S (xq+Z)\tilde x = S\,(x_q + Z); симметричное (Z=0Z = 0) и несимметричное, по тензору, каналу или группе; квантование после обучения (PTQ) и с обучением (QAT). Для LLM книга разбирает LLM.int8() (выбросы в активациях считаются отдельно в FP16), SmoothQuant (трудность переносится с активаций на веса), GPTQ (послойная оптимизация с учётом второго порядка) и AWQ (масштабирование весов, важных для активаций). Практические выводы:

  1. INT8 по весам почти бесплатен; 4 бита требуют хорошего метода. При равном объёме памяти лучше большая модель в 4 битах, чем вдвое меньшая в 8 битах — 60 ГБ модели в 4 битах обычно сильнее 30 ГБ модели того же семейства в 8 битах.
  2. Активации квантовать труднее весов: начиная с некоторого размера модели в них появляются большие выбросы.
  3. Потерю можно отыграть LoRA: 65B в 2 битах после дообучения адаптеров приближается к 13B в FP16.

Замер авторов на своих SFT-моделях: LLaMA-7B занимает 12,6 ГБ в FP16, 6,7 ГБ в INT8 и 3,9 ГБ в INT4, а точность на MMLU и BBH меняется в пределах одного-двух пунктов. Рекомендация книги: при нехватке памяти начинать с 4-битной модели.

Дистилляция — по ответам (логитам) учителя или по промежуточным признакам; «белый ящик» (доступ к внутренностям учителя) и «чёрный ящик» (только тексты учителя через API — так многие открытые модели учатся на ответах сильных закрытых). Прунинг — неструктурированный (обнуляем отдельные веса; SparseGPT) и структурированный (выкидываем головы, каналы, слои; Sheared LLaMA). Добавим от себя: неструктурированная разреженность лучше сохраняет качество, но без специальной поддержки в железе и ядрах почти не ускоряет вывод.

  1. Маска потерь для диалога. Возьмите шаблон чата своей модели из урока 6.1.2 и напишите функцию, которая по многоходовому диалогу строит labels с -100 на всех токенах пользователя и системы. Проверьте, что число токенов с потерей равно суммарной длине ответов ассистента.
  2. Память LoRA. Пересчитайте формулу 2P+16PLoRA2P + 16P_{\text{LoRA}} для Qwen3-8B с LoRA на всех линейных слоях (а не только на внимании) (как в нашем переводе рецепта LoRA, где target_modules включает и MLP) и сравните с реальным расходом видеопамяти при запуске.
  3. Знак и масштаб. Обучите модель награды на 1000 пар из любого открытого набора предпочтений двумя потерями: попарной и MSE по меткам 1/0. Какая лучше ранжирует отложенные пары?
  4. Потолок скорости. Измерьте токены в секунду при батче 1 для 7B-модели в FP16 и 4 битах (например, в llama.cpp из урока 7.2.2) и сравните с нашей прикидкой «пропускная способность / размер весов». Какую долю от потолка вы получили?
EnglishРусский
instruction tuning / supervised fine-tuning, SFTинструктивное / контролируемое дообучение (SFT)
synthetic dataсинтетические данные
parameter-efficient fine-tuning, PEFTпараметрически эффективное дообучение (PEFT)
low-rank adaptation, LoRAнизкоранговая адаптация (LoRA)
helpfulness / honesty / harmlessnessполезность / честность / безвредность
reward modelмодель награды
policy / reference / critic modelполитика / референс / критик
advantage functionфункция преимущества
importance samplingвыборка по значимости
rejection samplingвыборка с отклонением
alignment tax«налог на выравнивание»
beam searchлучевой поиск
nucleus (top-p) samplingядерное (top-p) сэмплирование
key-value cache, KV cacheKV-кэш
full / incremental decodingпрефилл / пошаговое декодирование
arithmetic intensityарифметическая интенсивность
memory wall«стена памяти»
speculative decodingспекулятивное декодирование
quantization / dequantizationквантование / деквантование
distillation / pruningдистилляция / прунинг