RL for Diffusion modelsPart 1

Андрей Филатов · 26 октября 2026 · ~21 минута

Глава 1

Зачем reward, если есть DPO

Претренинг учит модель связывать текст и изображение: по запросу про кота она рисует кота. Но среди картинок, которые подходят под запрос, одни выглядят лучше, другие хуже: где-то плоский свет, где-то пластиковая текстура. Чтобы модель чаще выдавала удачные варианты, нужен следующий этап обучения — preference optimization.

Один из её методов — DPO. Собираем пары winner и loser и учим модель приближаться к первому и отдаляться от второго. Данные собирать легко: подойдут картинки любых моделей.

Но у DPO две слабые стороны. Модель легко уходит из распределения претренинга, и её приходится сдерживать — SFT на winner-картинках или методами вроде ThermoDPO (подробнее об этом — в предыдущем посте про preference optimization). А главное — пара сообщает только «эта картинка лучше той». Что именно исправить, пара не говорит.

Например, просим нарисовать «четыре чашки», а модель рисует три. Можно собрать пару «четыре чашки лучше трёх», но из неё модель не поймёт, что ошиблась именно в счёте. Да и такие пары сначала нужно где-то найти.

Зато ошибку легко посчитать — детектор найдёт чашки на картинке и сравнит их число с запросом. Это и есть reward (число, которое говорит, насколько картинка решает конкретную задачу). Так же OCR проверяет текст на вывесках, отдельная модель оценивает эстетику, ещё одна — анатомию рук.

Если проблему можно оценить числом, её можно оптимизировать. Этим и занимается RL. Допустим, хорошая reward-модель (оценщик: смотрит на готовую картинку и возвращает это число) у нас уже есть.

Как обновить генератор, чтобы он чаще получал высокий reward? Об этом пост, первый из двух про RL для диффузии. Как строить и балансировать сами reward-модели — тема второго.

Путей два, и выбор зависит от того, можно ли взять от reward градиент. Если это дифференцируемая сеть, её градиент можно протащить назад через генерацию прямо в веса модели. Если reward — просто число (как счётчик чашек), остаётся работать с вероятностями: делать удачные генерации вероятнее, а неудачные — реже.

Довести reward до моделиОбновить генератор так, чтобы reward рос
Reward дифференцируемГрадиент от reward идёт через картинку назад в модельReFL, DRaFT, DRTune, ShortFT
Direct reward backpropagationПротащить градиент через траекторию
Reward — просто числоДостаточно оценки готового сэмплаFlow-GRPO, DiffusionNFT, AWM
Online policy gradientСдвигать распределение по rollouts

Первые методы шли по первому пути. Сейчас этот путь — скорее историческая справка. Но именно на их ограничениях видно, откуда пришли современные методы и почему они устроены так, а не иначе. С них и начнём.

Обозначения
картинка на шаге ; от шума до чистой
предсказание чистой картинки из  за один шаг
модель с весами : предсказывает шум или скорость
та же модель до обновления; генерирует rollouts
reward одной картинки; reward -го сэмпла в группе
advantage: насколько сэмпл лучше среднего по группе
насколько далеко можно уйти от старой модели
через сколько последних шагов идёт градиент

Глава 2

Один шаг в конце: ReFL

Диффузия рисует картинку за десятки шагов: из шума постепенно проявляется изображение . Шаги делают разную работу. На ранних модель решает, что будет в кадре и где: композицию, расположение объектов, свет. Сколько будет чашек, решается здесь. На поздних дорисовываются детали и текстура.

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

Direct reward backpropagation: градиент reward проходит назад по траектории и обновляет параметры модели на разных шагах.

Но протащить градиент через десятки шагов дорого. Первым градиент от reward в генератор довёл ReFL — в той же работе, где появилась reward-модель ImageReward. Решение лобовое: раз через всю траекторию не пройти, возьмём один шаг.

Выбираем случайный поздний шаг , доходим генерацией до него без градиента и из  за один шаг предсказываем чистое изображение , считаем на нём reward и обновляем модель по его градиенту [ReFL, разд. 3]:

ReFL: случайный поздний шаг, предсказание за один шаг, reward и градиент только через этот шаг.

Какой шаг выбрать

Почему именно поздний? На ранних шагах предсказание получается очень размытым. Reward-модель на такой картинке почти ничего не различает, и учить модель нечему. На последних шагах проблема обратная: изображение уже сформировано, и любое обновление — это чуть-чуть текстуры.

