Deep Residual Learning for Image Recognition (ResNet)
Make each block learn a correction to its input, not a whole new function. With that change, a 152-layer network trains more easily than a 34-layer one used to.
Start here (no maths needed)
Very deep networks used to get worse when you added more layers, until ResNet gave every few layers a shortcut so they only had to learn small fixes.
Think of it like this
Imagine passing a drawing down a line of 100 classmates, where each person redraws it from scratch. By the end it looks nothing like the original. Now change the rule: each person gets the drawing itself and only adds small touch-ups. After 100 people the drawing is still recognisable, and better. ResNet uses that second rule.
How it works
- The picture goes into a block of layers.
- The block works out a small change, a "correction".
- A shortcut carries the block's input straight past it, unchanged.
- The input and the correction are added together and passed to the next block.
- If a block has nothing useful to add, it can learn to add almost nothing. So extra blocks don't make things worse.
Why robots care
Many robots that learn by copying people (for example, learning to fold a towel from demonstrations) use a small ResNet to understand their camera images. The same idea also works for control: keep a robot controller that already works, and only learn a small correction on top of it.
Try it
- Play "telephone" with a sentence twice. The first time, each person whispers it from memory. The second time, each person can see the written sentence and only fixes one word. Which version arrives more correct?
- In the demo further down, move the Residual branch scale s slider. At 0 the input passes through untouched. Small values keep the signal close to the input for many layers. The plain stack (red line) scrambles it almost at once.
Words to know
- Layer
- One step of processing inside a neural network.
- Shortcut (skip connection)
- A path that carries the input past some layers without changing it.
- Residual
- The small change a block adds on top of its input.
- Deep network
- A network with many layers stacked on top of each other.
Going deeper: everything below is the full version, with some maths. On a first read, skim the headings and the "Why it matters for robotics" box, and come back for the rest later.
1. Summary
TL;DR
Stacking more layers onto a plain CNN made it worse, and not because of overfitting. Training error itself went up. In principle, the deeper net could copy the shallow one and set its extra layers to the identity, but SGD failed to find that solution. ResNet adds a shortcut around every few layers, so each block outputs F(x) + x. Doing nothing now just means pushing F towards zero. Residual nets of 50, 101 and 152 layers trained cleanly. An ensemble reached 3.57% top-5 error on the ImageNet test set and won ILSVRC 2015.
- The degradation problem: on ImageNet, plain-34 had higher error than plain-18 (28.54% vs 27.94% top-1). With shortcuts the order flipped: ResNet-34 scored 25.03% and ResNet-18 27.88%.
- Identity shortcuts are free. They add no parameters and almost no compute, so plain and residual nets can be compared fairly.
- Bottleneck blocks (1×1 → 3×3 → 1×1) keep very deep nets affordable. ResNet-152 needs 11.3 billion FLOPs, less than VGG-19's 19.6 billion.
- The features transfer. Swapping VGG-16 for ResNet-101 in Faster R-CNN gave a 28% relative gain on COCO detection.
- Not unlimited: a 1202-layer CIFAR net reached under 0.1% training error but tested worse than the 110-layer one. The authors blame overfitting.
2. The core idea
Call the mapping a few layers should learn H(x). Instead of fitting H directly, let the layers fit the residual F(x) = H(x) − x, and add the input back:
y = F(x, {W_i}) + x # identity shortcut
y = F(x, {W_i}) + W_s · x # projection shortcut, only when shapes change
F(x) = W_2 · σ(W_1 · x) # basic block (BN omitted); output is σ(y)
xis the block input andyits output. Both are feature maps of the same shape.Fis the residual branch: two 3×3 convs in ResNet-18/34, or a 1×1 → 3×3 → 1×1 bottleneck in ResNet-50/101/152. Each conv is followed by batch norm.σis ReLU. In this paper it is applied after the addition. Day 10 shows why moving it helps.W_sis a 1×1 conv that matches channels and stride when a stage changes resolution. The paper tests three options: zero-padding (A), projections only where needed (B) and projections everywhere (C). The differences were small, so it uses A or B.
The whole network is 3×3 convs in four stages (56, 28, 14 and 7 pixels wide). Channels double each time the resolution halves. It ends in global average pooling and a single 1000-way FC layer, with no big hidden FC layers like AlexNet's.
3. Deep dive
Why "learn the correction" is easier
Picture a good 18-layer net and add 16 layers. If the new layers computed the identity, the deeper net would be exactly as good. A stack of conv + ReLU layers with random weights is nowhere near the identity, though. It has to learn to pass its input through unchanged, and the experiments showed SGD doesn't manage it. With a shortcut, the identity is the default, reached when F = 0. Small weights are close to that already. The paper also measured the trained residual branches and found their responses generally small. The blocks really do act as small corrections.
Note what the paper does not claim. Its plain nets used batch norm, and the authors checked that gradients kept healthy norms. They argue that degradation is an optimisation problem, not vanishing gradients. The cleaner gradient story came a year later in Day 10.
Interactive: what a deep stack does to its input at initialisation
A 64-wide toy network with random He-initialised weights, before any training. The plot shows the cosine similarity between the input vector and the signal after each layer. Plain: x ← ReLU(W·x). Residual: x ← x + s·W₂·ReLU(W₁·x). The slider sets s, the scale of the residual branch.
A random plain layer scrambles its input at once, because a random matrix is nothing like the identity. Similarity falls below 0.2 after one layer. The residual stack drifts gradually instead. At s = 0.1 the similarity is still about 0.6 after 50 layers, and at s = 0 the stack is exactly the identity. Training then only has to learn useful edits to a signal that is already flowing. This is a toy without batch norm, so read it as intuition, not as a reproduction of the paper.
The bottleneck block
For ResNet-50 and deeper, each block is a 1×1 conv that cuts channels (say 256 → 64), a 3×3 conv at the reduced width, and a 1×1 conv back up to 256. The expensive 3×3 runs on a quarter of the channels. Identity shortcuts matter here: a projection on the 256-wide shortcut would roughly double the block's cost.
Limitations, and what came after
- The ReLU after the addition clips the shortcut signal. At around 1000 layers that hurts. Day 10 moves BN and ReLU inside the branch.
- Depth eventually overfits. The 1202-layer CIFAR net is the paper's own example.
- Batch norm dependence. BN behaves differently in training and at inference, and it struggles with tiny batches. The paper itself freezes BN statistics when fine-tuning for detection.
- The residual stream is everywhere now. Every Transformer layer (Day 13) is
x + Attention(x)thenx + MLP(x). Kimi K3's attention residuals in Module 05 revisit exactly this running sum, letting each layer pick a weighted mix of earlier layers instead of one fixed total.
4. Why it matters for robotics
- The default robot vision backbone. ResNet-18 and ResNet-50 are still the standard image encoders in imitation-learning policies (ACT and Diffusion Policy both use ResNet-18) and in pretrained visual representations for manipulation.
- Detection and segmentation heads sit on ResNet features. Grasp detection, bin picking and obstacle segmentation pipelines usually start from an ImageNet-pretrained ResNet trunk.
- Residual policy learning is the same idea in control. Keep a hand-tuned controller and learn only a correction
a = a_base + F(s), starting with F near zero. The robot begins at the baseline's behaviour, which is safer than starting from a random policy. Compare policy blending in Module 03. - Watch batch norm on robots. Small batches, frozen fine-tuning and train/test differences make BN fragile. Many robot policies swap it for GroupNorm or freeze its statistics.
- Depth is a latency choice. ResNet-18 at 1.8 GFLOPs versus ResNet-152 at 11.3 is a real control-loop trade-off on an embedded GPU. See Module 04.
5. How to study it
- Read the paper (about 1.5 h). Study Figure 1 (degradation), Figure 2 (the block), Table 1 (architectures) and Figure 4 (plain versus residual training curves).
- In the 30u30 Day 9 folder, read
implementation.py. Find the basic block, the bottleneck block and where the projection shortcut is used. Runtrain_minimal.py. - Work through
notebook.ipynb, then the exercises: build ResNet-18, ablate the skip connections, measure gradient flow, scale depth and try transfer learning. - Key experiment: train a plain and a residual net of the same depth (say 20 and 56 layers on CIFAR-10) and plot training error. You should see the degradation problem appear and disappear.
- Stretch: fine-tune a pretrained ResNet-18 on a small set of your own object images and time inference on the hardware you'd put on a robot.
6. Self-check
Why is the degradation problem not overfitting?
Overfitting means low training error and high test error. Here the deeper plain net had higher training error too. The optimiser failed to fit, even though a solution at least as good as the shallower net existed.
What does a residual block output when its weights are all zero?
Its input, up to the final ReLU. F(x) = 0, so y = x. The identity is the default behaviour.
When is a projection shortcut W_s needed?
When the block changes the number of channels or the spatial size, so x and F(x) can't be added directly. The paper uses a 1×1 conv with stride 2 at those points.
Why use 1×1 convs in the bottleneck block?
They shrink the channel count before the costly 3×3 conv and restore it afterwards. Depth grows while compute per block stays about the same.
Did the paper claim residuals fix vanishing gradients?
No. Its plain nets used batch norm and had healthy gradient norms. It frames the problem as optimisation difficulty and the residual form as a better starting point (preconditioning).
7. Further reading
- The original paper (arXiv, CVPR 2016)
- 30u30 Day 9: implementation, notebook, cheatsheet, exercises
- Next: Day 10, Identity Mappings in Deep Residual Networks