Reading — step 1 of 5
Convolution as sliding-window pattern matching
A convolutional layer detects a local pattern (an edge, a texture, a shape) by sliding a small kernel over the input and, at every position, computing a weighted sum of the pixels underneath it. The output at each position is high when the underlying patch resembles whatever pattern the kernel encodes.
Deep learning frameworks technically implement cross-correlation, not the "flip the kernel" convolution from signal-processing textbooks — the kernel is applied directly without being mirrored. This doesn't matter for a learned kernel (the network just learns whichever orientation is useful), so in this course "convolution" always means cross-correlation, matching PyTorch/TensorFlow conventions.
The core computation
For an input image, a kernel of size kH × kW, and an output position (r, c):
out[r][c] = Σ_u Σ_v image[r·stride + u][c·stride + v] · kernel[u][v]
That is: place the kernel's top-left corner at (r·stride, c·stride) in the image, multiply element-wise with the overlapping patch, and sum everything up. Slide the kernel across every valid position to build the full output feature map.
Padding
Without padding, the kernel can never be centered on a border pixel — the output shrinks with every convolution, and edge information gets used less than interior information. Zero-padding adds a border of zeros around the image before convolving, which lets you control the output size (or keep it unchanged, with "same" padding).
Hp = H + 2·pad
Wp = W + 2·pad
Build the padded image first (as its own 2D array), then run the same sliding-window logic over it — this keeps your convolution loop simple and pad-agnostic.
Stride
Stride controls how far the kernel moves between output positions. stride=1 produces the densest, largest possible output; stride=2 skips every other position, halving each output dimension (roughly) — a cheap way to downsample without a separate pooling layer.
Output size formula
out_dim = ((in_dim + 2·pad - kernel_dim) / stride) + 1
Apply this formula independently to height and width. This is the formula you'll reach for constantly once you start stacking conv layers — knowing the output shape in advance is essential for wiring up the next layer correctly.
Building it step by step
- Parse the image and kernel into 2D arrays.
- If
pad > 0, build a padded copy with zeros on all sides. - Compute output dimensions using the formula above.
- For every output position
(r, c), sum the element-wise product of the kernel with the patch at(r·stride, c·stride). - Format each output row as comma-separated floats.
Edge cases to watch:
- With
stride > 1, make sure you multiply the output index bystrideto find the input patch's top-left corner — a common bug is forgetting the stride multiplier and effectively always usingstride=1regardless of what was requested. - Padding is added symmetrically (same amount on all four sides) — a kernel or image position needs to account for the padding offset when indexing back into the original (unpadded) data if you ever need to map an output position back to input coordinates.
- All arithmetic should be done in floats throughout, even though kernels are sometimes conceptually integers (like the sum-kernel in this lesson's example) — mixing float and int accumulation can produce truncation bugs in other languages, though Python sidesteps this naturally.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…