Convolutional Neural Networks (CNNs) are how computers learned to see. They power face unlock, photo search, medical scan analysis and self-driving research. In this module you'll learn how a CNN scans an image for patterns, try it yourself, and build one in Keras.
- Level: Intermediate
- Time: about 45 minutes
- Needs: Modules 1 to 7
By the end of this module you will be able to
- Explain how a computer stores an image as numbers
- Explain why normal (dense) networks struggle with images
- Work out a convolution by hand, and describe what filters detect
- Explain stride, padding and pooling
- Describe the layers of a typical CNN and what each one learns
- Name famous CNNs and what made each one important
- Build, train and compare a CNN in Keras
8.1How a computer sees an image
To you, a photo is a face or a dog. To a computer, it's just a grid of numbers. Each tiny square, or pixel, gets a number for how bright it is.
| Image type | How it's stored | Example size |
|---|---|---|
| Greyscale | One grid of brightness values (1 channel) | 8 × 8 × 1 = 64 numbers |
| Colour | Three grids: red, green and blue (3 channels) | 224 × 224 × 3 = 150,528 numbers |
| Phone photo | Three grids at high resolution | 4,000 × 3,000 × 3 = 36 million numbers |
8.2Why normal networks struggle with images
You could feed an image into the dense networks from earlier modules by flattening it: laying every pixel out in one long row. It works for tiny images, but causes three big problems:
| Problem | What goes wrong |
|---|---|
| Far too many weights | A 224 × 224 colour image has 150,528 inputs. One dense layer of 1,000 neurons would need over 150 million weights, just for the first layer. That's slow to train and easy to overfit |
| It ignores which pixels are neighbours | Flattening throws away the 2D layout. The network no longer knows that one pixel sits right above another, even though nearby pixels together form edges and shapes |
| It depends on position | A dense network learns "a cat in the top-left corner" separately from "a cat in the bottom-right". Move the cat and it has to learn it all again |
How you actually look at a picture
When you look for your friend in a crowd photo, you don't take in every pixel at once. You scan across the picture looking for small, familiar features: a hairstyle, a face shape, a colour of jacket. And you'd recognise them wherever they're standing. A CNN works in exactly this way.
8.3Convolution: scanning with a filter
The key idea of a CNN is the filter (also called a kernel): a tiny grid of weights, usually 3 × 3. The filter slides across the image, one position at a time. At each position it:
- multiplies each of its 9 weights by the pixel underneath,
- adds up the 9 results,
- writes that one number into a new grid, called a feature map.
This sliding multiply-and-add is called convolution, which is where CNNs get their name.
Different filters detect different things. One filter finds vertical edges, another horizontal edges, another spots or corners. And here's the crucial part: in a CNN, nobody designs the filters. The weights in each filter are learned during training, exactly like any other weight. The network discovers for itself which patterns are useful.
Why this solves the three problems
| Problem | How convolution fixes it |
|---|---|
| Too many weights | A filter has only 9 weights (per channel), reused at every position. This is called weight sharing. 64 filters on a colour image need just 1,792 weights, not 150 million |
| Ignores neighbours | Each filter looks at a small patch of neighbouring pixels, keeping the 2D layout |
| Depends on position | The same filter scans everywhere, so an edge is found wherever it appears |
8.4Try convolution yourself
Choose a filter and watch it scan a simple picture of a house. Drag the slider (or press Play) to move the filter, and see the calculation at each position.
Try it: convolution explorer
Notice that the edge filters light up only along the edges of the house: the walls for "vertical", the roof base and floor for "horizontal". Positive values (amber) mark one direction of change, negative values (blue) the opposite. A real CNN layer runs dozens of filters at once, producing a stack of feature maps.
8.5Stride and padding
You may have noticed that the 12 × 12 image produced a smaller 10 × 10 feature map. That's because a 3 × 3 filter can't be centred on the edge pixels. Two settings control the size of the output:
| Setting | What it does | Effect on size | In Keras |
|---|---|---|---|
| Padding | Adds a border of zeros around the image, so the filter can reach the edge pixels | "valid" (no padding): output shrinks. "same": output stays the same size | padding="same" |
| Stride | How many pixels the filter moves each step | Stride 1: full size. Stride 2: half the width and height | strides=2 |
For the lab: (12 − 3 + 0) ÷ 1 + 1 = 10. With padding="same", the output would stay at 12 × 12.
8.6Pooling: shrinking the feature maps
After a convolution, CNNs usually shrink the feature maps with a pooling layer. The most common kind, max pooling, splits the map into small blocks (usually 2 × 2) and keeps only the biggest number from each.
| Why pool? | Explanation |
|---|---|
| Less work | A quarter of the numbers to process in the next layers |
| Keeps what matters | "Was there a strong edge somewhere in this area?" is kept; the exact pixel isn't |
| Tolerates small shifts | If a feature moves by a pixel, the biggest value in its block is often still the same |
| Wider view | After pooling, each filter in the next layer covers a larger area of the original image |
8.7Putting it together: a full CNN
A typical CNN has two parts. The first part finds patterns with repeated blocks of convolution, ReLU and pooling. The second part makes the decision with the dense layers you already know.
What each layer learns
Because each layer builds on the one before, CNNs learn a hierarchy of features, from simple to complex:
Colour images and many filters
For a colour image, each filter is actually 3 × 3 × 3: one 3 × 3 slice for each of the red, green and blue channels, all added together. And each layer uses many filters. A layer with 32 filters produces 32 feature maps, which become 32 channels for the next layer to scan.
8.8Famous CNNs
| Network | Year | Why it matters |
|---|---|---|
| LeNet-5 | 1998 | Yann LeCun's early CNN, used by banks to read handwritten digits on cheques. It had the same conv → pool → dense pattern still used today |
| AlexNet | 2012 | Won the ImageNet image competition by a huge margin, using ReLU, dropout and GPUs. Widely seen as the start of the deep learning boom |
| VGG | 2014 | From the University of Oxford. Showed that stacking many small 3 × 3 filters works brilliantly |
| ResNet | 2015 | From Microsoft Research. Added "skip connections" that let the signal jump over layers, making networks with 100+ layers trainable |
| MobileNet, EfficientNet | 2017 onwards | Designed to be small and fast enough to run on phones |
You rarely train from scratch
Training a big CNN needs millions of images and a lot of computing power. In practice, people usually take a CNN that has already been trained on a huge dataset (like ImageNet) and adapt it to their own task. This is called transfer learning, and it's the subject of Module 11.
8.9Building a CNN in Keras
We'll build a small CNN for the handwritten digits, and compare it with a normal dense network trained in exactly the same way. Then we'll test both on the same digits shifted one pixel to the right, to see which one really understands shapes.
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" # hide TensorFlow start-up messages
import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
import keras
from keras import layers
keras.utils.set_random_seed(42)
# 1. Images: 1,797 handwritten digits, each 8x8 pixels with 1 channel (greyscale)
X, y = load_digits(return_X_y=True)
X = (X / 16.0).reshape(-1, 8, 8, 1) # scale to 0-1, keep the 2D shape
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42, stratify=y)
# 2. A small CNN
cnn = keras.Sequential([
keras.Input(shape=(8, 8, 1)),
layers.Conv2D(16, kernel_size=3, padding="same", activation="relu"),
layers.MaxPooling2D(pool_size=2), # 8x8 -> 4x4
layers.Conv2D(32, kernel_size=3, padding="same", activation="relu"),
layers.MaxPooling2D(pool_size=2), # 4x4 -> 2x2
layers.Flatten(),
layers.Dense(64, activation="relu"),
layers.Dense(10, activation="softmax"), # one output per digit
])
cnn.summary(line_length=70) # look inside the CNN
# 3. A normal (dense) network for comparison
dense = keras.Sequential([
keras.Input(shape=(8, 8, 1)),
layers.Flatten(), # 8x8 grid -> 64 numbers in a row
layers.Dense(128, activation="relu"),
layers.Dense(64, activation="relu"),
layers.Dense(10, activation="softmax"),
])
# 4. Train both the same way
for name, model in [("CNN", cnn), ("Dense network", dense)]:
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
model.fit(X_train, y_train, epochs=30, batch_size=32, verbose=0,
validation_split=0.1)
_, acc = model.evaluate(X_test, y_test, verbose=0)
# Test again with every image shifted one pixel to the right
shifted = np.roll(X_test, shift=1, axis=2)
shifted[:, :, 0, :] = 0
_, acc_shift = model.evaluate(shifted, y_test, verbose=0)
print(f"{name:14} weights={model.count_params():6,} "
f"accuracy={acc:.3f} shifted images={acc_shift:.3f}")
Model: "sequential" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩ │ conv2d (Conv2D) │ (None, 8, 8, 16) │ 160 │ ├──────────────────────────────┼───────────────────────┼─────────────┤ │ max_pooling2d (MaxPooling2D) │ (None, 4, 4, 16) │ 0 │ ├──────────────────────────────┼───────────────────────┼─────────────┤ │ conv2d_1 (Conv2D) │ (None, 4, 4, 32) │ 4,640 │ ├──────────────────────────────┼───────────────────────┼─────────────┤ │ max_pooling2d_1 │ (None, 2, 2, 32) │ 0 │ │ (MaxPooling2D) │ │ │ ├──────────────────────────────┼───────────────────────┼─────────────┤ │ flatten (Flatten) │ (None, 128) │ 0 │ ├──────────────────────────────┼───────────────────────┼─────────────┤ │ dense (Dense) │ (None, 64) │ 8,256 │ ├──────────────────────────────┼───────────────────────┼─────────────┤ │ dense_1 (Dense) │ (None, 10) │ 650 │ └──────────────────────────────┴───────────────────────┴─────────────┘ Total params: 13,706 (53.54 KB) Trainable params: 13,706 (53.54 KB) Non-trainable params: 0 (0.00 B) CNN weights=13,706 accuracy=0.976 shifted images=0.673 Dense network weights=17,226 accuracy=0.973 shifted images=0.469
What the output tells us
- The model summary shows the shapes shrinking and deepening, just like Figure 4: 8 × 8 × 16 feature maps, pooled to 4 × 4, then 4 × 4 × 32, pooled to 2 × 2, then flattened to 128 numbers.
- The first convolution layer has only 160 weights: 16 filters × 9 weights, plus 16 biases. That's weight sharing at work.
- On normal test images, both networks score about the same (97.6% vs 97.3%). With tiny 8 × 8 images, a dense network can still cope.
- On shifted images, the difference is clear. The dense network drops to 46.9%, because it learned "pixel number 27 should be bright". The CNN keeps 67.3%, because its filters look for shapes wherever they are. On real photos, where objects can be anywhere, this advantage is huge.
- The CNN does it with fewer weights (13,706 vs 17,226).
Make it better yourself
Neither network was trained on shifted images, so both find them harder. Try adding data augmentation (Module 7): randomly shifting, rotating and zooming the training images so the network learns to expect variety. Keras makes this easy with layers like layers.RandomTranslation and layers.RandomRotation.
Running this code
You'll need TensorFlow installed (pip install tensorflow), or you can run it for free in Google Colab, which has it ready to go. This small example trains in under a minute on a normal laptop.
8.10CNNs in the real world
| Task | What the CNN does | Example |
|---|---|---|
| Image classification | Says what's in an image | Photo apps grouping pictures of dogs, beaches or food |
| Object detection | Finds and draws boxes around several objects | Cars spotting pedestrians and road signs |
| Segmentation | Labels every single pixel | Outlining a tumour on a medical scan |
| Face recognition | Checks whether two faces are the same person | Face unlock on phones |
| Quality control | Spots defects on a production line | Finding cracks or scratches on manufactured parts |
| Beyond images | Scans any grid-like data | Audio spectrograms, satellite maps, even game boards |
| Strengths | Weaknesses |
|---|---|
| Brilliant with images and other grid-shaped data | Need lots of labelled images to train from scratch |
| Far fewer weights than dense networks, thanks to weight sharing | Computationally heavy: big models need GPUs |
| Find patterns wherever they appear in the image | Hard to explain exactly why a decision was made |
| Learn their own features, with no hand-designed filters | Can be fooled by tiny, carefully designed changes to an image |
Since around 2020, a newer design called the Vision Transformer (based on Module 10) has matched or beaten CNNs on some large image tasks. But CNNs remain widely used, especially where speed and smaller datasets matter.
SummaryKey takeaways
- Computers see images as grids of numbers: 1 channel for greyscale, 3 for colour.
- Dense networks struggle with images: too many weights, no sense of neighbours, and position-dependent learning.
- Convolution slides a small filter over the image, multiplying and adding, to make a feature map.
- Filters are learned, and shared across every position, so CNNs need far fewer weights.
- Padding controls whether the output shrinks; stride controls how far the filter moves.
- Max pooling shrinks feature maps by keeping the strongest value in each block.
- A CNN stacks conv → ReLU → pool blocks, then flattens into dense layers with softmax.
- Layers learn a hierarchy: edges, shapes, parts, then whole objects.
Check your understanding
Your neural networks roadmap
- 01Introduction to Neural NetworksWhat neural networks are and how they work
- 02The Perceptron and the Artificial NeuronBuild a single neuron from scratch
- 03Activation FunctionsSigmoid, tanh, ReLU and softmax
- 04Loss Functions and Gradient DescentHow networks measure and reduce error
- 05BackpropagationHow every weight learns its share of the blame
- 06Building Networks with KerasYour first deep learning library
- 07Training Better NetworksOverfitting, dropout, batch normalisation, early stopping
- 08Convolutional Neural NetworksYou are here
- 09Recurrent Neural Networks and LSTMsWorking with sequences
- 10Transformers and AttentionThe architecture behind ChatGPT and Claude
- 11Transfer Learning and Pretrained ModelsStanding on the shoulders of giants
- 12Capstone ProjectBuild and present a deep learning project
Next module
Recurrent Neural Networks and LSTMs