Purpose
A reusable derivation note for the handful of matrix-calculus facts that carry nearly all of deep learning: layout conventions, the core identities, the four gradients that appear in every training loop (affine, quadratic, least squares, softmax cross-entropy), and the JVP/VJP framing that autodiff systems actually implement. Neural Networks from Scratch and Decoder-Only Transformers use these identities implicitly; this is where they are derived.
Notation and layout
Vectors are columns. For the Jacobian follows numerator layout, the convention in Parr and Howard:
Row is the transposed gradient of output . For a scalar loss , the Jacobian is a row vector, and the gradient is its transpose, a column the same shape as . The shape-matching rule does most of the error catching: a gradient always has the shape of the thing you differentiate with respect to, so has the shape of . The Hessian is the Jacobian of the gradient, symmetric when is twice continuously differentiable.
Layout conventions differ by a transpose
There are two incompatible conventions in the literature. Numerator layout (used here and in Parr and Howard) makes ; denominator layout (common in statistics texts and parts of the Matrix Cookbook) makes it , transposing every identity. Mixing sources without checking their convention is the classic way to end up with a chain rule that multiplies in the wrong order or a gradient that is secretly a row vector. Two defenses: fix one convention per derivation, and lean on the shape rule, must have the shape of , since a shape mismatch exposes a convention mix-up immediately.
Core identities
Each identity below can be checked by writing out components; sources are Parr and Howard, the UW matrix calculus notes, and the Matrix Cookbook.
| Expression | Derivative | Notes |
|---|---|---|
| , gradient | linear form | |
| Jacobian of a linear map is the matrix | ||
| gradient | when symmetric | |
| rank-one gradient | ||
| trace trick | ||
| invertible; Gaussian log-likelihoods | ||
| elementwise product | ||
| elementwise | activations: ReLU, tanh, sigmoid |
The chain rule composes Jacobians by matrix product, outermost first: for , . Because elementwise activations have diagonal Jacobians, their factor in the chain collapses to an elementwise multiply, which is why backprop code is full of * rather than matrix products with explicit diagonals.
The four gradients that matter
Quadratic form. has gradient : differentiate with respect to and collect the two sums where appears as row or column index.
Least squares. . Chain rule with inner function (Jacobian ) and outer (gradient ):
which is where the normal equations in Orthogonality, Projections, and Least Squares come from: set it to zero.
Affine layer. For with upstream gradient :
Derivation for : , so and , the outer product. In batched code with row-vector samples the same identities transpose to and the bias gradient sums over the batch, which is the version in Neural Networks from Scratch.
Softmax cross-entropy. With logits , softmax , and one-hot target , the softmax Jacobian is . Multiplying by the cross-entropy gradient (elementwise) and using collapses the whole thing:
This cancellation is why frameworks fuse softmax and cross-entropy into one op: the fused gradient is simpler, cheaper, and numerically safer than composing the two Jacobians.
JVPs, VJPs, and why backprop runs backward
Autodiff never materializes Jacobians. It computes Jacobian products (Baydin et al. 2018):
- Forward mode computes , a Jacobian-vector product: push one input direction through the chain. Cost of one forward pass per input direction, so passes for a full gradient.
- Reverse mode computes , a vector-Jacobian product: pull one output sensitivity backward through the chain. Cost of one backward pass per output.
Training minimizes a scalar loss, , so reverse mode gets the entire gradient with respect to millions of parameters in a single backward pass, while forward mode would need one pass per parameter. That asymmetry is the whole reason backprop is reverse-mode AD. The affine-layer identities above are exactly the VJP rules: given , produce for the input and for the weights.
Verification
Every identity above, checked against autograd:
import torch
torch.manual_seed(0)
n, m = 5, 4
A = torch.randn(n, n)
x = torch.randn(n, requires_grad=True)
(x @ A @ x).backward()
assert torch.allclose(x.grad, (A + A.T) @ x) # quadratic form
M = torch.randn(m, n)
b = torch.randn(m)
x.grad = None
((M @ x - b) @ (M @ x - b)).backward()
assert torch.allclose(x.grad, 2 * M.T @ (M @ x - b)) # least squares
W = torch.randn(m, n, requires_grad=True)
xd = torch.randn(n)
delta = torch.randn(m)
(W @ xd @ delta).backward() # L = delta^T (W x)
assert torch.allclose(W.grad, torch.outer(delta, xd)) # affine: delta x^T
z = torch.randn(n, requires_grad=True)
y = torch.zeros(n); y[2] = 1.0
torch.nn.functional.cross_entropy(z, torch.tensor(2)).backward()
assert torch.allclose(z.grad, torch.softmax(z.detach(), 0) - y) # s - y
X = torch.randn(n, n, requires_grad=True)
Xs = X @ X.T + n * torch.eye(n) # make it positive definite
torch.logdet(Xs).backward()
assert torch.allclose(X.grad, 2 * torch.inverse(Xs) @ X, atol=1e-5) # chain of logdet
print("all identities verified")Sources
- Parr and Howard, The Matrix Calculus You Need For Deep Learning (arXiv:1802.01528)
- UW Matrix Calculus notes
- Petersen and Pedersen, The Matrix Cookbook
- Baydin et al. (2018), Automatic Differentiation in Machine Learning: a Survey