Skip to content
AI360Xpert
Beta

Feature Maps Are Where Filters Fire

Each filter draws one map of where its pattern fired. Stack the maps and you hold the image as the network sees it, channels first.

Two 3 by 3 filters slide over a 5 by 5 input and stack two 3 by 3 maps into a 2 by 3 by 3 tensor, with an all-twos window under an all-ones filter scoring 18
Two 3 by 3 filters slide over a 5 by 5 input and stack two 3 by 3 maps into a 2 by 3 by 3 tensor, with an all-twos window under an all-ones filter scoring 18

Why Does This Exist?

Raw pixels mix everything: light, object and background share the same numbers. A classifier reading pixels directly must untangle all of it at once, which is why dense layers on images explode in weights and still miss shifted patterns.

Convolutional layers split the job. Each filter hunts one pattern and records where it fired as a 2D sheet. Stack those sheets and later layers read pattern locations instead of pixels. This page names that stack and its shape; the sliding operation behind each cell lives in convolution operation, and what the whole network does with the stack lives in feature extraction.

You need one idea first. A channel is a detector. Bright cells mean the pattern fired there.

Think of It Like This

Transparent overlays on a city map

You lay one clear sheet per question over a city map: one marks parks, one marks schools, one marks bus stops. Each sheet is sparse but honest. Stacked, they answer where a family should live.

Filters are those questions, maps are the marked sheets, and the stack is the pile you hand to the next analyst. Where the analogy stops: map sheets are drawn by people, while feature maps are learned numbers that shift during training.

How It Actually Works

One filter, one map

Filter kk with weights WkW_k slides over input XX and writes map YkY_k with one number per placement. With CoutC_{\text{out}} filters the output stacks to Cout×Hout×WoutC_{\text{out}} \times H_{\text{out}} \times W_{\text{out}}. Early maps fire on edges and blobs, middle maps on textures and parts, deep maps on object-level patterns.

A worked tensor shape

Input 5×5×15 \times 5 \times 1, two filters 3×33 \times 3, stride 11, no padding. Each map is:

(5−3)/1+1=3(5 - 3) / 1 + 1 = 3

So each map is 3×3=93 \times 3 = 9 numbers, and the stack is 2×3×3=182 \times 3 \times 3 = 18 numbers. One cell by hand: a 3 by 3 window of all 2s under an all-ones filter sums 9×2=189 \times 2 = 18, so that map cell reads 18. A real early block with 6464 filters on 224×224224 \times 224 gives 64×224×224=3,211,26464 \times 224 \times 224 = 3{,}211{,}264 numbers, which is why memory, not weights, often caps batch size. Check: 224×224=50,176224 \times 224 = 50{,}176, and 50,176×64=3,211,26450{,}176 \times 64 = 3{,}211{,}264.

Reading maps honestly

Bright means strong match, not probability. Maps are unnormalized activations that later layers rescale. Dead maps that stay near zero signal dead filters, often from too high a learning rate, and pruning them rarely hurts.

Code

The snippet below recomputes the worked numbers with only the standard library: one map cell plus the stack shape.

window = [[2] * 3 for _ in range(3)]kernel = [[1] * 3 for _ in range(3)]cell = sum(window[r][c] * kernel[r][c] for r in range(3) for c in range(3))
h_out = (5 - 3) // 1 + 1shape = (2, h_out, h_out)
print(cell)    # -> 18print(shape)   # -> (2, 3, 3)print(2 * h_out * h_out)  # -> 18

The all-twos window scores 18, each map is 3 by 3, and the stack holds 18 numbers. Change the input size or filter count and the same three lines give the new shape.

Watch Out For

Reading raw maps as heatmap proof

A bright patch shows filter match, not object proof. It shifts with normalization and means little alone. The symptom is screenshots presented as explanations that change under a new seed. Fix it by pairing maps with ablations before claiming one region caused the decision.

Adding channels past memory

Doubling channels quadruples the next 3×33 \times 3 cost and doubles activation memory. The symptom is out-of-memory errors at larger batches while accuracy barely moves. Fix it by widening in steps and watching validation gain per million activations, not per channel.

The Quick Version

  • Each filter writes one 2D map of where its pattern fired.
  • Stacking maps gives a channels by height by width tensor the next layer reads.
  • Two 3 by 3 filters on a 5 by 5 input give a 2 by 3 by 3 stack of 18 numbers.
  • An all-twos window under an all-ones filter scores a map cell of 18.
  • Bright means match strength, not probability, and dead maps signal dead filters.