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?