GAN обучает две сети в игре. Discriminator ищет отличие настоящего распределения от сгенерированного, generator меняет примеры по этому сигналу. Равновесие красиво на бумаге, а траектория обучения может вращаться, схлопываться и забывать целые режимы данных.

Фальшивомонетчик и эксперт

Пусть zpzz\sim p_z — простой шум, а generator Gθ(z)G_\theta(z) создаёт объект xx. Его распределение обозначим pgp_g. Discriminator Dϕ(x)(0,1)D_\phi(x)\in(0,1) оценивает вероятность, что объект пришёл из реальных данных pdatap_{\mathrm{data}}.

Исходная minimax-игра:

minGmaxDV(D,G)=ExpdatalogD(x)+Ezpzlog[1D(G(z))].\min_G\max_D V(D,G)= \mathbb E_{x\sim p_{\mathrm{data}}}\log D(x) + \mathbb E_{z\sim p_z}\log[1-D(G(z))].

DD максимизирует правильность различения, GG минимизирует её. У generator нет готового target-image для каждого zz: gradient приходит через discriminator.

Это adversarial learning, но не обязательно злонамеренная атака. «Соперник» служит обучаемой функцией потерь.

Рисунок шире экрана — проведите по немуОткрыть целиком ↗
Схема GAN с шумом генератором реальными данными discriminator и двумя градиентами
Рис. 82.1. Две выборки входят в одну проверку

Синие реальные объекты и красные G(z)G(z) поступают в discriminator. Сплошная обратная стрелка обновляет DD по двум классам; пунктирная проходит через замороженный на этом шаге DD к GG. Знаки stop-gradient разделяют два обновления.

Лучший discriminator и дивергенция

При фиксированном GG оптимальный discriminator в каждой точке:

D(x)=pdata(x)pdata(x)+pg(x).D^*(x)= \frac{p_{\mathrm{data}}(x)} {p_{\mathrm{data}}(x)+p_g(x)}.

Подстановка даёт

V(D,G)=log4+2JS(pdatapg).V(D^*,G)= -\log4+ 2\,\operatorname{JS} (p_{\mathrm{data}}\|p_g).

Минимум достигается при pg=pdatap_g=p_{\mathrm{data}}, тогда D(x)=1/2D^*(x)=1/2. Это описание идеального равновесия при бесконечной выразительности и оптимальном DD на каждом шаге. Реальные сети обновляются попеременно и не достигают точного optimum.

Исчезающий gradient generator

При плохом начальном generator discriminator легко выдаёт D(G(z))0D(G(z))\approx0. Minimax loss generator

LGsat=Ezlog[1D(G(z))]\mathcal L_G^{\mathrm{sat}} =\mathbb E_z\log[1-D(G(z))]

может насыщаться. На практике используют non-saturating loss:

LGNS=EzlogD(G(z)).\mathcal L_G^{\mathrm{NS}} =-\mathbb E_z\log D(G(z)).

У него тот же желаемый fixed point, но сильнее gradient, когда fake очевиден. Формулировка цели меняет динамику, хотя равновесие похоже.

Mode collapse

Если реальные данные имеют несколько мод — например, цифры 0–9, — generator может создавать только 1 и 7, зато очень убедительно. Качество отдельных картинок высоко, покрытие распределения низко.

Один batch discriminator видит ограниченную выборку и может не сразу наказать отсутствие редких мод. Generator получает похожие gradients для разных zz и отображает их в одну область.

Диагностика требует двух осей:

  • fidelity: насколько реалистичен отдельный объект;
  • diversity/coverage: сколько режимов данных представлено.

Precision–recall для generative models пытается разделить эти свойства. Одна FID смешивает их.

Рисунок шире экрана — проведите по немуОткрыть целиком ↗
Реальное двумерное распределение из восьми мод и генерации на разных шагах
Рис. 82.2. Красивая выборка может покрывать одну моду

Серые контуры показывают восемь мод данных. Красные точки generator сначала разбросаны, затем покрывают пять мод и в конце схлопываются в две. Под каждой панелью приведены precision, recall и FID, чтобы показать разные диагнозы.

Лаборатория игры

Generator, critic и две моды распределения

Загружается живая иллюстрация…

Установите две моды на плоскости и обучайте игроков с разными learning rates. Если discriminator обновляется слишком быстро, generator получает бесполезную границу; если слишком медленно — следует устаревшему сигналу.

Добавьте третью редкую моду. Смотрите не только scatter последнего batch, но и долю samples около каждой моды по времени. Короткая анимация обнаруживает циклическое забывание, которое финальная картинка скрывает.

Почему обучение вращается

Рассмотрим простую игру V(x,y)=xyV(x,y)=xy. Первый игрок минимизирует по xx, второй максимизирует по yy. Одновременный gradient:

xt+1=xtηyt,yt+1=yt+ηxtx_{t+1}=x_t-\eta y_t,\qquad y_{t+1}=y_t+\eta x_t

движется вокруг saddle point и даже может расходиться. У minimization одного loss gradient спускается по потенциальной поверхности; в игре векторное поле содержит вращение.

Из-за этого применяют разные частоты обновлений, momentum с осторожностью, extragradient и регуляризацию. Кривая loss GAN не обязана монотонно падать.

Wasserstein GAN

WGAN заменяет probabilistic discriminator critic-функцией ff и приближает Wasserstein-1:

maxfL1Expdataf(x)Ezf(G(z)).\max_{\|f\|_L\le1} \mathbb E_{x\sim p_{\mathrm{data}}}f(x) -\mathbb E_{z}f(G(z)).

Ограничение 1-Lipschitz существенно. Gradient penalty:

λEx^(x^f(x^)21)2\lambda\, \mathbb E_{\widehat x} \left(\|\nabla_{\widehat x}f(\widehat x)\|_2-1\right)^2

штрафует нарушение на точках между real и fake. Critic score нельзя читать как вероятность.

Wasserstein distance даёт информативный gradient даже при непересекающихся низкоразмерных распределениях, где JS может насыщаться. Но implementation details остаются важны.

Fashion-MNIST как контролируемый полигон

Fashion-MNIST содержит 28×28 grayscale изображения десяти классов одежды. Он мал, классы известны, поэтому можно измерить coverage classifier-ом. Generator не получает labels в unconditional режиме; метки используются только для аудита.

Сравните:

  • сетку случайных samples с фиксированными zz;
  • nearest neighbors из train для проверки копирования;
  • распределение предсказанных классов;
  • precision/recall;
  • FID на features подходящего classifier;
  • разнообразие внутри класса.

FID, вычисленная на ImageNet features для маленькой grayscale-одежды, предметно сомнительна. Feature extractor должен соответствовать данным.

Рисунок шире экрана — проведите по немуОткрыть целиком ↗
Сетка сгенерированной одежды, матрица классов и расстояния до ближайших train изображений
Рис. 82.3. Аудит генератора по трём осям

Слева samples упорядочены по predicted class, центр показывает real/generate доли классов, справа для подозрительно похожих объектов приведены nearest train neighbors и расстояния в feature space. Фигура различает realism, coverage и memorization.

Мини-исследование: различить collapse и запоминание

Generator выдаёт мало разных картинок по двум причинам. При mode collapse множество zz отображается почти в один output. При memorization outputs разнообразны, но подозрительно близки training examples. Нужны разные тесты.

Зафиксируйте 10 000 noise-кодов. Для каждой пары близких кодов z,z+δz,z+\delta измерьте perceptual distance outputs. Малый локальный Jacobian во многих областях указывает, что latent directions не меняют результат. Затем для каждого generated image найдите nearest neighbor в train и в независимом test. Если расстояния до train систематически меньше, возможна память.

Добавьте birthday-paradox test: среди большого generated set ищите почти дубликаты друг друга. Частые столкновения означают малый effective support. Но threshold perceptual distance калибруйте на реальных парах одного класса, иначе естественно похожие футболки будут считаться копиями.

Сопоставьте эти измерения с latent geometry StyleGAN. Ровный путь в latent уменьшает локальное схлопывание, но не доказывает покрытие всех data modes.

Мини-исследование: динамика, а не последний checkpoint

Сохраняйте generator каждые 500 шагов и сэмплируйте одни и те же fixed zz. Для каждого checkpoint вычислите coverage классов и pairwise diversity. Постройте heatmap «время обучения × класс». Она покажет, появляются ли и исчезают режимы.

Выбор лучшего checkpoint по test FID создаёт multiple comparisons. Выберите по validation protocol, а test откройте один раз. Если метрики осциллируют, сообщите диапазон последних checkpoint, а не единственное удачное число. Это продолжение честной валидации в нестационарной игре.

Сравните fixed-noise grid и fresh-noise grid. Первая показывает, как меняются одни и те же latent points, вторая — текущее распределение. Если fixed images улучшаются, а fresh coverage падает, generator точечно полирует часть пространства.

Записывайте также norm gradients обоих игроков. Резкий спад gradient generator при уверенном discriminator подтверждает saturation, рост без улучшения samples — нестабильность. Ни один diagnostic не достаточен, но совместная временная шкала помогает восстановить механизм сбоя.

Для conditional GAN постройте confusion matrix между заданным и распознанным классом. Mode collapse может происходить внутри класса, поэтому добавьте diversity по каждому. Средняя сетка маскирует слабый редкий класс так же, как средняя accuracy в классификации.

Добавьте latent interpolation между случайными парами и измерьте длину пути в feature space. Резкие скачки указывают на складки отображения, но слишком короткие пути могут означать отсутствие разнообразия. Сравните с путями между реальными nearest neighbors.

Интерполяция не доказывает density между концами: generator выдаёт объект для любого zz, даже если этот код почти не встречается под prior. Подписывайте prior probability along path или используйте spherical interpolation.

GAN среди других генераторов

VAE задаёт вероятностный encoder и явный компромисс реконструкции с prior. Diffusion учит много шагов denoising и обычно стабильнее, но sampling медленнее. GAN генерирует за один forward pass и способен на резкие изображения, зато обучение — хрупкая игра.

Архитектура выбирается по требованиям: скорость, likelihood, редактирование, покрытие, вычислительный бюджет. Историческая важность GAN не превращает его в универсальный лучший метод.

Равновесие не гарантирует траекторию

GAN сопоставляет два распределения через обучаемого критика. Идеальный optimum понятен, но путь к нему может вращаться и терять моды. Non-saturating loss, WGAN и регуляризация меняют gradient. Проверка обязана отдельно измерять реализм, покрытие и копирование.

Задачи