2 Learning the Filters: CNNs
Skills ladder. W&B from this week onward: every run logged, every config recorded. Seed everything. And the overfit-a-single-batch ritual: before any real training run, overfit one fixed batch to 100% accuracy and a very small loss.
Chapter 1 combined hand-designed filters and descriptors with components learned from data, including the visual vocabulary and classifier. CNNs move the learning further down the pipeline: the filter weights and intermediate representations are trained jointly with the classifier. The architecture, training data, loss, and hyperparameters are still chosen by people, but the parameters within the model are fitted by one error signal propagated through the network.
2.1 From MR8 to AlexNet’s first layer
In the ImageNet challenge, an entry looks at a photograph and names what is in it, choosing among 1,000 classes. Because many photographs contain several plausible answers, the challenge’s headline score is top-5 error: the entry proposes five classes, and is wrong only if the true label is not among them. Figure 2.1 shows what the four extra guesses are for.
The winning 2011 classification entry had a top-5 error of 25.8%. In 2012, the AlexNet-based SuperVision submission achieved 16.4% using the provided training data; an ensemble that included networks pretrained on the larger ImageNet 2011 release reached 15.3%. The best non-CNN entry recorded 26.2% [1], [2]. By 2013, almost all classification entries used deep convolutional networks.
Original AlexNet’s first convolutional layer contains 96 filters of size \(11 \times 11 \times 3\). Each can be displayed as an RGB patch. Many are selective for orientation or spatial frequency; others respond to colour contrasts or blobs. Their weights were not specified by hand but were fitted for ImageNet classification. They resemble some classical filters, but they do not reproduce the MR8 bank. Deeper layers learn combinations of these responses over wider receptive fields. Figure 2.2 compares the two banks.
Interactive: read the learned bank
Chapter 1 read the kernel before looking at what it does, and the same habit works on filters nobody wrote. Click any of the 64 and its response in the scene appears alongside it, signed, mid-grey for zero, as Section 1.4 displayed Sobel. Pick a tile, predict what it will draw out of the scene, then click it. Then find a filter whose response you cannot explain from its tile.
The idea was not new. Fukushima’s neocognitron used layers of local filters in 1980, trained by a self-organising procedure rather than end-to-end gradient descent [3]. LeCun and colleagues developed gradient-based training for convolutional networks, and by 1998 LeNet-5 formed part of commercial systems for reading handwritten digits on bank cheques [4]. CNNs remained useful for specialised tasks but did not dominate large-scale visual recognition. AlexNet combined several developments: 1.2 million labelled training images, an efficient GPU implementation, ReLU nonlinearities, data augmentation, and dropout [1]. Convolution and backpropagation were established ideas; their combination with this data, hardware, and training procedure produced the 2012 result.
The rest of the chapter takes the network apart. First the layer itself: what a learned filter is, and what shape it has. Then the operations between layers, which set what each filter can see. Then the zoo of convolution variants, and the assembly of the whole network. Training comes last: where the parameters are actually learned.
2.2 The convolution layer
2.2.1 Why not a fully-connected layer?
The obvious way to put an image into a neural network is the way that works for everything else: flatten it to a vector and connect every input to every unit. For a \(224 \times 224\) colour image and a first layer of 1,000 units, that is \(224 \times 224 \times 3 \times 1000\) weights, just over 150 million in the first layer alone. Even at CIFAR’s \(32 \times 32\) (the lab’s scale), one modest dense layer costs three million weights.
The count is not the only problem. A dense layer treats each pixel-channel value as a separate input coordinate, with no built-in preference for nearby pixels or shared detectors across positions. In principle, it can learn local structure from data. In practice, however, it must learn the same pattern separately at each location: seeing an eye in the top-left updates different weights from seeing one elsewhere. Its learned patterns are therefore tied to position, and the layer is not translation equivariant. Its input dimensionality is also fixed: a standard dense layer built for \(224 \times 224\) images cannot directly accept another image size.
Convolution is the dense layer with two constraints: each output reads only a local window, and the same weights are used at every window position. The result is the operation from Chapter 1: a kernel sliding over the image. Weight sharing makes the parameter count independent of the image’s height and width. With stride 1, a shift of the input shifts the feature map in the same way, apart from padding and boundary effects. A convolutional layer can process variable spatial dimensions large enough for its kernel, although later layers may impose a fixed input size. Figure 2.3 imposes the two constraints one at a time, and Lab 2 compares the resulting structure with a dense network on the same task.
2.2.2 A filter whose numbers are unknowns
A convolution layer, then, is Chapter 1’s operation with the kernel entries left blank. Sobel’s \([-1, 0, 1]\) columns were an argument about derivatives; the Gaussian’s weights follow from a formula; MR8’s bank was a design. Here the kernel starts as small random numbers and ends wherever training puts it. The habit the kernel zoo taught still applies: read the numbers and you know the filter. Only their source has changed.
Figure 2.4 shows the same thing at its smallest possible scale: nine numbers and one question. The task is the easiest one that still needs a filter: is the bar in this image vertical or horizontal? The only instruction the kernel ever receives is whether the answer came out right. Before running it, write down the nine numbers you would use, then compare them with where training arrives. A positive column with negative flanks is the bar detector of Section 1.7, reached by gradient descent rather than by construction. It is worth pressing new random start a few times: the run that ends with its positive column on the left and the run that ends with it on the right are the same filter twice, and neither was the one anybody had in mind.
One piece of fine print from Chapter 1 settles itself here. The “convolutions” in deep learning are correlations, with no kernel flip, and here the distinction stops mattering: a learned kernel has no prior orientation to preserve. If the flipped version were useful, training would learn it in that form.
2.2.3 The kernel is a volume
Chapter 1 convolved one grayscale image with one flat kernel. CNNs usually move beyond that setup immediately: a layer applies multiple filters and produces multiple feature maps, so subsequent filters must operate across channels. This is where the shapes change.
Unless stated otherwise, this chapter uses dense convolution, in which every filter reads every input channel. For a colour input, a \(3 \times 3\) filter therefore has size \(3 \times 3 \times 3\): nine weights for red, nine for green, and nine for blue. At each position, the products are summed across space and channels to produce one number. Sliding the filter produces one two-dimensional feature map. Grouped and depthwise convolutions, introduced below, relax the requirement that every filter read every channel.
One filter produces one feature map. A layer stacks the maps from \(C_{\text{out}}\) filters into an output volume with \(C_{\text{out}}\) channels. In the next dense convolution, each filter has \(C_{\text{out}}\) input channels. Its depth therefore matches the number of maps produced by the preceding layer. Figure 2.5 shows one step.
The parameter count follows directly. A layer with \(C_{\text{out}}\) filters of size \(k \times k \times C_{\text{in}}\), each with a bias, holds
\[ k \cdot k \cdot C_{\text{in}} \cdot C_{\text{out}} + C_{\text{out}} \]
parameters. AlexNet’s first layer has 96 filters of \(11 \times 11 \times 3\), so \(11 \cdot 11 \cdot 3 \cdot 96 + 96 = 34{,}944\) parameters. The formula does not contain the image height or width, so the number of learned parameters is the same for a thumbnail and a larger image. The computational cost is not: the filter is evaluated at more positions, so multiply-adds and activation memory grow with the output’s spatial dimensions. In parameter counts, the main term is \(k^2 C_{\text{in}} C_{\text{out}}\), and the product \(C_{\text{in}} C_{\text{out}}\) often dominates once the kernel size is fixed.
Interactive: the kernel with depth
One \(3 \times 3 \times 3\) kernel, one small three-channel input, one step at a time. Before pressing anything: the kernel holds 27 weights and the input is \(5 \times 5 \times 3\), so how many numbers land in the output map? Step through a position and watch the three per-channel products collapse into one, then add the second filter and see where its map goes.
2.2.4 Bias and nonlinearity
Two small additions complete the layer used here. Each filter has a bias, one number added to every position of its map; that is the \(+\,C_{\text{out}}\) in the parameter formula. The biased map then passes through a nonlinearity \(f\), applied to each value independently. Written out, filter \(c\)’s output map is
\[ A_c \;=\; f\bigl(I * K_c + b_c\bigr), \qquad c = 1, \dots, C_{\text{out}}: \]
the convolution of Chapter 1, one number added everywhere, one function applied everywhere. A common choice of \(f\) is the ReLU (rectified linear unit), \(f(v) = \max(0, v)\). Negative responses become zero; positive ones pass unchanged. Earlier networks used smooth S-shaped functions: the sigmoid, and its zero-centred cousin tanh. The reason ReLU displaced them is discussed in Chapter 3. For now it is enough that ReLU is cheap and does not flatten out for large positive inputs. Figure 2.6 draws the three side by side.
A convolution followed by a bias is an affine operation. A stack of affine convolutional layers with no nonlinearities can be represented by one affine convolution with a larger effective kernel, subject to the same boundary conventions. Extra layers change the parameterisation but do not make the overall function nonlinear. ReLU prevents this collapse: compositions of convolution and ReLU can represent functions that no single convolution can.
2.2.5 The 1×1 convolution
Set \(k = 1\) in the formula and something useful remains. A \(1 \times 1\) convolution has no spatial window, seeing one position at a time, but it still spans all \(C_{\text{in}}\) channels: each filter is a weighted sum across the channels at a point. It is pure channel mixing, with \(C_{\text{in}} \cdot C_{\text{out}} + C_{\text{out}}\) parameters.
You have used one. The grayscale conversion of Section 1.1.4, \(Y = 0.299R + 0.587G + 0.114B\), is a \(1 \times 1 \times 3\) convolution with one filter, the dot product that section flagged with fixed, for now. Now it is neither fixed nor limited to one output: a \(1 \times 1\) layer re-mixes 256 channels into 64, or 64 into 256, wherever a network needs its channel count changed cheaply. That re-mixing is how GoogLeNet and ResNet hold down their parameter counts and multiply-adds (Chapter 3), and it is half of the separable convolution below. Figure 2.7 draws its shape.
2.3 Pooling, stride, and receptive fields
2.3.1 Shrinking the map
Section 1.5 put the problem plainly: a \(3 \times 3\) kernel sees three pixels across, objects live at every scale, and the answer there was to shrink the image rather than grow the kernel. A CNN faces a related problem: later units need to combine information over wider regions without applying large kernels at full resolution. Pooling and strided convolution shrink intermediate feature maps, allowing receptive fields to grow more quickly while reducing computation.
There are two common ways. Pooling summarises each small window of a map and has no parameters; the usual summary is the maximum of a \(2 \times 2\) window taken with stride 2 (max pooling), sometimes the average. Strided convolution folds the shrinking into the layer itself: a stride of 2 computes every second position, typically reducing each spatial dimension by about half while it filters. The exact output size also depends on the input size, kernel, and padding, as the output-size formula of Chapter 1 describes. That formula, and the padding bookkeeping around it, apply here unchanged; exercise 4 of Chapter 1 was practice at this arithmetic. Figure 2.8 shows the operation at its smallest, and Figure 2.9 runs the stride itself.
2.3.2 Pooling and translation tolerance
A stride-1 convolution is translation equivariant away from padding and boundaries: shifting the input shifts its feature map. Strided pooling changes that relationship. Its windows are fixed to a sampling grid, so shifting the input by one pixel can move responses between windows and change the pooled values.
Max pooling can nevertheless provide limited translation tolerance. If a strong response moves but remains the maximum within the same pooling window, that pooled value does not change. This depends on the input and the position of the pooling grid; it is not a general invariance guarantee. A shift equal to the pooling stride instead shifts the pooled map by one cell, apart from boundary effects. Repeated downsampling discards spatial precision, which may help classification but is costly for tasks whose output must retain location. Figure 2.10 demonstrates these cases for one feature map.
2.3.3 Receptive fields
A unit in the first layer sees a \(3 \times 3\) patch of the image. A unit in the second layer sees a \(3 \times 3\) patch of feature maps, each position of which already summarises a patch of the image, so its window on the original is wider. Figure 2.11 traces one unit down the stack: it reads nine values, each of those values read nine pixels, and the union of their windows is \(5 \times 5\).
Track the receptive-field size \(R_\ell\) and the jump \(J_\ell\), the distance between neighbouring units measured on the original input. Before the first layer, \(R_0 = J_0 = 1\). For layer \(\ell\), with kernel size \(k_\ell\) and stride \(s_\ell\),
\[ R_\ell = R_{\ell-1} + (k_\ell - 1)J_{\ell-1}, \qquad J_\ell = s_\ell J_{\ell-1}. \]
Both calculations use the values entering the layer. In particular, the kernel samples positions in the preceding map, so receptive-field growth depends on \(J_{\ell-1}\); the new jump \(J_\ell\) applies to the next layer.
For the stack conv \(3 \times 3\), pool \(2 \times 2\)/2, conv \(3 \times 3\), pool \(2 \times 2\)/2, conv \(3 \times 3\), the receptive fields grow through \(3, 4, 8, 10,\) and \(18\) pixels. Applying the same calculation to AlexNet gives a \(163 \times 163\) theoretical receptive field at conv5. Depth is how a \(3 \times 3\) kernel comes to see a dog. Stacking gives later units access to progressively wider regions, while downsampling produces coarser feature maps. This resembles the image pyramid of Section 1.5, but the two are not equivalent: pyramid levels are rescaled versions of an image, whereas CNN layers contain different learned representations. A wider receptive field supplies context; it does not make a standard CNN scale invariant.
The arithmetic gives the field’s outer boundary. Influence within it is not uniform: it falls off roughly as a Gaussian from the centre, so the effective receptive field is considerably smaller than the box [6].
Interactive: receptive fields
Build a stack, then click a unit in its top map. Before clicking, predict the field’s size from the layer list alone; the running arithmetic is displayed, so you can check yourself layer by layer. Then find the cheapest stack whose top units see the whole image, and say whether an extra convolution or an extra pool got you there for fewer parameters. Switching responses on fills the map with a live response from one fixed edge filter standing in for a learned one, and each added stride visibly coarsens it.
2.4 The convolution zoo
Chapter 1’s kernel zoo varied the numbers inside the kernel. This zoo varies the wiring around it. Each variant answers one question about the dense convolution, each is a small change to the arithmetic already on the table, and each is put to work in a named later chapter.
2.4.1 Dilated: a wider view without more weights
A dilated convolution spaces the weights of a \(k \times k\) kernel \(r\) pixels apart. Its effective size is
\[ k^{\prime} = k + (k-1)(r-1). \]
A \(3 \times 3\) kernel therefore covers a \(5 \times 5\) footprint at rate 2 and a \(9 \times 9\) footprint at rate 4, without adding parameters. With stride 1 and suitable padding, dilation enlarges the receptive field without reducing the map resolution. Rates \(1, 2, 4, \ldots\) make the receptive field grow exponentially with depth. This is useful for dense prediction, where the network needs wide context without further downsampling (Chapter 6). Figure 2.12 shows the spacing.
Interactive: dilation arithmetic
The bookkeeping is easier to watch than to read [7]. The widget opens in dilated mode: set the rate, predict the output size with \(k'\) in place of \(k\), then step through and check. Its other modes replay the ordinary arithmetic of Chapter 1 and preview the transposed entry below.
2.4.2 Transposed: getting the resolution back
A strided convolution maps a large grid to a smaller one. A transposed convolution reverses the direction of its connections. Each input value is multiplied by every kernel weight, producing a \(k \times k\) patch that is added to a larger output. The stride sets the spacing between these patches, and overlapping contributions are summed. Its weights are learned like those of any other layer.
The name transposed is literal, and it is the clearest way to see what the operation is. After flattening the arrays, a convolution can be written as \(y = Cx\), where \(C\) is a sparse matrix containing copies of the kernel. A transposed convolution applies \(C^{\mathsf{T}}\). In Figure 2.13 it maps four values to sixteen; it is the transpose of the linear map, not its inverse, and it does not reconstruct the original input.
Figure 2.13 uses a particular kernel, and three of its nine weights happen to be zero, which hides part of the pattern. Figure 2.14 draws the same two matrices with the weights left as symbols \(w_{ij}\), so that every slot a weight occupies is visible.
Figure 2.15 runs the arithmetic on real numbers, and shows the second way of computing the same output.
For the stride and padding shown, inserting \(s - 1\) zeros between input samples and applying a stride-1 convolution with the corresponding padding gives the same result. The kernel is rotated \(180°\) when the forward operation is implemented as correlation. This construction motivates the name fractionally strided convolution.
It is sometimes called a “deconvolution”, which it is not: nothing is undone, and the operation is convolution’s shape-transpose. When the kernel size is not divisible by the stride, the patches overlap unevenly, creating a built-in source of checkerboard artefacts [8]. Choosing a divisible kernel size removes this uneven-overlap mechanism, but does not guarantee an artefact-free output. It returns in Chapter 6, where a network that has shrunk its maps must produce a full-resolution answer; the decoder half of U-Net is built from these. Figure 2.16 counts the deposits, and Figure 2.17 shows them surviving all the way into a trained generator’s pictures.
2.4.3 Grouped: cut the channel product
The main term in the parameter count, \(k^2 C_{\text{in}} C_{\text{out}}\), is proportional to the product of the two channel counts, and that product can be cut directly. A grouped convolution splits the channels into \(g\) groups and convolves each group separately: each filter sees only \(C_{\text{in}}/g\) channels, and the parameter count divides by \(g\). The cost is that no information passes between the groups inside the layer.
The variant is as old as the revival: AlexNet was grouped out of necessity, its 96 filters split across two 3 GB GPUs that exchanged data only at certain layers. In the original network the two halves specialised, one towards grayscale structure and one towards colour [1]. What began as a hardware workaround returned as a design principle (ResNeXt, [9]). Figure 2.18 compares the wiring, and Figure 2.19 shows the specialisation in a network trained the same way.
2.4.4 Separable: factor the kernel
A dense filter’s \(k \cdot k \cdot C_{\text{in}}\) weights do two jobs at once, filtering across space and mixing the channels. A depthwise separable convolution factors a dense convolution into two operations, one for each job. This is analogous to Gaussian separability, but it separates spatial filtering from channel mixing rather than horizontal filtering from vertical filtering. First, a depthwise step applies a \(k \times k\) filter to each input channel independently, and a different filter to each: \(C_{\text{in}}\) kernels of \(k^2\) weights, not one kernel reused. A pointwise \(1 \times 1\) convolution then mixes those \(C_{\text{in}}\) filtered maps to produce \(C_{\text{out}}\) output channels, using a different set of mixing weights for each one. Ignoring biases, the parameter count falls from
\[ k^2 C_{\text{in}}C_{\text{out}} \]
to
\[ k^2 C_{\text{in}} + C_{\text{in}}C_{\text{out}}. \]
For a \(3 \times 3\), 256-to-256 convolution, that is an 8.7× reduction in parameters. MobileNet uses these blocks through most of its convolutional body (Chapter 3). Figure 2.20 shows the factorisation.
Where the saving comes from is worth being precise about, because it is not in the depthwise step. Compare the two counts as \(C_{\text{out}}\) grows: the dense count \(k^2 C_{\text{in}} C_{\text{out}}\) scales with it, while in the separable count only the second term does, since the \(k^2 C_{\text{in}}\) spatial weights are the same whatever \(C_{\text{out}}\) is. The ratio is \(k^2 C_{\text{out}} / (k^2 + C_{\text{out}})\), which for \(k = 3\) is 0.9 at one output channel, 1.6 at two, 4.2 at eight, and approaches \(k^2 = 9\) from below. At \(C_{\text{out}} = 1\) the factorisation therefore costs slightly more than the dense convolution it replaces, and the two are doing much the same work. The saving appears only because a dense layer refilters the input spatially for every output channel it produces, and this one filters once and then mixes those results \(C_{\text{out}}\) different ways.
2.5 The network
2.5.1 The template
Most image classifiers of the decade after 2012 follow one template:
\[ \text{image} \;\to\; \bigl[[\text{conv} \to \text{ReLU}] \times M \to \text{downsample}\bigr] \times N \;\to\; \text{head}. \]
A few convolutions operate at one resolution, followed by downsampling. Height and width typically halve while the channel count doubles. Halving both spatial dimensions quarters the number of output positions. If both \(C_{\text{in}}\) and \(C_{\text{out}}\) double in the following block, its parameter count increases fourfold, but its number of multiply-adds remains roughly unchanged because the convolutions run at one quarter of the spatial positions. Later blocks can therefore use more channels at similar computational cost, though their parameter count is larger.
The first convolutional block plays the role of a learned filter bank. Intermediate layers produce learned descriptors, and the head classifies them. This resembles the stages of Chapter 1, but the correspondence is not layer for layer.
2.5.2 Two worked examples: a modernised LeNet-5 and AlexNet
Figure 2.21 compares a modernised LeNet-5-style network with AlexNet, with every shape and parameter count computed from the formulas of this chapter.
A modernised LeNet-5-style network [4] reads \(32 \times 32\) digits. A \(5 \times 5\) convolution produces 6 maps of \(28 \times 28\) (156 parameters), followed by pooling to \(14 \times 14\). A second \(5 \times 5\) convolution produces 16 maps of \(10 \times 10\) (2,416 parameters), followed by pooling to \(5 \times 5\). A final \(5 \times 5\) convolution produces 120 maps of \(1 \times 1\) (48,120 parameters), followed by dense layers of 84 and 10 units (10,164 and 850 parameters). The total is 61,706.1
AlexNet [1] has five convolutional layers with 96, 256, 384, 384, and 256 filters; three max pools; and dense layers of 4096, 4096, and 1000 units. The version diagrammed here takes a \(224 \times 224\) input and uses padding 2 in its first \(11 \times 11\), stride-4 convolution, producing a \(55 \times 55\) map. Without that padding, a \(227 \times 227\) input would be required to produce the same shape. Three of its convolutions are grouped with \(g = 2\), as the original two-GPU network had them, so the convolutional stack holds 2.3 million parameters rather than the 3.7 million a fully dense stack would need. The dense layers hold 58.6 million, so 96% of the 61.0 million parameters are in the head.
2.5.3 The head
The convolutional stack ends with a volume; the task needs one number per class. The head is whatever converts one into the other, and the classical choice is to flatten the volume into a vector and follow it with dense layers. That choice is expensive. AlexNet’s final \(6 \times 6 \times 256\) volume flattens to 9,216 numbers, and connecting those to 4,096 dense units costs 37.8 million parameters in a single layer. Two more dense layers follow, and the three together hold 58.6 million of the network’s 61 million: the head carries 96% of the parameters, and the convolutional stack that does the seeing carries 4%. A dense layer’s count depends on the spatial size of its input, so the height-and-width independence that made the convolutional layers cheap does not apply here. Figure 2.22 draws the head and where its weights sit.
Global average pooling [10] replaces each channel of the final volume with its mean. An \(H \times W \times 256\) volume therefore becomes 256 numbers, with no learned parameters, before a dense layer maps them to the classes. Averaging discards the spatial arrangement and retains the mean response of each channel. If the preceding feature maps are translation equivariant, this converts translation equivariance into invariance. In a finite CNN, padding, strides, aliasing, and boundary effects make that invariance approximate. Because global average pooling accepts any spatial map size, a fully convolutional body can accept variable input resolutions above the minimum imposed by its kernels and downsampling layers. Figure 2.23 shows the operation.
A dense layer applied to a \(6 \times 6 \times 256\) volume is a \(6 \times 6\) convolution with 4096 filters, and the parameter formula gives the same count either way. Read like that, the whole classifier is convolutions, and nothing stops it sliding: feed a larger image and the “classifier” produces its answer at every position, a map of dog-here. Detection and segmentation in Part II are built on that.
Interactive: count a network’s parameters
The two formulas of this chapter, applied to real networks. Open AlexNet and predict which row holds most of its 61 million parameters, then check against the gold row, which marks the most expensive. Then check the modernised LeNet-5: does the same imbalance hold at a thousandth of the size? Build your own stack and see what one dense layer does to the total.
2.5.4 Feature hierarchies
The first layer can be printed because its kernels have three channels, and three channels render as colour. That is the only reason Figure 2.2 could exist. A third-layer kernel is \(3 \times 3 \times 256\); there is nothing to print. Seeing what deep layers learned takes indirection: find the image patches that most excite a unit, or trace a response back to the pixels that produced it [11].
Many CNN classifiers develop a loose hierarchy of features [11]. First-layer filters often respond to edges and colour contrasts. Intermediate layers combine these responses into textures and parts, while later layers tend to be more task-specific and operate over wider receptive fields. The pattern depends on the architecture, dataset, and training objective, and not every channel has a simple semantic interpretation. Stacking the same type of learned layer allows the network to build these combinations without designing a new descriptor at each level, although additional layers still cost parameters and computation.
Figure 2.24 shows the hierarchy in the trained lab network, on the book’s scene.
2.6 Training
One question remains: where do the numbers come from? A trained AlexNet holds 61 million parameters, none of them set by hand. Three pieces fit them: a loss to say how wrong the network is, a gradient to say which way each parameter should move, and an optimiser to take the steps.
2.6.1 The loss
The network’s final layer produces one raw score per class, written \(z_c\) and called a logit. The softmax turns those scores into probabilities by exponentiating each, giving \(e^{z_c}\), and normalising by their sum:
\[ p_c = \frac{e^{z_c}}{\sum_j e^{z_j}}, \]
positive and summing to one. Training data supplies the true class, and the cross-entropy loss scores the network by the probability it gave that class: \(L = -\log p_{\text{true}}\). Confidently right costs nearly nothing; confidently wrong is punished without bound. A three-class example: logits \((2.0, -1.0, 0.5)\) give probabilities \((0.786, 0.039, 0.175)\). If the first class is true, \(L = -\log 0.786 = 0.24\); if the second, \(L = -\log 0.039 = 3.24\). One number says not just wrong but how confidently wrong.
Why not something simpler, like squared error against a one-hot target? Because its gradient, worked through the softmax, shrinks precisely when the network is most confidently wrong: the saturated cases that most need correcting are the ones squared error corrects most weakly. Cross-entropy’s gradient through the softmax is plain \(p - y\), large whenever the error is large. The loss is chosen for the gradient it sends backwards. Figure 2.25 draws the whole curve, with the two worked values on it.
2.6.2 Gradient descent, in batches
The loss is a single number depending on millions of parameters. The method is gradient descent: compute the gradient of the loss with respect to every parameter, and step each one a little downhill, \(\theta \leftarrow \theta - \eta \, \nabla_\theta L\). Computing the true gradient would mean the whole training set per step, so in practice each step uses a minibatch of, say, 128 images as a noisy estimate; one pass over the training set is an epoch. The noise is tolerable, and the saving in computation per step is what makes training feasible. This is stochastic gradient descent (SGD).
The step size \(\eta\) is the learning rate. If it is too small, optimisation proceeds slowly; if it is too large, updates can overshoot low-loss regions and the loss may oscillate or diverge. Momentum maintains an exponentially weighted sum of recent gradients and uses it to smooth the updates. Adam maintains running estimates of the gradients and their squares, using them to adapt the update for each parameter [12]. The lab uses Adam, but no optimiser removes the need to choose a suitable learning rate. Their relative performance depends on the model, data, and training setup. Many training runs reduce the learning rate over time, using a step schedule or cosine decay. Figure 2.26 shows the effects of three fixed learning rates.
2.6.3 Backpropagation
What remains is the gradient itself: the loss’s derivative with respect to every one of 61 million parameters, cheaply. The network is a chain of simple stages, so the chain rule applies stage by stage. Starting from the loss, each layer takes the gradient arriving at its output and produces two things: the gradient for its own weights, and the gradient at its input, which it hands to the layer below. One forward pass computes the network output, and one backward sweep computes every gradient. This is backpropagation. It is the same order of cost as the forward pass, but usually requires more arithmetic; for dense and convolutional layers, the backward computation is commonly about twice the forward computation. Figure 2.27 shows the two passes.
During backpropagation through a convolution, the layer computes two derivatives. The gradient with respect to its input, \(\partial L / \partial x\), applies the transpose of the forward operator and is passed to the preceding layer. The gradient with respect to its kernel weights, \(\partial L / \partial W\), correlates the stored input with the gradient arriving at the layer’s output. The optimiser uses this second gradient to update the weights.
PyTorch’s autograd records the forward operations and computes their gradients during the backward pass. Before a full training run, overfit a single batch: disable data augmentation and regularisation, then train repeatedly on one fixed batch. This checks that the model can memorise the examples and that the data, model, loss, and optimiser are connected correctly. The network should reach 100% accuracy and a very small loss on the batch. If it cannot, fix that problem before training on the full dataset.
2.6.4 Initialisation
Biases can be initialised to zero, but the filters in a layer must not all start with identical weights. Identical filters receive identical gradients and remain identical during training, so their weights are initialised randomly. The scale also matters. If it is too small, activations and gradients shrink through the network; if it is too large, they can grow until training becomes numerically unstable. ReLU does not saturate for positive inputs, but it does not prevent this growth. He initialisation [13] uses zero-mean weights with variance
\[ \frac{2}{k^2 C_{\text{in}}} \]
for a convolutional ReLU layer. This keeps the activation scale approximately stable at the start of training. Figure 2.28 shows the effect through a 40-layer stack.
2.6.5 Regularisation
A model is overfitting when its training performance continues to improve while its validation performance stalls or worsens. Common countermeasures include weight decay, dropout, early stopping, and data augmentation. AlexNet used weight decay, dropout, and data augmentation [1].
Weight decay penalises large weights, commonly by adding a term proportional to \(\lVert \theta \rVert^2\) to the loss. With ordinary SGD, this pulls each weight towards zero on every update.
Dropout [15] sets activations to zero independently with probability \(p\) during training. In PyTorch’s inverted-dropout convention, the retained activations are divided by \(1-p\) during training, so evaluation requires no rescaling.
Early stopping retains the parameters from the epoch with the best validation performance. It limits how long the model can adapt to details specific to the training set.
Data augmentation trains on transformed examples that retain the same label, such as flips, crops, and small colour changes. It encourages the network to produce similar outputs for those transformations, but does not create exact invariance. A standard CNN has no built-in equivariance to rotation, scale, or changes in illumination, while its translation equivariance is limited by padding, strides, and boundaries, as discussed above. The lab uses random flips and crops; augmentation pipelines receive fuller treatment in the next chapter. Figure 2.29 shows examples.
2.6.6 Reading the curves
Training and validation curves provide symptoms, not unique diagnoses. Figure 2.30 shows four controlled runs of the same network. In the healthy run, both accuracies rise with a modest gap. In the overfitting run, training accuracy reaches 100% while validation accuracy stalls. The low-learning-rate run improves slowly, while the high-learning-rate run remains near chance. Other faults can produce similar curves, so diagnose them by checking the configuration and changing one factor at a time.
The filters change over those same epochs. Figure 2.31 prints the first layer at initialisation and after 1, 5, 20, and 40 epochs: random static organising itself, epoch by epoch, into oriented edges and colour contrasts.
Interactive: train one yourself
A small CNN, a small digit set, training live. Set the learning rate an order of magnitude too high, predict which curve shape from Figure 2.30 you will get, and run it; then find the largest rate that still trains cleanly. The first-layer filters update as it runs; note the epoch at which structure first appears.
2.7 The learned filter bank
Figure 2.2 can now be read as a learned filter bank. Its \(11 \times 11 \times 3\) kernels can be displayed directly because the input has three colour channels. Their Gabor-like patterns emerged from random initial weights under the classification loss. A CNN does not explicitly learn a Gaussian \(\sigma\), a Sobel kernel, or the members of an MR8 bank. It learns unconstrained kernels and intermediate representations jointly with the classifier. Some first-layer kernels resemble classical filters because edges, colour contrasts, and oriented patterns are useful for the task.
The deeper layers are the part with no Chapter 1 counterpart at all: nothing in the design says what layer five should compute. A loss at the top and a gradient path to the bottom were enough.
One fact about these filters is left unexplained. They were fitted to a single dataset and a single task: 1.2 million photographs, 1,000 nouns. Yet the first layers keep rediscovering Gabor filters, which were designed with no dataset at all. How much of what this network learned is about ImageNet, and how much is about images? Chapter 3 takes that question up directly.
Exercises
- Reading learned filters. Pick four filters from Figure 2.2: one oriented achromatic filter, one colour-opponent filter, and two of your choice. For each, say what image structure maximises its response, and name its nearest relative in the MR8 bank, or state that it has none, and why.
- Parameter counting. A network for \(32 \times 32 \times 3\) inputs: conv \(3 \times 3\), 32 filters; conv \(3 \times 3\), 32 filters; max pool 2; conv \(3 \times 3\), 64 filters; conv \(1 \times 1\), 16 filters; global average pool; dense to 10 classes. Count the parameters of every layer, then count a single dense layer from the flattened input to 10 classes, and compare.
- Receptive fields. For the stack conv \(5 \times 5\)/1, pool \(2 \times 2\)/2, conv \(3 \times 3\)/1, conv \(3 \times 3\)/1, pool \(2 \times 2\)/2, conv \(3 \times 3\)/1, compute the receptive field and jump after every layer. A pedestrian is 96 pixels tall. Assume the final feature map has 64 channels. Without adding further downsampling, extend the stack using \(3 \times 3\), stride-1 convolutions that map 64 channels to 64 channels and include a bias. How many layers are required for one top-layer unit to see all 96 pixels, and how many parameters do they add?
- Choosing from the zoo. For each requirement, name the variant and show the arithmetic, ignoring biases throughout: (a) an output map at twice the input resolution; (b) a \(9 \times 9\) receptive field from nine weights; (c) the parameter count of a \(3 \times 3\), 256-to-256 layer cut by a factor of four, accepting the loss of channel mixing across groups of 64; (d) the same layer cut roughly ninefold, channel mixing preserved.
- Shapes through a modernised LeNet-5. Reproduce the modernised LeNet-5 table of Figure 2.21 from the two formulas alone: every output shape and every parameter count, given only the layer specifications in the text.
- One step, by hand. Logits \((1.0, 3.0)\), true class 1 (the first). Compute the softmax, the cross-entropy loss, and the gradient \(p - y\) at the logits. Then, for a 1-D convolution with kernel \([w_1, w_2]\) on input \([x_1, x_2, x_3]\), write the two outputs, and use the chain rule to express \(\partial L / \partial w_1\) in terms of the output gradients.
- Diagnosis. Four runs are described: (a) training accuracy 99%, validation 62%; (b) both accuracies at 10% after twenty epochs, loss unchanged from its initial value; (c) both curves improving smoothly, training a steady 3% ahead; (d) loss alternating between 1.2 and 6.0 from epoch to epoch. Diagnose each and propose the single change you would try first.
- The audit, rerun. Rerun the invariance audit for a CNN. First assess the exact architectural properties of: a stride-1 convolutional stack; the stack after pooling or strided convolution; and the network after global average pooling. Account for padding, boundaries, and aliasing. Then consider a network trained with flip-and-crop augmentation: which transformations should it become more robust to, and does the augmentation provide an exact guarantee? Consider translation, rotation, uniform scaling, and horizontal reflection.
Lab 2
Lab 2: a small CNN on CIFAR-10 from scratch; compare to an MLP; visualise the learned first-layer filters next to Chapter 1’s Gabor bank. W&B logging from the first run; seed everything; overfit a single batch before training for real.
Further reading
- LeCun et al. [4] — LeNet-5, and a strikingly complete statement of the whole programme, fourteen years early.
- Krizhevsky, Sutskever, and Hinton [1] — AlexNet; short, readable, and the origin of half this chapter’s numbers.
- Zeiler and Fergus [11] — what the layers learn, and how anyone found out.
- Dumoulin and Visin [7] — the convolution-arithmetic reference the zoo widget animates.
- Zhang [5] — the aliasing callout, taken seriously and fixed.
- Goodfellow, Bengio, and Courville [16], chapter 9 — the formal treatment of everything here; free online.
References
The published LeNet-5 has 60,000 trainable parameters. Its C3 layer is sparsely connected, its subsampling layers have trainable scales and biases, and its output uses fixed radial-basis-function prototypes. The version counted here uses full channel connectivity, parameter-free pooling, and a learned affine output layer.↩︎