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

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

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

Исходная минимаксная игра записывается одной строкой:

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\bigl[1-D(G(z))\bigr].

Распределение pgp_g задано неявно — как образ шума под действием сети:

pg=Gθ#pz,x=Gθ(z),  zpz.p_g=G_\theta\#p_z,\qquad x=G_\theta(z),\;z\sim p_z .

Судья максимизирует правильность различения, генератор минимизирует её. Важная особенность: у генератора нет готового правильного ответа для каждого zz. Никто не говорит ему «вот такую картинку надо было выдать». Градиент приходит к нему только через судью — то есть через обучаемую функцию потерь.

Это состязательное (adversarial) обучение, но не обязательно злонамеренная атака, как в уроке про атаки на модели. Соперник здесь служит измерительным прибором: он превращает расплывчатое «похоже на правду» в конкретное число, по которому можно взять производную.

Судья, который читает отношение плотностей

Начнём не с сетей, а с честной арифметики. Возьмём реальные данные — 17 379 часов работы велопроката из урока про регрессию. Число поездок за час имеет среднее 189,5, медиану 142 и стандартное отклонение 181,4: распределение сильно скошено вправо. Пусть «генератор» — не сеть, а простая вероятностная модель, подогнанная под эти данные. Возьмём две: нормальную с тем же средним и той же дисперсией и логнормальную.

При фиксированном GG оптимального судью можно найти вообще без обучения. Запишем VV как интеграл, в котором каждая точка xx разбирается отдельно и независимо от остальных:

V(D,G)=[pdata(x)logD(x)+pg(x)log(1D(x))]dx.V(D,G)=\int\Bigl[p_{\mathrm{data}}(x)\log D(x)+p_g(x)\log(1-D(x))\Bigr]dx .

Теперь максимизируем подынтегральное выражение по одному числу D(x)D(x):

pdata(x)logD+pg(x)log(1D)maxD,p_{\mathrm{data}}(x)\log D+p_g(x)\log(1-D)\to\max_D, pdata(x)Dpg(x)1D=0D(x)=pdata(x)pdata(x)+pg(x).\frac{p_{\mathrm{data}}(x)}{D}-\frac{p_g(x)}{1-D}=0 \quad\Longrightarrow\quad D^*(x)= \frac{p_{\mathrm{data}}(x)} {p_{\mathrm{data}}(x)+p_g(x)}.

Никакой мистики: идеальный судья — это перенормированное отношение плотностей, ровно тот же объект, что и апостериорная вероятность класса в формуле Байеса при равных априорных долях настоящих и поддельных объектов.

Рисунок шире экрана — проведите по немуОткрыть целиком ↗
Слева плотность реального почасового проката и две подгонки: нормальная и логнормальная; справа кривые оптимального дискриминатора для обеих подгонок с отмеченными значениями 0.66 при 50 поездках и 0.41 при 400
Рис. 82.1. Оптимальный судья читает отношение плотностей

Реальный велопрокат (17 379 часов) против двух простых генераторов. Нормальная подгонка промахивается по форме: JS-дивергенция 0,053 бит, логнормальная — 0,032 бит. Справа оптимальный судья D(x)D^*(x): против нормального генератора он уверенно говорит «это настоящее» там, где данных много, а подделки мало (D(50)=0,66D^*(50)=0{,}66), и «это подделка» там, где нормальная кривая раздула хвост (D(400)=0,41D^*(400)=0{,}41). Судья не выдумывает признаков — он просто читает, где одна плотность больше другой.

Нормальный генератор проваливается ещё и физически: 14,8% его массы приходится на отрицательное число поездок за час. Судье даже не нужна тонкая статистика, чтобы поймать такую подделку, — достаточно посмотреть на знак.

Что на самом деле минимизирует генератор

Подставим DD^* обратно в VV. После группировки получается

V(D,G)=Epdatalogpdatapdata+pg+Epglogpgpdata+pg,V(D^*,G)= \mathbb E_{p_{\mathrm{data}}} \log\frac{p_{\mathrm{data}}}{p_{\mathrm{data}}+p_g} + \mathbb E_{p_g} \log\frac{p_g}{p_{\mathrm{data}}+p_g},

