3.4.3 · D3Convolutional Neural Networks

Worked examples — Pooling layers (max, average)

2,511 words11 min readBack to topic

This is a worked-examples clinic for the parent note Pooling layers. There, you met the two rules — take the max or take the average of a small window — and the output-size formula. Here we push those rules through every situation they can meet: clean cases, ugly cases, degenerate cases, and the exam-twist cases.

Before we compute anything, let us re-anchor the two words we will use hundreds of times.


The scenario matrix

Every pooling situation is one of these cells. Each example below is tagged with the cell(s) it covers, so together they leave no gap.

Cell What makes it tricky Covered by
A. Clean divide , divisible by Ex 1
B. Non-divisible / floor bites not a multiple → floor drops a strip Ex 2
C. Overlapping windows → windows share pixels Ex 3
D. Negative activations numbers below zero (post-conv, pre-ReLU) Ex 4
E. Degenerate window pool, or window = whole map Ex 5
F. Ties / plateau two equal maxima in one window (backprop gap) Ex 6
G. Backprop routing gradient flow, max vs average Ex 7
H. Real-world word problem pick pooling for a task, reason about it Ex 8
I. Exam twist rectangular input, stride ≠ pool, both dims Ex 9

Two facts we will lean on repeatedly:


Example 1 — Cell A: the clean, textbook case

Forecast: guess the output size before reading on. (, so — but why is it exactly a half?)

Figure — Pooling layers (max, average)
  1. Output size. . Same for width. Why this step? We must know how many windows fit before computing values. Here divides perfectly, so no pixel is left over — a clean half.
  2. Slide window to the 4 non-overlapping positions (look at the four coloured blocks in the figure). Top-left block is rows , cols : values . Why this step? Stride means each new window starts 2 pixels along, so blocks tile the grid with no overlap and no gap.
  3. Max of each block: ; ; ; .
  4. Average of each block: ; ; ; .

Verify: every average lies between the min and max of its block (e.g. sits inside ) — a mean can never escape its data. And each max appears somewhere in its block. ✓


Example 2 — Cell B: floor bites, a strip is dropped

Forecast: is odd. Does the bright column survive pooling, or get thrown away?

  1. Output size. . So the output is , not . Why this step? The floor throws away the fractional window. Window starts allowed: position and position . A window at position would need columns — but there is no column , so it doesn't fit.
  2. Which columns get pooled? Column starts are , so windows cover columns and . Column 4 is never inside any window. Why this step? This is the whole lesson of the floor: the last strip (row/col 4 here) is silently ignored when it can't complete a window.
  3. Consequence. Since only columns are all zeros, every max is and every average is . The bright column of s vanished.

Verify: count pooled pixels: windows/row columns used, column unused — matches "one strip dropped". If we had wanted column 4 kept, we'd add padding (see Stride and Padding) so becomes . ✓ (Lesson: floor can delete real information at the border.)


Example 3 — Cell C: overlapping windows ()

Forecast: now windows are wide but only step by . Will column 4 be seen this time?

Figure — Pooling layers (max, average)
  1. Output size. . So output again.
  2. Column starts are . A window at start covers columns — so column 4 IS now inside a window. Why this step? Because , consecutive windows share one column (overlap ). Overlap lets a border pixel sneak into a window. Look at the shaded overlap band in the figure.
  3. Second-column outputs see the bright column: .

Verify: overlap width column shared between neighbours — consistent with the figure's overlap band. And unlike Example 2, the s survived, exactly because overlap reached the border. ✓


Example 4 — Cell D: negative activations

Forecast: what is "the max" when everything is negative? People instinctively pick (biggest magnitude). Guess before step 1.

  1. Max. . Why this step? "Maximum" means largest on the number line, and sits furthest to the right (closest to zero). Magnitude is irrelevant. This matters because a convolution output before an activation function can be negative.
  2. Average. .
  3. Sanity gap. Max () and average () disagree a lot here — max clings to the least-negative pixel, average is dragged down by the very negative .

Verify: the average lies inside ✓, and the max every entry ✓. (Lesson: never confuse "max" with "largest magnitude" — with negatives they point opposite ways.)


Example 5 — Cell E: degenerate windows

