Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Convolutions and pooling explained

After this lesson: I can explain how a convolution finds a pattern in a grid of numbers.

60 min lesson2 commandsJupyterLab data science lab: pandas, Matplotlib and scikit-learn in the browser

How a network finds edges

A convolution slides a small grid of numbers, called a filter, across an image and records how strongly each patch matches a pattern. It is how a convolutional neural network (CNN) finds edges and shapes in a photo without anyone describing them.

The same idea works on a row of numbers, so we start with one.

By the end of this lesson

Note

I can explain how a convolution finds a pattern in a grid of numbers.

Key words

WordWhat it meansExample
Pixelone number in an image: how bright a dot is
Filtera small grid of weights that looks for a pattern[-1, 1]
Convolutionsliding a filter over the input and adding the products
Feature mapthe grid of results a filter gives
Max poolingkeeping the biggest value in each small block

The cells students fill in are left blank in this preview.

A filter slides and adds products

Take a row of numbers and a short filter. Place the filter at the start. Multiply each number under it by the matching filter weight, and add. That is one output.

Slide the filter one place along and repeat. Our row is dark then bright: 0, 0, 0, 9, 9, 9. Our filter is -1 and 1, so each output says how much brighter the next number is.

Worked example: filter -1, 1 on a row

PlaceNumbers under the filterWorkingOutput
10, 0-1x0 + 1x00
20, 0-1x0 + 1x00
30, 9-1x0 + 1x99
49, 9-1x9 + 1x90
59, 9-1x9 + 1x90

The cells students fill in are left blank in this preview.

Slide the filter with NumPy

Command
docker exec jupyter python3 -c "import numpy as np; print(np.correlate([0, 0, 0, 9, 9, 9], [-1, 1], 'valid').tolist())"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

In an image the filter slides two ways

A grey photo is a grid of pixels. Each pixel is one number, here from 0 for black to 9 for bright. A 2 by 2 filter covers four pixels at a time. It moves along a row, then down to the next.

A 4 by 4 image and a 2 by 2 filter give a 3 by 3 result. The size is the image size minus the filter size plus 1.

Worked example: an image with an edge

RowColumn 1Column 2Column 3Column 4
10099
20099
30099
40099

The cells students fill in are left blank in this preview.

Worked example: the vertical edge filter, top row

PlacePatchWorkingOutput
Column 10 0 over 0 0-1x0 + 1x0 + -1x0 + 1x00
Column 20 9 over 0 9-1x0 + 1x9 + -1x0 + 1x918
Column 39 9 over 9 9-1x9 + 1x9 + -1x9 + 1x90

The cells students fill in are left blank in this preview.

Slide a filter over a grid

Code: python
image = [[0, 0, 9, 9], [0, 0, 9, 9], [0, 0, 9, 9], [0, 0, 9, 9]]
filt = [[-1, 1], [-1, 1]]

for r in range(3):
    row = []
    for c in range(3):
        total = 0
        for a in range(2):
            for b in range(2):
                total = total + image[r + a][c + b] * filt[a][b]
        row.append(total)
    print(row)
# Change the filter to [[-1, -1], [1, 1]] and press Run.
# This one looks for a horizontal edge. What do you see?

Max pooling shrinks the result

Max pooling keeps the biggest value in each small block. A 2 by 2 pool turns a 4 by 4 feature map into a 2 by 2 map.

It keeps the strongest signal and forgets exactly where it was. That makes the next layer smaller, and less fussy about where a pattern sits.

Worked example: pooling a 4 by 4 map

BlockValuesBiggest
Top left1 3 over 4 66
Top right2 0 over 1 12
Bottom left0 2 over 1 12
Bottom right5 7 over 3 27

The cells students fill in are left blank in this preview.

Pool the 4 by 4 map with NumPy

Command
docker exec jupyter python3 -c "import numpy as np; print(np.array([[1, 3, 2, 0], [4, 6, 1, 1], [0, 2, 5, 7], [1, 1, 3, 2]]).reshape(2, 2, 2, 2).max(axis=(1, 3)).tolist())"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A convolutional network stacks these steps

A CNN repeats convolution, ReLU and pooling, then ends with ordinary dense layers that give the answer. Early filters tend to find edges. Later ones combine edges into shapes.

A filter's weights are learned by gradient descent, like any other weight. They are shared across the whole image, which keeps the count small.

Worked example: shared weights save parameters

LayerWeightsBiasesParameters
One 3 by 3 filter9110
32 such filters28832320
Dense layer, 784 inputs, 128 neurons100,352128100,480

The cells students fill in are left blank in this preview.

A common mistake

Warning

Many people think someone chooses a filter's numbers by hand to find cats or faces. We chose ours to show the idea. In a real network the filter weights start random, and gradient descent sets them, the same as every other weight.

Going further

In a notebook cell, call np.correlate([1, 2, 3, 4, 5], [1, 1, 1], 'valid') after import numpy as np. Work out the three answers by hand first.

What does a filter of three ones do to a row? Then try a filter of 1, 0 and -1, and say what it measures.

About this lab and its source: JupyterLab data science lab: pandas, Matplotlib and scikit-learn in the browser

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.