а если внести множитель 22 под логарифм и вычесть его снаружи —

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

где

JS(pq)=12KL ⁣(pp+q2)+12KL ⁣(qp+q2).\operatorname{JS}(p\|q)= \tfrac12\operatorname{KL}\!\left(p\,\Big\|\,\tfrac{p+q}2\right) +\tfrac12\operatorname{KL}\!\left(q\,\Big\|\,\tfrac{p+q}2\right).

Минимум достигается при pg=pdatap_g=p_{\mathrm{data}}, тогда JS=0\operatorname{JS}=0, D(x)1/2D^*(x)\equiv1/2 и V=log41,386V=-\log4\approx-1{,}386. Проверим на наших данных: нормальный генератор даёт V=1,313V=-1{,}313, логнормальный 1,342-1{,}342 — ближе к идеальному 1,386-1{,}386, что и соответствует меньшей JS. Значение игры честно ранжирует две модели.

Полезно помнить границы этой величины:

0JS(pq)log2,log4V(D,G)0.0\le\operatorname{JS}(p\|q)\le\log2, \qquad -\log4\le V(D^*,G)\le0 .

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

Когда подделка очевидна, уклон исчезает

В начале обучения генератор плох, и судья уверенно ставит на подделке D(G(z))0D(G(z))\approx0. Посмотрим, что при этом чувствует генератор. Насыщающая (исходная минимаксная) цель

LGsat=Ezlog[1D(G(z))],LGsatD=11D,\mathcal L_G^{\mathrm{sat}} =\mathbb E_z\log\bigl[1-D(G(z))\bigr], \qquad \left|\frac{\partial\mathcal L^{\mathrm{sat}}_G}{\partial D}\right| =\frac1{1-D},

при D=0,05D=0{,}05 даёт модуль градиента 1,05. Non-saturating цель

LGNS=EzlogD(G(z)),LGNSD=1D,\mathcal L_G^{\mathrm{NS}} =-\mathbb E_z\log D(G(z)), \qquad \left|\frac{\partial\mathcal L^{\mathrm{NS}}_G}{\partial D}\right| =\frac1D,

при том же D=0,05D=0{,}05 даёт 20,0 — в 19 раз больше. Разрыв ещё нагляднее, если считать градиент по логиту ss, где D=σ(s)D=\sigma(s):

slog(1σ(s))=σ(s),s(logσ(s))=1σ(s).\left|\frac{\partial}{\partial s}\log(1-\sigma(s))\right|=\sigma(s), \qquad \left|\frac{\partial}{\partial s}\bigl(-\log\sigma(s)\bigr)\right|=1-\sigma(s).

До весов генератора этот множитель доходит по цепному правилу обратного распространения:

LGθ=Ez[LGDxD(x)x=G(z)Gθ(z)θ],\frac{\partial\mathcal L_G}{\partial\theta} =\mathbb E_z\left[ \frac{\partial\mathcal L_G}{\partial D}\cdot \nabla_xD(x)\Big|_{x=G(z)}\cdot \frac{\partial G_\theta(z)}{\partial\theta}\right],

так что маленький первый сомножитель обнуляет всё произведение независимо от того, насколько хороша архитектура генератора. При s=4s=-4 (то есть D=0,018D=0{,}018) насыщающая цель передаёт генератору 0,018, а non-saturating — 0,982: отношение 54,6. Одна и та же уверенность судьи для первой цели означает «уклона нет», для второй — «уклон максимален».

Рисунок шире экрана — проведите по немуОткрыть целиком ↗
Слева кривые логарифм от единица минус D и минус логарифм D как функции выхода судьи; справа модули их градиентов по логиту, пересекающиеся в нуле: при логите минус четыре значения 0.018 и 0.982
Рис. 82.2. Две цели с одним желаемым концом и разной динамикой

Обе цели хотят одного и того же — чтобы судья ошибался. Но насыщающая цель плоская именно там, где генератор плох: при уверенном судье (s=4s=-4, D=0,018D=0{,}018) её градиент равен 0,018 против 0,982 у non-saturating. Смена формулировки цели не меняет положения желаемой неподвижной точки, но полностью меняет силу сигнала на пути к ней.

