Skip to content

Useful Identities for Computing Gradients

Deriving matrix gradients from scratch every time is slow and error-prone. In practice you reach for a small set of identities — ready-made formulas for the gradients that appear over and over in machine learning (least squares, log-likelihoods, regularizers). This page collects the ones worth memorizing, and shows how to gradient-check any derivation numerically.

A real-life example: deriving the least-squares gradient

To fit linear regression you minimize yΦθ2\lVert \mathbf{y} - \Phi\boldsymbol\theta\rVert^2. Finding the optimum needs its gradient with respect to θ\boldsymbol\theta. Instead of expanding everything by hand, one identity — (xBx)/x=x(B+B)\partial(\mathbf{x}^\top B\mathbf{x})/\partial\mathbf{x} = \mathbf{x}^\top(B + B^\top) — plus the chain rule gets you there in two lines. These identities are the difference between a page of algebra and a one-liner.

The cheat sheet

Here tr\text{tr} is the trace, det\det the determinant, and f(X)1f(X)^{-1} the inverse (assumed to exist). a,b\mathbf{a}, \mathbf{b} are constant vectors; B,WB, W constant matrices.

Vector-in identities (the ones you’ll use most):

(xa)x=a,(ax)x=a,(xBx)x=x(B+B).\frac{\partial (\mathbf{x}^\top \mathbf{a})}{\partial \mathbf{x}} = \mathbf{a}^\top, \qquad \frac{\partial (\mathbf{a}^\top \mathbf{x})}{\partial \mathbf{x}} = \mathbf{a}^\top, \qquad \frac{\partial (\mathbf{x}^\top B \mathbf{x})}{\partial \mathbf{x}} = \mathbf{x}^\top(B + B^\top).
s(xAs)W(xAs)=2(xAs)WA(for symmetric W).\frac{\partial}{\partial \mathbf{s}} (\mathbf{x} - A\mathbf{s})^\top W (\mathbf{x} - A\mathbf{s}) = -2(\mathbf{x} - A\mathbf{s})^\top W A \quad (\text{for symmetric } W).

Matrix-in identities:

(aXb)X=ab,Xtr(f(X))=tr ⁣(f(X)X),\frac{\partial (\mathbf{a}^\top X \mathbf{b})}{\partial X} = \mathbf{a}\mathbf{b}^\top, \qquad \frac{\partial}{\partial X}\text{tr}(f(X)) = \text{tr}\!\left(\frac{\partial f(X)}{\partial X}\right),
Xdet(f(X))=det(f(X))tr ⁣(f(X)1f(X)X),Xf(X)1=f(X)1f(X)Xf(X)1.\frac{\partial}{\partial X}\det(f(X)) = \det(f(X))\,\text{tr}\!\left(f(X)^{-1}\frac{\partial f(X)}{\partial X}\right), \qquad \frac{\partial}{\partial X} f(X)^{-1} = -f(X)^{-1}\frac{\partial f(X)}{\partial X}f(X)^{-1}.

The two most-used in everyday ML are (ax)/x=a\partial(\mathbf{a}^\top\mathbf{x})/\partial\mathbf{x} = \mathbf{a}^\top (linear terms) and (xBx)/x=x(B+B)\partial(\mathbf{x}^\top B\mathbf{x})/\partial\mathbf{x} = \mathbf{x}^\top(B + B^\top) (quadratic terms). For symmetric BB the latter simplifies to 2xB2\mathbf{x}^\top B.

The safety net: gradient checking

However you derive a gradient, verify it numerically. Compare your analytic gradient to a finite-difference approximation:

fxif(x+hei)f(x)h.\frac{\partial f}{\partial x_i} \approx \frac{f(\mathbf{x} + h\mathbf{e}_i) - f(\mathbf{x})}{h}.

But there’s a catch: too-large hh has truncation error; too-small hh has floating-point round-off error. The total error is a V-shape with a sweet spot in the middle. Watch the error sweep as hh shrinks — it drops, bottoms out (~10810^{-8} for forward differences), then rises again as round-off takes over:

