- The 3×3 kernel — columns weighted , , , a genuine vertical-edge detector — sits over a patch of the 6×6 input. All nine pixel-times-weight products flow into one cell of the feature map.
- The kernel slides one step and repeats. After three positions the sweep speeds up, but nothing else changes: it is the identical multiply-and-sum at all 16 positions.
- The finished 4×4 feature map lights up in exactly the columns where the input's vertical edge sits, and stays dark everywhere the input is flat.
- Takeaway: one tiny set of weights asked the same question at every location, and the feature map is the spatial record of the answers.
The essence: pattern matching by dot product
A kernel is a template — a small grid of numbers that encodes one visual pattern. The kernel in the clip above encodes “dark on the left, bright on the right.” To ask whether a patch of the image contains that pattern, you take the dot product: multiply each kernel weight by the pixel under it and add everything up. Patches that match the template produce a large sum; patches that don't produce a sum near zero. A convolution simply asks that one question at every position, and the feature map it produces is a map of where the pattern occurs.
Here is the whole operation in symbols. is the input image, is a kernel, and the output at position is the dot product between the kernel and the patch whose top-left corner sits at :
The cross-correlation sum — what every deep-learning framework computes when you write Conv2d.
Plug numbers in once and the formula stops being abstract. Take a 3×3 patch whose columns read — a vertical edge — and the vertical-edge kernel with columns . Each row contributes , and three rows sum to 3: a strong response, because the patch is exactly the pattern the kernel encodes. Slide the same kernel onto a flat patch (all ones) and the row sums become — no edge, no response. Every multiplication is laid out below.
A naming footnote worth knowing: the sum above is technically cross-correlation. True mathematical convolution flips the kernel 180° before sliding it, which makes the algebra tidier (it turns convolution into multiplication in the frequency domain). Deep-learning libraries skip the flip and call it convolution anyway — and nobody minds, because the kernel weights are learned. If the optimizer needs the flipped version of a filter, it simply learns the flipped weights. The distinction matters in signal processing; in a CNN it is a historical naming accident.
Now run the operation yourself. The playground below applies your kernel to a 16×16 image entirely in the browser — edit any weight, or load a preset, and watch the feature map react. Teal cells are positive responses, cinnamon cells are negative ones (the pattern matched in reverse).
Kernel playground
Edit any weight directly — the feature map recomputes live.
Try this: load vertical edge on the digit image and find the stroke outlines; then load blur and watch every response shrink toward the local average. The identity kernel reproduces the input — one centre weight, eight zeros.
The arithmetic of the sliding window
Four knobs control where the window lands. Kernel size sets the patch each output value sees. Stride is how far the window jumps between positions — stride 2 visits every other position and halves the resolution, which is why it is described as “convolve and downsample in one move.” Padding adds a border of zeros so the window can sit on the edges; without it, corner pixels appear in only one window while centre pixels appear in of them, so edge information gets systematically under-counted and the output shrinks at every layer. Dilation spreads the kernel's taps apart with gaps, widening the region the kernel spans without adding a single weight.
One formula sizes the output of any combination. For an input, first widen the kernel by its dilation, then count how many strides fit:
The output-size formula. The floor matters: when the division is not exact, the rightmost input columns are simply never visited.
Check it against real layers from this site's model gallery — each row is a convolution that actually runs in the workspaces:
| Layer | n | k | p | s | d | k_eff | output |
|---|---|---|---|---|---|---|---|
| MNIST CNN body conv | 28 | 3 | 1 | 1 | 1 | 3 | |
| CIFAR-10 dilated d=2 block | 32 | 3 | 2 | 1 | 2 | 5 | |
| ResNet-50 7×7 stem | 224 | 7 | 3 | 2 | 1 | 7 |
The explorer below puts all four knobs on sliders over an 8×8 input. Watch the gray cells: whenever does not divide evenly by the stride, the floor in the formula throws those input pixels away — they are read by no window at all.
Arithmetic explorer
Try : the output drops to 3×3 and the last input row and column go dead. Add and the formula lands exactly — every pixel is covered again.
Convolution is three-dimensional
Here is the part nearly every diagram gets wrong, including the classic textbook GIFs: a “2D” convolution on a colour image is a three-dimensional operation. The input is not a flat grid — it is a volume with channels (3 for RGB, often 64 or 256 deeper in the network). One kernel is therefore a volume of weights that reads every input channel at once, and its sliding dot product still produces exactly one 2-D feature map. Depth in, flat out.
The output gains depth only because a layer learns many kernels: independent kernel volumes produce stacked feature maps, and that stack becomes the next layer's input volume. So the parameter count of a convolutional layer multiplies three things — output channels, kernel area, and input depth (plus one bias per kernel):
Spatial size never appears — a kernel costs the same whether the image is 32×32 or 224×224.
Plug in a real layer: the 3×3 convolution inside ResNet-50's first bottleneck block has and , so it holds parameters. Notice what the formula does not contain: the spatial size of the input. The same 36,928 weights process a 56×56 feature map in ResNet-50 — or a billboard, if you fed it one.
- The input is three offset slabs — the R, G, B channels of one image. The kernel is a matching three-deep volume, not a flat square.
- The kernel volume sweeps the input once. All three channels feed its dot product, and exactly one teal map fills on the right: many channels in, one map out.
- Three more kernel volumes fan in, and the output stack deepens to four — each kernel contributes its own map.
- Takeaway: output depth is the number of kernels, not the number of input channels. is a design choice you read straight off the architecture table.
Sidebar: factorising the volume. Because multiplies, it pays to split it. A depthwise-separable convolution first applies one filter per input channel (the spatial part, weights), then mixes channels with a 1×1 convolution ( weights). For a 3×3 layer mapping 64 channels to 64, that is weights instead of — roughly an 8× cut, and the saving approaches as channel counts grow. The CIFAR-10 dilated model in this gallery uses exactly this factorisation to stay under its 200K parameter budget.
Weight sharing: why this beats dense layers
The brutal comparison first. Connect a 28×28 image to a 28×28 output with a dense layer — every output pixel free to look at every input pixel — and you need weights. A 3×3 convolution producing the same-sized output needs 9. That is a factor of about 68,000, and it comes from two structural bets baked into the operation: each output only needs to look at a small neighbourhood (locality), and the same pattern detector is worth applying at every position (weight sharing).
Weight sharing buys more than efficiency — it buys a guarantee called translation equivariance: shift the input and the feature map shifts with it, exactly. Formally, if translates an image, then . A dense layer offers nothing of the sort; it would have to relearn the digit “7” separately at every position it might appear. A convolution learns the detector once and gets every position free, which is also why convolutions generalise from so much less data: the 614,656-weight dense layer has the capacity to memorise positions, and the 9-weight kernel has no choice but to learn the pattern.
The fine print: equivariance is not invariance. The feature map moves with the object; it is the later global pooling stage that collapses position away and makes the final classification translation-tolerant. And sharing weights is exactly the right bias only because image statistics are roughly the same everywhere — an edge is an edge in any corner of the photo. Break that assumption (say, on data with a fixed layout) and the bet pays less.
What the kernels learn: the feature hierarchy
Everything above treated the kernel's weights as given — but nobody writes the vertical-edge kernel anymore. The weights are learned: backpropagation nudges every kernel toward whatever pattern reduces the loss. The remarkable, repeatable result is that the first layer of essentially every vision model ever trained — AlexNet made this famous in 2012 — rediscovers the same vocabulary on its own: oriented edge detectors, colour-opponent blobs, and Gabor-like texture filters. Decades of hand-designed computer-vision features, reinvented from pixels by gradient descent in a few epochs.
Depth is what turns that vocabulary into understanding. A first-layer kernel sees a 3×3 patch and can only assert “an edge at 40° is here.” A second-layer kernel reads feature maps, not pixels — its input channels are “edge here, edge there” — so it can detect conjunctions: corners, stripe pairs, textures. Stack again and motifs compose into object parts; again, and parts compose into objects. Each stage also sees a wider patch of the original image than the last (the receptive field grows with depth), which is precisely what gives the later kernels room to represent something as large as a whole object.
- An input image (a schematic car) enters from the left. As the pulse reaches stage 1, its panel settles into short oriented strokes — the edge vocabulary of layer-1 kernels.
- Stage 2 composes those strokes into repeated motifs: corners and stripe pairs. Stage 3 assembles motifs into recognisable parts — a wheel, a window arch.
- Stage 4 binds the parts into a whole silhouette, and the confidence meter fills: the network has evidence for “car.”
- Takeaway: these panels are schematic by design — the real feature maps live in the ResNet-50 workspace, and they tell the same story.
This page will not fake the evidence with screenshots — you can generate it live. The ResNet-50 workspace runs channel attribution on any image you upload: it ranks which feature-map channels drove the prediction, stage by stage. Early-stage channels respond to edges and colour patches regardless of the subject; by stage 4 the top-ranked channels fire on object-specific structure — wheels, faces, fur. The hierarchy in the clip above is a cartoon of what that probe shows on real photographs.
Where convolution lives in this site's models
Every model in the gallery is built from the operation on this page — the differences are which variant each one bets on:
| Model | Convolution variants | What it demonstrates |
|---|---|---|
| MNIST CNN | plain 3×3 | the textbook pipeline — conv, pool, classify, ~60K params |
| CIFAR-10 dilated | dilated (d = 2, 4, 8, 16) + depthwise-separable | receptive field 65 with zero pooling, under 100K params |
| CIFAR-100 ResNet-18 | plain 3×3 in residual blocks | two-conv blocks with identity shortcuts, 4 stages |
| ResNet-50 | bottleneck 1×1 → 3×3 → 1×1 | 1×1 convs squeeze channels so the 3×3 works at low width |
Sources & further reading
- linkStanford CS231n — Convolutional Networks
- linkDive into Deep Learning — Convolutions
- linkConvolutional neural network (Wikipedia)
- linkGoodfellow, Bengio & Courville — Deep Learning, ch. 9: Convolutional Networks
- linkKrizhevsky, Sutskever & Hinton — ImageNet Classification with Deep CNNs (AlexNet, 2012)