Это тот же сюжет, что и с выбором функции потерь: равенство минимумов не означает равенства траекторий. Формулировка цели — это выбор не только «куда», но и «насколько круто».

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

Разница между минимизацией и игрой глубже, чем формулировка потери. Возьмём простейшую игру V(x,y)=xyV(x,y)=xy: игрок xx минимизирует, игрок yy максимизирует. Равновесие очевидно — точка (0,0)(0,0). Одновременный градиентный шаг:

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

или в матричной форме

(xt+1yt+1)=(1ηη1)(xtyt).\begin{pmatrix}x_{t+1}\\y_{t+1}\end{pmatrix} = \begin{pmatrix}1&-\eta\\ \eta&1\end{pmatrix} \begin{pmatrix}x_t\\y_t\end{pmatrix}.

Её собственные значения и их модуль равны

λ1,2=1±iη,λ1,2=1+η2>1при любом η>0.\lambda_{1,2}=1\pm i\eta, \qquad |\lambda_{1,2}|=\sqrt{1+\eta^2}>1 \quad\text{при любом }\eta>0 .

Значит,

rt+12=xt+12+yt+12=(1+η2)rt2,r_{t+1}^2=x_{t+1}^2+y_{t+1}^2=(1+\eta^2)\,r_t^2,

и расстояние до равновесия строго растёт. За 100 шагов из точки (1,0)(1,0) радиус становится равен 1,005 при η=0,01\eta=0{,}01, 1,64 при η=0,1\eta=0{,}1 и 70 065 при η=0,5\eta=0{,}5. Уменьшение шага замедляет катастрофу, но не меняет её знака: в игре векторное поле обновлений содержит вращательную часть, у которой нет потенциала.

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

Одновременный шаг в игре V=xyV=xy уводит от седловой точки при любой скорости обучения: за 100 шагов радиус растёт с 1 до 1,005 (η=0,01\eta=0{,}01), 1,64 (η=0,1\eta=0{,}1) и 70 065 (η=0,5\eta=0{,}5). Поочерёдные обновления, при которых второй игрок отвечает уже на новый ход первого, ведут себя иначе: тот же η=0,1\eta=0{,}1 даёт радиус 1,023, а η=0,5\eta=0{,}5 — 1,069. Порядок ходов оказывается не деталью реализации, а частью алгоритма.

Вот почему в градиентном спуске кривая потери падает, а в GAN она не обязана падать вовсе. Отсюда же весь арсенал лечения: разные частоты обновления игроков, осторожный моментум, экстраградиентные и «раскрученные» (unrolled) схемы, регуляризация градиента судьи.

Красовский: равновесие есть, а как в него попасть?

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

Для нас важна методологическая мораль. Красовский отделил два вопроса, которые в наивном изложении GAN сливаются в один: «существует ли равновесие» и «какое правило пошагового поведения к нему ведёт». Первый вопрос решается теоремой, второй — конструкцией стратегии. Обучение GAN живёт целиком во втором вопросе: доказанное pg=pdatap_g=p_{\mathrm{data}} ничего не говорит о том, что делают Adam, батч из 128 объектов и поочерёдные обновления.

Схлопывание мод: узкий латент на реальных цифрах

Перейдём к настоящему обучению. Возьмём реальные данные — 1797 рукописных цифр из sklearn — и спроецируем их на две дискриминантные оси, чтобы получить двумерное распределение с десятью честными модами (по одной на цифру). Модой считаем окрестность центра класса радиуса 0,412 (медиана внутриклассового расстояния); мода покрыта, если в неё попал хотя бы 1% выборки генератора.

Формально доля выборки в моде kk и признак покрытия записываются так:

πk=1Mj=1M1[x^jckr    k=argminlx^jcl],мода покрыта    πk0,01.\pi_k=\frac1M\sum_{j=1}^M \mathbb 1\bigl[\,\|\hat x_j-c_k\|\le r\;\wedge\; k=\arg\min_l\|\hat x_j-c_l\|\,\bigr], \qquad \text{мода покрыта}\iff\pi_k\ge0{,}01 .

