Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 18

Perceptual VAE for Image Compression

Recommended resources

Hello! Welcome back to our module on latent diffusion.

In our last lesson, we explored the "why" of latent diffusion, analyzing the computational and quality trade-offs that motivate moving from pixel space to a compressed latent space. We concluded that the success of this entire strategy hinges on the quality of the autoencoder used for this compression.

Today, we move from theory to practice. Our learning outcome is to train a Variational Autoencoder (VAE) with perceptual and adversarial losses for high-fidelity image compression. This is the critical first stage of building a latent diffusion model. We'll construct the architecture and, more importantly, dissect the sophisticated loss function and training procedure required to create a latent space that is both compact and perceptually rich.

1. From Standard VAE to a High-Fidelity Autoencoder

You're likely familiar with the standard Variational Autoencoder. It consists of an encoder that maps an image to a distribution in the latent space (parameterized by a mean and variance), and a decoder that reconstructs the image from a sample of that distribution.

Variational Autoencoder (VAE) Architecture and Loss Function
A standard VAE consists of an encoder, a latent space regularized by a KL divergence loss, and a decoder that reconstructs the input. Its loss is a combination of reconstruction error and a KL term.

The traditional VAE loss function is a sum of a reconstruction term (like Mean Squared Error) and a KL divergence term that regularizes the latent space. As we discussed, relying on MSE alone leads to blurry reconstructions, which is unacceptable for our purposes.

To build a high-fidelity autoencoder for latent diffusion, we need to upgrade both the architecture and the loss function.

Architectural Foundation

The autoencoder used in latent diffusion models is often built with similar blocks to the U-Net you're familiar with from DDPMs (e.g., ResNet blocks, self-attention), but with two key differences:

  1. No skip connections between the encoder and decoder. The latent space must be a true information bottleneck.
  2. No time embeddings, as the autoencoder's job is purely spatial compression, not denoising over time.