Forecast: what does a window do? And what is a whole-map pool secretly called?

  1. (a) pool. . Output is unchanged. Why this step? A window of one pixel has nothing to summarise; its max = its average = itself. This is the identity pooling — a useful edge check that the formula still behaves.
  2. (b) Whole-map average pool. . Output is a single number: the mean of all entries. Sum , so average . Why this step? When the window equals the whole feature map, average pooling collapses each map to one number — this is exactly Global Average Pooling, used to replace fully-connected layers.

Verify: for (a) the formula gives output size input size, matching "identity". For (b), , and it lies inside ✓. Whole-map max would instead give (the single largest). ✓


Example 6 — Cell F: a tie (two equal maxima)

Forecast: if backprop later sends gradient here, does it split between both s?

  1. Forward max. . The output is unambiguous — either way.
  2. Backward tie-break. Frameworks pick one position (usually the first encountered, here top-left). The gradient flows to that single ; the other gets . Why this step? Max is not differentiable at a tie, so libraries make a deterministic choice. Only one path is "credited" for the output.

Verify: whatever the choice, the total gradient leaving the window equals the incoming gradient (conservation) — it isn't duplicated, just routed to one cell. If incoming grad , then routed grad sums to . ✓


Example 7 — Cell G: full backprop routing, max vs average

Forecast: max sends where? Average sends what to each cell?

Figure — Pooling layers (max, average)
  1. Max routing. Forward max was (bottom-right). So all of goes to that one cell; the other three get . Why this step? Only the influenced the output, so by the chain rule only its path carries gradient (a "gate": open at the max, shut elsewhere).
  2. Average routing. Every cell contributed equally with weight . So each cell gets . Why this step? Average is a linear blend , so for all four — gradient spreads democratically.
  3. Conservation check (both). Max: . Average: . Why this step? A pooling layer has no parameters to absorb gradient, so what comes in must go out — total is preserved either way.

Verify: both total to ✓. Max = sparse (1 nonzero), average = dense (4 nonzeros) — matching the parent note's gradient-flow table. ✓


Example 8 — Cell H: real-world word problem

Forecast: blob detection, location-agnostic — max or average?

  1. Identify the question the layer must answer. We need "is the bright blob present somewhere?" — a presence/spike question. Why this step? The pooling choice is dictated by the question, per the intuition box: presence → max, overall level → average.
  2. Pick max pooling in the feature-extraction stack. A tiny high activation from the blob survives max pooling even if surrounded by dark tissue; average would dilute it toward the background mean. Why this step? Averaging gives , nearly indistinguishable from all-zero background; gives — a clear signal.
  3. Add Global Average Pooling only at the very end, right before the classifier, to collapse each feature map to one number cheaply (fewer parameters, less overfitting). Why this step? Different jobs: max inside to keep spikes, GAP at the end to summarise for the final decision.

Verify: sanity via the diluting numbers — mean of vs max . The gap confirms max preserves the blob's signal. ✓ (Contrast: for a "how rough is this texture?" task, average wins — see parent note Mistake 3.)


Example 9 — Cell I: the exam twist (rectangular, stride ≠ pool, both dims)

Forecast: height and width start different (7 vs 5). Will the output be square or rectangular?

  1. Height. . Why this step? Each dimension uses the same formula independently — pooling never mixes rows into columns.
  2. Width. .
  3. Result: output is — rectangular, mirroring the rectangular input. Why this step? Because we applied the formula per-axis, unequal inputs stay unequal (they don't "average out").

Verify: double-check the dropped strips. Height: window starts ; last window covers rows — row is the last, so all 7 rows are used, none dropped. Width: starts ; last covers cols — all 5 cols used. So here no border is lost even with the floor. ✓ (This is the trap: same formula gives Mistake-4's answer, but is asymmetric.)


Recall Quick self-test

Output size of input, pool, stride ? ::: . Max of the window ? ::: (largest on the number line, not largest magnitude). Average-pooling gradient for incoming over a window, each cell? ::: . Whole--map average of Example 1's grid (sum )? ::: . Does overlap () let a border pixel enter a window? ::: Yes — overlap width can reach it.

Back to the parent note · related: Receptive Field, VGG Network, ResNet Architecture.