Gradient Checking
Gradient checking compares an automatically computed gradient with a numerical finite-difference estimate. It is a debugging tool for custom losses, custom layers, coordinate transforms, masking logic, and scientific model code.
For a scalar objective , the central finite-difference estimate for parameter is:
where is a unit vector and is a small perturbation.
Relative Error
A common comparison is:
The threshold depends on dtype, function smoothness, reduction scale, and numerical conditioning. The point is not to prove all training is correct; it is to catch broken derivative paths.
When to Use
- A custom differentiable operation is added.
- A loss has masks, weights, or reductions.
- A coordinate transform affects geometry-sensitive outputs.
- A constraint, projection, or reparameterization affects the optimized variable.
- A model uses manual gradient manipulation.
- Training diverges before basic gradients have been validated.
Pitfalls
- Finite differences are unreliable around discontinuities, argmax, hard thresholds, indexing, and random branches.
- Float32 can be too noisy; use double precision when possible.
- Stochastic layers should be disabled or seeded.
- Regularization terms and loss reductions must match exactly.
- Checking every parameter is expensive; sample representative elements.
- Projected or constrained updates may be nondifferentiable at boundaries.
Constrained Variables
For a reparameterized constrained variable:
the gradient check should usually compare derivatives with respect to , not only :
For projected updates:
finite differences can fail near the boundary of . In that case, check interior points, smooth penalty versions, or task-level invariants.
Checks
- Is the model in deterministic mode?
- Is the same scalar loss used for both automatic and numerical gradients?
- Is the perturbation appropriate for the dtype and scale?
- Are masks and constraints applied identically in both evaluations?
- Are gradients checked before running a long experiment?
- If variables are constrained, is the check performed in the right parameterization?