A tied weight that receives half its gradient
counterexample▲▲△A scalar weight is used twice in the same graph:
Compute correctly. Then compute what a backward pass would produce if each use assigned into the gradient slot instead of adding to it, and say why the resulting number is not merely inaccurate.
Hint
has two consumers. (I.6.2) says its adjoint is a sum over them, and an assignment keeps whichever term arrives last.
Solution
Correct. Substituting, and , so
By the graph. . The node has two producers:
The node then contributes
By (I.6.2) the adjoint of is the sum of the contributions from its consumers:
which matches the direct computation.
With assignment instead of accumulation. Whichever contribution is written last survives, and each is exactly — half the truth. The gradient is not noisy, not biased in a complicated way, and not sometimes right: it is consistently a factor of two short.
Why that is worse than it sounds. A gradient scaled by a constant is still a descent direction, so training does not diverge or produce obvious garbage. It converges, more slowly, and looks like a learning-rate problem. Now make the two uses asymmetric — an embedding matrix that is also the output projection, a convolutional filter applied at 4096 positions, a recurrent matrix at 512 timesteps — and the surviving term is one of many, in a proportion that varies per example. That is not a rescaled gradient; it is the gradient of a different function, and it descends confidently to the wrong place.
Which is why frameworks accumulate. .grad is added into, never assigned,
and the mirror-image bug follows immediately: forget to zero it between steps
and every step’s gradient is the sum of all steps so far. Both errors come from
the same line of (I.6.2), read in opposite directions.