ai_learning/modules/12_generative_handwriting/notes/01_autoencoders_vae.md

9.4 KiB
Raw Permalink Blame History

Латентные модели: autoencoder и VAE

Глава выводит цели обычного autoencoder и variational autoencoder и связывает ELBO с реконструкцией, регуляризацией и генерацией символов.

Мотивация и интуиция

Изображение глифа содержит тысячи пикселей, но его вариативность часто объясняется меньшим числом факторов: символом, наклоном, толщиной, связностью и стилем. Encoder сжимает \mathbf{x} в latent code \mathbf{z}, decoder восстанавливает изображение. Узкое место заставляет хранить существенное, но само по себе не гарантирует осмысленного или гладкого пространства.

Обычный autoencoder учит детерминированное преобразование и хорошо реконструирует, но пустые области latent space могут декодироваться в мусор. VAE учит распределение кодов и приближает его к prior, чтобы можно было семплировать новые объекты. Цена — часто более размытая реконструкция.

Autoencoder

Для \mathbf{x}\in[0,1]^d:


\mathbf{z}=f_{\boldsymbol{\phi}}(\mathbf{x})\in\mathbb{R}^k,\qquad
\hat{\mathbf{x}}=g_{\boldsymbol{\theta}}(\mathbf{z}).

Цель на датасете:


\min_{\boldsymbol{\phi},\boldsymbol{\theta}}
\frac1n\sum_{i=1}^{n}
\ell(\mathbf{x}^{(i)},g_{\boldsymbol{\theta}}
(f_{\boldsymbol{\phi}}(\mathbf{x}^{(i)}))).

Для непрерывной яркости используют MSE; для Bernoulli-модели пикселей — binary cross-entropy. BCE с sigmoid соответствует отрицательному log-likelihood независимых Bernoulli pixels, но реальные antialiased pixels и их зависимости этому предположению не вполне соответствуют.

Если сеть слишком мощная и k велико, она может приблизить identity. Denoising AE получает испорченный \tilde{\mathbf{x}}, но восстанавливает чистый \mathbf{x}; sparse/contractive варианты добавляют регуляризацию.

Вероятностная постановка VAE

Задаём prior p(\mathbf{z})=\mathcal{N}(\mathbf{0},\mathbf{I}) и decoder p_{\boldsymbol{\theta}}(\mathbf{x}\mid\mathbf{z}). Marginal likelihood:


p_{\boldsymbol{\theta}}(\mathbf{x})
=\int p_{\boldsymbol{\theta}}(\mathbf{x}\mid\mathbf{z})p(\mathbf{z})d\mathbf{z}.

Posterior p(\mathbf{z}\mid\mathbf{x}) обычно недоступен. Encoder задаёт приближение


q_{\boldsymbol{\phi}}(\mathbf{z}\mid\mathbf{x})
=\mathcal{N}(\boldsymbol{\mu}_{\boldsymbol{\phi}}(\mathbf{x}),
\operatorname{diag}(\boldsymbol{\sigma}^2_{\boldsymbol{\phi}}(\mathbf{x}))).

Вывод ELBO

Вставим q/q, затем применим неравенство Jensen:


\begin{aligned}
\log p_{\boldsymbol{\theta}}(\mathbf{x})
&=\log\int q_{\boldsymbol{\phi}}(\mathbf{z}\mid\mathbf{x})
\frac{p_{\boldsymbol{\theta}}(\mathbf{x},\mathbf{z})}
{q_{\boldsymbol{\phi}}(\mathbf{z}\mid\mathbf{x})}d\mathbf{z}\\
&=\log\mathbb{E}_{q_{\boldsymbol{\phi}}}
\left[\frac{p_{\boldsymbol{\theta}}(\mathbf{x},\mathbf{z})}{q_{\boldsymbol{\phi}}}\right]\\
&\ge \mathbb{E}_{q_{\boldsymbol{\phi}}}
\left[\log p_{\boldsymbol{\theta}}(\mathbf{x}\mid\mathbf{z})\right]
-D_{\mathrm{KL}}\!\left(q_{\boldsymbol{\phi}}(\mathbf{z}\mid\mathbf{x})
\|p(\mathbf{z})\right)
=\mathcal{L}_{\mathrm{ELBO}}.
\end{aligned}

Точнее, (\log p(\mathbf{x})=\mathcal{L}{ELBO} +D{KL}(q(\mathbf{z}\mid\mathbf{x})|p(\mathbf{z}\mid\mathbf{x}))), поэтому это нижняя граница. Обучение минимизирует negative ELBO:


