Residual Connections and ResNet
Imagine stacking convolutional layers to build a deeper network. The hope is that depth alone buys accuracy. In practice, past a certain depth, training and test error both get worse. This isn't from overfitting. It comes from a mysterious inability to even fit the training set well. This is the degradation problem. It stumped the field for years after AlexNet and Deep CNNs showed depth was valuable. A 56-layer plain CNN trained on CIFAR-10 achieves higher training error than its 20-layer counterpart. This happens even though the deeper network can, in principle, represent every function the shallow one can. You would just set the extra layers to identity. The fix, introduced by He, Zhang, Ren, and Sun in 2015, is deceptively simple. Let each block of layers learn a residual — the difference between its desired output and its input. Then add the input back via a skip connection. Instead of asking a stack of layers to learn a mapping directly, we ask it to learn . We reconstruct by literally wiring around the block. This one architectural change let networks scale from tens to over a thousand layers. They kept improving accuracy the whole time. It won ILSVRC 2015 by a wide margin. Residual connections matter far beyond image classification. They are now a default ingredient in almost every deep architecture. This includes every modern CNN backbone and every Transformer block (attention and feed-forward sublayers are both wrapped in residual connections). As this article foreshadows, the gating mechanisms in Recurrent Neural Networks that fight vanishing gradients across time are solving a structurally identical problem. Understanding residual connections is understanding why deep learning works at all once you go beyond a handful of layers. This article builds the idea precisely. It derives why it fixes vanishing/degrading gradients. It walks through the ResNet block and bottleneck designs with pseudocode and diagrams. It traces a concrete numeric example through a residual block. Finally, it surveys the classic mistakes and the history that produced this now-ubiquitous idea.
- Residual blocks compute instead of , letting layers learn a correction rather than a full transform.
- This solves the degradation problem: very deep plain networks get harder to optimize, not just prone to overfitting.
- The skip connection creates an identity gradient path, so always has a "+1" term that can't vanish.
- ResNet's basic block uses two 3×3 convolutions; its bottleneck block uses 1×1→3×3→1×1 convolutions for efficiency at scale.
- ResNets scaled cleanly to 152+ layers (and experimentally 1000+), winning ILSVRC 2015 classification, detection, and localization.
- The pattern generalizes: Transformers, RNW gating, and most modern architectures wrap sublayers in residual connections.
Instead of learning a full mapping, let a layer stack learn only the residual correction to its input, and add the input back — turning "does adding depth help?" from a hard optimization question into an easy one.
The idea
A plain deep network stacks layers so that the output of layer feeds directly into layer as , where bundles a convolution, normalization, and nonlinearity. As depth grows, two related pathologies appear. First, vanishing/exploding gradients: the chain rule multiplies many Jacobians together, and if their norms are consistently below or above 1, gradients shrink or blow up exponentially with depth. Batch normalization and careful initialization mitigate this but do not eliminate it for very deep stacks. Second, and more surprising, is the degradation problem: even when gradients are numerically healthy, plain networks beyond roughly 20–30 layers become harder to optimize in a way that is not explained by overfitting — the training error itself rises with added depth. This is puzzling because a deeper network can always simulate a shallower one: take the shallow network's layers, then append extra layers that compute the identity function. The composed function loses nothing. So the optimal solution for the deep network is at least as good as the shallow one. The empirical fact that solvers fail to find even this trivial identity solution is the real diagnosis: it is hard for a stack of nonlinear layers to learn an identity mapping, because that requires precisely tuned weights (e.g., driving convolution kernels toward a Dirac-delta-like configuration) rather than the generic small-random-weight regime that gradient descent naturally explores. A residual block reparametrizes the problem. Instead of asking a block to learn the mapping directly, define
where is the residual function — typically two or three weight layers — and the raw input is added back via an identity shortcut (also called a skip connection). If the optimal underlying mapping really is close to the identity, the block only needs to drive , which is easy: push weights toward zero, a direction gradient descent is very good at finding. The reformulation does not change the hypothesis space — any expressible by a plain block is still expressible as with — but it changes the optimization landscape dramatically, biasing the default (near-zero-weight) behavior toward identity rather than toward an arbitrary, hard-to-discover function.
How it works
The basic residual block. For feature maps with matching shape, the canonical two-layer block is:
Two 3×3 convolutions, each followed by batch normalization, with a ReLU after the first conv and a second ReLU applied after the addition. The shortcut adds the raw (or projected) input to the output of the second BN, before the final activation.
Handling shape mismatches. A skip connection requires and to have the same shape. Two situations break this: 1. Channel count changes (e.g., 64 → 128 channels between stages). 2. Spatial downsampling (e.g., stride-2 convolution halves height/width). ResNet handles both with a projection shortcut: a 1×1 convolution with the matching stride and output channels, applied to before addition:
When shapes already match, is simply the identity (no extra parameters) — this is the default, cheaper option, reserved for the first block of each new stage where dimensions change.
The bottleneck block. For deeper variants (ResNet-50/101/152), a three-layer bottleneck design keeps computation tractable: a 1×1 convolution reduces channels (e.g., 256 → 64), a 3×3 convolution operates on the reduced representation, and a final 1×1 convolution restores the channel count (64 → 256). The identity shortcut connects across all three layers. This design has roughly the same time complexity as the two-layer block on wide feature maps but far fewer parameters, because the expensive 3×3 convolution operates on a narrow (bottlenecked) representation.
Stacking into stages. A full ResNet is organized into stages, each stage repeating a residual block a fixed number of times at a constant resolution and channel width; resolution is halved and channels doubled between stages (typically via a strided 1×1 projection in the first block of the new stage), mirroring the pattern from LeNet and the CNN Blueprint of alternating feature extraction with downsampling, but replacing each "layer" with a residual block. ```
# Residual block (basic, 2-layer variant) function ResidualBlock(x, W1, W2, stride, W_shortcut=None):
# Main path h = Conv3x3(x, W1, stride=stride) h = BatchNorm(h) h = ReLU(h) h = Conv3x3(h, W2, stride=1) h = BatchNorm(h)
# Shortcut path if W_shortcut is not None: # shape changes: project shortcut = Conv1x1(x, W_shortcut, stride=stride) shortcut = BatchNorm(shortcut) else: # shapes match: identity shortcut = x out = h + shortcut # element-wise add out = ReLU(out) return out
# Bottleneck block (3-layer variant, used in ResNet-50/101/152) function BottleneckBlock(x, W1, W2, W3, stride, W_shortcut=None): h = Conv1x1(x, W1, stride=1) # channel reduction, e.g. 256 -> 64 h = BatchNorm(h); h = ReLU(h) h = Conv3x3(h, W2, stride=stride) # spatial work on reduced channels h = BatchNorm(h); h = ReLU(h) h = Conv1x1(h, W3, stride=1) # channel expansion, e.g. 64 -> 256 h = BatchNorm(h) if W_shortcut is not None: shortcut = Conv1x1(x, W_shortcut, stride=stride) shortcut = BatchNorm(shortcut) else: shortcut = x out = ReLU(h + shortcut) return out
# Full network: stem + stages of blocks + head function ResNet(image, params): x = Conv7x7(image, stride=2); x = BatchNorm(x); x = ReLU(x) x = MaxPool3x3(x, stride=2) for stage in [1, 2, 3, 4]: num_blocks = params.blocks_per_stage[stage] for i in 1..num_blocks: stride = 2 if (i == 1 and stage > 1) else 1 needs_projection = (i == 1) # first block of a stage x = BottleneckBlock(x, ..., stride=stride, W_shortcut = params.W_s[stage] if needs_projection else None) x = GlobalAveragePool(x) logits = FullyConnected(x, params.W_fc) return Softmax(logits) ```
Complexity & correctness
Time and space complexity. A residual (or bottleneck) block adds only an element-wise addition and, for projection shortcuts, one extra 1×1 convolution to whatever a plain stack of the same layers would already cost. For an input feature map with channels, spatial size , and a convolution producing output channels, one convolutional layer costs multiply-adds. A basic block with two 3×3 layers costs (assuming ); a bottleneck block with reduction ratio 4 costs roughly — comparable to a single 3×3 layer at full width, which is precisely why bottlenecks let ResNet-50/101/152 go deep without exploding cost. The identity shortcut itself is , negligible next to convolution cost; the projection shortcut adds , the cost of one 1×1 convolution, used only once per stage. Space is dominated by storing activations for backpropagation, per block, unchanged in order from the plain-network case — residual connections are essentially free in asymptotic terms while changing optimization behavior completely.
Why the shortcut fixes gradient flow (the core argument). Consider a chain of residual blocks:
This follows by induction: , so unrolling from telescopes into plus a sum of residual contributions — no products, only sums. Differentiate the loss with respect to an early activation using the chain rule:
The crucial structural fact is the additive 1: the gradient with respect to is the downstream gradient plus a correction term, never a pure product of many Jacobians each potentially or . In a plain network, , a product of Jacobians whose norms compound multiplicatively — this is exactly the mechanism behind vanishing/exploding gradients. With the residual formulation, even if every 's Jacobian happens to vanish, the gradient signal still reaches every earlier layer undiminished through the shortcut term. This is the same principle later reused explicitly in gated architectures for Recurrent Neural Networks, where a "keep" gate near 1 similarly guarantees an additive identity path through time.
Why deeper is never worse (in principle). Because a residual block reduces to the identity when and has matching shape, a residual network of depth contains, as a special case within its hypothesis space, every function representable by a residual network of depth (append a block with ). Optimization is not guaranteed to find the global optimum, but the existence of an easy-to-reach path to "no worse than the shallower network" removes the specific degradation pathology observed in plain stacks, where discovering an identity block requires a delicate, non-default configuration of weights across an entire nonlinear sub-network rather than simply zeroing out a residual branch.
Tradeoffs, honestly. Residual connections do not repeal the no-free-lunch nature of optimization: extremely deep ResNets (1000+ layers) still show some instability and require care (better initialization, sometimes different normalization). The reformulation also assumes the optimal function really is close to identity per block, which is empirically reasonable for image classification but not universally guaranteed. Skip connections increase peak memory during training somewhat, since both the block input and its output must often be retained for the backward pass. Finally, projection shortcuts add parameters and computation exactly where feature maps change shape, a small but real cost concentrated at stage boundaries.
Worked example
Consider a tiny basic residual block operating on a single scalar feature (to make the arithmetic fully explicit; real blocks operate on tensors, but the additive mechanics are identical). Suppose , and the residual function is a two-layer linear-then-ReLU stack (dropping BN for clarity) with weights , :
The residual block output is
Compare against a plain (non-residual) block with the same two weights: — the plain block, with these particular (small, near-initialization-scale) weights, kills the signal entirely, while the residual version preserves most of because the shortcut dominates. Now trace the backward pass for a loss with target (residual case, , so ; ReLU is active since so its local gradient is 1):
| Step | Quantity | Value |
|---|---|---|
| loss gradient at output | ||
| ReLU active () | ||
| (shortcut term) | identity path | |
| (residual term) | ||
| , total | sum of both paths, times upstream |
Note the gradient reaching is : the "" from the shortcut guarantees a substantial gradient regardless of how small or even sign-flipped the residual branch's own Jacobian is. If we imagine 50 such blocks stacked and the residual branch's local Jacobian averaging around each, a plain network's gradient would involve a product — catastrophic vanishing. The residual network's gradient involves a sum of 50 small correction terms around an anchor of , staying throughout. This numeric miniature is exactly the mechanism formalized in the complexity/correctness section above.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Adding with mismatched shapes | Stride or channel changes between stages break the shortcut's shape | Use a 1×1 projection shortcut with matching stride/channels exactly where shape changes |
| Applying the final ReLU before the addition | Copying a plain block's activation placement without checking the original design | Add first, then apply ReLU after the sum, so the identity path is truly linear |
| Initializing the last BN's scale () to 1 in every block | Makes each block behave like a "generic" nonlinear map from the start rather than near-identity | Zero-initialize the last BN in each residual branch so blocks start close to identity |
| Assuming residual connections fix exploding activations, not just gradients | Confusing gradient flow with activation-magnitude control | Keep batch/layer normalization; residual connections address gradient pathways, not variance growth alone |
| Treating "deeper is always better" as automatic even with skip connections | Forgetting that skip connections only ease optimization, not guarantee monotonic gains without enough data/regularization | Validate depth choices empirically; add regularization (weight decay, stochastic depth) at extreme depths |
| Forgetting the shortcut in the backward-pass mental model, assuming standard chain-rule product only | Habitual plain-network intuition carried over | Always account for the additive identity term when reasoning about gradient magnitude through a residual stack |
Pioneers & history
Residual networks were introduced by a team at Microsoft Research Asia. Kaiming He led the work alongside Xiangyu Zhang, Shaoqing Ren, and Jian Sun, building directly on the momentum of deep CNN successes chronicled from AlexNet and Deep CNNs onward, and extending the layer-stacking blueprint established by LeNet and the CNN Blueprint to unprecedented depths.
Origins · 1 minKaiming He and how this was discovered
Where this matters
ResNet architectures (ResNet-50 above all) remain the default backbone for transfer learning in computer vision, embedded in object detectors (Faster R-CNN, Mask R-CNN), semantic segmentation networks, and countless production image-classification pipelines because pretrained ResNet weights are cheap, reliable, and widely available. Beyond vision, the residual-connection pattern itself — add the sublayer's input back to its output — is now load-bearing infrastructure in Transformer architectures that power large language models, where every attention sublayer and every feed-forward sublayer is wrapped in a residual connection (often paired with layer normalization) for exactly the gradient-flow reasons derived above. Autonomous-vehicle perception stacks, medical-imaging diagnostic models, and speech-recognition acoustic models built on deep convolutional or Transformer backbones inherit residual connections as a foundational, largely invisible piece of plumbing. The idea also directly foreshadows the gating mechanisms used to stabilize training across long sequences in Recurrent Neural Networks, where an additive "carry" path plays the same mathematical role across time steps that the shortcut plays across depth.
Ask the tutor: Can you show how stacking many residual blocks compares numerically to a plain network when the residual branch's Jacobian is small at every layer?
Do residual connections change what functions a network can represent?
No. Any function a plain block could represent is also representable by a residual block, since can simply be set to ; the hypothesis space is unchanged in principle. What changes is the optimization landscape: the residual parametrization makes the identity function (or near-identity functions) trivially reachable by driving toward zero, which gradient descent finds easy starting from small random weights. In a plain block, reaching an identity mapping requires a specific, non-generic configuration across every nonlinear layer in the block, which optimizers struggle to discover. So the benefit is entirely about trainability, not expressiveness.
Why does the final ReLU come after the addition rather than inside the residual branch only?
Placing ReLU after the sum keeps the shortcut path perfectly linear (an untouched identity or a linear projection), which is exactly what makes the "+1" term in the gradient derivation exact and unconditional. If a nonlinearity sat on the shortcut path itself, the identity mapping would no longer be a fixed point reachable simply by zeroing , and the gradient contribution through the shortcut could shrink depending on activation regions. Keeping the shortcut linear preserves both the clean forward-pass identity property and the clean backward-pass additive gradient property simultaneously.
How do bottleneck blocks differ from basic blocks, and why does ResNet-50 use them?
A basic block uses two 3×3 convolutions at full channel width; a bottleneck block uses 1×1 (reduce channels) → 3×3 (process at reduced width) → 1×1 (restore channels). At the channel widths used in deeper ResNets (256, 512, 1024, 2048), a full-width 3×3 convolution would be prohibitively expensive. The bottleneck design lets the expensive 3×3 operate on a quarter of the channels, keeping FLOPs roughly comparable to a single full-width 3×3 layer while allowing far more channels and depth overall — this is precisely why ResNet-50/101/152 are feasible to train.
Are residual connections the same thing as "highway networks"?
They're closely related but not identical. Highway networks (Srivastava et al., slightly earlier) use a learned, input-dependent gate so the output is , generalizing the plain-vs-identity choice into a soft, learned mixture per unit. ResNet's shortcut is a fixed, ungated identity (or a fixed linear projection), which is simpler, cheaper, and empirically worked at least as well or better for very deep vision networks. Highway-style gating reappears explicitly in LSTM/GRU cells for Recurrent Neural Networks, where the gate is a genuine learned function of the current input and hidden state.
Can residual connections make a network worse than a plain one?
In principle, no additional expressiveness is lost, and empirically residual connections almost always help once depth exceeds a modest threshold; for shallow networks (say under 10–20 layers) the benefit is smaller since plain optimization is not yet badly degraded. The main practical risk is not "worse accuracy" but subtle bugs at shape-changing boundaries (see the pitfalls table), or overly aggressive depth without matching data/regularization, which can still overfit or underfit for reasons unrelated to the skip connection itself.
Why does He initialize the last batch-norm's scale parameter to zero in each residual branch?
This trick (used in some ResNet variants and widely adopted afterward) forces every residual block to compute exactly at the very start of training, so the whole network begins as a pure identity function end-to-end. This gives training a maximally stable starting point: the initial loss and gradient signal are governed only by the final classification layer, and depth is "grown into" gradually as each block's residual branch learns to deviate from zero. It is a natural, sharper realization of the "near-identity by default" philosophy that motivates residual connections generally.
How do residual connections relate to Transformer architectures?
Every Transformer block wraps both its self-attention sublayer and its feed-forward sublayer in a residual connection: , then , typically combined with layer normalization. This is structurally identical to the ResNet block — a sublayer computes a correction, added back to its input — and serves the same purpose: it keeps gradients flowing cleanly through dozens of stacked Transformer layers in large language models, exactly as it keeps gradients flowing through 50+ convolutional layers in ResNet.