Содержание курса 37 / 37

37 / 37 · Продвинутая генерация

Неавторегрессионная генерация и текстовая диффузия

Порождать все позиции сразу двунаправленной моделью, оставлять уверенные предсказания, маскировать остальные и повторять: взгляд на этот цикл как на маскированную дискретную диффузию, её целевая функция обучения, процедура генерации с блоками, шагами, повторным маскированием по уверенности и classifier-free guidance, а также сравнение с декодированием слева направо по тому, что даёт каждое.

На этой странице 10

Каждый генератор в этом курсе порождал текст слева направо: один токен за вызов модели, каждый — при условии всех предыдущих, TT вызовов на TT токенов, и никакой возможности исправить уже написанный токен. Заметка о BERT обучала модель, делающую другое — заполнять замаскированные позиции с обеих сторон, — и не могла ею порождать, потому что не было процедуры, ведущей от пустоты к полной последовательности. Эта заметка такую процедуру даёт. Она превращает предсказатель замаскированных токенов в генератор, применяя его многократно, и в результате получается дискретный аналог диффузионных моделей из курса о генеративных моделях.

Обозначения. Последовательность токенов x0=(x01,…,x0L)x_0 = (x_0^1, \dots, x_0^L); токен маски M\mathrm{M}; уровень шума t∈[0,1]t \in [0, 1]; частично замаскированная последовательность xtx_t; модель pθ(x0i∣xt)p_\theta(x_0^i \mid x_t), предсказывающая чистый токен на позиции ii по всей замаскированной последовательности. Промпт занимает первые позиции и никогда не маскируется.

Базовый вариант: авторегрессионное декодирование#

P(x)=∏iP(xi∣x<i)P(x) = \prod_i P(x^i \mid x^{<i}), сэмплируемое по одному множителю за раз. Его свойства, из заметки о GPT: обучение параллельно благодаря каузальной маске; генерация последовательна; каждый шаг читает кэш предыдущих; представление позиции ii никогда не видит i+1i + 1. Порождение TT токенов стоит TT вызовов модели, а ошибка на шаге 10 обусловливает все последующие шаги.

Первая попытка распараллелить предсказывала все токены перевода независимо за один проход (Gu et al., 2018). Это быстро, но выходы несвязны: каждая позиция сэмплирует свой правдоподобный токен, не зная, что выбрали соседи (a man на позиции 2 и are на позиции 3), — это проблема мультимодальности (multimodality problem). Исправлением стала итерация: предсказать всё, оставить часть и заново предсказать остальное при условии оставленного (Ghazvininejad et al., 2019). Маскированная диффузия — та же идея с вероятностной целевой функцией обучения.

Прямой и обратный процессы#

Прямой. При уровне шума tt каждый токен x0x_0 независимо заменяется на M\mathrm{M} с вероятностью tt:

