Deep learning and neural networksLoading progress…

Local filters

Calculate a convolutional output and explain filters, stride, padding, pooling and residual connections.

Look at a small window, then slide it

Looking at every pixel of an image at once needs a huge number of weights. A convolutional layer instead learns one tiny pattern detector, a kernel (also called a filter), and applies it at every position. At each position you multiply the kernel with the numbers underneath it and add the results. That single sum is one output value.

Position 1 of 4
12345

kernel [1,-1] sits on positions 0 and 1: 1·1 + -1·2 = -1

outputs so far:-1
A kernel [1, −1] sliding over [1, 2, 3, 4, 5]. Each output is the difference between neighbours.

Deep-learning libraries call this convolution, but strictly it is cross-correlation: the kernel is not flipped. True mathematical convolution flips the kernel first. Because the kernel is learned, the difference does not matter in practice, but it matters when you compare with a maths textbook or check an answer by hand.

Predict first. Cross-correlate [1, 2, 3] with the kernel [1, −1], no padding. What do you get?

The same idea in two dimensions

On an image the kernel is a small grid, and the same weights are reused at every position. Different weights detect different things: the kernel with −1 on the left and +1 on the right responds where brightness jumps from left to right, which is a vertical edge. Try it: pick an image, a preset, then edit single weights.

image:
presets:
image (8×8)
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
3×3 kernel (editable)
output (6×6)
0
0
3
3
0
0
0
0
3
3
0
0
0
0
3
3
0
0
0
0
3
3
0
0
0
0
3
3
0
0
0
0
3
3
0
0
total |response| on this image: 36 vertical-edge image: 36 horizontal-edge image: 0
Blue is negative, orange positive. The output is large only where the pattern the kernel looks for is present.
window = image[i:i+3, j:j+3]
out[i, j] = (window * kernel).sum()
Chapter context

A convolutional layer reuses a local filter across positions. Weight sharing encodes a structural assumption about repeated local patterns while greatly reducing parameters compared with a fully connected map over all pixels.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

For one spatial dimension, output size is

nout=⌊n+2p−d(k−1)−1s⌋+1.n_{out}=\left\lfloor\frac{n+2p-d(k-1)-1}{s}\right\rfloor+1.

Here n is input size, k kernel size, p padding, d dilation and s stride. Cross-correlation is yt=∑iwixt+iy_t=\sum_iw_i x_{t+i}. A residual block has form hout=h+F(h)h_{out}=h+F(h) when shapes agree.

Worked example

For input [1,2,3,4] and kernel [1,−1], stride-one valid cross-correlation returns [−1,−1,−1]. Separately, n=7,k=3,p=1,s=2,d=1 gives floor((7+2−2−1)/2)+1=4 output positions.

Reference code

The following example uses the Python standard library and does not call a remote service.

x,w = [1,2,3,4],[1,-1]
y = [sum(x[t+i]*w[i] for i in range(len(w))) for t in range(len(x)-len(w)+1)]
assert y == [-1,-1,-1]
n,k,p,s,d = 7,3,1,2,1
assert (n+2*p-d*(k-1)-1)//s+1 == 4

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

Padding does not reveal missing real pixels. Kernel flipping conventions change calculations. A residual shortcut needs a defined shape-compatible path.