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 H(x)H(x) directly, we ask it to learn F(x)=H(x)−xF(x) = H(x) - x. We reconstruct H(x)=F(x)+xH(x) = F(x) + x by literally wiring xx 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.

Key takeaways
  • Residual blocks compute y=F(x)+xy = F(x) + x instead of y=F(x)y = F(x), 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 ∂L/∂x\partial \mathcal{L}/\partial x 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.
The core insight

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 ℓ\ell feeds directly into layer ℓ+1\ell+1 as xℓ+1=F(xℓ)x_{\ell+1} = F(x_\ell), where FF 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 H(x)H(x) directly, define

y=F(x,{Wi})+x,y = F(x, \{W_i\}) + x,

where FF is the residual function — typically two or three weight layers — and the raw input xx 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 F(x)→0F(x) \to 0, 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 HH expressible by a plain block is still expressible as F(x)+xF(x) + x with F(x)=H(x)−xF(x) = H(x) - x — 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:

y=ReLU(x+BN(W2∗ReLU(BN(W1∗x))))y = \text{ReLU}\big(x + \text{BN}(W_2 * \text{ReLU}(\text{BN}(W_1 * x))) \big)

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 F(x)F(x) and xx 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 xx before addition:

y=F(x,{Wi})+Wsx.y = F(x, \{W_i\}) + W_s x.