Остаётся поздний, но не самый последний участок, где картинка уже читается, но ещё не готова [ReFL, рис. 4]. Например, при 50 шагах генерации — шаги примерно с 30-го по 40-й.

Отсюда и главное ограничение. Какой бы дифференцируемый reward мы ни взяли, к этому моменту композиция уже выбрана: если модель нарисовала три чашки, четвёртая не появится. ReFL может только сделать эти три аккуратнее.

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

А если сдвигать окно раньше?

Напрашивается идея. По мере обучения модель рисует всё более чёткие картинки уже на ранних шагах. Может, постепенно сдвигать окно обучения к началу траектории — и так добраться до композиции?

И это правда работает: если дообучить модель на таких траекториях, ReFL начнёт работать и на более ранних шагах. Но чем раньше шаг, тем дальше одношаговое предсказание от настоящей картинки, а reward-модель обучали на реальных изображениях.

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

Глава 3

До конца, но только последние шаги: DRaFT

Через десятки шагов сразу — дорого. Но между «один шаг» и «все шаги» есть середина: пройти генерацию до конца, а градиент пустить только через последние шагов сэмплирования. Так делает DRaFT, вариант DRaFT-K. Reward считается на настоящем : мы проходим реальный путь до картинки, а не угадываем её за один шаг.

DRaFT-K: градиент reward идёт через последние шагов, здесь .

Но четвёртой чашки по-прежнему не будет. Мы всё так же обновляем только конец траектории, а сколько чашек в кадре, решилось задолго до него. Модель чуть лучше рисует текстуру или пальцы, и только.1 DRaFT-LV: усреднить reward. Простая модификация DRaFT, которую полезно знать для любого RL. Получив без градиента, зашумим его раз с разным шумом и снова расшумим за один шаг. Reward усредняем по всем предсказаниям. У такой оценки меньше дисперсия, и обновление получается чище: DRaFT-LV учится примерно вдвое быстрее ReFL [DRaFT, рис. 4].

DRaFT-LV: одно и то же , разных шумов, средний reward.

Почему нельзя просто взять больше шагов

Кажется, что можно увеличивать: четыре, пять, десять шагов, пока не дойдём до шага, где выбирается число чашек. Но градиент от  к более раннему — это произведение якобианов всех шагов между ними:

Если эти матрицы не близки к единичной, после десятка умножений градиенты сильно растут, и обновления перестают работать [DRaFT, рис. 8]. Добавьте к этому память на хранение всех промежуточных активаций. В самой работе DRaFT маленькие , вплоть до , оказываются лучшим компромиссом [DRaFT, рис. 9].

Ранние шаги, где решается число чашек, отделены от reward десятком таких умножений. И каждое из них добавляет к взрыву.

Глава 4

До ранних шагов без взрыва: DRTune, ShortFT

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

DRTune: стоп-градиент на входе сети

DRTune останавливает градиент на входе денойзера [DRTune, разд. 3.2]. Тогда градиент не проходит через сеть на каждом шаге и не перемножает якобианы. Он идёт по траектории только через линейную часть шага сэмплирования, и нормы перестают расти [DRTune, рис. 7].

Обучаются при этом не все шаги, а несколько, разбросанных по траектории, включая ранние. Генерацию можно остановить раньше и предсказать за один шаг.

DRTune: стоп-градиент на входе сети, градиент проходит между шагами только через линейный член.

Так мы обновляем модель на разумной, не слишком шумной картинке и дотягиваемся до ранних шагов, а значит — до композиции. Авторы показывают, что именно обучение ранних шагов важно для низкоуровневых reward, где методы с поверхностной супервизией не справляются [DRTune, табл. 1 и рис. 4].

ShortFT: короткая траектория через shortcut-модель

ShortFT решает задачу с другой стороны. Вместо траектории из пятидесяти шагов возьмём few-step модель на 4–10 шагов, которая сохраняет траекторию исходной модели. По такой короткой цепочке можно протащить градиент целиком, от reward до шума — и до шага, где выбирается число чашек.

ShortFT: короткая цепочка shortcut-шагов вместо полной траектории; градиент reward проходит её до конца.

Как перенести результат на полную модель? Shortcut можно сделать LoRA-дистилляцией, например Hyper-SD. Поверх неё совместно учим ещё одну LoRA уже на reward. После обучения дистилляционную LoRA убираем, а обученную оставляем — и она переносится на полную модель.

