One full backward pass through a 2-2-1 network
numeric▲△△Eight decimal places throughout; the finite-difference check uses a step of 1e-6.
STATEMENT
Run one forward pass and one backward pass through a small network by hand, producing every intermediate and every parameter gradient. Then check the result against central differences, which is the only way to know a hand-derived gradient is right rather than merely consistent with itself.
GIVEN
A network with two inputs, two sigmoid hidden units and one linear output. One example, so every activation is a row.
The hidden nonlinearity is , the head carries none, and the loss is .
FIND
Every intermediate of the forward pass; the adjoints and ; the gradients with respect to all nine parameters; and the largest disagreement between those gradients and a central-difference estimate.
STRATEGY
Forward first, keeping everything — by Definition 3 the backward pass consumes the stored values, so discarding them means starting again. Then apply (I.6.2) from the sink: the loss adjoint is 1, and each node passes its own adjoint times its local Jacobian to its producers. For this architecture that is exactly the recurrence (I.6.3) and the outer product (I.6.4).
SOLUTION
Step 1 — forward. The pre-activations are :
Step 2 — the adjoint at the sink. by definition, and the head is linear, so
The sign says the prediction is below the target, which it is.
Step 3 — the second layer’s parameters. By (I.6.4) the weight gradient is the outer product of what entered the layer with what came back:
The bias gradient is the adjoint, because a bias enters its node with coefficient one.
Step 4 — travel back through the layer. By (I.6.3), multiply by and gate by the slope of the nonlinearity:
For the logistic function , so it is read off the stored activations rather than recomputed:
Step 5 — the first layer’s parameters. The same outer product, one layer down:
The second row is exactly twice the first, because the second input is twice the first. A weight’s gradient carries the size of the thing that fed it.
Step 6 — the check. Central differences with , evaluating the loss twice per parameter and taking , agree with all nine analytic gradients. The largest disagreement is .
That agreement is worth more than any of the individual numbers. The analytic gradient came from the chain rule; the numeric one came from evaluating the forward function eighteen times and never differentiating anything. Two unrelated computations landing on the same nine numbers is evidence the derivation is correct.
Answer
| quantity | value |
|---|---|
| largest gradient-check gap |
Check — sanity
The bias gradients equal the adjoints. and , to the last digit. A bias adds into its node with coefficient one, so its local Jacobian is the identity and (I.6.2) leaves the adjoint unchanged. Any discrepancy here is an arithmetic slip, not a modelling question.
The rows of are in the ratio of the inputs. exactly, matching . The outer product in (I.6.4) says the gradient of a weight scales with the activation entering it, so this ratio is forced.
The sigmoid slopes are below . and , against the maximum . Every layer of this kind multiplies the travelling adjoint by something no larger than a quarter, which is the observation I.6.B04 turns into a depth limit.
Where this breaks
The finite-difference check that validates the gradient here does not scale, and it is worth being precise about why. It costs two forward passes per parameter, so checking a model with parameters costs evaluations — for , the network audited in I.5.B03, that is over a million forward passes to verify one gradient that reverse mode produced in a single traversal. By (I.6.6) the analytic gradient cost about four forward passes. The ratio of a million to four is the cheap gradient principle, seen from the other side.
The step size has its own trap. Too large and the truncation error of the difference dominates; too small and floating-point cancellation does, because and agree in their leading digits and subtracting them discards exactly those. At in fp64 this same check returns visible garbage. Gradient checking is a debugging tool for small cases, not a verification method for a real model.
Variation
Replace the linear head with a second sigmoid, so , and keep everything else. Which of the nine gradients change, and by what factor? Predict the factor before recomputing — one number in Step 2 is responsible for all of it.