sketch Gradient checking: the error sweet spot p5.js
Error between the finite-difference approximation and the true derivative, as step size h shrinks (log-log). Large h → truncation error; tiny h → floating-point round-off. The minimum is the best h to gradient-check with.

The practical rule: use h106h \approx 10^{-6} to 10810^{-8} for forward differences, and flag a bug if the relative error numericanalyticnumeric+analytic\frac{\lVert \text{numeric} - \text{analytic}\rVert}{\lVert \text{numeric} + \text{analytic}\rVert} exceeds 106\sim 10^{-6}.

diagram Diagram mermaid

NumPy: using identities and gradient checking

identities.py
import numpy as np
 
# Identity: ∂(xᵀ B x)/∂x = xᵀ(B + Bᵀ);  for symmetric B this is 2 xᵀ B
B = np.array([[2.0, 1.0], [1.0, 3.0]])       # symmetric
x = np.array([1.0, 2.0])
 
analytic = x @ (B + B.T)                       # = 2 xᵀB here
print("analytic gradient:", analytic)
 
# Gradient check with finite differences
def f(v): return v @ B @ v
def numeric_grad(f, x, h=1e-6):
    g = np.zeros_like(x)
    for i in range(len(x)):
        xp = x.copy(); xp[i] += h
        g[i] = (f(xp) - f(x)) / h
    return g
 
num = numeric_grad(f, x)
print("numeric  gradient:", np.round(num, 4))
rel = np.linalg.norm(num - analytic) / np.linalg.norm(num + analytic)
print("relative error:", f"{rel:.2e}", "-> OK" if rel < 1e-4 else "-> BUG")
identities.py
import numpy as np
 
# Identity: ∂(xᵀ B x)/∂x = xᵀ(B + Bᵀ);  for symmetric B this is 2 xᵀ B
B = np.array([[2.0, 1.0], [1.0, 3.0]])       # symmetric
x = np.array([1.0, 2.0])
 
analytic = x @ (B + B.T)                       # = 2 xᵀB here
print("analytic gradient:", analytic)
 
# Gradient check with finite differences
def f(v): return v @ B @ v
def numeric_grad(f, x, h=1e-6):
    g = np.zeros_like(x)
    for i in range(len(x)):
        xp = x.copy(); xp[i] += h
        g[i] = (f(xp) - f(x)) / h
    return g
 
num = numeric_grad(f, x)
print("numeric  gradient:", np.round(num, 4))
rel = np.linalg.norm(num - analytic) / np.linalg.norm(num + analytic)
print("relative error:", f"{rel:.2e}", "-> OK" if rel < 1e-4 else "-> BUG")
text
analytic gradient: [ 8. 14.]
numeric  gradient: [ 8.     14.0001]
relative error: 3.02e-06 -> OK
text
analytic gradient: [ 8. 14.]
numeric  gradient: [ 8.     14.0001]
relative error: 3.02e-06 -> OK

Why this matters for ML

  • Deriving loss gradients (regression, logistic regression, Gaussian likelihoods) is fast with these identities instead of index-by-index calculus.
  • Gradient checking is the standard sanity test when implementing a custom layer or loss — it catches sign errors and transpose mistakes instantly.
  • Understanding the identities helps you read papers where gradients are stated without derivation.

🧪 Try It Yourself

Exercise 1 – Linear-term identity

Exercise 2 – Quadratic-form identity

Exercise 3 – Gradient check a derivation

Recap

  • A handful of identities (ax\mathbf{a}^\top\mathbf{x}, xBx\mathbf{x}^\top B\mathbf{x}, trace, determinant, inverse) cover most ML gradient derivations.
  • Always gradient-check against finite differences; watch for the truncation/round-off trade-off (best h106h \approx 10^{-6}10810^{-8}).
  • These tools turn page-long derivations into one-liners and catch bugs instantly.

Next: how frameworks compute these gradients automatically at scale — Backpropagation and Automatic Differentiation.

If this helped you, consider buying me a coffee ☕

Buy me a coffee

Was this page helpful?

Let us know how we did