🧠 Machine Learning · Deep Learning
📅 Березень 2026⏱ ≈ 12 хв читання🟡 Середній

Neural Network Backpropagation

A neural network learns by repeatedly asking: "which weights, if nudged, would reduce the error?" Backpropagation is the efficient algorithm that answers this question for every weight simultaneously, using nothing more than the chain rule of calculus.

1. Forward Pass

A neural network is a function composition. Each layer computes a linear transformation followed by a nonlinearity:

Layer computation z^(l) = W^(l) · a^(l−1) + b^(l) // pre-activation a^(l) = σ(z^(l)) // post-activation (e.g. ReLU) Shapes: W^(l) ∈ ℝ^(n_l × n_{l-1}), b^(l) ∈ ℝ^(n_l)

The forward pass propagates input x through all L layers to produce output ŷ = a^(L). Nothing about "learning" yet — this is just function evaluation.

Forward pass →

Compute all activations from input to output. Store intermediate values (needed for backprop).

← Backward pass

Propagate error signal from output back to input. Compute gradient of loss w.r.t. every weight.

2. Loss Functions

The loss L(ŷ, y) measures how wrong the prediction is. It must be differentiable so we can compute gradients.

3. The Chain Rule

If f and g are differentiable functions and h(x) = f(g(x)), then:

Chain rule dh/dx = (df/dg) · (dg/dx) Or in partial derivative notation: ∂L/∂w = ∂L/∂a · ∂a/∂z · ∂z/∂w

A neural network is a composition of many functions. The loss depends on the final output, which depends on the last layer's weights, which depend on the previous layer's activations — all the way back to the input. The chain rule lets us compute ∂L/∂w for any weight w by multiplying local gradients along the path.

Why this is efficient: Naïvely computing ∂L/∂w_ij for every weight independently would require one full forward pass per weight — prohibitive for millions of weights. Backpropagation reuses intermediate computations so one backward pass computes all gradients simultaneously in O(P) time, matching the forward pass cost.

4. Backpropagation

Define the "delta" error signal δ^(l) = ∂L/∂z^(l). The backprop algorithm computes these deltas from output to input:

Backprop equations // Output layer delta: δ^(L) = ∂L/∂a^(L) ⊙ σ'(z^(L)) // Hidden layer delta (propagate backward): δ^(l) = (W^(l+1)ᵀ · δ^(l+1)) ⊙ σ'(z^(l)) // Gradients for this layer's parameters: ∂L/∂W^(l) = δ^(l) · (a^(l-1))ᵀ ∂L/∂b^(l) = δ^(l) ⊙ = element-wise product ᵀ = transpose

This is the full algorithm. In code, modern frameworks compute this via a computation graph where every operation registers its backward function. The "backward pass" traverses the graph in reverse topological order.

5. Gradient Descent

Once gradients are known, weights are updated to reduce the loss:

SGD weight update W ← W − α · ∂L/∂W α = learning rate (typically 1e-4 to 1e-2)

Variants address SGD's limitations:

Mini-batch gradient descent: Rather than one sample (stochastic) or all samples (batch), use batches of 32–256. This gives a good noise/compute tradeoff — noisy enough to escape local minima, efficient enough for GPU parallelism.

6. Activation Functions & Vanishing Gradients

The choice of σ determines how gradients flow through many layers.

Batch normalisation: Normalise layer inputs to zero mean/unit variance during training. Reduces internal covariate shift, stabilises gradients, allows higher learning rates. Makes very deep networks trainable.

7. Automatic Differentiation

Modern frameworks (PyTorch, JAX, TensorFlow) implement reverse-mode automatic differentiation — a generalisation of backpropagation to arbitrary computation graphs.

Every operation on a tensor records a backward function in a tape/graph. During the backward pass, the engine traverses this graph and accumulates gradients using the chain rule, entirely automatically. You write the forward computation; gradients come for free.

PyTorch example (conceptual) x = torch.tensor([2.0], requires_grad=True) y = x ** 3 + 2 * x // y = 12 y.backward() // dy/dx = 3x² + 2 = 14 print(x.grad) // tensor([14.])

Forward-mode autodiff (where you propagate a tangent, not gradient) is efficient when input dimension << output dimension. Reverse-mode is efficient when output dimension << input (i.e. computing scalar loss gradient wrt millions of weights). Neural network training always uses reverse mode.

Gradient checkpointing: For very deep or memory-constrained models, don't store all intermediate activations. Recompute them during backward pass from checkpointed values. Trades compute for memory (useful for training large language models).