Обучаем маленький GAN на numpy: генератор z64642z\to64\to64\to2, судья 2646412\to64\to64\to1, LeakyReLU, Adam, non-saturating цель, 6000 шагов. Меняем одну вещь — размерность шума. При zR8z\in\mathbb R^8 генератор к концу покрывает все 10 мод из 10. При zR1z\in\mathbb R^1 образ генератора — кривая: одномерная линия физически не может одновременно накрыть десять островов. Покрытие колеблется между 1 и 8 модами, в среднем 4,9, к шагу 6000 равно 5. За обучение покрытие падало 21 раз, и каждая из 10 мод хотя бы однажды была потеряна и позже возвращена.

Рисунок шире экрана — проведите по немуОткрыть целиком ↗
Три панели с реальным облаком десяти мод цифр и красной кривой генератора на шагах 200, 1500 и 6000, покрывающей 2, 5 и 5 мод; ниже тепловая карта доли выборки в каждой моде по времени с гаснущими и загорающимися полосами
Рис. 82.4. Режимы гаснут и возвращаются

GAN с одномерным шумом на реальных цифрах. На шаге 200 покрыто 2 моды из 10 и 61% выборки лежит вне мод вообще, на шаге 1500 — 5 мод и 40%, на шаге 6000 — опять 5 мод и 43%. Красная линия — буквально образ отрезка: генератор протягивает кривую сквозь облако, задевая одни сгущения и пропуская другие. Внизу доля выборки в каждой моде по времени: полосы гаснут и загораются, то есть режимы не «накапливаются», а сменяют друг друга. Финальная картинка скрывает эту динамику полностью.

Причина схлопывания не сводится к нехватке размерности. Судья видит один батч и не наказывает за отсутствие редкой моды сразу; генератор получает похожие градиенты для разных zz и сносит их в одну область; судья наконец обучается ловить это скопление, генератор перебегает в другое место — и цикл повторяется. Узкий латент лишь делает механизм наглядным.

Реализм и покрытие — две разные оси

Соблазнительно свести качество генератора к одному числу. Наш эксперимент показывает, чем это кончается. Посчитаем по методу ближайших соседей две величины: precision — долю сгенерированных объектов, попавших в многообразие реальных данных, и recall — долю реальных объектов, попавших в многообразие сгенерированных (k=5k=5, по 600 объектов в каждой выборке).

precision=1Mj=1M1[x^jM(real)],recall=1ni=1n1[xiM(fake)].\text{precision}= \frac1M\sum_{j=1}^M\mathbb 1\bigl[\hat x_j\in \mathcal M(\text{real})\bigr], \qquad \text{recall}= \frac1n\sum_{i=1}^n\mathbb 1\bigl[x_i\in \mathcal M(\text{fake})\bigr].

Многообразие здесь определяется через kk-го ближайшего соседа: точка считается принадлежащей выборке, если она попала в чей-нибудь шар радиуса до kk-го соседа,

M(real)=i=1nB(xi,  xiNNk(xi)).\mathcal M(\text{real})= \bigcup_{i=1}^n B\bigl(x_i,\;\|x_i-\mathrm{NN}_k(x_i)\|\bigr).

Для генератора с zR8z\in\mathbb R^8: precision 0,96, recall 0,99. Для схлопнувшегося с zR1z\in\mathbb R^1: precision 0,98 — выше! — а recall 0,10. Схлопнувшийся генератор делает почти безупречные объекты; он просто делает их десятую часть от нужного разнообразия.

Рисунок шире экрана — проведите по немуОткрыть целиком ↗
Две диаграммы рассеяния: слева генератор с восьмимерным шумом заполняет всё облако реальных точек, справа генератор с одномерным шумом рисует узкую кривую внутри облака; справа столбики precision 0.96 и 0.98 против recall 0.99 и 0.10
Рис. 82.5. Реализм почти не падает, покрытие рушится