When shapes already match, WsW_s 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) ```

Figure
A residual block: the shortcut runs an identity path around two convolutions, joined by addition before the final ReLU
input x Conv 3×3, BN ReLU Conv 3×3, BN identity shortcut + ReLU output y F(x): residual function learned by the two conv layers y = F(x) + x

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 CC channels, spatial size H×WH \times W, and a k×kk\times k convolution producing C′C' output channels, one convolutional layer costs O(HWCC′k2)O(H W C C' k^2) multiply-adds. A basic block with two 3×3 layers costs O(HWC2⋅9)O(HWC^2 \cdot 9) (assuming C=C′C=C'); a bottleneck block with reduction ratio 4 costs roughly O(HWC2/4⋅(1+9/16+1))≈O(HWC2)O(HWC^2/4 \cdot (1 + 9/16 + 1)) \approx O(HWC^2) — 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 O(HWC)O(HWC), negligible next to convolution cost; the projection shortcut adds O(HWCC′)O(HWC C'), the cost of one 1×1 convolution, used only once per stage. Space is dominated by storing activations for backpropagation, O(HWC)O(HWC) 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 LL residual blocks:

xL=x0+∑i=0L−1Fi(xi).x_L = x_0 + \sum_{i=0}^{L-1} F_i(x_i).

This follows by induction: xi+1=xi+Fi(xi)x_{i+1} = x_i + F_i(x_i), so unrolling from x0x_0 telescopes into x0x_0 plus a sum of residual contributions — no products, only sums. Differentiate the loss L\mathcal{L} with respect to an early activation x0x_0 using the chain rule:

∂L∂x0=∂L∂xL⋅∂xL∂x0=∂L∂xL(1+∂∂x0∑i=0L−1Fi(xi)).\frac{\partial \mathcal{L}}{\partial x_0} = \frac{\partial \mathcal{L}}{\partial x_L}\cdot \frac{\partial x_L}{\partial x_0} = \frac{\partial \mathcal{L}}{\partial x_L} \left(1 + \frac{\partial}{\partial x_0}\sum_{i=0}^{L-1} F_i(x_i)\right).

The crucial structural fact is the additive 1: the gradient with respect to x0x_0 is the downstream gradient ∂L/∂xL\partial \mathcal{L}/\partial x_L plus a correction term, never a pure product of many Jacobians each potentially ≪1\ll 1 or ≫1\gg 1. In a plain network, ∂xL/∂x0=∏i∂xi+1/∂xi\partial x_L/\partial x_0 = \prod_i \partial x_{i+1}/\partial x_i, a product of LL Jacobians whose norms compound multiplicatively — this is exactly the mechanism behind vanishing/exploding gradients. With the residual formulation, even if every FiF_i's Jacobian happens to vanish, the gradient signal ∂L/∂xL\partial \mathcal{L}/\partial x_L 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 F(x)→0F(x) \to 0 and xx has matching shape, a residual network of depth L+1L+1 contains, as a special case within its hypothesis space, every function representable by a residual network of depth LL (append a block with F≡0F \equiv 0). 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 x=2.0x = 2.0, and the residual function is a two-layer linear-then-ReLU stack (dropping BN for clarity) with weights w1=0.5w_1 = 0.5, w2=−0.3w_2 = -0.3:

h1=ReLU(w1x)=ReLU(1.0)=1.0,h_1 = \text{ReLU}(w_1 x) = \text{ReLU}(1.0) = 1.0,
F(x)=w2h1=−0.3.F(x) = w_2 h_1 = -0.3.

The residual block output is

y=ReLU(F(x)+x)=ReLU(−0.3+2.0)=ReLU(1.7)=1.7.y = \text{ReLU}(F(x) + x) = \text{ReLU}(-0.3 + 2.0) = \text{ReLU}(1.7) = 1.7.

Compare against a plain (non-residual) block with the same two weights: yplain=ReLU(F(x))=ReLU(−0.3)=0y_{\text{plain}} = \text{ReLU}(F(x)) = \text{ReLU}(-0.3) = 0 — the plain block, with these particular (small, near-initialization-scale) weights, kills the signal entirely, while the residual version preserves most of xx because the shortcut dominates. Now trace the backward pass for a loss L=12(y−y∗)2\mathcal{L} = \frac{1}{2}(y - y^*)^2 with target y∗=1.5y^* = 1.5 (residual case, y=1.7y = 1.7, so ∂L/∂y=0.2\partial\mathcal{L}/\partial y = 0.2; ReLU is active since y>0y>0 so its local gradient is 1):

StepQuantityValue
∂L/∂y\partial \mathcal{L}/\partial yloss gradient at output0.20.2
∂y/∂(pre-ReLU sum)\partial y/\partial(\text{pre-ReLU sum})ReLU active (1.7>01.7>0)11
∂(sum)/∂x\partial(\text{sum})/\partial x (shortcut term)identity path11
∂(sum)/∂x\partial(\text{sum})/\partial x (residual term)w2⋅1[h1>0]⋅w1w_2 \cdot \mathbb{1}[h_1>0]\cdot w_1(−0.3)(1)(0.5)=−0.15(-0.3)(1)(0.5) = -0.15
∂L/∂x\partial \mathcal{L}/\partial x, totalsum of both paths, times upstream0.2×(1−0.15)=0.170.2 \times (1 - 0.15) = 0.17

Note the gradient reaching xx is 0.2×(1+(−0.15))=0.170.2 \times (1 + (-0.15)) = 0.17: the "11" 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 −0.15-0.15 each, a plain network's gradient would involve a product (−0.15)50≈0(-0.15)^{50} \approx 0 — catastrophic vanishing. The residual network's gradient involves a sum of 50 small correction terms around an anchor of 11, staying O(1)O(1) throughout. This numeric miniature is exactly the mechanism formalized in the complexity/correctness section above.

Common pitfalls & traps

PitfallWhy it happensFix
Adding F(x)+xF(x) + x with mismatched shapesStride or channel changes between stages break the shortcut's shapeUse a 1×1 projection shortcut with matching stride/channels exactly where shape changes
Applying the final ReLU before the additionCopying a plain block's activation placement without checking the original designAdd first, then apply ReLU after the sum, so the identity path is truly linear
Initializing the last BN's scale (γ\gamma) to 1 in every blockMakes each block behave like a "generic" nonlinear map from the start rather than near-identityZero-initialize the last BN γ\gamma in each residual branch so blocks start close to identity
Assuming residual connections fix exploding activations, not just gradientsConfusing gradient flow with activation-magnitude controlKeep batch/layer normalization; residual connections address gradient pathways, not variance growth alone
Treating "deeper is always better" as automatic even with skip connectionsForgetting that skip connections only ease optimization, not guarantee monotonic gains without enough data/regularizationValidate 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 onlyHabitual plain-network intuition carried overAlways 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
KH
Kaiming He
b. 1984 · Computer vision researcher at Microsoft Research Asia (later FAIR/Meta), co-inventor of ResNet, Mask R-CNN, and Faster R-CNN, whose 2015 residual learning framework resolved the degradation problem and enabled networks with over 150 layers to train reliably

History
2012
— AlexNet demonstrates deep CNNs can dominate ImageNet, igniting a race toward greater depth.
2014
— VGGNet and GoogLeNet push depth to roughly 19–22 layers; deeper plain stacks begin degrading.
2015
— He, Zhang, Ren, and Sun publish "Deep Residual Learning for Image Recognition," introducing skip connections.
2015
— ResNet wins ILSVRC 2015 classification, detection, and localization tracks with a 152-layer network.
2016
onward — Residual connections become a default component of nearly every deep architecture, including Transformers.

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 H(x)H(x) a plain block could represent is also representable by a residual block, since F(x)F(x) can simply be set to H(x)−xH(x) - x; 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 F(x)F(x) 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 FF, 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 T(x)T(x) so the output is T(x)⋅F(x)+(1−T(x))⋅xT(x)\cdot F(x) + (1-T(x))\cdot x, 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 F(x)=0F(x) = 0 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: x′=x+Attention(x)x' = x + \text{Attention}(x), then x′′=x′+FFN(x′)x'' = x' + \text{FFN}(x'), 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.

Before this

Where this leads