q(xti∣x0i)={x0iс вероятностью 1−t,Mс вероятностью t.q(x_t^i \mid x_0^i) = \begin{cases} x_0^i & \text{с вероятностью } 1 - t, \\ \mathrm{M} & \text{с вероятностью } t. \end{cases}

При t=0t = 0 последовательность чистая; при t=1t = 1 она состоит из одних масок. В отличие от гауссова прямого процесса для изображений, замаскированный токен не несёт остаточной информации и прямым процессом никогда не раскрывается; пространство состояний — словарь плюс один поглощающий символ.

Обратный. Модель получает xtx_t и выдаёт для каждой замаскированной позиции распределение по словарю. При обучении tt сэмплируется равномерно, x0x_0 маскируется соответственно и минимизируется кросс-энтропия на замаскированных позициях с весом 1/t1/t:

L(θ)=− Et, x0, xt[1t∑i=1L1[xti=M] log⁡pθ(x0i∣xt)].\mathcal L(\theta) = -\,\mathbb E_{t,\, x_0,\, x_t}\Big[\frac{1}{t}\sum_{i=1}^L \mathbb 1[x_t^i = \mathrm{M}]\,\log p_\theta(x_0^i \mid x_t)\Big].

Это функция потерь маскированного языкового моделирования BERT со случайной долей маскирования вместо фиксированных 15% и весом 1/t1/t. Именно вес делает целевую функцию оценкой правдоподобия: Ou et al. (2025) и Nie et al. (2025) показывают, что L\mathcal L — верхняя оценка отрицательного логарифма правдоподобия −log⁡pθ(x0)-\log p_\theta(x_0), аналог вариационной оценки из заметки об обучении DDPM, так что уменьшение функции потерь поднимает оценку правдоподобия данных. Вес действует на каждый замаскированный токен и больше всего при малых tt: токен, замаскированный при t=0.1t = 0.1, весит в десять раз больше, чем замаскированный при t=1t = 1. Он компенсирует число замаскированных токенов. При уровне tt замаскировано около LtLt позиций, так что без веса сильно замаскированные входы давали бы большую часть слагаемых функции потерь; с весом ожидаемое взвешенное число равно 1t⋅Lt=L\frac{1}{t} \cdot Lt = L при любом tt. Для L=10L = 10: один замаскированный токен при t=0.1t = 0.1 с весом 10 или девять при t=0.9t = 0.9 с весом 1/0.91/0.9 — в обоих случаях 10. Вес выравнивает число, а не трудность: насколько трудно предсказать замаскированный токен, по-прежнему зависит от того, какая часть его контекста видна. Архитектура — трансформер с полным (некаузальным) вниманием, устройство энкодера из заметки о семействах моделей; LLaDA обучает такую модель на 8 млрд параметров с нуля на этой целевой функции. В разобранном ниже примере используется LLaDA-MoE — вариант со смесью экспертов (mixture of experts) на 7 млрд параметров, из которых на каждый токен активны около 1 млрд.

Рисунок

Маскирование и предсказание

Прямой и обратный процессы маскированной диффузииШесть токенов фразы she runs 6 km per hour при t = 0, t = 0.5 (три токена заменены на M) и t = 1 (все токены M). Прямой процесс маскирует токены, обратный — предсказывает их моделью.t = 0sheruns6kmperhourt = 0.5sheMMkmperMt = 1MMMMMM→ маскировать← предсказатьпрямой процесс q: каждый токен независимо становится M с вероятностью t; M поглощающийобратный pθ: двунаправленная модель предсказывает каждый M по всей последовательности сразуобучение: t ~ U[0, 1], кросс-энтропия на позициях M с весом 1/tПрямой и обратный процессы маскированной диффузииШесть токенов фразы she runs 6 km per hour при t = 0, t = 0.5 (три токена заменены на M) и t = 1 (все токены M). Прямой процесс маскирует токены, обратный — предсказывает их моделью.t = 0sheruns6kmperhourt = 0.5sheMMkmperMt = 1MMMMMM↓ маскировать↑ предсказатьпрямой: токен → M с вероятностью tобратный: модель предсказывает каждый Mобучение: t ~ U[0, 1], CE на M × 1/t
Два процесса маскированной диффузии на куске разобранного примера. Прямой (жёлтый): каждый токен независимо заменяется маской M с вероятностью t; при t = 0 последовательность чистая, при t = 1 от неё ничего не остаётся, и замаскированный токен остаётся замаскированным. Обратный (синий): двунаправленная модель видит частично замаскированную последовательность и сразу предсказывает токен для каждой замаскированной позиции; генерация идёт от t = 1 к 0, сохраняя на каждом шаге несколько предсказаний. Для обучения нужен только прямой процесс: взять t, замаскировать и оценить предсказания модели на замаскированных позициях кросс-энтропией с весом 1/t.

Генерация#

Сэмплер, сведённый к шагам, для промпта длины pp и длины генерации GG:

  1. Построить x=[промпт,M,…,M]x = [\text{промпт}, \mathrm{M}, \dots, \mathrm{M}] длины p+Gp + G.
  2. Разбить GG позиций на блоки длины bb (здесь 32) и обрабатывать блоки слева направо; внутри текущего блока позиции порождаются параллельно, а более поздние блоки остаются замаскированными. Это полуавторегрессионный компромисс: полностью параллельная генерация по GG позициям возможна, но на длинных выходах ухудшает качество.
  3. Каждый блок получает Sb=S/(G/b)S_b = S / (G / b) шагов (128 шагов при G=128G = 128 и b=32b = 32 дают 32 шага на блок). На каждом шаге:
    • один раз прогнать модель по всей последовательности и взять в каждой замаскированной позиции предсказанный токен x^i=arg⁡max⁡pθ(⋅∣xt)\hat x^i = \arg\max p_\theta(\cdot \mid x_t) (с шумом Гумбеля, добавленным к логитам, при сэмплировании с температурой выше 0);
    • вычислить для каждой замаскированной позиции уверенность (confidence) — вероятность pθ(x^i∣xt)p_\theta(\hat x^i \mid x_t) выбранного токена (повторное маскирование по низкой уверенности) или случайное число (случайное повторное маскирование);
    • открыть kk самых уверенных позиций текущего блока, а остальные оставить замаскированными; kk берётся из расписания, фиксируемого в начале блока: его замаскированные позиции делятся поровну между его шагами (остаток уходит первым шагам), чтобы блок опустел точно по расписанию;
  4. Остановиться, когда заполнены все позиции. Позиции после токена конца текста — заполнение до фиксированной длины.
Рисунок

Итеративное раскрытие: двенадцать позиций за четыре параллельных шага

Раскрытие по уверенности за четыре проходаСетка из пяти рядов по двенадцать позиций. Первый ряд полностью замаскирован. В каждом следующем ряду ещё три позиции открываются и показывают свои токены, пока последний ряд не становится законченной фразой.начало▒▒▒▒▒▒▒▒▒▒▒▒проход 1The▒▒72▒▒▒plus▒▒▒▒проход 2The▒is72▒:▒plus▒over▒▒проход 3Theansweris72▒:48plus▒over8▒проход 4Theansweris72km:48plus24over8hoursжёлтые: замаскированы · синие: открыты на этом проходе · серые: открыты раньшеРаскрытие по уверенности за четыре проходаСетка из пяти рядов по двенадцать позиций. Первый ряд полностью замаскирован. В каждом следующем ряду ещё три позиции открываются и показывают свои токены, пока последний ряд не становится законченной фразой.начало▒▒▒▒▒▒▒▒▒▒▒▒проход 1The▒▒72▒▒▒plus▒▒▒▒проход 2The▒is72▒:▒plus▒over▒▒проход 3Theansweris72▒:48plus▒over8▒проход 4Theansweris72km:48plus24over8hoursжёлтые: замаскированысиние: открыты на этом проходесерые: открыты раньше
Каждый ряд — один проход двунаправленной модели по всей последовательности. На каждом проходе модель предсказывает токен для каждой ещё замаскированной позиции; 3 предсказания с наибольшей вероятностью сохраняются (синие), остальные снова маскируются. Через 4 прохода заполнены все 12 позиций. Порядок раскрытия условный: на практике первыми обычно открываются короткие частые токены и токены, сильно ограниченные промптом. При 4 шагах на 12 токенов модель запускается 4 раза вместо 12; при 12 шагах она открывала бы по одному токену за проход и ничего не выигрывала бы у декодирования слева направо. Блочный сэмплер делает то же внутри блоков по 32 позиции, обрабатывая блоки слева направо.

Раскрытие по уверенности — эвристика с ясным обоснованием: модель сначала фиксирует то, в чём уверена больше всего, и каждое решение становится условием следующего прохода, так что трудные позиции решаются последними и с наибольшим контекстом. В статьях анализируется вариант со случайным повторным маскированием; вариант с уверенностью эмпирически работает лучше.

Classifier-free guidance переносится из диффузии изображений. Модель запускается дважды — с промптом и с замаскированным промптом (безусловное предсказание) — и результат экстраполируется: ℓ=ℓuncond+(w+1)(ℓcond−ℓuncond)\ell = \ell_{\text{uncond}} + (w + 1)(\ell_{\text{cond}} - \ell_{\text{uncond}}) на логитах, где ww — масштаб guidance (w=0w = 0 — обычная модель). Это усиливает следование промпту ценой двойных вычислений на шаг.

Разобранный пример#

Промпт: Lily can run 12 kilometers per hour for 4 hours. After that, she runs 6 kilometers per hour. How many kilometers can she run in 8 hours? в чат-шаблоне. G=128G = 128, b=32b = 32, S=128S = 128, температура 0, повторное маскирование по низкой уверенности, без guidance. Выход:

Lily runs 12 kilometers per hour for 4 hours, so she runs a total of 12 * 4 = 48 kilometers in the first 4 hours. After that, she runs 6 kilometers per hour for 4 hours, so she runs a total of 6 * 4 = 24 kilometers in the next 4 hours. Therefore, in 8 hours, Lily can run a total of 48 + 24 = 72 kilometers. The answer is: 72

а затем токен конца реплики и заполнение. Ответ верный, и его породила модель, которая никогда не видела свой левый контекст как «прошлое». Стоит посмотреть на арифметику расписания: при S=128S = 128 шагах на 128 позиций каждый проход открывает ровно один токен (32 позиции блока за 32 шага), так что этому примеру понадобилось 128 полных прямых проходов — столько же, сколько декодирование слева направо, причём каждый проход идёт по всей последовательности, а не по одному токену с кэшем. Параллельное ускорение возникает только при S<GS < G: 32 шага открывали бы по 4 токена за проход и вчетверо сократили бы число вызовов модели ценой некоторой потери качества, которую статьи измеряют на бенчмарках, а этот один пример измерить не может.

Авторегрессионная и диффузионная генерация#

АвторегрессионнаяМаскированная диффузия
Порядокслева направо, фиксированныйлюбой; выбирается по уверенности, блоки по желанию
Вызовов модели на GG токеновGGSS, задаётся; S≪GS \ll G ради скорости
Контекст предсказаниятолько слеваобе стороны уже построенной последовательности
Исправление токенаневозможнозамаскированные позиции заново предсказываются на каждом шаге; зафиксированные — нет (в базовом сэмплере)
Стоимость вызоваодна новая позиция с KV-кэшемвся последовательность, без кэша
Длина выходаоткрытая, до токена концафиксированный бюджет GG с заполнением
Вставка и редактированиенужно специальное обучениеестественны: замаскировать фрагмент, который нужно переписать
Правдоподобиеточное, по цепному правилуоценка
Параметры декодированиятемпература, top-pp, лучевой поискшаги, размер блока, правило повторного маскирования, guidance
Зрелостьстандарт в продакшенеисследования и первые внедрения

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

Что изменилось#

BERT (MLM)Маскированная диффузионная LM
Доля маскированияфиксированные 15%t∼U[0,1]t \sim U[0, 1]
Вес в функции потерьнет1/t1/t
Смысл целевой функцииобучение представленийоценка правдоподобия
Может порождатьнетда, итеративным раскрытием
Архитектураэнкодерэнкодер (то же устройство), масштабированный

Ограничения#

  • Нет кэша. Каждый шаг заново кодирует всю последовательность; стоимость шага O((p+G)2d)O((p + G)^2 d), и длинные промпты делают шаги дорогими.
  • Фиксированная длина. GG — гиперпараметр; слишком короткая обрезает, слишком длинная заполняется и тратит шаги впустую.
  • Зафиксированные токены окончательны в базовом сэмплере, так что ранняя уверенная ошибка сохраняется; сэмплеры, повторно маскирующие зафиксированные токены, существуют и требуют больше шагов.
  • Качество в зависимости от числа шагов — кривая, измеряемая на бенчмарках, а не гарантия; один верный пример о ней ничего не говорит.
  • Инструменты. Ограниченное декодирование, спекулятивные приёмы, движки для развёртывания и вся экосистема вокруг авторегрессионных моделей в основном пока не переносятся.

Что нужно запомнить#

  • Маскированная диффузия: прямой процесс маскирует каждый токен с вероятностью tt; модель предсказывает замаскированные токены по всей последовательности; функция потерь — маскированная кросс-энтропия с весом 1/t1/t, ограничивающая отрицательный логарифм правдоподобия.
  • Генерация: старт со всех масок, повторные полные проходы, открытие kk самых уверенных позиций за проход, по желанию в блоках слева направо и с classifier-free guidance.
  • Ускорение требует, чтобы шагов было << порождаемых токенов; при равенстве метод делает столько же вызовов, сколько декодирование слева направо, и каждый дороже.
  • По сравнению с авторегрессией: двунаправленный контекст, редактирование маскированием, выбираемое число шагов; против — нет KV-кэша, фиксированная длина, оценка вместо точного правдоподобия.

Ноутбук#

Ноутбук об агентах и диффузии, ячейка 19. Номера ячеек считают все ячейки, включая текстовые, начиная с 1. Приведённые числа взяты из прогона, сохранённого в курсе; у ячеек, изменённых с тех пор под текущие версии библиотек, сохранённого выхода нет. Ячейка определяет add_gumbel_noise (сэмплирование с температурой на логитах), get_num_transfer_tokens (число открываемых на каждом шаге токенов, опустошающее блок по расписанию) и generate — сэмплер из раздела «Генерация» (блоки, шаги, необязательная ветка guidance, которая склеивает условный и безусловный входы, правила повторного маскирования low_confidence и random и перенос top-kk на блок); загружает inclusionAI/LLaDA-MoE-7B-A1B-Instruct, маскированную диффузионную модель со смесью экспертов, обученную на инструкциях, с её токенизатором и чат-шаблоном; и запускает промпт про Лили с steps=128, gen_length=128, block_length=32, temperature=0., cfg_scale=0.. Напечатанный выход — тот, что приведён выше, и заканчивается токеном конца реплики модели и заполнением токенами конца текста.

Дальше#

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

Литература#