Насколько легко это работает, зависит от метода дистилляции. Разрыв между обучением и инференсом авторы отдельно закрывают прогрессивной схемой [ShortFT, разд. 3.3 и рис. 6].

Почему не дистиллировать после RL?

Логичный вопрос: может, сразу взять дистиллированную модель и сделать RL на ней? Проблема в разнообразии. Дистиллированная модель на четырёх шагах почти не даёт diversity. Без него не работает exploration: модели нечего сравнивать и не из чего выбирать.

Поэтому дистилляцию обычно делают после RL. К тому же модель после RL уже частично схлопнута, и её проще дистиллировать.

Что изменил flow matching

У flow matching траектории прямее. В диффузии на ранних шагах предсказанное изображение может быть очень далеко от итогового. У flow-моделей уже на раннем участке траектории видна почти готовая композиция: мелких деталей ещё нет, но сцена уже понятна. На таких предсказаниях можно считать reward.

Поэтому для flow-моделей полные rollouts (прогоны генерации от шума до готовой картинки) стали реальными и без shortcut-LoRA. Траектории изначально хорошие и прямые, можно генерировать на десяти шагах. Картинки получатся немного размытыми, но модель со временем учится делать их чётче сама.

Где этот подход остаётся полезным

Есть и практический вывод. Если задача — конкретные детали, полный RL может быть не нужен: попиксельные градиенты дифференцируемого reward очень плотные и хорошо работают на мелочах. Для композиции нужно что-то умнее.

Получить надёжный дифференцируемый reward для сложных глобальных свойств трудно; сейчас это получается в основном у больших VLM. Можно комбинировать reward: с полным rollout часть оценщиков считается только на готовой картинке, в конце траектории.

Но наш счётчик чашек — не сеть. Он возвращает «три» или «четыре», и градиента у него нет.

Глава 5

Если от reward нельзя взять градиент: Flow-GRPO

Градиент от reward и не нужен, если есть другое: число на готовом сэмпле и вероятности шагов, которыми мы к нему пришли. Тогда можно делать траектории с высоким reward вероятнее, а с низким — реже. Это policy gradient, и у него три причины вытеснить direct backpropagation.

Первая — многие оракулы бинарные: четыре чашки или нет, текстура хорошая или нет. Такие вещи не описываются дифференцируемо. Вторая — даже обученной reward-модели трудно доверять её градиенты. Модель легко находит направления, в которых reward растёт, а картинка не становится лучше, — reward hacking.

Третья — хочется online-контроля: генерировать rollouts текущей моделью и исправлять именно её проблемы.

Поэтому формулируем денойзинг как марковский процесс принятия решений. Состояние — текущий шумный сэмпл, действие — следующий шаг, policy (правило выбора действия; здесь это сама модель), reward выдаётся в конце:

Градиент ожидаемого reward записывается по трюку REINFORCE:

насколько сэмпл лучше среднего по запросу ( — baseline)сделать каждый шаг этой траектории вероятнее

Ни одной производной от  здесь нет: reward входит как число.

Flow-GRPO

Flow-GRPO — сейчас один из основных методов RL для flow-моделей. Делаем полный rollout на небольшом числе шагов, считаем reward и через policy gradient обновляем модель целиком. Поверх этого — GRPO: advantage (насколько сэмпл лучше среднего по группе) считается внутри группы rollouts на один запрос.

Flow-GRPO: группа SDE-rollouts на один запрос, reward каждого, advantage как нормировка внутри группы, обновление policy с KL к reference. По схеме из статьи Flow-GRPO.

Первая проблема — сэмплирование. Flow matching генерирует через ODE: один шум даёт одно изображение. Для разных траекторий пришлось бы брать разные шумы, но это уже ближе к поиску удачного seed, чем к улучшению модели.

Используем известный приём: у каждого ODE есть эквивалентное SDE с теми же маргинальными распределениями [Flow-GRPO, разд. 4]. Тогда из одного шума можно получать разные траектории, а шаги становятся гауссовыми — у них есть посчитанный .

ODE задаёт одну траекторию; эквивалентное SDE даёт exploration и вероятность каждого шага при тех же маргиналях.

Уровень шума задаётся так:

