Traffic sign classifier

A convolutional neural network that recognizes 43 kinds of German road signs from tiny 32×32 photos. Pick a sign, then try to break it: rotate it, darken it, blur it, or slap a sticker on it, and watch how the model's confidence changes.

2. Try to break it

Drag on the sign to move the sticker
Loading the model…

What the model sees

Grayscale
Contrast evened out

The data

The German Traffic Sign Recognition Benchmark contains photos of real signs taken from a moving car, cropped and shrunk to 32×32 pixels: 34,799 for training, 4,410 for validation and 12,630 for testing. The photos vary a lot in lighting, angle and sharpness, and the classes are very uneven. Common signs like the 50 km/h limit have about ten times as many training examples as rare ones like the 20 km/h limit.

Preprocessing and augmentation

Each image goes through the same three steps:

  1. Convert to grayscale. Shapes and symbols matter more than color here, and using one channel instead of three makes the model smaller.
  2. Spread the brightness values across the full range, so dark and washed-out photos end up with similar contrast.
  3. Scale pixel values to between 0 and 1 according to brightness.

During training, each batch was also randomly shifted (up to 10%), zoomed (up to 20%), sheared and rotated (up to 10°), so the model saw slightly different versions of every sign. That's why the model is resistant to minor changes but still fails on more drastic ones.

The model

A modified version of LeNet, a classic convolutional network design, built with Keras. The convolutional layers learn small visual patterns (edges, curves, shapes and symbols) and the dense layers combine them into a decision. It has about 620,000 weights in total.

LayerDetailsOutput size
Convolution60 filters, 5×5, ReLU28×28×60
Convolution60 filters, 5×5, ReLU24×24×60
Max pooling2×212×12×60
Convolution30 filters, 3×3, ReLU10×10×30
Convolution30 filters, 3×3, ReLU8×8×30
Max pooling2×24×4×30
Dense960 units, ReLU, 50% dropout960
DenseSoftmax43 classes

Trained for 10 epochs with the Adam optimizer (learning rate 0.001) in batches of 50. It reaches … accuracy on the 12,630-image test set, which it never saw during training. In the browser, the network runs in a few dozen lines of plain JavaScript using the exported weights, with no machine learning library.

Where it gets confused

The grid below compares every test image's actual sign (rows) with the model's prediction (columns). Correct answers fall on the grey diagonal, and every red square is a mistake: the darker the red, the more often it happened. Hover over a square to see which signs it compares.

Most common mistakes

Click one to load that exact image into the demo.