3.4.6 · D2Convolutional Neural Networks

Visual walkthrough — LeNet and AlexNet

1,978 words9 min readBack to topic

Both LeNet and AlexNet describe their layers with lines like "Input , 6 filters of → Output ". Where does that 28 come from? The whole architecture — every layer size, every parameter count — rests on one small counting result. Let us build it from absolute zero: no formula assumed, just squares sliding over a grid.

We will need three plain words before any symbol:

Symbols earned: (input side), (kernel side), (stride). We will add (padding) only when we need it, in Step 5.


Step 1 — Lay the kernel at the top-left corner

WHAT. Put the window so its top-left cell sits on the image's top-left cell. Multiply the overlapping numbers, add them up: that produces the first output value.

WHY. Every counting problem needs a starting point. The left-most, top-most legal position is the natural "position 1". If we can count how far the window travels from here, we are done.

PICTURE. The orange window covers columns through of the blue image. Look at how much room is left to its right — that leftover room is what limits how far it can travel.

Figure — LeNet and AlexNet

Here , (a toy image so we can count by eye). The window occupies columns 1–3; columns 4–7 are still free to its right.


Step 2 — Slide right one pixel at a time and count landings (stride 1)

WHAT. Move the window right by pixel repeatedly. Each landing is a new output value. We stop the instant the window's right edge would fall off the image.

WHY. We are literally counting positions. The output width is nothing more mysterious than "how many times did the window land before running out of room?"

PICTURE. Below, each colored outline is one legal landing of the window on the -wide image. Count them: positions starting at column — that is 5 landings.

Figure — LeNet and AlexNet

Now reason about the count. The window's left edge may start at column and may go as far right as column (any further and the right edge, at start-column , would exceed ). So the number of landings is

  • is the last column the left edge can sit on.
  • Subtracting the first start () and adding back is the classic "fence-post" count — the number of integers from to inclusive is .

Check with the picture: . That matches the five outlines. This is exactly the parent note's "the kernel can slide positions" for LeNet's C1.


Step 3 — Big jumps: what stride changes

WHAT. Instead of moving pixel per step, move pixels. Fewer landings fit, so the output shrinks faster.

WHY. AlexNet's Conv1 uses stride to aggressively downsample — collapse a huge image quickly so later layers are cheap. Stride is our knob for "how coarsely do we sample positions?"

PICTURE. The window starts at column , then , then , ... The gaps between landings are now wide. We count how many jumps of size fit inside the travel room .

Figure — LeNet and AlexNet

The total distance the left edge is allowed to travel is (from Step 2). Each step consumes pixels of that budget, so the number of extra steps we can take is . Add the very first landing (the ""):

  • — total travel room for the left edge (Step 2).
  • — how many jumps of size fit in that room.
  • — the floor: round down, because a partial jump that would push the window off the edge is not a legal landing. You cannot half-land.
  • — the starting position, which took zero jumps.

Step 4 — Worked landings for AlexNet's Conv1 (the "224 vs 227" puzzle)

WHAT. Apply Step 3 to AlexNet: , , , no padding yet.

WHY. The parent note flags a famous confusion — the paper says the output is but the plain formula gives . Let us see both numbers appear and understand which input produces which.

PICTURE. The bar shows the travel budget chopped into jumps of . It does not divide evenly — a stub of length is left over, which the floor discards.

Figure — LeNet and AlexNet

  • — the travel room.
  • — jumps including an impossible quarter-jump.
  • — discard the quarter; that stub is the gray leftover in the figure.

So the honest arithmetic gives 54. The paper's comes from feeding the layer a -wide input (one pixel of implicit border added), which we resolve next.


Step 5 — Padding : gluing a border so the count comes out clean

WHAT. Wrap the image in rings of extra pixels (usually zeros) on every side. The window now has more room, so more landings fit and the output grows.

WHY. Two reasons. (1) It lets you choose the output size — e.g. keep it equal to the input ("same" convolution), as AlexNet's Conv2/3/4/5 do with padding . (2) It rescues edge pixels, which otherwise get visited by the window far less often than centre pixels.

PICTURE. The blue image gains a green border of width on each side. Its effective width becomes — the "" because padding is added on both the left and the right.

Figure — LeNet and AlexNet

Replace by everywhere in Step 3's count:

AlexNet resolved. With effectively giving a -wide input: The mystery "" was padding hiding inside the implementation, exactly as the parent note says.


Step 6 — Every case, including the degenerate ones

WHAT. Push the formula to its limits so no scenario surprises you.

WHY. Contract rule: the reader must never meet an input we did not show.

Figure — LeNet and AlexNet
  • , , (window as big as image): . Output is a single number. This is exactly LeNet's C5: input , kernel . The window fits in one and only one spot — hence C5 "is effectively fully connected".
  • , , (single-pixel window): . Output = input; a convolution mixes channels but never moves spatially.
  • Pooling is the same formula. LeNet's S2: pool, on a -wide map: . Matches . Pooling windows count landings identically to conv windows — see Pooling Layers and Convolutional Layers.
  • Non-even division ( not a multiple of ): the floor silently drops the leftover stub (Step 4). No error, just a slightly smaller map.
  • Illegal (): numerator negative, "output " — the window does not even fit once. The layer is impossible; frameworks throw an error.

The one-picture summary

Figure — LeNet and AlexNet

The entire derivation on one line: start room, minus the window, plus padding on both sides, divided into jumps, round down, add the starting landing.

Recall Feynman retelling — say it like you'd explain to a friend

Imagine parking a square car in a long thin garage. The garage is pixels long; the car is pixels long. Once the car nose is at the very back, the room left in front of it is . If you nudge the car forward pixels each parking spot, the number of extra spots is that leftover room divided by — and you round down, because a spot that pokes the car out the door doesn't count. Then add one for the very first spot (nose against the back wall). That total number of parking spots is how wide the output image is. Padding is just building a little porch of length on both ends of the garage, so the garage is really long and more spots fit. That's why LeNet's -image with a -car and no porch gives spots, and why AlexNet's only appears once you admit there was a secret one-pixel porch making the input , not . Same one rule builds every layer size in both networks — convolution and pooling alike.

Recall Quick self-test

LeNet C1 output side for input 32, kernel 5, stride 1, pad 0 ::: AlexNet Conv1 with the honest 224 input ::: AlexNet Conv1 with the implicit 227 input ::: LeNet S2 pooling, input 28, kernel 2, stride 2 ::: Why "" and not ""? ::: padding is added on both left and right sides Why the floor? ::: landings are whole things; a window poking off the edge is not a legal position

Related builds: deeper stacks of this same counting rule underlie VGGNet and ResNet; the regularization tricks around it live in Dropout and Batch Normalization; see also Image Classification where these output maps finally become class scores.