Параметр регулирует разнообразие траекторий. Если он слишком маленький, примерно меньше 0,5, rollouts почти не отличаются. Если слишком большой, сэмплы начинают портиться [Flow-GRPO, рис. 7b]. На практике я беру порядка 0,7.

Вторая проблема — стоимость rollouts. Здесь помогает то же наблюдение, что и в ShortFT: траектории flow matching прямые. В Flow-GRPO rollouts для обучения делают на 10 шагах, а на инференсе остаются исходные 40 [Flow-GRPO, разд. 4 и рис. 7a]. Грубых rollouts хватает, чтобы ранжировать сэмплы внутри группы.

Denoising reduction: для сравнения сэмплов в группе хватает 10 шагов.

Дальше — обычный GRPO. Для запроса «четыре чашки» генерируем группу rollouts: детектор ставит 1 там, где чашек четыре, и 0 там, где три. Нормируем reward внутри группы и получаем advantage : у четырёх чашек он положительный, у трёх — отрицательный. Каждый шаг траектории получает тот же advantage, включая ранние, где число чашек и решалось.

Траектория с высоким reward становится вероятнее целиком, с низким — менее вероятной; при обновления нет.

Механически всё выглядит так. Делаем полный rollout и сохраняем шаги. Считаем reward на итоговой картинке. Затем идём по траектории, на каждом шаге считаем , накапливаем градиенты и делаем один шаг оптимизатора. Градиент через цепочку шагов не протаскивается, поэтому проблемы со взрывом нет.

Результат заметный. Для SD3.5-M Flow-GRPO поднимает точность на GenEval с 63% до 95%, а на рендеринге текста — с 59% до 92% [Flow-GRPO, табл. 2]. Авторы также добавляют KL к reference-модели (замороженной копии исходной модели): он сдерживает reward hacking [Flow-GRPO, рис. 6].

Где Flow-GRPO неудобен

У метода две проблемы. Первая: мы оптимизируем обратный процесс, а не прямой, хотя модель предобучалась на прямом. Из-за этого сильные ограничения на сэмплер: работает только эйлеровская дискретизация SDE, иначе не сходится математика [Flow-GRPO, разд. 4].

Вторая: rollouts делаются с CFG. Значит, в обучении участвуют и conditional-, и unconditional-ветки. Вероятность шага считается по скорости после CFG, и нужно хранить и обновлять обе. Это в два раза больше памяти и в два раза больше вычислений.

Итого: нужны вероятности каждого шага и особый сэмплер, который их даёт. Но reward — это число на готовой картинке. Нельзя ли обойтись только им?

Глава 6

Без вероятностей и сэмплера: DiffusionNFT, AWM

Можно, если учиться на прямом процессе, а не на обратном. Хранить только чистые сэмплы и их reward, зашумлять их и учить модель тем же loss, что на претренинге, — только с весом от reward. Так делают DiffusionNFT и AWM, и в итоге diffusion RL оказывается взвешенным flow matching.

DiffusionNFT: учиться на прямом процессе

DiffusionNFT отказывается от likelihood обратного процесса. Rollouts генерируются любым сэмплером, хоть ODE высокого порядка. Сохраняем только чистые сэмплы и их reward. Затем зашумляем эти сэмплы и учим модель обычным flow matching loss (функция ошибки претренинга: насколько предсказанная скорость отличается от настоящей).

Flow-GRPO учится на обратном процессе и требует likelihood шагов. DiffusionNFT хранит только и учится на прямом процессе.

Как отделить хорошие сэмплы от плохих? Сначала reward в группе нормируют и переводят в вероятность оптимальности . Можно было бы просто дообучаться на хороших примерах. Но rejection fine-tuning без негативов быстро схлопывает модель [DiffusionNFT, разд. 4.4]. От трёх чашек нужно отталкиваться так же, как тянуться к четырём.

Для этого обучаемую скорость представляют как скорость старой модели плюс добавку . Добавка с плюсом задаёт неявную позитивную policy, с минусом — негативную:

Позитивную ветку учим на сэмплах с весом , негативную — с весом :

Посмотрим, куда двигается добавка в начале обучения:

Для хорошего сэмпла , и модель тянется к его flow matching target (тому, к чему loss тянет предсказание). Для плохого — отталкивается. Old-модель остаётся опорой: обучение отталкивается от неё, а не от пустого места. Поэтому оно стабильнее, чем DPO по тем же сэмплам и чем дообучение только на позитивных.

