Skip to content
  • Convolutions, Padding, Stride & Pooling · Deep Learning

Convolutions, Padding, Stride & Pooling

LearnViaNotes @learnvianotes· 4 min read

A convolutional layer slides small learned filters over an image. Each filter detects one local pattern (an edge, a texture) everywhere in the image, using the same few weights at every position.

Why not a dense layer?

The operation

At each position, multiply the filter element-wise with the patch underneath and sum (deep-learning “convolution” is technically cross-correlation — the filter isn't flipped).

Python
import numpy as np

def conv2d(img, k):
    kh, kw = k.shape
    out = np.zeros((img.shape[0] - kh + 1, img.shape[1] - kw + 1))
    for i in range(out.shape[0]):
        for j in range(out.shape[1]):
            out[i, j] = np.sum(img[i:i + kh, j:j + kw] * k)
    return out

img = np.array([[0, 0, 0, 9, 9, 9]] * 5, dtype=float)    # dark left half, bright right half
vertical_edge = np.array([[-1, 0, 1],
                          [-1, 0, 1],
                          [-1, 0, 1]], dtype=float)     # Sobel-like filter
out = conv2d(img, vertical_edge)
print(out.shape)            # (3, 4) ← 5×6 input, 3×3 filter
print(out[0].tolist())      # [0.0, 27.0, 27.0, 0.0] ← fires only where brightness changes

Output size: padding and stride

out = ⌊ (n + 2p − k) / s ⌋ + 1 n = input size, k = kernel, p = padding, s = stride

SettingEffect
Padding p = (k−1)/2 (“same”)Output keeps the input size (stride 1) — edges get processed too
No padding (“valid”)Output shrinks by k − 1
Stride 2Moves the filter 2 pixels at a time — roughly halves height and width
Dilation dSpreads the filter taps out — larger view, same parameters
Python
import torch
from torch import nn

out_size = lambda n, k, p=0, s=1: (n + 2 * p - k) // s + 1
print(out_size(32, 3), out_size(32, 3, p=1), out_size(32, 3, p=1, s=2), out_size(224, 7, p=3, s=2))   # 30 32 16 112

x = torch.randn(8, 3, 32, 32)                    # (batch, channels, height, width)
conv = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, padding=1, stride=2)
print(conv(x).shape)                             # torch.Size([8, 16, 16, 16])
print(conv.weight.shape, conv.bias.shape)        # torch.Size([16, 3, 3, 3]) torch.Size([16]) ← 16 filters, each 3×3×3
print(sum(p.numel() for p in conv.parameters()))   # 448 ← 16·(3·3·3) + 16

conv parameters = C_out × (C_in × k × k) + C_out — independent of the image size

Pooling

Python
import torch
from torch import nn

x = torch.tensor([[[[1.0, 3.0, 2.0, 0.0],
                    [4.0, 2.0, 1.0, 1.0],
                    [0.0, 1.0, 5.0, 6.0],
                    [2.0, 2.0, 7.0, 8.0]]]])            # (1, 1, 4, 4)
print(nn.MaxPool2d(2)(x).squeeze().tolist())          # [[4.0, 2.0], [2.0, 8.0]] ← max of each 2×2 block
print(nn.AvgPool2d(2)(x).squeeze().tolist())          # [[2.5, 1.0], [1.25, 6.5]]
print(nn.AdaptiveAvgPool2d(1)(x).flatten().tolist())  # [2.8125] ← global average pooling

Pooling shrinks feature maps (less compute, bigger receptive field) and adds a little tolerance to small shifts. It has no parameters. Modern CNNs often use stride-2 convolutions instead, and end with global average pooling — one number per channel — before the classifier.

Receptive field

The receptive field is the patch of the input that can influence one output unit. Each 3×3 conv (stride 1) adds 2 pixels; each stride multiplies how fast later layers grow it.

Python
def receptive_field(layers):          # layers: list of (kernel, stride)
    rf, jump = 1, 1
    for k, s in layers:
        rf += (k - 1) * jump
        jump *= s
    return rf

print(receptive_field([(3, 1)] * 2))                 # 5 ← two 3×3 convs see 5×5 (like one 5×5)
print(receptive_field([(3, 1)] * 3))                 # 7 ← three see 7×7
print(receptive_field([(3, 1), (2, 2), (3, 1), (2, 2), (3, 1)]))   # 18 ← pooling speeds growth

How do you compute the output size of a conv layer?

Why are CNNs better than MLPs for images?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report