Chapter 5

Seeing: convolutional networks

A network that reads handwritten digits uses a few small stencils over and over. Train it, and the stencils turn into stroke detectors that nobody designed. Then look closer: what it thinks a 3 looks like, and how a faint haze of pixels fools it.

The problem: getting a computer to see

You recognize a handwritten 7 in a fraction of a second, without thinking about it. A computer gets only a grid of numbers, one per pixel. Turning those numbers into "this is a 7" is a problem from computer vision, the field that teaches computers to make sense of images. Deciding which of a fixed set of things a picture shows is called image classification, and reading handwritten digits is its classic first example.

Why recognize anything?

Because otherwise a person has to look. Reading handwritten digits used to be real work: post offices sorted letters by the zip codes written on them, and banks read the amounts written on checks. In 1989, Yann LeCun and colleagues at Bell Labs trained a convolutional network on handwritten zip codes from US mail, and by the late 1990s a descendant of it, LeNet-5, was at the heart of a system reading several million bank checks a day. Today the same kind of recognition finds the photos of dogs on your phone, reads street signs for cars, helps doctors look at medical scans, and describes pictures aloud to people who cannot see them.

Why is it hard?

Nobody writes a digit the same way twice. Try writing rules for a 7: a flat stroke on top and a slanted one down? Some 7s have a bar across the middle, some tops curve, some lean, some are thin or thick. And the rules would have to be written in pixel numbers, not words. These are real digits from the MNIST collection, written by employees of the US Census Bureau and by high-school students:

24 of the 600 training digits
Their average

Loading 7,000 digits…

Misread by the averages, read correctly by the convolutional network

A simple idea that avoids rules is to compare: keep one picture per digit, the average of its 600 examples, and call each new digit by the average it is closest to. It reads 77% of our 1,000 test digits correctly. Each average is a blur of every way of writing that digit, so a digit written unlike most can end up closer to another digit's blur, and is misread.

Why neural networks do so well

Share of the 1,000 test digits read correctly, measured in your browser.

The same recipe, scaled up, took computer vision from digits to photographs. In 2012 a large convolutional network called AlexNet won the ImageNet challenge, sorting photos into 1,000 categories after training on about 1.2 million of them. Its five best guesses missed the right category for 16% of the test photos, against 26% for the runner-up, which used features designed by hand. Since then, neural networks have become the standard way to recognize what is in an image.

What this is

This film follows one handwritten 7 through a small convolutional network, then shows three things the network learned that nobody told it, and one way it can be fooled.

The question

Chapter 4's networks read two numbers per dot; a digit is 784. The plain network in the ladder above is the kind you already know, fed all 784 pixels: one hidden layer of 8 neurons, 6,370 weights and biases in all, and it reads 88% of the test digits correctly. The convolutional network has fewer, 5,994, and reads 97%. Both were trained on the same 6,000 digits, centered in the picture.

Now move the digits a couple of pixels. Shifted 2 pixels up, down, left or right, the plain network drops to 57% on average and the convolutional one to 83%. Try it:

Plain network · 6,370 parameters

Convolutional network · 5,994 parameters

Loading 7,000 digits…

Even with four times as many parameters (32 hidden neurons, 25,450 in all), the plain network reaches only 91% on centered digits. So what does the convolutional network know? Two tools explain how it works, and three secrets show what it actually learned.

Tool 1: one small stencil, used everywhere

A plain neuron has one weight for every pixel: 784 of them, each tied to one spot in the picture. A convolution uses a small stencil instead, here 5 × 5 = 25 weights. It slides the stencil over every position of the picture. At each position it multiplies the 25 pixels under the stencil by the 25 weights and adds them up, plus a bias. Those sums form a new picture, called a feature map: large where the pattern in the stencil appears. (Deep-learning libraries call this a convolution; mathematicians would call it a cross-correlation, because the stencil is not flipped.)

The picture · 28 × 28
The stencil · 25 weights
The feature map · 24 × 24

The same 25 weights are used at all 576 positions, so a stencil that finds a horizontal stroke finds it anywhere in the picture. That is why a convolution needs so few weights for all the numbers it computes, and part of why the network copes better with a moved digit: the pattern is still found, just in a different place on the map.

Tool 2: layers of stencils

The network stacks two such layers. Layer 1 has 8 stencils, giving 8 feature maps; the activation ReLU (as in chapter 1) keeps the positive values and sets the rest to 0. Then pooling shrinks each map by keeping only the largest value in each 2 × 2 block, so a stroke that moves by a pixel often lands in the same block. Layer 2 has 16 stencils, each 5 × 5 but 8 layers deep, one layer per map (200 weights each), so each one looks at all 8 maps at once and can respond to combinations of strokes: a corner, a curve, a crossing. After another pooling, an ordinary dense layer weighs the 256 remaining numbers into 10 scores, one per digit.

Input

28 × 28

→ Layer 1 · 8 stencils

8 maps of 24 × 24, after ReLU
208 parameters

→ Pooling

8 maps of 12 × 12

→ Layer 2 · 16 stencils

16 maps of 8 × 8, after ReLU
3,216 parameters

→ Pooling

16 × 4 × 4 = 256 numbers

→ 10 probabilities

dense layer, then softmax
2,570 parameters

Secret 1: nobody taught it edges

