Kahibaro
Discord Login Register

9.1 Convolutions, Padding, and Stride

What a 2D Convolution Layer Does

In image models, a 2D convolution takes a small grid of learnable weights called a kernel or filter and slides it across an image, producing a new image like output called a feature map. At each spatial position, the layer computes a weighted sum between the kernel and the local patch of the input, then outputs a single number for that position. Repeating this at every position creates one feature map. Using multiple kernels creates multiple output channels, which lets the network detect many patterns at once, such as edges, corners, or textures.

In PyTorch, the typical input to a convolution has shape $(N, C_{in}, H, W)$, where $N$ is batch size, $C_{in}$ is the number of input channels, and $H, W$ are height and width. The output has shape $(N, C_{out}, H_{out}, W_{out})$, where $C_{out}$ is the number of filters.

Kernel Size and the Sliding Window

The kernel size sets the spatial footprint of each filter, for example $3 \times 3$ or $5 \times 5$. A $3 \times 3$ kernel looks at a $3$ by $3$ patch of the input at a time, across all input channels, and produces one output value per output channel.

Conceptually, for one output channel, the computation at location $(i, j)$ is a sum over input channels and kernel positions:

$$
y[i, j] = b + \sum_{c=1}^{C_{in}} \sum_{u=1}^{k_h} \sum_{v=1}^{k_w} w[c, u, v] \cdot x[c, i+u, j+v]
$$

PyTorch’s nn.Conv2d uses cross correlation rather than the mathematically flipped convolution. In practice for deep learning, this naming difference rarely matters because the weights are learned either way.

Stride, How Far the Kernel Moves

Stride controls how many pixels the kernel moves each step. With stride $1$, the filter slides one pixel at a time, producing a dense feature map. With stride $2$, it jumps two pixels each step, producing a smaller output and performing downsampling.

Stride affects only the spatial dimensions, not the number of channels. Larger stride reduces $H_{out}$ and $W_{out}$, which often reduces compute and memory, but also throws away spatial detail.

Rule of thumb: increasing stride decreases spatial resolution. If your output becomes unexpectedly small, check the stride first.

Padding, What Happens at the Borders

Without padding, the kernel cannot be centered near the border without falling off the image, so the output shrinks. Padding adds extra pixels around the input, usually zeros, so the kernel can be applied near the edges. Padding is specified as the number of pixels added to each side.

For a $3 \times 3$ kernel with stride $1$, using padding $1$ keeps the height and width the same, because you add a one pixel border and the kernel’s radius is one pixel.

PyTorch’s nn.Conv2d supports common padding setups via the padding argument. When padding is an integer, the same padding is applied to height and width. When it is a tuple, you can specify separate padding for height and width.

If you want to preserve spatial size with stride $1$ and an odd kernel size $k$, use padding $p = \frac{k-1}{2}$, for example $k=3 \Rightarrow p=1$, $k=5 \Rightarrow p=2$.

Output Size Formula

To reason about shapes, you need the output size formula. For one spatial dimension, the output length is:

$$
L_{out} = \left\lfloor \frac{L_{in} + 2p - d\,(k-1) - 1}{s} + 1 \right\rfloor
$$

Here $L_{in}$ is input size, $p$ is padding, $k$ is kernel size, $s$ is stride, and $d$ is dilation. In many beginner CNNs, dilation is left at $1$, which simplifies the formula to:

$$
L_{out} = \left\lfloor \frac{L_{in} + 2p - k}{s} + 1 \right\rfloor
$$

You apply the same logic to height and width to get $H_{out}$ and $W_{out}$.

Always check shapes with the formula when stacking conv layers. Small changes in stride or padding compound quickly across layers.

“Same” vs “Valid” Padding

In many explanations, you will see two common conventions. Valid means no padding, so the output shrinks. Same means padding is chosen so that for stride $1$ the output has the same height and width as the input.

In PyTorch, newer versions allow padding="same" in nn.Conv2d for many settings, but it is important to remember that same is straightforward when stride is $1$. When stride is greater than $1$, same padding still reduces spatial size, because downsampling is caused by stride, not by lack of padding.

How This Looks in PyTorch Code

A convolution layer is created like this:

python
import torch
import torch.nn as nn
conv = nn.Conv2d(
    in_channels=3,
    out_channels=16,
    kernel_size=3,
    stride=1,
    padding=1
)
x = torch.randn(8, 3, 64, 64)  # (N, C, H, W)
y = conv(x)
print(y.shape)  # torch.Size([8, 16, 64, 64])

If you change stride to 2 while keeping the same kernel and padding, the spatial size halves:

python
conv2 = nn.Conv2d(3, 16, kernel_size=3, stride=2, padding=1)
y2 = conv2(x)
print(y2.shape)  # torch.Size([8, 16, 32, 32])

Common Beginner Mistakes Specific to Padding and Stride

A frequent confusion is mixing up channels and spatial dimensions. Padding and stride apply to height and width, not to channels. Another common issue is accidentally shrinking the feature maps too aggressively early in the network by using stride $2$ repeatedly, which can remove useful detail for small images.

If your feature maps reach very small sizes like $1 \times 1$ too early, reduce the number of stride 2 operations, or move downsampling deeper in the network.

Connecting the Ideas to CNN Design

Padding determines whether you preserve border information and control the output size. Stride determines how quickly you downsample. Kernel size determines how large a local neighborhood the layer can inspect at once. These three parameters are the basic tools you use to control spatial resolution and receptive field as you build CNNs, and you will apply them directly when you start assembling a complete CNN architecture in the next chapters.

Views: 69

Comments

Please login to add a comment.

Don't have an account? Register now!