LLM + RoboticsUnit 5 · Generative models & scaling · Day 23

Variational Lossy Autoencoder

A VAE's latent code only holds what its decoder can't work out alone. Choose what the decoder can see, and you choose what the latent must remember.

AuthorsXi Chen, Diederik P. Kingma, Tim Salimans, Yan Duan, Prafulla Dhariwal, John Schulman, Ilya Sutskever, Pieter Abbeel (UC Berkeley, OpenAI)
Year / venue2017 · ICLR
Core ideaRestrict the decoder to control what goes into the latent
Study time3–5 h

Original: arXiv:1611.02731 · Code, notebook and exercises: 30u30 Day 23

Start here (no maths needed)

When a program squashes a picture into a short code, it only stores what it can't easily guess back, so you can choose what goes into the code.

Think of it like this

Imagine describing a drawing to a friend who will redraw it. You only have a few words. If your friend is great at drawing small details, you don't waste words on them. You say the big things: "a big number 7, slanting right". Your friend fills in the rest. Their drawing will have the same big shape, but the little details may differ. That's why it's called "lossy": some details get lost, on purpose.

How it works

  1. One part of the program, the encoder, squashes a picture into a short code.
  2. Another part, the decoder, rebuilds the picture from that code.
  3. Space in the code is costly, so the program only stores what the decoder can't figure out alone.
  4. The researchers let the decoder see only a few nearby pixels. It can draw small details, but not the big shape.
  5. So the big shape has to go into the code. The tiny details are left for the decoder to fill in.

Why robots care

A robot's camera sees a lot: carpet patterns, shadows, the cup it needs to grab. If the robot squashes each picture into a short code, it wants that code to hold where the cup is, not the carpet pattern. This idea helps choose what the robot remembers.

Try it

Words to know

Autoencoder
A program that squashes data into a short code and then rebuilds it.
Code
The short summary the picture is squashed into. Also called the latent.
Decoder
The part that rebuilds the picture from the code.
Lossy
Keeps the important parts and lets some details go.

Going deeper: everything below is the full version, with some maths. On a first read, skim the headings and the "Why it matters for robotics" box, and come back for the rest later.

1. Summary

TL;DR

People kept trying to pair VAEs with powerful autoregressive decoders (RNNs, PixelCNNs), and kept finding the latent code ignored. The usual explanation was "optimisation is hard". This paper argues it's not just optimisation: even at the optimum, a VAE prefers to model anything the decoder can handle on its own, and only puts the rest into the latent. The authors turn that into a tool. Give the decoder only a small local window of pixels, and it can model texture but not global shape, so shape must go into the latent. The result is a deliberately lossy code, plus state-of-the-art likelihoods on several image benchmarks.

2. The core idea

A VAE maximises the evidence lower bound (ELBO):

L(x) = E_{q(z|x)}[ log p(x|z) ]  −  KL( q(z|x) ‖ p(z) )

The first term rewards reconstruction. The second charges for every bit the encoder q(z|x) puts into z beyond the prior p(z). Read as a code length (bits-back coding, the idea from Day 4), the expected cost is:

E[−L(x)] = E[ −log p(x) ] + E[ KL( q(z|x) ‖ p(z|x) ) ]
        ≥ H(data)       + E[ KL( q(z|x) ‖ p(z|x) ) ]

The VLAE uses this on purpose. Its decoder only sees a local window:

p_local(x|z) = Π_i p( x_i | z, x_{window(i)} )

Whatever is predictable from nearby pixels (texture, stroke edges) gets modelled locally. Long-range structure (the digit's identity and shape) can't be, so it must come through z.

3. Deep dive

"Lossy" is the feature

Decode the same z twice and you get two images with the same global shape but different local detail: stroke width and exact pixel masks change. That's the point. The latent is a summary of what matters globally, and the decoder fills in plausible detail. On CIFAR-10, widening the decoder window (4×2, then 5×3, then 7×4) let the decoder take over more structure, so the latent kept only rough shapes. Colour often went missing from the latent, since it's easy to predict locally. Conditioning the decoder on a grayscale version of the image forced colour back into z. Change what the decoder sees, change what the code stores.

The paper is honest that this isn't magic. On OMNIGLOT, where small patches carry meaning, the lossy code sometimes lost the character's identity. You still have to decide which information your task needs.

Autoregressive flow prior

A plain Gaussian prior is a poor fit for a rich latent. The authors make the prior an autoregressive flow: start from simple noise ε and transform it, z = f(ε). Rewriting the bound shows this is the same, on the encoder side, as using an inverse autoregressive flow posterior, with the same training cost. But on the generation side the model gets an extra deep transformation for free. On MNIST, swapping an IAF posterior for an equivalent AF prior improved test likelihood (79.88 to 79.30 nats without the autoregressive decoder).

Where it sits in the course

4. Why it matters for robotics

5. How to study it

  1. Read sections 2 and 3 of the paper slowly (about 1.5 h). Re-derive the step from the bits-back code length to the KL penalty yourself.
  2. Look at the paper's figures of original vs "decompressed" images on MNIST and CIFAR-10. Note what changes and what stays.
  3. In the 30u30 Day 23 folder, run setup.py, read implementation.py (masked convolutions, PixelCNN decoder, flow prior), then run train_minimal.py with the flow prior on.
  4. Do the exercises in order: masked convolution, a PixelCNN prior, reproducing posterior collapse by growing the receptive field, the flow prior, then the full VLAE.
  5. Stretch: log the KL term (bits in the latent) as you widen the decoder's window. It should fall as the decoder takes over.

6. Self-check

Why does a VAE with a powerful decoder ignore its latent, even if optimisation were perfect?

Using the latent costs an extra KL penalty whenever the approximate posterior isn't exact. If the decoder can model the data alone, setting the posterior equal to the prior is cheaper.

How does the VLAE force global structure into z?

Its decoder only sees a small local window of previous pixels. Local detail can be modelled there, but long-range shape can't, so it has to come from z.

What happens to the latent as the decoder's receptive field grows?

The decoder models more structure itself, so the latent keeps less, ending with only rough shape.

Why is an autoregressive-flow prior "free"?

On the encoder path it's mathematically equivalent to an IAF posterior with the same training cost, but it adds a deeper transformation on the generation path.

How did the authors get colour back into the latent on CIFAR-10?

They made the decoder condition only on a grayscale version of the image, so colour could no longer be predicted locally and had to be stored in z.

7. Further reading