Autoencoders & VAEs
- Autoencoders as dimensionality reduction: Rumelhart et al. (1986) used backpropagation for non-linear PCA
- Variational Autoencoders (VAEs) by Kingma & Welling (2013) added a probabilistic latent space enabling generation
- Foundation for latent diffusion models (Stable Diffusion) and representation learning
Autoencoders compress input to a latent code (encoder) then reconstruct it (decoder), learning a compact representation. VAEs add a constraint that the latent space follows a Gaussian distribution, enabling sampling and interpolation - you can generate new examples by sampling from the latent space.
- Latent diffusion models (Stable Diffusion) use VAE encoders/decoders around a diffusion process
- The VAE ELBO loss connects to variational inference and KL divergence
- Representation learning connects to SSL (self-supervised learning), contrastive learning, and CLIP
- Define the vanilla, denoising, and sparse autoencoders and explain when each helps.
- Derive the ELBO from the marginal log-likelihood and the KL divergence between the variational posterior and the true posterior.
- Justify the reparameterization trick: why we sample z = mu + sigma * eps instead of z ~ q(z|x), and how it enables backpropagation through stochastic nodes.
- Derive the closed-form KL divergence between two diagonal Gaussians and apply it as the regularizer in a VAE.
- Explain the beta-VAE disentanglement trade-off and the KL-vanishing failure mode (Bowman 2015).
TL;DR
An autoencoder learns a bottlenecked encoder-decoder pair that minimizes reconstruction error on its inputs [1]. Denoising autoencoders [2] corrupt the input and reconstruct the clean target, learning robust features. Sparse autoencoders add an L1 penalty on activations to learn sparse codes. The variational autoencoder (VAE) [3][4] places a probabilistic prior on the latent and trains by maximizing the evidence lower bound (ELBO)
with the reparameterization trick for enabling gradients through the sample. beta-VAE [5] upweights the KL term to encourage disentangled factors at the cost of reconstruction sharpness. VAE samples are blurry because the per-pixel Gaussian likelihood is the wrong noise model for natural images, a fact diffusion models partially fix.
Intuition
An autoencoder is a network that learns to copy its input to its output through a bottleneck: the encoder compresses the input into a low-dimensional latent code , and the decoder reconstructs from . The bottleneck forces the network to discover a compressed representation; once trained, the latent code is a learned feature vector for downstream tasks.
The plain autoencoder is deterministic: one input maps to one latent, and reconstructing is just a non-linear PCA-like operation. The variational autoencoder makes everything stochastic: the encoder outputs a distribution over latents (typically a diagonal Gaussian), the decoder defines a distribution (typically Gaussian or Bernoulli), and we train by maximizing a lower bound on . The reward is a generative model: sample , pass through the decoder, and you get a new “thought” from the same distribution as the training data.
A plain autoencoder produces an arbitrary code per example, with no constraint on what the code distribution looks like across the dataset. The codes can land anywhere in the latent space. To sample new data you would need to know which regions of latent space are plausible.
A VAE imposes a prior on the latent distribution and pulls the encoder’s output toward it via a KL term. After training, the marginal posterior is approximately , so to generate new examples you sample from and decode. The KL term is what turns “compressor” into “generative model” [3].
Vanilla and denoising autoencoders
A vanilla autoencoder with squared loss is
If the encoder and decoder are linear and the loss is squared error, the optimum recovers PCA: projects onto the top- principal directions and is the transpose. With non-linear encoders/decoders the autoencoder generalizes PCA to arbitrary manifolds [1].
A denoising autoencoder [2] introduces a corruption distribution (Gaussian noise, masking, salt-and-pepper) and trains the model to reconstruct the clean from the corrupted :
The model cannot just memorize the input; it has to learn structure that survives noise. Empirically denoising autoencoders learn features that transfer better to downstream tasks than vanilla autoencoders, and BERT’s masked-language-modelling objective is exactly denoising at the level of tokens.
A sparse autoencoder keeps the vanilla reconstruction loss but adds an L1 penalty on the latent activations:
The L1 pulls most latent units to zero, leaving only a few active per example. The result is a sparse, often more interpretable code; this is the textbook setup that motivated dictionary-learning and the mainstream sparse-coding literature.
The variational autoencoder
The full ELBO derivation (interview gold)
Setup
We have a generative model with prior and decoder (e.g. Gaussian or Bernoulli). We want maximum likelihood: maximize over . The trouble is that
is intractable, and the true posterior is intractable for the same reason.
Step 1: introduce a variational posterior
Introduce a tractable approximation to the true posterior. The encoder network produces the parameters of (e.g. mean and log-variance of a diagonal Gaussian).
Step 2: identity for
For any distribution that has the same support as ,
because the expectation of a constant (in ) is the constant. Now use :
Step 3: insert and split with
Multiply and divide by inside the log:
Split the log into two terms:
Both pieces have a name. The first is the evidence lower bound, ; the second is the KL divergence from the variational posterior to the true posterior.
Step 4: KL is non-negative, so ELBO
By Gibbs’ inequality , with equality iff almost everywhere. Therefore
This is the evidence lower bound (ELBO). Maximizing the ELBO over does two things at once: it pushes up (the gap closes from below) and it tightens the bound by minimizing (the variational posterior approaches the true posterior).
Step 5: split the ELBO into reconstruction and prior-matching
Use :
This is the standard form of the ELBO that the VAE optimizes:
- is the reconstruction term: how well the decoder explains given a code drawn from the encoder.
- is the prior-matching term: how close the encoder’s output distribution is to the prior .
The VAE training objective for a minibatch is
The reconstruction expectation is estimated with a single Monte-Carlo sample ; the KL has a closed form for diagonal Gaussians (next DeepDive).
Reparameterization trick: gradients through a stochastic node
The problem
The ELBO contains . To optimize over we need
If we sample directly, the sampling step has no gradient (it is just an index into a random number stream), so the standard chain rule does not apply through .
REINFORCE-style estimator (high variance)
The score-function (REINFORCE) estimator handles this with the identity :
This works for any , including discrete distributions, but its variance is large: the gradient signal is whatever the log-likelihood ratio happens to be at the sample, scaled by . Plain REINFORCE without baselines is too noisy to train a VAE in reasonable time.
Reparameterization
For continuous that can be written as a deterministic transformation of a parameter-free noise distribution, do the change of variables. For a diagonal Gaussian:
The noise does not depend on ; the transformation does. Now
and the gradient passes through and the transformation by ordinary chain rule:
This is the reparameterization trick [3][4]. The variance is much lower than REINFORCE because the gradient uses the shape of (its derivative), not just its value at the sample.
Why is parameterized as in practice
To keep positive, the encoder outputs (a real-valued network output) and we recover . This avoids softplus or absolute-value tricks and gives a well-behaved gradient near .
Beyond Gaussian
The same trick works for any distribution that is the pushforward of a parameter-free base distribution under a smooth map: Gumbel-Softmax for categorical, planar/radial flows, normalizing flows in general. Discrete distributions need REINFORCE or relaxations.
Closed-form KL between two diagonal Gaussians
Statement
For and in :
For the VAE special case , so and :
This is what the VAE actually computes for the KL term; no Monte Carlo needed.
Derivation
Start from the definition of KL and substitute the Gaussian density:
For a diagonal Gaussian, . Take the expectation under , using :
For , expand the squared term: (variance plus mean shift). So
Subtract:
beta-VAE and the disentanglement trade-off
The standard VAE objective is the ELBO. Higgins et al. [5] proposed multiplying the KL term by a tunable coefficient :
- is the standard VAE.
- strengthens the prior-matching pressure. Each latent dimension is pushed to be more independent from the others (because is itself factorized), which encourages the latent code to align with disentangled factors of variation in the data: rotation, scale, lighting.
- relaxes the prior; the code carries more information about , reconstructions sharpen, but sampling quality suffers.
The trade-off is sharp: at on dSprites, -VAE produces a code where each latent corresponds to one interpretable factor, but reconstructions are blurrier than at . In practice, is tuned on the downstream task; for representation learning is typical, for image generation .
The -VAE objective is mathematically equivalent to a Lagrangian on the information bottleneck principle [7]:
where denotes mutual information. The KL term in the VAE is an upper bound on measured against the prior, and pushing the KL down corresponds to compressing to remove variance unrelated to the reconstruction objective. The ” as compression dial” intuition is the practical takeaway.
Implementations
A canonical PyTorch VAE on MNIST and the equivalent in TensorFlow Keras.
import torch
import torch.nn as nn
import torch.nn.functional as F
class VAE(nn.Module):
"""Diagonal-Gaussian VAE on flattened MNIST."""
def __init__(self, in_dim: int = 784, h_dim: int = 400, z_dim: int = 20) -> None:
super().__init__()
# Encoder.
self.fc1 = nn.Linear(in_dim, h_dim)
self.fc_mu = nn.Linear(h_dim, z_dim)
self.fc_logvar = nn.Linear(h_dim, z_dim)
# Decoder.
self.fc2 = nn.Linear(z_dim, h_dim)
self.fc3 = nn.Linear(h_dim, in_dim)
def encode(self, x):
h = F.relu(self.fc1(x))
return self.fc_mu(h), self.fc_logvar(h)
def reparameterize(self, mu, logvar):
# z = mu + sigma * eps, where sigma = exp(0.5 * logvar).
std = torch.exp(0.5 * logvar)
eps = torch.randn_like(std)
return mu + std * eps
def decode(self, z):
h = F.relu(self.fc2(z))
return torch.sigmoid(self.fc3(h)) # Bernoulli mean over pixels.
def forward(self, x):
mu, logvar = self.encode(x)
z = self.reparameterize(mu, logvar)
x_recon = self.decode(z)
return x_recon, mu, logvar
def vae_loss(x, x_recon, mu, logvar, beta: float = 1.0):
# Bernoulli reconstruction; sum over pixels, mean over batch.
bce = F.binary_cross_entropy(x_recon, x, reduction='sum')
# Closed-form KL between q and N(0, I), summed over latent dims.
kl = -0.5 * torch.sum(1.0 + logvar - mu.pow(2) - logvar.exp())
return (bce + beta * kl) / x.shape[0]
# Training step (assuming x is a flattened MNIST minibatch in [0, 1]):
# vae = VAE().to(device); opt = torch.optim.Adam(vae.parameters(), lr=1e-3)
# for x, _ in loader:
# x = x.to(device).view(x.size(0), -1)
# x_recon, mu, logvar = vae(x)
# loss = vae_loss(x, x_recon, mu, logvar, beta=1.0)
# opt.zero_grad(); loss.backward(); opt.step()Run a tiny denoising autoencoder in NumPy on a flat random vector. The model has to remove additive Gaussian noise from a fixed clean target:
(no output yet)
Comparison
| Model | Loss | Supports sampling? | Disentanglement | Output sharpness | Notes |
|---|---|---|---|---|---|
| Vanilla AE | reconstruction MSE | no (no prior on z) | no | sharp on training data | Reduces to PCA when linear; non-linear AEs generalize PCA. |
| Denoising AE | reconstruction MSE on (noisy -> clean) pairs | no (deterministic) | no | sharp | Robust features; basis of masked-LM (BERT-style) pretraining. |
| Sparse AE | reconstruction + L1 on z | no | partial (active units) | sharp | Learns sparse codes; classical motivation for dictionary learning. |
| VAE | ELBO = recon - KL | yes (sample from prior) | no (entangled latents) | blurry (Gaussian likelihood) | Standard generative AE; mode-covering due to KL(q || p) form. |
| beta-VAE (beta > 1) | recon - beta * KL | yes | yes (compresses + factorizes) | blurrier than VAE | Higgins 2017; trade reconstruction for disentanglement. |
Real-world uses
| Domain | Use | Why an autoencoder works |
|---|---|---|
| Denoising | image, audio, signal | Bottleneck enforces a clean reconstruction; the network learns the data manifold and projects noise off it. |
| Anomaly detection | fraud, manufacturing defects, log analytics | Train on "normal" only; high reconstruction error at inference flags an outlier. |
| Representation learning | pretraining for downstream classifiers | Latent code captures a compressed, often more linearly separable, view of the input. |
| Image generation (pre-2020) | sampling from a learned latent | VAEs were one of the two main generative models pre-diffusion; now mostly displaced by diffusion + Latent Diffusion (which uses a VAE encoder under the hood). |
| Recommender / embedding compression | compress sparse user/item vectors | Dense bottleneck makes downstream similarity search and ranking cheap. |
Pitfalls
The standard VAE decoder is a diagonal Gaussian, which is equivalent to per-pixel MSE between the decoder mean and the target. MSE assumes Gaussian noise, which is wrong for natural images: the actual residuals are heavy-tailed and structured. The MSE-optimal decoder under uncertainty is the conditional mean, which averages over plausible images and produces a blurry result.
Two fixes beyond plain VAE:
- Stronger likelihoods: pixelCNN/PixelSNAIL decoders (autoregressive over pixels), or a VAE-GAN hybrid where a discriminator provides perceptual loss.
- Use the VAE as a feature compressor: train a VAE to land in a clean latent and put a separate generative model (diffusion, autoregressive) on the latent. This is exactly what Latent Diffusion / Stable Diffusion does.
If the decoder is too powerful, the model can learn to ignore entirely: it sets (so the KL term goes to zero) and uses the decoder’s autoregressive capacity to fit directly. The latent code carries no information; the VAE is degenerate. Bowman et al. [8] first documented this on text VAEs with LSTM decoders.
Standard mitigations: KL annealing (start training with the KL term scaled down and ramp it up), free-bits (clip the per-dimension KL to a minimum so the model cannot collapse all dimensions to the prior), or weaker decoders. KL-vanishing is a known recurring failure mode that requires explicit attention.
Tuning buys disentanglement but spends reconstruction sharpness; buys reconstruction sharpness but spends sample quality and disentanglement. Always evaluate both objectives (reconstruction error AND a disentanglement metric like MIG) when choosing , not one alone [5].
Parameterize the encoder to output , not directly: it keeps positive without softplus tricks, the gradient is well-behaved near , and the closed-form KL formula is in already.
Pop quiz
- 1. Starting from log p(x), the ELBO is derived by:
- 2. Why do we need the reparameterization trick for VAEs?
- 3. Why are VAE samples blurry?
- 4. In beta-VAE, increasing beta:
- 5. The closed-form KL between q = N(mu, diag(sigma^2)) and p = N(0, I) is:
Interview Q&A
Derive the ELBO from the marginal log-likelihood and KL divergence.research
We want to maximize but the marginal is intractable. Introduce a variational posterior and use that the expectation of a constant-in- quantity under any distribution is the constant:
Substitute :
Insert and divide by :
The first term is the ELBO ; the second is . Therefore , with equality iff matches the true posterior.
Splitting the joint rewrites the ELBO as
The reconstruction term is estimated by a single Monte Carlo sample via the reparameterization trick; the KL term has a closed form when and are both diagonal Gaussian [3][6].
Why do we need the reparameterization trick instead of just sampling z?onsite
The ELBO contains . To optimize over the encoder parameters we need
If we sample directly, the sample is a black-box random number with no gradient path back through .
REINFORCE would fix this with , but the variance is enormous because the gradient depends on the value of at the sample, not on its shape. Training a VAE with REINFORCE without baselines is impractical.
Reparameterization rewrites as a deterministic function of an external noise variable: , . The randomness lives in , which is independent of . The expectation becomes
and ordinary backprop flows through , then through the linear transformation, then into . The gradient uses the derivative of , not its raw value, which gives much lower variance.
The trick generalizes to any distribution that can be written as the pushforward of a parameter-free base distribution under a smooth map: planar/radial flows, Gumbel-Softmax for categorical, normalizing flows in general. Discrete or heavy-tailed distributions still need REINFORCE or relaxations [4].
Why are VAE samples blurry, and what fixes the problem?onsite
The standard VAE decoder is , equivalent to per-pixel MSE between the decoder mean and the target . Per-pixel MSE assumes pixel residuals are independent Gaussian with constant variance. That is wrong for natural images: residuals are heavy-tailed, spatially correlated, and structured (edges, textures).
Under the wrong noise model, the loss-optimal decoder at any point in latent space is the conditional mean of the data conditional on . The conditional mean averages over plausible images consistent with the latent code (e.g. a digit at slightly different positions/styles), and the average of plausible images is blurry. There is no “blurry photograph” in the data; blur is an artifact of MSE optimality.
Three classes of fix:
- Stronger likelihoods. Replace the diagonal Gaussian decoder with an autoregressive PixelCNN/PixelSNAIL or a discretized logistic mixture. The model now puts probability mass on actual sharp images, not their average.
- Adversarial / perceptual loss (VAE-GAN). Train a discriminator that distinguishes real from reconstructed images, and replace pixel MSE with a feature-space loss from a fixed perceptual network. This pushes reconstructions toward the true image manifold rather than its mean.
- Use the VAE as a compressor, put a generative model on the latent. This is the Latent Diffusion / Stable Diffusion architecture: a VAE compresses pixels to a small latent, a diffusion model is trained on the latent, and decoding back to pixels uses the (sharp) VAE decoder. The diffusion handles the mode-seeking; the VAE handles the compression.
The blurriness is a known property of the standard VAE objective, not a bug to debug.
What is the beta-VAE trade-off and how do you tune beta in practice?onsite
The beta-VAE objective [5] is
The KL term is upper-bounded by mutual information measured against the prior. Multiplying by changes the trade-off:
- : standard VAE, optimizes the ELBO exactly.
- : stronger compression of . Forces the encoder’s output distribution toward the factorized prior , encouraging each latent dimension to be independent and align with one disentangled factor of variation in the data. Reconstruction sharpness drops because the code carries less information.
- : weaker compression. Code carries more information, reconstructions sharpen, but sampling from the prior becomes less faithful and disentanglement disappears.
Tuning in practice:
- Pick the metric that matters: reconstruction error for compression, sample FID/IS for generation, mutual information gap (MIG) or modularity for disentanglement.
- Sweep across on the train+val split. Plot the trade-off curve.
- Beware KL-vanishing at very small : even does not guarantee informative latents because the decoder may simply ignore (Bowman 2015 [8]). Always check the per-dim KL after training; if many dims are at zero, the latent is collapsing.
- Production recipe for representation learning: with KL annealing (start near 0, ramp to target).
- Production recipe for generation: with a stronger decoder (PixelCNN, GAN, diffusion on the latent).
The tradeoff is sharp: there is no that gives both perfect reconstruction and full disentanglement on natural data, only a Pareto curve.
Derive the closed-form KL divergence between two diagonal Gaussians.onsite
For and in , the KL is
For a diagonal Gaussian,
Take the expectation under , using :
For , use (variance plus squared mean shift):
Subtract:
For the VAE special case (, ):
This is what the VAE actually computes; no Monte Carlo needed. The corresponding code is -0.5 * (1 + logvar - mu**2 - logvar.exp()).sum() [9][3].
A weekend project that takes a VAE from textbook to working:
- Implement the PyTorch VAE above on MNIST. Train for 20 epochs at . Check that the per-dim KL after training is non-zero on most dimensions (no collapse).
- Plot a 2D latent slice: encode a few training images, then decode points along a line in latent space. The decoder should produce a smooth interpolation (e.g. 3 morphing into 8). This is the qualitative test that the latent is well-organized.
- Sweep . Record reconstruction error and sample quality at each. You should see the Pareto curve appear.
- Trigger KL-vanishing on purpose: replace the decoder with a powerful autoregressive PixelCNN (or a deep ResNet) and train at . Watch the per-dim KL collapse to ~0 and the latent become uninformative. Add KL annealing as the fix.
- Stretch: train a denoising autoencoder on MNIST with masked input (set 50% of pixels to 0). Compare features extracted from the bottleneck against the VAE’s mean encoding for downstream classification. Denoising features often transfer better.
References
- Hinton, G. E. and Salakhutdinov, R. R. (2006). Reducing the Dimensionality of Data with Neural Networks. Science 313(5786), 504-507. doi:10.1126/science.1127647
- Vincent, P., Larochelle, H., Bengio, Y., and Manzagol, P.-A. (2008). Extracting and composing robust features with denoising autoencoders. ICML 2008. doi:10.1145/1390156.1390294
- Kingma, D. P. and Welling, M. (2013). Auto-Encoding Variational Bayes. ICLR 2014 (arXiv preprint 2013). arXiv:1312.6114
- Rezende, D. J., Mohamed, S., and Wierstra, D. (2014). Stochastic Backpropagation and Approximate Inference in Deep Generative Models. ICML 2014. arXiv:1401.4082
- Higgins, I., Matthey, L., Pal, A., Burgess, C., Glorot, X., Botvinick, M., Mohamed, S., and Lerchner, A. (2017). beta-VAE: Learning Basic Visual Concepts with a Constrained Variational Framework. ICLR 2017. https://openreview.net/forum?id=Sy2fzU9gl
- Doersch, C. (2016). Tutorial on Variational Autoencoders. arXiv preprint. arXiv:1606.05908
- Tishby, N. and Zaslavsky, N. (2015). Deep Learning and the Information Bottleneck Principle. IEEE Information Theory Workshop. arXiv:1503.02406
- Bowman, S. R., Vilnis, L., Vinyals, O., Dai, A. M., Jozefowicz, R., and Bengio, S. (2015). Generating Sentences from a Continuous Space. CoNLL 2016 (arXiv preprint 2015). arXiv:1511.06349
- Bishop, C. M. (2006). Pattern Recognition and Machine Learning. Springer. ISBN 978-0-387-31073-2
Interactive Demo
Tip: Use Interpolate mode and slide between two shapes to see a smooth latent space transition