How to compute all second derivatives only the diagonal of the Hessian matrix in Tensorflow?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The Hessian matrix captures second-order curvature information for a scalar function, but many applications only need its diagonal entries. In TensorFlow, that usually means computing second derivatives of each gradient component with respect to the matching input variable, without spending memory on the entire dense Hessian if you do not need it.
Understand What the Diagonal Means
For a scalar function f(x) where x is a vector, the Hessian diagonal contains:
- '
d2f / dx0^2' - '
d2f / dx1^2' - and so on
Those terms tell you how curvature behaves along each coordinate independently. They are useful in optimization diagnostics, uncertainty approximations, and diagonal preconditioning methods.
TensorFlow's automatic differentiation makes this possible with nested GradientTape objects.
Compute the Diagonal with Nested Gradient Tapes
The cleanest pattern is:
- watch the input vector
- compute the scalar output
- compute the first gradient
- differentiate each gradient component again and keep the matching coordinate
For the function above, the exact second derivative per coordinate is 6x + 4, so the output should be [10, 16, 22].
This approach avoids manually writing derivatives and is easy to verify against analytic formulas.
When jacobian Is Simpler but More Expensive
TensorFlow can also build the full Hessian by taking the Jacobian of the gradient and then extracting the diagonal.
This is often shorter, but it materializes the full Hessian first. For large parameter vectors, that can be far more memory-intensive than needed.
So the tradeoff is:
- use
jacobianwhen the vector is small or code clarity matters more - use coordinate-wise second derivatives when you truly want only the diagonal
Batched Inputs Need Extra Care
If x has a batch dimension, decide what the scalar function actually is. GradientTape expects a scalar target for gradient, so you often reduce across the batch first or compute per-example diagonals deliberately.
A common pattern is to compute loss per example, then loop or vectorize over examples. The important point is to be explicit about whether you want:
- Hessian diagonal of the total loss
- Hessian diagonal per example
- Hessian diagonal with respect to model weights instead of input features
Those are different objects and can produce very different shapes.
Common Pitfalls
- Calling
gradienton a non-scalar target without understanding how TensorFlow reduces it. - Using
outer_tape.jacobianon large vectors and accidentally building a huge dense Hessian. - Forgetting
persistent=Truewhen taking multiple second-derivative queries from the same outer tape. - Mixing batch dimensions and feature dimensions without deciding which Hessian you actually want.
Summary
- The Hessian diagonal contains the second derivative of each coordinate with respect to itself.
- In TensorFlow, nested
GradientTapeobjects are the standard way to compute it. - '
jacobianplusdiag_partis simple but can allocate the full Hessian.' - A coordinate-wise second-derivative loop is often better when only the diagonal is needed.
- Be explicit about whether you are differentiating with respect to inputs, per-example losses, or model parameters.

