AI Computer Institute
Expert-curated CS & AI curriculum aligned to CBSE standards. A bharath.ai initiative. About Us

Vanishing Gradients: The Deep Learning Crisis

📚 Deep Learning⏱️ 25 min read🎓 Grade 10
✍️ AI Computer Institute Editorial Team Updated: August 2026 CBSE-aligned · Peer-reviewed · 25 min read
Content curated by subject matter experts with IIT/NIT backgrounds. All chapters are fact-checked against official CBSE/NCERT syllabi.

The Telephone Game That Broke Deep Learning

Play the "telephone game" with sixteen people in a line. Whisper a sentence to the first person. By the time it reaches the sixteenth, it has usually mutated into nonsense — not because any one person was careless, but because every whisper loses a little signal, and those small losses multiply down the chain. Now replace "sentence" with "correction signal" and "sixteen people" with "sixteen layers of a neural network," and you have the exact problem that nearly killed deep learning before it properly began.

Here is the historical fact that should surprise you: for most of the 1990s and early 2000s, a neural network with many hidden layers usually trained worse than one with two or three layers, even though a deeper network has strictly more representational power on paper. Researchers had the architecture right and the math right, yet stacking more layers made results worse, not better. The culprit was first documented rigorously by Sepp Hochreiter in his 1991 diploma thesis, and formalized further by Yoshua Bengio, Patrice Simard, and Paolo Frasconi in a 1994 paper bluntly titled "Learning long-term dependencies with gradient descent is difficult." The name later given to the problem is exactly what this chapter is about: vanishing gradients. You are about to derive, from scratch, exactly why it happens — with real numbers, not just a metaphor.

Why a Network Needs Gradients to Learn At All

A neural network learns by adjusting its weights so that its output gets closer to the correct answer. The rule that does the adjusting is gradient descent:

w := w - eta * (dL/dw)

Here L is the loss (how wrong the network currently is), w is one weight somewhere in the network, eta is the learning rate, and dL/dw — "the gradient of the loss with respect to w" — tells you how much the loss would change if you nudged w by a tiny amount. This single number is the entire instruction a weight receives about how to improve. If dL/dw is a reasonably sized number, the weight update is meaningful and the layer learns. If dL/dw is astronomically small — say, 0.0000000001 — then no matter how many training steps you run, that weight barely moves. The layer is technically "connected" to the loss, but for all practical purposes it has stopped learning. That is what "vanishing" means: not that the gradient becomes exactly zero, but that it becomes so small it is functionally useless as a training signal.

The question this chapter answers precisely is: why does the gradient reaching early layers of a deep network shrink so dramatically, and can we predict by how much?

The Sigmoid's Built-In Speed Limit

Early neural networks (and still many textbook introductions) use the sigmoid activation function:

sigma(z) = 1 / (1 + e^(-z))

To understand backpropagation we need its derivative, and we should derive it rather than just quote it. Let u = 1 + e^(-z), so sigma(z) = 1/u. Using the fact that the derivative of 1/u with respect to z is -(1/u^2) * (du/dz), and du/dz = -e^(-z):

d(sigma)/dz = -(1/u^2) * (-e^(-z)) = e^(-z) / (1 + e^(-z))^2

Now split that fraction into two copies of a familiar shape:

e^(-z) / (1+e^(-z))^2 = [1/(1+e^(-z))] * [e^(-z)/(1+e^(-z))]

The first bracket is just sigma(z). For the second bracket, notice that 1 - sigma(z) = 1 - 1/(1+e^(-z)) = e^(-z)/(1+e^(-z)), which is exactly that bracket. So we arrive at the clean, famous identity:

sigma'(z) = sigma(z) * (1 - sigma(z))

This is elegant, but it hides a trap. Since sigma(z) always lies between 0 and 1, write x = sigma(z) and ask: what is the largest possible value of x(1-x)? Expand it as x - x^2, complete the square:

x - x^2 = -(x^2 - x) = -[(x - 0.5)^2 - 0.25] = 0.25 - (x - 0.5)^2