Схлопнувшийся генератор (справа) выигрывает по реализму: 0,98 против 0,96, ведь все его точки лежат глубоко внутри плотных областей. По покрытию он проигрывает почти в десять раз: 0,10 против 0,99. Любая одиночная метрика, смешивающая эти две оси, объявит его как минимум не хуже. Раздельные измерения — единственный способ увидеть провал.

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

Кривая потерь не ведёт счёт матча

В обычном обучении падение потери — сигнал прогресса. В GAN это не так, и у нас есть число: корреляция между потерей генератора и числом покрытых мод по всей истории обучения равна 0,02. Практически ноль. Формально это обычный коэффициент корреляции по 61 замеру:

ρ=cov(LG(t),K(t))VarLG(t)VarK(t)=0,02,\rho= \frac{\operatorname{cov}\bigl(\mathcal L_G(t),\,K(t)\bigr)} {\sqrt{\operatorname{Var}\mathcal L_G(t)\cdot\operatorname{Var}K(t)}} =0{,}02,

где K(t)K(t) — число покрытых мод на шаге tt. Финальные значения потерь — 1,35 у судьи и 0,70 у генератора — не отличают модель, покрывающую 5 мод, от модели, покрывающей 10.

Отсюда практическое правило: чекпойнт нельзя выбирать по кривой потерь. Нужны независимые измерения — покрытие, precision/recall, расстояние до реальных объектов — и протокол выбора, зафиксированный заранее, как в уроке про валидацию. Если метрики колеблются, честнее сообщить диапазон последних чекпойнтов, чем единственное удачное число.

Wasserstein: мера, у которой не кончается уклон

Слабое место JS видно на простом примере. Пусть данные — узкое распределение около нуля, а генератор — такое же, сдвинутое на θ\theta. При θ=1\theta=1 и θ=2\theta=2 носители практически не пересекаются, и JS равна 1,000 бит в обоих случаях: её производная по θ\theta численно равна 31053\cdot10^{-5}, то есть нулю. Мера не может подсказать, в какую сторону двигаться, потому что она уже на потолке.

Расстояние Вассерштейна-1 ведёт себя иначе:

W1(p,q)=infγΠ(p,q)E(x,y)γxy=Fp(t)Fq(t)dt.W_1(p,q)= \inf_{\gamma\in\Pi(p,q)} \mathbb E_{(x,y)\sim\gamma}\|x-y\| = \int_{-\infty}^{\infty}\bigl|F_p(t)-F_q(t)\bigr|\,dt.

В нашем примере W1=θW_1=|\theta|: 1,00 при θ=1\theta=1 и 2,00 при θ=2\theta=2, наклон равен единице всюду. Уклон есть даже там, где распределения не пересекаются вовсе.

Рисунок шире экрана — проведите по немуОткрыть целиком ↗
График двух мер как функций сдвига: JS-дивергенция быстро выходит на плато в один бит и остаётся плоской, расстояние Вассерштейна растёт линейно
Рис. 82.6. Плато против прямой

Сдвиг узкого распределения. JS выходит на плато в 1 бит уже при небольшом сдвиге: при θ=1\theta=1 и θ=2\theta=2 она равна 1,000, наклон 31053\cdot10^{-5}. W1W_1 равна 1,00 и 2,00 соответственно и растёт с постоянным наклоном 1. Обучающий сигнал — это не значение меры, а её производная; на плато производная исчезает.

Отсюда WGAN: вместо вероятностного судьи вводится критик ff и приближается двойственная форма Канторовича–Рубинштейна:

W1(pdata,pg)=supfL1(Expdataf(x)Ezf(G(z))).W_1(p_{\mathrm{data}},p_g)= \sup_{\|f\|_L\le1} \Bigl(\mathbb E_{x\sim p_{\mathrm{data}}}f(x) -\mathbb E_{z}f(G(z))\Bigr).

На практике оба матожидания заменяются средними по батчу:

W^1=1Bi=1Bf(xi)1Bi=1Bf(G(zi)).\widehat W_1= \frac1B\sum_{i=1}^Bf(x_i)- \frac1B\sum_{i=1}^Bf(G(z_i)).

Ограничение 1-липшицевости здесь не украшение: без него супремум бесконечен. Его обеспечивают штрафом за градиент

