Force data through a bottleneck and the network must learn what matters. Draw an 8x8 image, train a real autoencoder in your browser, and watch the reconstruction sharpen as you widen the bottleneck from 1 latent number to 16.
Compression as a learning signal
An autoencoder is two networks glued together. The encoder squeezes the input into a small latent code, and the decoder tries to rebuild the original from that code alone. Nothing else gets through: if the bottleneck holds 4 numbers, the entire 64-pixel image must survive as 4 numbers. The network is never told what a digit is. It discovers strokes, loops, and symmetries on its own, because keeping them is the only way to score a low reconstruction error.
1. Pick an input
Draw on the canvas or load a preset digit. Presets and their 1-pixel shifts are also the training set (50 images).
Brush
Preset digits (keyboard path)
Draw your own shape or load a preset. The network reconstructs whatever is on this canvas, live.
2. Train and squeeze
Train at the current bottleneck width, then drag the slider: each new width trains a fresh network so you can compare capacities honestly.
Train the network first, then this slider retrains at each new width you pick (results are cached per width for this session).
Real gradient descent runs in your browser: full-batch, learning rate 2, momentum 0.9, deterministic initialization per width, so retraining the same width reproduces the exact same weights.
3. Input vs reconstruction
The reconstruction and every number below are recomputed live from the canvas and the active weights.
Untrained network: the reconstruction below comes from the deterministic starting weights, before any learning. Run training to watch it sharpen.
Input (64 pixels)
Reconstruction (untrained)
Per-pixel error (abs)
Darker means accurate, brighter red means wrong. Largest error: 0.60 at row 8, col 7.
MSE
0.2565
Mean squared error between input and reconstruction, over all 64 pixels, recomputed on every edit.
The bottleneck: this whole image, as 4 numbers
Each bar is one tanh latent value in [-1, 1] (baseline is zero). The decoder rebuilds all 64 pixels from these 4 numbers alone. This latent code is exactly what variational autoencoders turn into a probability distribution.
Try drawing something that is not a digit
Scribble a face or a diagonal line and watch the reconstruction drift toward digit-like strokes. The bottleneck only has room for the patterns the training data rewarded, so the network projects everything onto its learned manifold. That failure is informative: an autoencoder's reconstruction error is a classic anomaly detector, because things it has never seen reconstruct badly.
Simplifications in this demo
Undercomplete by design
The bottleneck is narrower than the input on purpose. With fewer latent dimensions than pixels, copying is impossible, so the network must compress. Capacity buys fidelity: you watched MSE fall as the slider widened.
The latent space
Those few numbers are coordinates in a learned space where similar inputs land close together. Downstream models can classify, cluster, or search in this space far more cheaply than in pixel space.
The on-ramp to generative AI
A plain autoencoder only compresses points it was given. Make the latent code a probability distribution instead of a point and you can sample new latent codes, and decode images that never existed. That is the variational autoencoder, the next guide.