# GAN и diffusion: цели, обучение и типичные сбои > Глава сопоставляет состязательное обучение и пошаговое удаление шума, выводит > основные цели и разбирает сбои на генерации рукописных символов. ## Мотивация и интуиция VAE задаёт likelihood-bound, но простой pixel decoder часто усредняет допустимые варианты и размывает штрихи. GAN учит generator через discriminator: один создаёт образцы, другой отличает их от данных. Получаются резкие изображения, но обучение может быть нестабильным и пропускать варианты. Diffusion намеренно постепенно зашумляет данные, а затем учит сеть обращать каждый малый шаг. Обучение стабильно, режимы покрытия обычно лучше, но sampling требует многих вызовов сети. Ни один подход не гарантирует читаемость или правомерность сгенерированного почерка. ## GAN: minimax-цель Пусть \(\mathbf{z}\sim p(\mathbf{z})\), generator \(G_{\boldsymbol{\theta}}(\mathbf{z})\), discriminator \(D_{\boldsymbol{\psi}}(\mathbf{x})\in(0,1)\). Исходная игра: \[ \min_G\max_D V(D,G)= \mathbb{E}_{\mathbf{x}\sim p_{\mathrm{data}}}\log D(\mathbf{x})+ \mathbb{E}_{\mathbf{z}}\log(1-D(G(\mathbf{z}))). \] Для фиксированного \(G\) оптимизируем каждую точку \(\mathbf{x}\): \[ p_d(\mathbf{x})\log D(\mathbf{x})+ p_g(\mathbf{x})\log(1-D(\mathbf{x})). \] Производная равна \(p_d/D-p_g/(1-D)\); приравнивая к нулю, получаем \[ D^*(\mathbf{x})=\frac{p_d(\mathbf{x})}{p_d(\mathbf{x})+p_g(\mathbf{x})}. \] Подстановка даёт \(V(D^*,G)=-\log4+2\,D_{JS}(p_d\|p_g)\), минимум при \(p_g=p_d\). На практике saturating loss \(\log(1-D(G(z)))\) даёт слабый градиент в начале, поэтому generator минимизирует non-saturating \(-\mathbb{E}\log D(G(z))\). Conditional GAN использует label \(y\): \(G(\mathbf{z},y)\), \(D(\mathbf{x},y)\). Label embedding можно конкатенировать с latent, а discriminator строить projection-методом. Условие помогает content, но style diversity всё ещё требует latent и данных. ## Сбои GAN - **Mode collapse:** разные \(\mathbf{z}\) дают несколько похожих глифов. - **Discriminator dominance:** почти идеальный \(D\) оставляет слабый сигнал \(G\). - **Oscillation/non-convergence:** игроки преследуют меняющиеся цели. - **Artifacts:** transpose convolution создаёт checkerboard; resize-convolution часто безопаснее. - **Memorization:** резкий образец может быть копией train, особенно на малых данных. Помогают balanced update rates, spectral normalization, gradient penalty, augmentation, EMA generator weights и проверка diversity. WGAN заменяет JS-подобную цель приближением Wasserstein-1 с 1-Lipschitz critic; Lipschitz ограничивают gradient penalty, а не sigmoid classification. ## Forward diffusion Задаём schedule \(\beta_t\in(0,1)\), \(\alpha_t=1-\beta_t\), \(\bar\alpha_t=\prod_{s=1}^t\alpha_s\): \[ q(\mathbf{x}_t\mid\mathbf{x}_{t-1}) =\mathcal{N}(\sqrt{\alpha_t}\mathbf{x}_{t-1},\beta_t\mathbf{I}). \] Повторная подстановка Gaussian переходов даёт закрытую форму: \[ \mathbf{x}_t=\sqrt{\bar\alpha_t}\mathbf{x}_0+ \sqrt{1-\bar\alpha_t}\boldsymbol{\varepsilon},\qquad \boldsymbol{\varepsilon}\sim\mathcal{N}(\mathbf{0},\mathbf{I}). \] Значит, для train не нужно последовательно выполнять все \(t\) шагов: выбираем \(t\), семплируем \(\varepsilon\), сразу строим \(\mathbf{x}_t\). ## Reverse process и noise prediction Обратный переход моделируется: \[ p_{\boldsymbol{\theta}}(\mathbf{x}_{t-1}\mid\mathbf{x}_t) =\mathcal{N}(\boldsymbol{\mu}_{\boldsymbol{\theta}}(\mathbf{x}_t,t), \boldsymbol{\Sigma}_t). \] Популярная параметризация учит UNet предсказывать добавленный шум: \[ \mathcal{L}_{simple}= \mathbb{E}_{\mathbf{x}_0,t,\varepsilon} \|\varepsilon-\varepsilon_{\boldsymbol{\theta}}(\mathbf{x}_t,t)\|_2^2. \] Из оценки шума восстанавливается оценка чистого изображения: \[ \hat{\mathbf{x}}_0= \frac{\mathbf{x}_t-\sqrt{1-\bar\alpha_t}\, \varepsilon_{\boldsymbol{\theta}}(\mathbf{x}_t,t)} {\sqrt{\bar\alpha_t}}. \] ### Почему noise predictor обычно является UNet UNet имеет нисходящий путь из convolution/residual-блоков с downsampling, узкое bottleneck и восходящий путь с upsampling. Skip-связи передают feature maps одинакового разрешения из encoder в decoder, поэтому bottleneck видит глобальный контекст, а decoder не теряет точные границы штрихов. Embedding шага \(t\) добавляется в блоки и сообщает уровень шума. Условие класса можно подать через embedding/adaptive normalization, а текст — через cross-attention. Свёртки и формы разобраны в [модуле 10](../../10_computer_vision/notes/01_convolutions_and_cnn.md), cross-attention — в [модуле 13](../../13_nlp_transformers/notes/02_attention_and_transformer_block.md). ### Один обратный шаг DDPM Для noise-prediction параметризации среднее перехода можно записать: \[ \boldsymbol\mu_\theta(\mathbf x_t,t)= \frac{1}{\sqrt{\alpha_t}}\left( \mathbf x_t-\frac{\beta_t}{\sqrt{1-\bar\alpha_t}} \varepsilon_\theta(\mathbf x_t,t)\right). \] Затем семплируют \(\mathbf x_{t-1}=\boldsymbol\mu_\theta+\sqrt{\tilde\beta_t}\mathbf z\), где \(\mathbf z\sim\mathcal N(0,I)\), а на последнем шаге шум не добавляют. Полный sampler: начать с \(\mathbf x_T\sim\mathcal N(0,I)\), пройти \(t=T,T-1,\ldots,1\), на каждом шаге предсказать шум и получить \(\mathbf x_{t-1}\). Формула зависит от выбранной variance/sampler параметризации, поэтому schedule обучения и sampling-код должны совпадать. DDPM sampling добавляет рассчитанное среднее reverse posterior и шум на каждом шаге (кроме последнего). DDIM и современные solvers сокращают число шагов, меняя траекторию/аппроксимацию; меньше шагов обычно обменивает скорость на качество. Conditional diffusion подаёт embedding символа, стиля или reference через concatenation, adaptive normalization или cross-attention. Classifier-free guidance комбинирует unconditional и conditional noise estimates: \[ \hat\varepsilon=(1+w)\varepsilon_{\rm cond}-w\varepsilon_{\rm uncond}. \] Большой \(w\) усиливает соответствие условию, но снижает diversity и может искажать штрихи. ## Разобранный пример forward process Пусть \(\bar\alpha_t=0.64\), скаляр \(x_0=0.5\), шум \(\varepsilon=-1\). Тогда \[ x_t=0.8\cdot0.5+0.6\cdot(-1)=-0.2. \] Если сеть идеально предскажет \(-1\), то \(\hat x_0=(-0.2-0.6(-1))/0.8=0.5\). При больших \(t\), когда \(\bar\alpha_t\to0\), восстановление особенно чувствительно к ошибке noise model. ## Runnable PyTorch-код forward diffusion ```python import torch T = 100 betas = torch.linspace(1e-4, 0.02, T) alphas = 1.0 - betas alpha_bar = torch.cumprod(alphas, dim=0) x0 = torch.rand(8, 1, 28, 28) * 2 - 1 t = torch.randint(0, T, (x0.shape[0],)) noise = torch.randn_like(x0) a = alpha_bar[t].view(-1, 1, 1, 1) xt = a.sqrt() * x0 + (1 - a).sqrt() * noise # Заглушка показывает интерфейс noise predictor. model = torch.nn.Conv2d(1, 1, kernel_size=3, padding=1) pred = model(xt) # реальная модель также обязана получить embedding t loss = torch.nn.functional.mse_loss(pred, noise) loss.backward() print(xt.shape, float(loss)) ``` Одной convolution недостаточно: реальная UNet получает time embedding и имеет receptive field на весь глиф. Этот фрагмент проверяет формулы и формы массива. ## Сравнение и оценка GAN генерирует за один проход, diffusion — итеративно. GAN часто резче при малом размере, diffusion обычно проще оптимизировать и лучше покрывает распределение. Сравнение при разном compute нечестно. FID на natural-image features может плохо соответствовать качеству чёрно-белых глифов; добавляйте accuracy независимого character recognizer, diversity внутри класса, nearest-neighbor к train и человеческую оценку читаемости вслепую. ## Типичные ошибки и ограничения - Считать низкий generator loss признаком качества без просмотра и метрик. - Обучать discriminator до насыщения или забывать `detach` при его update. - Называть critic WGAN discriminator-вероятностью и добавлять sigmoid. - Путать \(\alpha_t\) и cumulative \(\bar\alpha_t\). - Не передавать timestep diffusion-модели. - Использовать schedule/sampler, не соответствующий обученной параметризации `epsilon`, `x0` или `v`. - Повышать guidance до потери diversity. - Не проверять memorization и генерацию имитаций подписей реальных людей. ## Краткое резюме - GAN решает игру generator/discriminator; оптимальный discriminator сравнивает плотности данных и модели. - Mode collapse и нестабильность требуют независимой оценки diversity. - Diffusion имеет известный forward Gaussian process и учит обратное denoising. - Условность усиливает контроль, но не гарантирует читаемость, оригинальность и безопасное применение. ## Связанные материалы - Предыдущая глава: [Autoencoder и VAE](01_autoencoders_vae.md). - Следующая глава: [Условные глифы и композиция](03_conditional_glyphs.md). - Архитектурная база: [CNN](../../10_computer_vision/notes/01_convolutions_and_cnn.md) и [attention](../../13_nlp_transformers/notes/02_attention_and_transformer_block.md). - Термины: [glossary.md](../glossary.md).