λEx^(x^f(x^)21)2,x^=αx+(1α)G(z),  αU[0,1],\lambda\, \mathbb E_{\widehat x} \bigl(\|\nabla_{\widehat x}f(\widehat x)\|_2-1\bigr)^2, \qquad \widehat x=\alpha x+(1-\alpha)G(z),\;\alpha\sim U[0,1],

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

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

Генератор, оптимальный судья и две моды распределения

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

Здесь всё считается точно: данные — модельная смесь двух гауссовых мод (пример придуман, а не взят из наблюдений), судья не обучается, а берётся оптимальным для текущего генератора. Уведите центр генератора далеко от данных (μ=4,5\mu=4{,}5): JS упрётся в 0,984 бит, W1W_1 покажет 4,90, а модуль градиента по μ\mu у насыщающей цели составит 0,028 против 6,08 у non-saturating — разница в 217 раз. Это ровно тот случай, ради которого меняли формулировку потери.

Затем поставьте генератор точно на левую моду (μ=2\mu=-2, доля второй моды 0): получится идеальное схлопывание — precision 0,99 при recall 0,60 и JS 0,236. Раздуйте ширину (σ=2,5\sigma=2{,}5, μ=0\mu=0) — картина зеркальная: recall 1,00, но precision 0,62. И только когда доля второй моды поднята до 0,4, а центр стоит на 2-2, обе плотности совпадают и JS обращается в нуль. Три способа быть неправым и один — правым.

Как честно проверять генератор

Аудит генератора — это не одна метрика, а протокол. Минимальный список:

  • сетка выборок при фиксированных zz на всех чекпойнтах — показывает, как меняются одни и те же латентные точки;
  • сетка при свежих zz — показывает текущее распределение;
  • доля каждой моды по времени (тепловая карта рисунка 82.4);
  • precision и recall по методу ближайших соседей;
  • расстояния до ближайших обучающих объектов — тест на копирование;
  • разнообразие внутри класса для условных моделей.

Если сетка с фиксированными zz улучшается, а покрытие свежих выборок падает, генератор точечно полирует часть пространства. Если качество выросло сразу по всем осям — вероятно, честно.

Схлопывание и запоминание — разные болезни

Генератор выдаёт мало разного по двум противоположным причинам. При схлопывании множество zz отображается почти в одну область. При запоминании выходы разнообразны, но подозрительно близки к конкретным обучающим объектам. Тесты нужны разные.

Проверка на запоминание строится на сравнении двух расстояний. Разобьём реальные данные на обучающую часть и отложенную, которую генератор не видел, и для каждой сгенерированной точки найдём ближайшего соседа в обеих. В нашем эксперименте медиана расстояния до обучающих равна 0,050, до отложенных — 0,065; отношение 1,30. Небольшая систематическая близость к обучающим есть — она и должна быть, ведь генератор учился именно на них, — но разрыв не похож на копирование, при котором расстояние до обучающих упало бы почти до нуля.

Дополнительно применяют тест дня рождения: в большом сгенерированном наборе ищут почти-дубликаты друг друга. Частые столкновения означают малый эффективный носитель распределения. И измеряют локальную чувствительность: для пар близких кодов zz и z+δz+\delta смотрят, насколько различаются выходы. Если

G(z+δ)G(z)δ0\frac{\|G(z+\delta)-G(z)\|}{\|\delta\|}\approx0

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

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

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

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

GAN сопоставляет два распределения через обучаемого критика — и это красивая идея: функция потерь перестаёт быть выдумкой инженера и становится результатом обучения. Идеальный оптимум описан точно: D=pdata/(pdata+pg)D^*=p_{\mathrm{data}}/(p_{\mathrm{data}}+p_g), V=log4+2JSV=-\log4+2\operatorname{JS}, минимум при совпадении распределений. Но путь к нему проходит по векторному полю с вращением, а не по склону: в игре V=xyV=xy одновременный шаг уводит от равновесия при любом η\eta. По дороге исчезает уклон у насыщающей цели, гаснут и загораются моды, а кривые потерь остаются немы: корреляция потери генератора с покрытием 0,02.

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

Задачи