
I cover the motivation, mathematical derivation, PyTorch implementation, and practical training considerations for variational autoencoders using the CelebA dataset.
The idea
The manifold hypothesis: High-dimensional sensory data naturally lies on a much lower-dimensional continuous manifold where semantic attributes are smoothly organized. Standard autoencoders can compress data, but their latent spaces lack structure, making it difficult to generate valid new samples. Variational autoencoders fix this by forcing the encoder to map inputs to probability distributions over the latent space rather than single deterministic points, encouraging continuous and smooth latent representations. By balancing how well the decoder reconstructs inputs against how closely the latent distributions match a simple Gaussian prior, I build a generative model capable of synthesizing novel data points.
The mechanism
This equation defines the evidence lower bound objective by balancing reconstruction fidelity against latent regularization relative to a prior.
This reparameterization trick isolates the stochastic sampling step outside the computational graph, allowing backpropagation of gradients through encoder parameters.
This computes the closed-form distance between the predicted diagonal Gaussian posterior and the standard normal prior.
This loss objective applies a hyperparameter weight to the KL divergence term to mitigate posterior collapse while preserving reconstruction capability.
Worth knowing
- Performing image resizing before converting images to PyTorch tensors prevents severe CPU bottlenecks during data loading.
- Setting the KL divergence weight () too high degrades reconstruction fidelity, while setting it to zero collapses the architecture into a deterministic autoencoder.
- Direct stochastic sampling blocks gradient flow during backpropagation, requiring explicit extraction of random noise via the reparameterization trick.
Code
The core reparameterization trick, KL divergence calculation, and forward sampling pass are implemented in modeling.py inside the VAE class.
@staticmethod
def sample_z_from_mean_logvar(mu: T.Tensor, log_var: T.Tensor) -> T.Tensor:
# reparameterization trick
eps = T.randn(size=mu.shape).to(mu.device)
z = mu + (T.sqrt(T.exp(log_var)) * eps)
return zUse it when / don't use it when
Use it when
- You want to learn continuous, semantically meaningful latent representations in a self-supervised manner without labels.
- You need a foundational generative building block for downstream tasks or advanced diffusion architectures.
Don't use it when
- You require hyper-realistic, photorealistic image output quality without applying hierarchical or vector-quantized extensions.
- You only need simple deterministic dimensionality reduction or compression without generating new data points.
Further reading
- Auto-Encoding Variational Bayes (Kingma & Welling, 2013)
- beta-VAE: Learning Basic Visual Concepts with a Constrained Variational Framework (Higgins et al., 2017)
- Understanding Deep Learning (Simon J.D. Prince)