Skip to content
AI360XpertBeta

Pooling and Downsampling

Pooling summarizes each small patch of a feature map into one value, trading exact positions for cheaper maps and sturdier features.

A 2 by 2 max-pooling window keeps only the strongest activation per patch, halving each side of a 4 by 4 map.
A 2 by 2 max-pooling window keeps only the strongest activation per patch, halving each side of a 4 by 4 map.

Why Does This Exist?

A 1080p frame at 1920×10801920 \times 1080 with 3232 float32 channels costs 1920×1080×32×4=265,420,8001920 \times 1080 \times 32 \times 4 = 265{,}420{,}800 bytes, about 265265 MB for one feature map, before any batch or gradient. Running every later layer at full resolution is unaffordable, and exact pixel positions are often noise: a classifier should fire whether the tire sits ten pixels left or right. Pooling compresses each local patch into one value, halving spatial sides per step while keeping the strongest signals. Two stride-2 steps shrink that 265265 MB map 1616-fold to about 16.616.6 MB. This page covers window pooling and its learned cousin, strided convolution. What flows through the windows is taught in feature maps, and the stride arithmetic in padding and stride.

Think of It Like This

Judging a choir by section

A judge scores a choir split into sections. For each section the judge writes down one number: with max-pooling it is the loudest singer's volume, with average-pooling it is the section's overall hum. Swapping two singers inside one section changes nothing on the score sheet.

The window is the section, the stride is how sections tile the stage, and swap-proof scores are translation invariance. The analogy stops at seating: the judge still remembers where each section sat, but pooling forgets exact positions. Tasks that need locations, like drawing boxes or masks, must recover them elsewhere.

How It Actually Works

A pooling layer slides a K×KK \times K window with stride SS over each channel independently, where KK is the window side and SS is the step between windows. The output side is ⌊(W−K)/S⌋+1\lfloor (W - K)/S \rfloor + 1 for input side WW, so K=2K = 2 and S=2S = 2 halves each side and quarters the values. Max pooling outputs y=max⁡i∈R(xi)y = \max_{i \in R}(x_i) over window RR, keeping the strongest activation and killing the rest, which suits sparse signals like edges. Average pooling outputs y=1∣R∣∑i∈Rxiy = \frac{1}{|R|} \sum_{i \in R} x_i, smoothing the patch, which suits texture and density but dilutes a lone strong spike. Global average pooling pushes this to the limit: one value per channel for the whole map, feeding the classifier with no dense layer. Strided convolution instead steps its learned kernel with S=2S = 2, downsampling with weights the network tunes rather than a fixed rule.

Worked 4 by 4 example

Input rows [1,3,2,4][1, 3, 2, 4], [5,6,1,2][5, 6, 1, 2], [0,1,8,7][0, 1, 8, 7], [3,2,4,5][3, 2, 4, 5] with K=2K = 2, S=2S = 2 give output side ⌊(4−2)/2⌋+1=2\lfloor (4 - 2)/2 \rfloor + 1 = 2. The top-left window [1,3,5,6][1, 3, 5, 6] max-pools to 66 and averages to (1+3+5+6)/4=3.75(1 + 3 + 5 + 6)/4 = 3.75. Scoring all four windows gives max output rows [6,4][6, 4] and [3,8][3, 8], and average output rows [3.75,2.25][3.75, 2.25] and [1.5,6.0][1.5, 6.0].

Code

img = [    [1.0, 3.0, 2.0, 4.0],    [5.0, 6.0, 1.0, 2.0],    [0.0, 1.0, 8.0, 7.0],    [3.0, 2.0, 4.0, 5.0],]
def pool(img, fn):    out = []    for r in (0, 2):        row = []        for c in (0, 2):            window = [img[r + dr][c + dc] for dr in (0, 1) for dc in (0, 1)]            row.append(fn(window))        out.append(row)    return out
print(pool(img, max))# -> [[6.0, 4.0], [3.0, 8.0]]
def mean(xs):    return sum(xs) / len(xs)
print(pool(img, mean))# -> [[3.75, 2.25], [1.5, 6.0]]

Watch Out For

Pooling away the resolution a locator needs

Classification survives heavy downsampling, but detectors and segmenters read positions off the map. The symptom is vanished small objects and blobby masks after a total stride of 3232 on tiny inputs. Budget the strides across the backbone, and recover detail with skip connections or dilated convolutions instead of stacking more pools.

Average-pooling a sparse signal map

When only a few cells carry the defect, edge or spike, averaging divides it by the whole window. The symptom is a strong 9.09.0 spike inside a 2×22 \times 2 window of zeros scoring 2.252.25 and missing its threshold. Use max pooling for sparse presence signals and reserve averaging for texture, density and tail summaries.

The Quick Version

  • Pooling summarizes each K×KK \times K patch into one value with stride SS between windows.
  • A 2×22 \times 2 stride-2 pool halves each side and quarters the value count.
  • Max pooling keeps the strongest activation; average pooling smooths the patch.
  • Example: the 4×44 \times 4 map above max-pools to rows [6,4][6, 4] and [3,8][3, 8].
  • Global average pooling collapses each channel to one value for the classifier.
  • Strided convolution downsamples with learned weights instead of a fixed rule.