\mathcal{J}=\underbrace{-\mathbb{E}_q\log p(\mathbf{x}\mid\mathbf{z})}
_{\text{reconstruction}}+
\underbrace{D_{KL}(q(\mathbf{z}\mid\mathbf{x})\|p(\mathbf{z}))}
_{\text{regularization}}.

Для diagonal Gaussian и standard normal:


D_{KL}=-\frac12\sum_{j=1}^k
(1+\log\sigma_j^2-\mu_j^2-\sigma_j^2).

Reparameterization trick

Нельзя напрямую backpropagate через случайное семплирование, зависящее от \boldsymbol{\phi}. Переносим случайность:


\boldsymbol{\varepsilon}\sim\mathcal{N}(\mathbf{0},\mathbf{I}),\qquad
\mathbf{z}=\boldsymbol{\mu}+
\boldsymbol{\sigma}\odot\boldsymbol{\varepsilon}.

Теперь \varepsilon независимо от параметров, а \mu,\sigma участвуют в дифференцируемой операции. Сеть предсказывает logvar, затем \sigma=\exp(0.5\,\mathrm{logvar}) для положительности.

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

Для одного объекта \boldsymbol{\mu}=(1,0), \log\boldsymbol{\sigma}^2=(0,\log4):


D_{KL}=-\frac12[(1+0-1-1)+(1+\log4-0-4)]
\approx1.807.

Первое измерение платит 0.5 за сдвиг mean, второе — примерно 1.307 за variance 4. При \mu=0,\sigma^2=1 вклад равен нулю.

Runnable PyTorch-код

import torch
from torch import nn
from torch.nn import functional as F

class VAE(nn.Module):
    def __init__(self, d=28*28, k=16):
        super().__init__()
        self.enc = nn.Sequential(nn.Linear(d, 256), nn.ReLU())
        self.mu, self.logvar = nn.Linear(256, k), nn.Linear(256, k)
        self.dec = nn.Sequential(nn.Linear(k, 256), nn.ReLU(),
                                 nn.Linear(256, d))
    def forward(self, x):
        h = self.enc(x)
        mu, logvar = self.mu(h), self.logvar(h)
        z = mu + torch.exp(0.5 * logvar) * torch.randn_like(mu)
        return self.dec(z), mu, logvar

x = torch.rand(8, 28*28)
model = VAE()
logits, mu, logvar = model(x)
recon = F.binary_cross_entropy_with_logits(logits, x, reduction="sum") / len(x)
kl = (-0.5 * (1 + logvar - mu.square() - logvar.exp()).sum()) / len(x)
loss = recon + kl
loss.backward()
print(float(recon), float(kl), mu.shape)

Суммирование по pixels и latent dimensions, затем деление по batch делает масштаб явным. Нельзя случайно усреднить reconstruction по всем pixels, оставив KL суммой: это радикально меняет баланс.

Практика для рукописных глифов

Делите данные по писателям, иначе модель увидит стиль test-пользователя на train. Нормализуйте canvas и baseline осторожно: чрезмерное выравнивание удалит признаки почерка. Интерполяция между двумя кодами показывает гладкость, но не доказывает disentanglement. Для conditional VAE подавайте label символа и encoder, и decoder; иначе latent обязан одновременно хранить content и style.

(\beta)-VAE использует \mathcal{J}=\text{recon}+\beta KL. Большое (\beta) усиливает prior и иногда disentanglement, но ухудшает детали. KL annealing и free bits помогают против posterior collapse, когда decoder игнорирует \mathbf{z}.

Типичные ошибки и ограничения

  • Называть AE генеративной моделью только потому, что decoder рисует: sampling distribution не определено.
  • Использовать sigmoid перед binary_cross_entropy_with_logits.
  • Сравнивать модели с разными reduction и масштабом loss.
  • Считать низкую reconstruction loss доказательством полезного latent space.
  • Допустить writer leakage или дубликаты глифов между split.
  • Интерпретировать координату latent как конкретный стиль без controlled evidence.
  • Хранить реальные образцы подписи: это биометрические данные и потенциальный материал для подделки.

Краткое резюме

  • AE сжимает и реконструирует, но не формирует автоматически удобный prior.
  • VAE максимизирует ELBO: likelihood-реконструкцию минус KL к prior.
  • Reparameterization делает stochastic latent дифференцируемым.
  • Баланс reconstruction/KL, split по писателям и этика данных критичны.

Связанные материалы