Python · Course navigation

Convolutional networks: output shapes and parameter counts

Compute how convolution and pooling change the size of an image, and why sharing weights saves parameters.

On this page
Before you start

Integer division and multiplication.

  • Compute how convolution and pooling change the size of an image, and why sharing weights saves parameters.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

A convolutional neural network (CNN) is built for data with a grid structure, such as images. A convolutional layer slides small filters over the input. Each filter has a fixed number of weights and is applied at every position, so the same weights are reused: this is weight sharing. A layer with c_out filters of size k × k on an input with c_in channels has (k·k·c_in + 1)·c_out parameters, including one bias per filter, however large the image is.

The size of the output depends on the input size n, the filter size k, the stride s (how far the filter moves), and the padding p added around the border: out = floor((n + 2p − k) / s) + 1. Pooling layers shrink the maps further, for example 2 × 2 max pooling with stride 2 halves the width and height. Each output value depends only on a small neighbourhood of its input, so the network is built from local features that later layers combine into larger patterns. Deep learning libraries actually compute cross-correlation, which does not flip the filter, and call it convolution.

The program follows a small LeNet-style network on a 28 × 28 grayscale image. The first layer has 6 filters of size 5 × 5 and needs only 156 parameters. A fully connected layer producing the same 24 × 24 × 6 output from all 784 inputs would need 2,712,960. The second convolution, with 16 filters, adds 2,416 parameters. After pooling, 4 × 4 × 16 = 256 values feed into a dense layer with 120 units.

Code example

Python
def conv_out(n, k, stride=1, pad=0):
    return (n + 2 * pad - k) // stride + 1


size, channels = 28, 1
size = conv_out(size, 5)
conv1_params = (5 * 5 * channels + 1) * 6
channels = 6
print(size, channels, conv1_params)
size = conv_out(size, 2, stride=2)
print(size, channels)
size = conv_out(size, 5)
conv2_params = (5 * 5 * channels + 1) * 16
channels = 16
print(size, channels, conv2_params)
size = conv_out(size, 2, stride=2)
print(size, channels, size * size * channels)
print((28 * 28) * (24 * 24 * 6) + 24 * 24 * 6)
print(256 * 120 + 120)
Output
24 6 156
12 6
8 16 2416
4 16 256
2712960
30840

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1def conv_out(n, k, stride=1, pad=0):
2 return (n + 2 * pad - k) // stride + 1
3
4
5size, channels = 28, 1
6size = conv_out(size, 5)
7conv1_params = (5 * 5 * channels + 1) * 6
8channels = 6
9print(size, channels, conv1_params)
10size = conv_out(size, 2, stride=2)
11print(size, channels)
12size = conv_out(size, 5)
13conv2_params = (5 * 5 * channels + 1) * 16
14channels = 16
15print(size, channels, conv2_params)
16size = conv_out(size, 2, stride=2)
17print(size, channels, size * size * channels)
18print((28 * 28) * (24 * 24 * 6) + 24 * 24 * 6)
19print(256 * 120 + 120)

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Output size = floor((n + 2·pad − k) / stride) + 1: how many positions the filter fits.—
—
Each of 6 filters has 5 × 5 × 1 weights plus a bias: 26 × 6 = 156 parameters, regardless of image size.—
—
A 28 × 28 image becomes 24 × 24 with 6 channels.—
24 6 156
After the second convolution and pooling, the maps are 4 × 4 with 16 channels: 256 values to flatten.—
24 6 156
12 6
8 16 2416
4 16 256
A fully connected layer with the same output size would need almost 2.7 million parameters.—
24 6 156
12 6
8 16 2416
4 16 256
2712960
The dense layer after flattening has 30,840 parameters, far more than the convolutions before it.—
24 6 156
12 6
8 16 2416
4 16 256
2712960
30840

Behind the scenes

How Python processes this code

Python runs this source through its interpreter. It creates objects for values and resolves names as each statement runs.

Cost and common mistakes

A convolution layer costs O(out_h · out_w · c_out · k² · c_in) multiply-adds, and stores only O(k² · c_in · c_out) parameters.

  • Shape mistakes are the most common bug in CNNs. Compute the output size of every layer before training.
  • Filters are learned, not designed. The 5 × 5 size is a hyperparameter you choose.
  • Pooling and strides discard spatial detail. Too much downsampling can lose information needed for fine tasks.

Try it yourself

What output size does a 3 × 3 filter with padding 1 and stride 1 give for a 32 × 32 input?

Reveal answer and reasoning

(32 + 2·1 − 3) / 1 + 1 = 32. Padding of 1 with a 3 × 3 filter preserves the size.

Further reading