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.
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 with weights slides over input and writes map with one number per placement. With filters the output stacks to . Early maps fire on edges and blobs, middle maps on textures and parts, deep maps on object-level patterns.
A worked tensor shape
Input , two filters , stride , no padding. Each map is:
So each map is numbers, and the stack is numbers. One cell by hand: a 3 by 3 window of all 2s under an all-ones filter sums , so that map cell reads 18. A real early block with filters on gives numbers, which is why memory, not weights, often caps batch size. Check: , and .
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) # -> 18The 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 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.