Nobody chose the stencils. Training started them as tiny random numbers and adjusted them by gradient descent, as in the earlier chapters (with one difference, explained below: each step uses a batch of 20 digits), to make the right digit's probability higher. Here are layer 1's 8 stencils at several moments of training. Each row is one moment. The first five rows are a fresh copy of the network training in your browser right now; the last row is the finished network used on the rest of this page, trained with the same settings for longer.

Loading 7,000 digits…

Within a few hundred steps the noise turns into smooth patterns: edges between blue and orange at different angles, and broad strokes. One choice makes this visible: layer 1's starting weights are 50 times smaller than usual, so the pattern that training adds is not hidden under the starting noise. With a normal start the network learns just as well, but its stencils keep much of their starting noise. These are the same kinds of detectors people used to design by hand for reading images, and large networks trained on photographs find similar ones in their first layer. Each stencil found a pattern that helps tell digits apart, because that is what lowered the loss.

Secret 2: what it thinks a 3 looks like

Training changes the weights to fit the pictures. You can also run it the other way: keep the weights fixed and change the pixels, step by step, in the direction that makes the network more sure it sees a 3. The gradient with respect to each pixel comes from the same backward pass, just carried one step further, down to the picture. Start from blank paper and see what the network draws. (A gentle pull back toward blank paper at every step means only the pixels that matter get ink.)

The average of 600 real ones

Pixels changed to raise its confidence

The network is nearly as sure of these faint scribbles as of a clear digit. It never learned what a 3 is, only which strokes in which places push the score for 3 above the others. A few strokes in the right places are enough.

Secret 3: fooled by a faint haze

The same pixel gradients can be used against the network. Take a digit it reads correctly and change every pixel by at most a small amount ε (epsilon), each one in the direction that lowers the right answer's probability. Ten small steps like that, never letting any pixel move more than ε from where it started, is enough.

The original

The change

blue: more ink, orange: less; strongest color = ±ε

What the network sees

We tried this on 300 test digits the network reads correctly. With ε = 0.1 it was fooled on 43% of them, with ε = 0.15 on 84%, and with ε = 0.2 on 98%, usually with high confidence in the wrong answer. A random change of ±0.2 per pixel (staying between paper and ink) fooled it on only 1%. The change that fools it is not noise: it is aimed. Every pixel is pushed whichever way hurts the network most, including pixels far from the strokes. Changes like this are called adversarial examples. They have been found in networks of every size trained on pictures, from tiny ones like this to large ones trained on photographs.

The algorithm, layer by layer

The convolutional network is trained like every network in this series: forward pass, loss, backward pass, a small step for every weight. What is new is the shape of the layers, the 10 answers instead of 2, and that each step uses a small batch of digits instead of all of them. Here is the whole program in six parts. The code is the JavaScript this page actually runs, or the same program in Python.

The playground

Draw a digit and watch both networks read it. Move it with the arrows, see the feature maps your drawing produces, and see where the network looks. Or train your own convolutional network from scratch and watch its stencils form.

Draw a digitscaled and centered like the training digits; move it with the arrows

what it sees

where it looks

Convolutional network

Plain network

784 → 8 → 10, trained on the same digits

Layer 1's feature maps for your drawing

Layer 2's feature maps

Train your own

Its 8 layer-1 stencils

How to read the figures

Digits
Each pixel is a number from 0 (paper) to 1 (ink), drawn as a square shaded from the paper color to the ink color.
Stencils and maps
Blue is positive, orange negative, paper-colored zero. Each stencil square is stretched to its own strongest weight, so faint stencils still show their pattern; in Secret 1, the "largest" number beside each row is the largest weight among that row's 8 stencils, so you can see how big the weights really are. Feature maps in one layer share a scale.
Probability bars
The network's 10 probabilities, one per digit, adding up to 100%. The longest bar is its answer.
The change
In Secret 3, blue pixels were given more ink and orange ones less; the strongest color is a change of ε.
Where it looks
In the playground: blue where more ink would make the network more sure of its answer, orange where less ink would. Strong colors mark the pixels it is most sensitive to.

Things to try

What runs where

Everything runs in your browser, with no machine-learning library. The digits are 7,000 images from the MNIST database by Yann LeCun and Corinna Cortes: 600 of each digit for training and 100 of each for testing. They are shared under the CC BY-SA 3.0 license, and so are this chapter's copy of them, the images made from them, and the weights trained on them. The trained convolutional network and the plain network were trained in advance with exactly the code above: 6 passes over the 6,000 training digits in batches of 20, with learning rate 0.1 and then 0.03 for the last two passes, about 30 seconds on a laptop. Their weights load from a file. Everything else runs live: the training in the film, in Secret 1 and in the playground, the dreams and the attacks. When this page loaded it checked the backward pass the slow way, nudging weights and pixels one at a time and measuring how the loss changed: the check is running… Browsers round a few math functions very slightly differently, so live training can come out a little differently from one browser to another.

Where this is going

  1. 1A network you can touch
  2. 2Loss and gradients: walking downhill
  3. 3Backprop, one operation at a time
  4. 4Going deeper: why layers help
  5. 5Seeing: convolutional networksThis page
  6. 5′Listening: spectrograms and soundBranch
  7. 6Words as vectors: tokens and embeddings
  8. 7Attention: looking back over the whole story
  9. 8A tiny GPT, trained in your browser

Working prototype, October 2026. Every figure on this page is a live computation.
Source on GitHub · code under MIT, text and figures under CC BY 4.0, MNIST digits and what is made from them under CC BY-SA 3.0.