The video below details this architecture and contrasts the VAE approach (which we're using) with the VQ-VAE variant.

Stable Diffusion from Scratch in PyTorch | Unconditional Latent Diffusion Models

Let's watch a segment from 'ExplainingAI' that describes the U-Net-like architecture of the autoencoder used in latent diffusion models.

Watch the section from 19:32 to 24:26. Pay attention to how standard DDPM blocks are repurposed for the encoder and decoder, and note the specific modifications made for the VAE variant (outputting mean and log-variance).


2. The Loss Function Quartet

The real power of this autoencoder comes from a carefully constructed loss function that balances four distinct objectives. Let's break down each component.

The total loss can be expressed as a weighted sum:

Where are hyperparameters that balance the contribution of each term.

A. Reconstruction Loss ()

This is a straightforward pixel-wise L1 or Mean Squared Error (MSE) loss between the input image and its reconstruction .

Its role is to provide a strong, stable gradient signal that ensures the overall structure and color of the image are preserved. As we've established, on its own it is insufficient and leads to blurriness, but it acts as an essential "guardrail" during training.

B. KL Regularization ()

This term comes from the VAE formulation and measures the KL divergence between the learned latent distribution and a standard normal prior . While in a classic VAE this is a core part of the Evidence Lower Bound (ELBO), its role here is more pragmatic.

In latent diffusion models, the weight of this term, , is typically very small. Its primary function is not to strictly enforce a Gaussian latent space, but rather to act as a mild regularizer. It keeps the latent codes from growing to extreme values and helps prevent the variance from collapsing to zero, which makes the subsequent training of the diffusion model on these latents more stable.

Generative modelling in latent space

This blog post from Sander Dieleman provides an excellent, nuanced take on the practical role of KL regularization in modern autoencoders for generative models.

Read the section titled 'VQGAN and KL-regularised latents'. Focus on the discussion about why the KL term is heavily scaled down and how its practical effect is more about constraining the shape and scale of the latents rather than strictly enforcing a Gaussian posterior.

C. Perceptual Loss ()

This is our first major tool for fighting blurriness. Instead of comparing pixels, perceptual loss compares high-level features extracted from a pre-trained network (like VGG). The idea is that if two images have similar feature activations inside a network trained to understand images, they are perceptually similar to a human. The most common implementation is called LPIPS (Learned Perceptual Image Patch Similarity).

The following videos explain the concept and implementation of perceptual loss and LPIPS.

Text to Image Diffusion AI Model from scratch - Explained one line of code at a time!

First, let's get a concise overview of how perceptual loss, KL divergence, and adversarial loss fit together in training the autoencoder.

Watch the segment from 16:07 to 18:17. It quickly summarizes the roles of reconstruction loss, perceptual loss using VGG, KL divergence, and a discriminator loss.

Stable Diffusion from Scratch in PyTorch | Unconditional Latent Diffusion Models

Now, for a deeper dive into the LPIPS implementation, let's return to the 'ExplainingAI' video. This will be very useful for understanding the code you might encounter.

Watch from 07:18 to 16:29. This covers both the 'what' and the 'how' of LPIPS, including the VGG feature extraction and the learned 1x1 convolutions that weight the feature channels.

D. Adversarial Loss ()

To achieve maximum realism and sharpness, we introduce a GAN-style training setup.

  • Generator: Our autoencoder's decoder, , which generates the reconstructed image .
  • Discriminator: A separate network, , trained to distinguish between "real" images (from the dataset, ) and "fake" ones (the reconstructions, ).

The autoencoder is then trained not just to reconstruct the input, but to produce reconstructions that are so realistic they can "fool" the discriminator. This adversarial pressure forces the decoder to learn how to generate the fine-grained textures and high-frequency details that a simple pixel loss would ignore. Typically, a PatchGAN discriminator is used, which classifies overlapping image patches as real or fake, providing a more localized and efficient gradient signal.

The Illustrated VQGAN

To understand the interplay between the generator (our autoencoder) and the discriminator, let's look at this illustrated guide to VQGAN, which uses the same principle.

Read the section 'Training the GAN'. Focus on the diagrams showing the generator (encoder-decoder) and discriminator, and the description of the minimax game. Note the mention of a patch-based discriminator.


3. The Training Loop: An Adversarial Dance

Because we have a discriminator, the training loop is more complex than a standard model.fit(). It involves an alternating optimization process with two separate optimizers.

  1. Instantiate Models:

    • The Autoencoder (Generator)
    • The Discriminator (e.g., PatchGAN)
    • The LPIPS model for perceptual loss (with frozen weights).
  2. Instantiate Optimizers:

    • opt_ae: An optimizer for the autoencoder's parameters.
    • opt_disc: An optimizer for the discriminator's parameters.
  3. In each training step:

    • Discriminator Update:
      • Get reconstructions from the autoencoder.
      • Calculate the discriminator's loss: its ability to correctly label real images as real and fake reconstructions as fake.
      • Perform a backward pass and update the discriminator's weights using opt_disc.
    • Autoencoder (Generator) Update:
      • Calculate the adversarial loss for the generator: its ability to fool the discriminator into labeling reconstructions as real.
      • Calculate the other losses: reconstruction , perceptual , and KL divergence .
      • Combine all losses into the total autoencoder loss .
      • Perform a backward pass and update the autoencoder's weights using opt_ae.

A common and important practical trick is to delay the introduction of the adversarial loss. This allows the autoencoder to first learn a decent reconstruction with the more stable losses before the discriminator's influence begins.

This entire process is detailed exceptionally well in the following video.

Stable Diffusion from Scratch in PyTorch | Unconditional Latent Diffusion Models

This final video segment walks through the PyTorch code for the complete training loop, putting all the pieces together.

Watch from 31:58 to 36:25. This is the most critical part of the lesson. It shows the instantiation of the models, the two optimizers, the calculation of each loss component (L2, perceptual, adversarial), the separate optimization steps, and the disc_start parameter.

Test your understanding!

You are training a VAE with this combined loss. After many epochs, you notice your reconstructions are very sharp and detailed, but they often have noticeable color shifts and slight structural deviations from the input images (e.g., a person's shirt color changes from red to pink).

Which component of the loss function, , would you suspect is improperly weighted, and would you increase or decrease its weight to fix the problem?

Show answer

I would suspect that the weight of the reconstruction loss () is too low relative to the perceptual and adversarial losses.

The perceptual and adversarial losses are excellent at ensuring high-frequency details and realism, but they don't strictly enforce pixel-for-pixel identity with the input. The reconstruction loss is the primary term responsible for this global structural and color fidelity.

To fix the problem, I would increase the weight of . This would penalize deviations in color and structure more heavily, forcing the autoencoder to be more faithful to the original input, potentially at a slight cost to the ultra-fine details enforced by the adversarial loss.


Conclusion

In this lesson, we've detailed the process of training the high-fidelity VAE that forms the foundation of a latent diffusion model. You've seen how it moves beyond a simple autoencoder by incorporating a more powerful architecture and a sophisticated, multi-part loss function.

Key Takeaways:

  • Architecture: The autoencoder uses proven building blocks (ResNet, Attention) in an encoder-decoder setup without inter-level skip connections to create a true information bottleneck.
  • Loss Function: High-fidelity reconstruction is achieved by balancing four loss terms:
    1. Reconstruction Loss: For global structural integrity.
    2. Perceptual Loss (LPIPS): To ensure outputs are perceptually similar to inputs, preserving details that humans notice.
    3. Adversarial Loss: To force the generation of realistic, sharp textures by trying to fool a discriminator.
    4. KL Divergence: As a mild regularizer to keep the latent space well-behaved for the subsequent diffusion training.
  • Training: The process requires a GAN-style loop with two separate optimizers, one for the autoencoder (generator) and one for the discriminator, updated in an alternating fashion.

Next Lesson Preview:

With our high-quality perceptual compression model trained, we are now ready for the second stage. In the next lesson, we will implement a latent diffusion model by adapting the training loop to operate on latent vectors. We'll take our pre-trained autoencoder, freeze its weights, and use it to convert our entire dataset into latent representations. Then, we will train a U-Net—very similar to the one you've built before—to perform diffusion in this compact and efficient new space.