Since (x-0.5)^2 is never negative, this expression is always at most 0.25, and it hits exactly 0.25 only when x = 0.5, i.e. when z = 0. This is pure algebra — no calculus required to see the ceiling, only to derive the derivative itself. The conclusion is unavoidable: every single sigmoid neuron in your network, at its absolute best, passes along at most a quarter of any gradient signal that flows through it. Move away from z=0 in either direction and the multiplier drops further, toward zero. This one algebraic fact is the seed of the entire vanishing gradient crisis.

Backpropagation Is Multiplication All the Way Down

To see how this 0.25 ceiling compounds with depth, strip a network down to the simplest possible "deep" case: one neuron per layer, chained in a straight line, so we can track every quantity by hand without matrix notation. Let there be L layers, weights w_1, w_2, ..., w_L, input x, and target y:

z_1 = w_1 * x,        a_1 = sigma(z_1)
z_2 = w_2 * a_1,       a_2 = sigma(z_2)
...
z_L = w_L * a_(L-1),   a_L = sigma(z_L)   (this is the output)
Loss = 0.5 * (a_L - y)^2

Now apply the chain rule to find how the loss depends on the very first weight, w_1. Each layer contributes one factor: how the loss changes with the next activation, times how that activation changes with the pre-activation value (the sigmoid derivative), times how the pre-activation value changes with the previous activation (which is just the weight). Chaining all of this from the output back to w_1 gives:

dL/dw_1 = (a_L - y) * sigma'(z_L) * w_L * sigma'(z_(L-1)) * w_(L-1) * ... * sigma'(z_1) * x

Written compactly as a product:

dL/dw_1 = (a_L - y) * x * [ sigma'(z_1) * sigma'(z_2) * ... * sigma'(z_L) ] * [ w_2 * w_3 * ... * w_L ]

Look at what is being multiplied: L separate sigmoid-derivative terms, each capped at 0.25, and L-1 weight terms. If the weights are initialized to modest values (commonly less than 1, which was standard practice before the fixes you will see later in this chapter), then every additional layer contributes another factor smaller than 0.25 to the product. This is not a coincidence or a bug in some particular implementation — it is a direct, provable consequence of using bounded, saturating activation functions in a chain. A gradient traveling backward through 10 such layers is being multiplied by roughly ten numbers each at most a quarter — and multiplying small fractions together shrinks a number exponentially fast, not linearly.

Worked Example: Watching a Gradient Vanish Across Four Layers

Numbers make this concrete. Take a 4-layer chain with every weight set to w = 0.5, input x = 1.0, and target y = 1.0 (a case the network has to work to get right, since its sigmoid output can only approach 1, never reach it). First, the forward pass, computed one layer at a time:

z_1 = 0.5 * 1.0 = 0.5        a_1 = sigma(0.5)   = 0.6225
z_2 = 0.5 * 0.6225 = 0.3112   a_2 = sigma(0.3112) = 0.5772
z_3 = 0.5 * 0.5772 = 0.2886   a_3 = sigma(0.2886) = 0.5716
z_4 = 0.5 * 0.5716 = 0.2858   a_4 = sigma(0.2858) = 0.5710   (network's output)

The output settles near 0.571 against a target of 1, giving a loss of 0.5 * (0.571 - 1)^2 = 0.0920. Notice something already: the activations barely move after layer 2 (0.6225 to 0.5772 to 0.5716 to 0.5710) — the chain is converging toward a fixed point. That stability in the forward direction is precisely what makes the backward direction so treacherous, as you're about to see.

Now backpropagate, one layer at a time, computing sigma'(z) = a(1-a) at each layer using the activations just found:

dL/da_4 = a_4 - y = 0.571 - 1 = -0.4290

Layer 4: sigma'(z_4) = 0.5710 * 0.4290 = 0.2449
         dL/dz_4 = -0.4290 * 0.2449 = -0.1051
         dL/dw_4 = dL/dz_4 * a_3   = -0.1051 * 0.5716 = -0.06006

Layer 3: dL/da_3 = dL/dz_4 * w_4  = -0.1051 * 0.5 = -0.05255
         sigma'(z_3) = 0.5716 * 0.4284 = 0.2448
         dL/dz_3 = -0.05255 * 0.2448 = -0.01287
         dL/dw_3 = dL/dz_3 * a_2   = -0.01287 * 0.5772 = -0.007426

Layer 2: dL/da_2 = dL/dz_3 * w_3  = -0.01287 * 0.5 = -0.006435
         sigma'(z_2) = 0.5772 * 0.4228 = 0.2441
         dL/dz_2 = -0.006435 * 0.2441 = -0.001571
         dL/dw_2 = dL/dz_2 * a_1   = -0.001571 * 0.6225 = -0.000978

Layer 1: dL/da_1 = dL/dz_2 * w_2  = -0.001571 * 0.5 = -0.0007855
         sigma'(z_1) = 0.6225 * 0.3775 = 0.2350
         dL/dz_1 = -0.0007855 * 0.2350 = -0.0001846
         dL/dw_1 = dL/dz_1 * x    = -0.0001846 * 1.0 = -0.0001846

Line those four final numbers up: dL/dw_4 = -0.0601, dL/dw_3 = -0.00743, dL/dw_2 = -0.000978, dL/dw_1 = -0.0001846. The gradient reaching the very first layer is about 326 times smaller than the gradient reaching the last layer — and this network only has four layers. Under gradient descent with the same learning rate applied everywhere, layer 4 makes a real, useful correction on every step, while layer 1's weight is nudged by a number so small it would take hundreds of extra training steps just to catch up. This is not a hypothetical: it is exactly what researchers observed when they tried to train early deep sigmoid networks — the last layer or two would learn something, while everything closer to the input stayed close to its random initialization forever.

Simulating It: What Happens at Real Depth

The four-layer example already shows a 326x gap. Real deep networks — image classifiers, deep RNNs, early attempts at deep language models — commonly had 10, 20, or more layers. You can extend the exact same computation in code:

import numpy as np

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

L = 12                        # number of layers
w = [0.5] * L                  # every weight starts at 0.5
x, y = 1.0, 1.0                 # one input, one target

# ---- forward pass ----
a = [x]                        # a[0] is the input itself
z_list = []
for l in range(L):
    z = w[l] * a[-1]
    z_list.append(z)
    a.append(sigmoid(z))

output = a[-1]
loss = 0.5 * (output - y) ** 2

# ---- backward pass ----
grad_a = output - y            # dL/da_L
gradients = [0.0] * L
for l in reversed(range(L)):
    a_l = a[l + 1]
    local_slope = a_l * (1 - a_l)       # sigma'(z_l) via sigma(z_l)
    grad_z = grad_a * local_slope       # dL/dz_l
    gradients[l] = grad_z * a[l]        # dL/dw_l
    grad_a = grad_z * w[l]              # dL/da_(l-1), sent one layer back

for l in range(L):
    print(f"layer {l + 1:2d}:  dL/dw = {gradients[l]:.3e}")

This is literally the same layer-by-layer arithmetic performed above, just automated for arbitrary depth. Because the activations converge to a fixed point almost immediately (as you saw: 0.6225 to 0.5772 to 0.5716 to 0.5710, barely moving after that), the per-layer shrink factor also settles down, at roughly w * sigma'(z) ≈ 0.5 * 0.245 ≈ 0.122 for every layer beyond the fourth. Extend the chain to 12 layers and the first layer's gradient is smaller than the twelfth layer's by roughly 0.122 raised to the 11th power — on the order of 10^-10. Since the last layer's own gradient is around 10^-2, the first layer ends up with a gradient on the order of 10^-12: about ten orders of magnitude smaller. At that scale, even millions of training steps produce no visible change in the early layers' weights. This is the precise, quantitative reason "just add more layers" silently failed for over a decade of neural network research.

Diagram: Forward Signal vs. Backward Gradient

The asymmetry is the whole story: information flows forward through the network with its magnitude roughly preserved (the activations converge and stay near 0.57), while the correction signal flowing backward collapses by nearly two orders of magnitude every few layers. The diagram below plots exactly the numbers computed in the worked example.

Forward signal vs. backward gradient (4-layer chain) Forward pass -- activation stays near 0.57 L1 a=0.62 L2 a=0.58 L3 a=0.57 L4 output=0.57 Backward pass -- |dLoss/dw| at each layer (log-scaled bar height) 0.0001846 L1 0.000978 L2 0.00743 L3 0.0601 L4 |dL/dw1| is about 326x smaller than |dL/dw4| -- with only 4 layers

Common Misconception: "Vanishing" Does Not Mean "Zero"

A mistake students often make is picturing a vanished gradient as literally 0.000000, as if the layer's connection to the loss has been severed. It has not. In the worked example, dL/dw_1 = -0.0001846 is a perfectly real, non-zero number — it is just too small, relative to the gradients elsewhere in the network, to produce learning at a usable rate within a reasonable number of training steps. This distinction matters for two reasons. First, it explains why vanishing gradients are hard to detect: the training loss often still decreases (because the last one or two layers are learning), which can fool you into thinking the network is training fine, while the early layers are quietly stuck near their random initialization. Second, do not confuse this with a "dead ReLU," a different and unrelated failure mode where a ReLU neuron's input is permanently negative, making its output and gradient exactly zero for every example — genuinely zero, not just small. Vanishing gradients are a depth-and-multiplication problem across the whole network; dead ReLUs are a per-neuron problem caused by a bad update pushing one unit's weights into a region it can never recover from. Related to this, do not assume "deeper is automatically smarter." A 20-layer sigmoid network is not a strictly better learner than a 4-layer one — without the fixes described below, it can be a strictly worse one, because depth is exactly what causes the gradient to collapse in the first place.

Why Saturation Makes It Even Worse

The 0.25 ceiling on sigma'(z) is the best case, occurring only when z is near 0. Push z far from 0 in either direction — which happens whenever weights or inputs are even moderately large — and the sigmoid enters its saturated region, where the curve is nearly flat. Check the formula directly: at z = 4, sigma(4) ≈ 0.982, so sigma'(4) = 0.982 * 0.018 ≈ 0.0176 — already more than 14 times smaller than the best-case 0.25. At z = 6, sigma'(6) ≈ 0.00247. In deep networks trained with the large, carelessly scaled initial weights that were standard before this problem was understood, neurons deep in the network routinely operated in these saturated zones, making the effective per-layer shrink factor far worse than the idealized 0.25 used in the worked example above. This is why the vanishing gradient problem was originally so mysterious and so severe: it was not a mild inefficiency but a near-total training failure for networks beyond about 5–8 layers.

The Fixes That Rebuilt Deep Learning

Modern deep learning exists because several independent fixes attack this multiplicative shrinkage from different angles.

ReLU activation. The rectified linear unit, ReLU(z) = max(0, z), has a derivative that is exactly 1 for every z > 0 and exactly 0 for z < 0 — there is no fractional squashing like the sigmoid's 0.25 ceiling for the "active" half of its range. A chain of active ReLU neurons multiplies gradients by 1 instead of by a shrinking fraction, which is why ReLU (and its variants such as Leaky ReLU) became the default hidden-layer activation for essentially all deep networks after around 2011–2012, when it was shown to enable training of much deeper networks than sigmoid or tanh allowed.

Better weight initialization. Xavier/Glorot initialization (Xavier Glorot and Yoshua Bengio, 2010) and He initialization (Kaiming He and colleagues, 2015, designed specifically for ReLU) scale each layer's starting weights based on the number of inputs and outputs of that layer. The goal is to keep the variance of activations — and therefore the variance of gradients flowing backward — roughly constant from layer to layer, rather than letting it shrink or explode as depth increases. This does not eliminate the multiplicative structure of backpropagation, but it stops the starting point of training from being catastrophically bad.

Residual (skip) connections. Introduced in the ResNet architecture (Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun, 2015), a residual block computes output = F(x) + x instead of just output = F(x). Because the derivative of the added x term with respect to x is exactly 1, every residual block contributes an additive path through which gradients can flow completely undiminished, alongside the usual multiplicative path through F. This "gradient highway" is what allowed ResNet to train networks over 100 layers deep — an order of magnitude beyond what was previously feasible — and residual connections are now a standard component in nearly every modern deep architecture, including transformers.

Batch normalization. Proposed by Sergey Ioffe and Christian Szegedy (2015), batch normalization rescales each layer's inputs to have roughly zero mean and unit variance before the activation function is applied. This keeps z values clustered near 0 — precisely the region where sigma'(z) is closest to its 0.25 maximum rather than deep in a saturated near-zero region — which directly counteracts the saturation problem described above, even when sigmoid-like activations are used.

Gated recurrent architectures. For recurrent networks processing sequences (relevant to speech, text, and time-series problems such as UPI transaction fraud detection or IRCTC demand forecasting), the vanishing gradient problem appears across time steps rather than layers, since a long sequence is effectively a very deep chain. The Long Short-Term Memory network (Sepp Hochreiter and Jürgen Schmidhuber, 1997) solves this with a separate "cell state" pathway updated mostly by addition rather than repeated multiplication, letting gradients travel across many time steps largely unshrunk — the recurrent analogue of a residual connection.

Where This Shows Up in Your Exams

CBSE's Artificial Intelligence curriculum introduces neural network training conceptually; this chapter gives you the rigorous version underneath those diagrams, including the exact algebra of why depth without the right activation function is a liability, not an asset. For competitive and GATE-track preparation, GATE's Data Science and Artificial Intelligence (DA) paper, introduced in 2024, includes a dedicated Deep Learning section covering feedforward networks and backpropagation — a question asking you to compute or reason about how a gradient changes across layers, exactly as you did in the worked example, is squarely the kind of conceptual-plus-numerical question that paper tests. JEE and BITSAT do not test neural network training directly, but the underlying skill this chapter builds — deriving a bound algebraically (as with the 0.25 ceiling via completing the square) and then reasoning about how repeated multiplication of bounded quantities behaves as the number of terms grows — is exactly the kind of inequality-and-limits reasoning that appears in JEE-level sequences-and-series and calculus problems. Treat the derivation, not just the conclusion, as the transferable skill.

Active Recall

  • Derive, without looking back, why sigma(z)(1-sigma(z)) has a maximum value of exactly 0.25, and state at which value of z this maximum occurs.
  • A 6-layer sigmoid chain has every weight equal to 0.6, and every layer happens to sit near z=0 so sigma'(z) ≈ 0.25 at each layer. Estimate the ratio between the gradient reaching layer 1 and the gradient reaching layer 6. (Hint: each layer beyond the last contributes one more factor of roughly 0.6 * 0.25 = 0.15.)
  • Explain, in one or two sentences, why "the training loss is decreasing" does not prove that all layers of a deep network are learning.
  • A classmate says, "Vanishing gradients mean the gradient is literally zero, just like a dead ReLU neuron." Correct this statement precisely, naming the actual difference between the two failure modes.
  • Explain, using the derivative of ReLU, why replacing sigmoid with ReLU in the hidden layers of a deep network directly attacks the multiplicative shrinkage derived in this chapter.
  • A residual block computes output = F(x) + x. Using the sum rule for derivatives, explain why this guarantees at least one gradient path through the block has derivative exactly 1, regardless of what F does.

Summary

Backpropagation computes dL/dw for an early weight as a long product of local derivatives and weights, one term contributed by every layer between that weight and the output. For sigmoid (and tanh) activations, each local derivative term is bounded — provably, by completing the square on x(1-x) — at 0.25, and often far lower once a neuron saturates away from z=0. Multiplying many such small fractions together shrinks the gradient exponentially with depth: a mere four layers produced a 326-fold gap in the worked example above, and twelve layers push the gap to roughly ten orders of magnitude. The practical consequence was a decade-plus period where deeper networks trained worse than shallow ones, because early layers received a training signal too small to matter. The fix was never one single trick but a combination: ReLU activations that don't cap the gradient at 0.25, initialization schemes that keep activation variance stable across depth, residual connections that give gradients an additive shortcut with derivative exactly 1, batch normalization that keeps neurons out of saturated regions, and gated architectures like LSTMs that apply the same additive-shortcut idea across time. Understanding the exact multiplicative mechanism — not just its name — is what lets you predict when a network will suffer from it and reason about which fix actually addresses the cause.

Think About It

Think about this: How would you explain vanishing gradients: the deep learning crisis to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.

← Optimizers: SGD, Adam, and FriendsResidual Connections: Skip and Learn →

Found this useful? Share it!

📱 WhatsApp 🐦 Twitter 💼 LinkedIn