Old-модель, которая генерирует rollouts, обновляют мягко, через EMA [DiffusionNFT, разд. 3.3]. Если сразу копировать в неё текущие веса, reward поначалу растёт быстро, но потом обучение разваливается [DiffusionNFT, рис. 8].

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

Разнообразие rollouts при этом берётся из самой модели, а не из искусственного шума SDE. Шаги для loss — те же, что при сэмплировании. DiffusionNFT до 25 раз эффективнее Flow-GRPO и поднимает GenEval с 0,24 до 0,98 за тысячу шагов без CFG [DiffusionNFT, рис. 1 и 6].

Advantage Weighted Matching: просто взвешенный flow matching

Следующий шаг делает связь явной. Advantage Weighted Matching показывает, что DDPO-подобные методы, включая Flow-GRPO, по сути делают flow matching с шумными targets [AWM, разд. 2]. Отсюда большая дисперсия и медленная сходимость.

Рецепт AWM: в policy gradient заменить недоступный на его диффузионную ELBO-оценку. Эта оценка — и есть loss претренинга. Получается обычный flow matching, где каждый сэмпл взвешен своим advantage.

Policy gradient → диффузионная ELBO → AWM: advantage умножается на loss претренинга.

При модель тянется к target этого сэмпла, при — отталкивается. Как и в Flow-GRPO, к loss добавляют KL к reference-модели. Сэмплер может быть любым: ODE, SDE, few-step. Вес — тот же приём, которым перевзвешивают шаги в обычном диффузионном loss.

AWM: группа сэмплов, advantage на каждый, обычный flow matching loss с весом.

На SD3.5-M и FLUX это до 34 раз быстрее Flow-GRPO при том же качестве генерации [AWM, табл. 2 и рис. 5].

Если это просто SFT, зачем такие сложности?

Если сэмплы с высоким reward — это просто SFT на позитивных, нельзя ли сделать это напрямую? Можно: AWM это и показывает. Достаточно выписать ELBO-оценку policy gradient, и останется такая схема: отталкиваемся от примеров, которые не нравятся, и двигаемся к тем, что нравятся, ориентируясь только на reward.

Конструкция DiffusionNFT с позитивной и негативной ветками — скорее интуитивно найденный способ это стабилизировать. При этом сохраняется главный плюс online policy gradient: reward может быть недифференцируемым, он задаёт только направление движения.

А если генерировать сэмплы заранее?

Насколько часто нужно обновлять сэмплы с разметкой reward? Можно ли, как в DPO, заготовить их заранее? Самый надёжный вариант — всегда online. Можно попробовать отставание на один шаг, но это сложно сделать стабильным: даже такая задержка может схлопнуть модель.

Поэтому, если есть возможность, генерируем rollouts текущей моделью — точнее, её медленной EMA-копией, как в DiffusionNFT. От коллапса на собственной синтетике защищает KL к reference-модели: модель не уходит от неё слишком далеко. Эта регуляризация здесь работает намного лучше, чем в DPO.

Доставка reward закончилась весом на loss претренинга. Значит, и следить нужно за тем же, за чем на претренинге: за данными и за тем, чему учит reward.

Источники

  • Градиент через траекторию
  • ReFL (ImageReward, 2023)Откуда взялись reward-модель ImageReward и одношаговое предсказание. Читать раздел 3; окно поздних шагов — рис. 4.
  • DRaFT (2023)Последние шагов и вариант LV. Взрыв градиента с ростом — рис. 8, абляция по  — рис. 9, LV против ReFL — рис. 4.
  • DRTune (2024) · ShortFT (2025)Два способа дойти до ранних шагов: стоп-градиент на входе (DRTune, разд. 3.2 и табл. 1) и короткая цепочка shortcut-шагов (ShortFT, разд. 3.3).
  • Online RL
  • Flow-GRPO (2025)SDE-сэмплер (разд. 4), групповые advantages, denoising reduction и уровень шума (рис. 7), результаты — табл. 2. Главный источник главы 5.
  • DiffusionNFT (2025) · AWM (2025)RL без вероятностей шагов: прямой процесс с позитивной и негативной ветками (DiffusionNFT, разд. 3) и взвешенный flow matching loss (AWM, разд. 2–3; скорость — табл. 2).
  • Контекст
  • Diffusion-DPO (2023)Точка отсчёта из главы 1: пары winner и loser вместо reward.