02

The Math You Actually Need

Cantonese podcast title: 數學基礎

Learning Objectives

  1. Given a differentiable map f:Rm→Rnf: \mathbb{R}^m \to \mathbb{R}^n, write the Jacobian
  2. Prove that ∇f(x)\nabla f(x) is the direction of steepest *ascent* of ff at xx, and
  3. For a joint distribution p(x,y)p(x, y), write Bayes' theorem as a reweighting of the
  4. Name the assumption whose violation breaks the chain rule (non-differentiability),
  5. Translate any expression in this lesson into runnable NumPy code, and predict the
The Math You Actually Need — visual guide
The matrix as a linear map and the Jacobian as the matrix derivative A diagram showing two parallel vector spaces R^m and R^n connected by a linear map A: a vector x in R^m is mapped to y = Ax in R^n. Below, a chain of two maps g and f, with their Jacobians J_g and J_f, illustrates the matrix-product chain rule J_{g o f} = J_g J_f. Linear map A : ℝ^m → ℝ^n ℝ^m x A · x ℝ^n y = A x A = a₁₁ a₁₂ a₁₃ a₁₄ a₂₁ a₂₂ a₂₃ a₂₄ n × m matrix of numbers (representation, not the object) Chain rule J_{g ○ f} = J_g · J_f ℝ^m domain of f x ∈ ℝ^m ℝ^n image of f = domain of g f(x) ℝ^p image of g ○ f g(f(x)) f J_f ∈ ℝ^{n×m} g J_g ∈ ℝ^{p×n} compose left-to-right → multiply Jacobians left-to-right

Assumes you know from ML-101

You have completed ML-101 lesson 3 — Linear Regression, where you met the normal equation; ML-101 lesson 11 — Gradient Descent & Optimization, where you saw that ∇f(x)\nabla f(x) points uphill; and ML-101 lesson 14 — Neural Networks & Backprop, where the chain rule ∂L/∂w=∂L/∂a⋅∂a/∂w\partial L / \partial w = \partial L / \partial a \cdot \partial a / \partial w was applied without comment. This lesson does not re-derive those facts from the foundations of real analysis. Instead it re-states them in the language that the rest of ML-201 will use: linear maps between finite-dimensional spaces, Jacobians as the matrix form of the chain rule, and gradients as the Riesz representer of the differential. The aim is not to teach new symbols; it is to fix the meaning of the symbols you already use, so that every later derivation in ML-201 can speak in the same vocabulary.

Learning Objectives

  1. Given a differentiable map f:Rm→Rnf: \mathbb{R}^m \to \mathbb{R}^n, write the Jacobian Jf(x)J_f(x) as the n×mn \times m matrix of partial derivatives, and state the chain rule for the composition g∘fg \circ f as a matrix product.
  2. Prove that ∇f(x)\nabla f(x) is the direction of steepest ascent of ff at xx, and translate that proof into the algorithm "negative gradient descent".
  3. For a joint distribution p(x,y)p(x, y), write Bayes' theorem as a reweighting of the prior p(y)p(y) by the likelihood ratio p(x∣y)/p(x)p(x \mid y) / p(x), and identify the place in the calculation where the marginal p(x)=∑yp(x∣y)p(y)p(x) = \sum_y p(x \mid y) p(y) is intractable.
  4. Name the assumption whose violation breaks the chain rule (non-differentiability), breaks the gradient-as-steepest-ascent statement (non-Euclidean norm), and breaks Bayes' theorem (zero measure on the conditioning event).
  5. Translate any expression in this lesson into runnable NumPy code, and predict the shape of every intermediate array.

Linear maps and the matrix as function

A matrix A∈Rn×mA \in \mathbb{R}^{n \times m} is not a grid of numbers. It is a function A:Rm→RnA: \mathbb{R}^m \to \mathbb{R}^n, defined by the rule A(x)=AxA(x) = Ax, with the properties that AA is linear (A(αu+βv)=αAu+βAvA(\alpha u + \beta v) = \alpha A u + \beta A v) and continuous (which on a finite-dimensional space follows from linearity plus a bounded operator norm). The grid-of-numbers picture is the representation of AA in the standard basis; the picture that supports every later derivation is "linear function from one vector space to another".

The matrix-vector product y=Axy = Ax has a concrete shape rule: the ii-th row of AA is dotted with xx to produce the ii-th entry of yy. The ii-th column of AA is the image of the ii-th standard basis vector eie_i. The shape rule is the same when you swap AA for A⊤A^\top: now rows become columns, and A⊤:Rn→RmA^\top: \mathbb{R}^n \to \mathbb{R}^m. This is the source of the backprop shape convention: in a two-layer network y=W2 σ(W1x+b1)+b2y = W_2 \, \sigma(W_1 x + b_1) + b_2, the weight W2W_2 maps hidden activations to outputs, and the gradient of the loss with respect to W1W_1 must be the product of matrices whose shapes match the rule — not the product of any two adjacent matrices.

The matrix-as-function picture is what makes a non-square matrix coherent. A∈Rn×mA \in \mathbb{R}^{n \times m} maps a 12-dimensional input to a 4-dimensional output in one application, with no iteration and no implicit "filling in". When you see AA with n≠mn \neq m, ask which space is the domain and which is the codomain — the question is unambiguous once AA is read as a function.

Three consequences matter for the rest of the course:

  1. Rank is a function statement. rank(A)=dim⁡im(A)\mathrm{rank}(A) = \dim \mathrm{im}(A), which is at most min⁡(n,m)\min(n, m) and equals that bound iff AA is surjective onto its image. Rank deficiency is not "small numbers in the determinant"; it is the non-existence of a pre-image for some output.
  2. Singular values measure stretch. ∥A∥2=σmax⁡(A)\|A\|_2 = \sigma_{\max}(A) is the largest factor by which AA stretches any unit vector, and the singular vectors are the directions in which that maximum is attained. The condition number κ(A)=σmax⁡(A)/σmin⁡(A)\kappa(A) = \sigma_{\max}(A)/\sigma_{\min}(A) is the ratio of the largest to the smallest stretch. It controls the speed of gradient descent: under the spectral bound on ∇2f\nabla^2 f, convergence in κ\kappa times the optimal steps is required for O(κlog⁡(1/ε))O(\kappa \log(1/\varepsilon)) iteration complexity.
  3. Transpose is the adjoint. ⟨Ax,y⟩=⟨x,A⊤y⟩\langle Ax, y \rangle = \langle x, A^\top y\rangle, with respect to the standard inner product. This identity is the bridge between the matrix-as-function picture and the gradient-as-linear-functional picture in the next section.

Jacobians and the chain rule, in matrix form

For f:Rm→Rnf: \mathbb{R}^m \to \mathbb{R}^n differentiable at xx, the Jacobian is the matrix

Jf(x)  =  [∂f1/∂x1⋯∂f1/∂xm⋮⋮∂fn/∂x1⋯∂fn/∂xm]  ∈  Rn×m.J_f(x) \;=\; \begin{bmatrix} \partial f_1 / \partial x_1 & \cdots & \partial f_1 / \partial x_m \\ \vdots & & \vdots \\ \partial f_n / \partial x_1 & \cdots & \partial f_n / \partial x_m \end{bmatrix} \;\in\; \mathbb{R}^{n \times m}.

The ii-th row of Jf(x)J_f(x) is the gradient of the ii-th scalar component fi:Rm→Rf_i : \mathbb{R}^m \to \mathbb{R}. The Jacobian is the linear approximation to ff at xx:

f(x+h)  =  f(x)+Jf(x) h+o(∥h∥).f(x + h) \;=\; f(x) + J_f(x)\, h + o(\|h\|).

This is a Taylor expansion up to first order, with the Jacobian playing the role the derivative plays for scalar functions. The full statement of differentiability at xx is exactly this limit, with o(∥h∥)o(\|h\|) meaning a term whose magnitude is negligible relative to ∥h∥\|h\|.

The chain rule in matrix form is the statement that the Jacobian of a composition is the product of Jacobians. If g:Rn→Rpg: \mathbb{R}^n \to \mathbb{R}^p and f:Rm→Rnf: \mathbb{R}^m \to \mathbb{R}^n, then

Jg∘f(x)  =  Jg(f(x))⋅Jf(x).J_{g \circ f}(x) \;=\; J_g(f(x)) \cdot J_f(x).

The dimensions check: Jf(x)∈Rn×mJ_f(x) \in \mathbb{R}^{n \times m}, Jg(f(x))∈Rp×nJ_g(f(x)) \in \mathbb{R}^{p \times n}, and the product lives in Rp×m\mathbb{R}^{p \times m}, which is the correct shape for the Jacobian of g∘fg \circ f. This is the single line that backs backpropagation in ML-201 lesson 4: every backprop step is a matrix product along a path in the computational graph, and the matrix product is literally the chain rule, not an analogy.

The scalar case is recovered when n=1n = 1. Then Jf(x)∈R1×mJ_f(x) \in \mathbb{R}^{1 \times m}, which is conventionally written as a row vector and identified with the gradient ∇f(x)⊤\nabla f(x)^\top when ff is scalar-valued. The chain rule for scalar f:R→Rf: \mathbb{R} \to \mathbb{R} reduces to (f∘g)′(x)=f′(g(x))⋅g′(x)(f \circ g)'(x) = f'(g(x)) \cdot g'(x), which is the form taught in ML-101 lesson 11. The matrix form is the correct generalisation; the scalar form is what survives when the intermediate space is one-dimensional.

import numpy as np

def numerical_jacobian(f, x, h=1e-5):
    """Central-difference estimate of the Jacobian of vector-valued f at x.

    f: R^m -> R^n. Returns an (n, m) matrix. The estimate is O(h^2) per entry.
    """
    x = np.asarray(x, dtype=float)
    n = len(f(x))
    m = len(x)
    J = np.zeros((n, m))
    for j in range(m):
        ej = np.zeros_like(x); ej[j] = h
        J[:, j] = (f(x + ej) - f(x - ej)) / (2 * h)
    return J

# Example: f(x) = (x_0^2, x_0 * x_1, exp(x_1)).
f = lambda x: np.array([x[0] ** 2, x[0] * x[1], np.exp(x[1])])
x0 = np.array([0.7, -0.4])
J_num = numerical_jacobian(f, x0)
J_ana = np.array([
    [2 * x0[0], 0.0],        # d/dx of x_0^2
    [x0[1],    x0[0]],       # d/dx of x_0 * x_1
    [0.0,      np.exp(x0[1])]
])
print("max abs error:", float(np.abs(J_num - J_ana).max()))

The assumption whose violation breaks the chain rule is differentiability at the evaluation point. If gg has a kink at xx (a ReLU evaluated exactly at zero, for instance), the Jacobian does not exist there and the chain rule has nothing to multiply. The 201-level fix is sub-derivative or Clarke generalised Jacobian, which is a different theory and a different product rule; the 101-level fix is "treat the kink as one-sided" and pretend the chain rule still holds — it does not.

Gradient as steepest ascent

For a scalar function f:Rm→Rf: \mathbb{R}^m \to \mathbb{R}, the gradient is the vector

∇f(x)  =  (∂f∂x1, …, ∂f∂xm)⊤  ∈  Rm.\nabla f(x) \;=\; \left(\frac{\partial f}{\partial x_1},\, \dots,\, \frac{\partial f}{\partial x_m}\right)^\top \;\in\; \mathbb{R}^m.

The first-order Taylor expansion gives f(x+h)≈f(x)+∇f(x)⊤hf(x + h) \approx f(x) + \nabla f(x)^\top h. To maximise this linear approximation over unit vectors hh with ∥h∥2=1\|h\|_2 = 1, write h=(∇f/∥∇f∥)cos⁡θ+(∇f⊥/∥∇f⊥∥)sin⁡θh = (\nabla f / \|\nabla f\|) \cos\theta + (\nabla f^\perp / \|\nabla f^\perp\|) \sin\theta, where θ\theta is the angle between hh and ∇f\nabla f. The linear term becomes ∥∇f∥cos⁡θ\|\nabla f\| \cos\theta, which is maximised at θ=0\theta = 0, giving the maximiser h⋆=∇f/∥∇f∥h^\star = \nabla f / \|\nabla f\| and the maximum value ∥∇f∥\|\nabla f\|. So ∇f\nabla f points uphill, and −∇f-\nabla f points downhill; the gradient descent step xk+1=xk−α∇f(xk)x_{k+1} = x_k - \alpha \nabla f(x_k) is exactly steepest descent.

The argument is more subtle than ML-101 presented. The conclusion "gradient points uphill" is true under the Euclidean norm. If the descent step uses a different norm — say the dual norm of a weighted ℓ2\ell_2, or the ℓ1\ell_1 norm — then the direction of steepest descent is not the negative gradient; it is −∇LH(x)-\nabla^L H(x), where ∇LH(x)\nabla^L H(x) is the vector solving ⟨∇LH(x),v⟩≤∥v∥\langle \nabla^L H(x), v\rangle \le \|v\| for all vv, with equality on the minimiser. This is the entire mathematical content of mirror descent, natural-gradient descent, and Hessian-aware optimisation, all of which would be incoherent under the 101-level claim "the negative gradient is always the steepest direction".

import numpy as np

def gradient_descent(f, grad_f, x0, lr=1e-2, n_steps=200):
    """Plain Euclidean gradient descent: x_{k+1} = x_k - lr * grad_f(x_k)."""
    x = np.asarray(x0, dtype=float).copy()
    history = [x.copy()]
    for _ in range(n_steps):
        x = x - lr * grad_f(x)        # negative gradient = direction of steepest DESCENT
        history.append(x.copy())
    return x, np.asarray(history)

# Toy quadratic f(x) = 0.5 x^T A x, with grad f(x) = A x.
A = np.array([[3.0, 1.0], [1.0, 2.0]])
f      = lambda x: 0.5 * x @ A @ x
grad_f = lambda x: A @ x

x_star, path = gradient_descent(f, grad_f, x0=np.array([4.0, -3.0]), lr=0.2)
print("final x:", x_star.round(6))   # should approach [0, 0] (the unique minimiser)

The deeper 201-level point is that the gradient is the Riesz representer of the differential. For every continuous linear functional L:Rm→RL: \mathbb{R}^m \to \mathbb{R}, there is a unique vector v∈Rmv \in \mathbb{R}^m such that L(h)=v⊤hL(h) = v^\top h for all hh. The differential df(x):Rm→Rdf(x): \mathbb{R}^m \to \mathbb{R} is such a linear functional; its Riesz representer is the gradient. This definition is independent of basis, and that basis-independence is why the gradient is the same object in Rm\mathbb{R}^m and in the parameter space of a model, and why the chain rule can be expressed without choosing coordinates.

Conditional probability and Bayes' theorem, derived

Conditional probability is defined, in the measure-theoretic foundations, by

p(A∣B)  =  p(A∩B)p(B),p(A \mid B) \;=\; \frac{p(A \cap B)}{p(B)},

provided p(B)>0p(B) > 0. The conditional probability p(A∣B)p(A \mid B) is not an independent primitive; it is defined in terms of the joint. ML-101 used this definition to compute p(A∣B)p(A \mid B) in tabular examples; ML-201 uses it to derive Bayes' theorem, which is a corollary of the definition:

p(y∣x)  =  p(x∣y) p(y)p(x),p(x)  =  ∑yp(x∣y) p(y).p(y \mid x) \;=\; \frac{p(x \mid y)\, p(y)}{p(x)}, \qquad p(x) \;=\; \sum_y p(x \mid y)\, p(y).

The numerator is the joint; the denominator is the marginal of the joint over yy. This is not a profound identity. It is a reweighting of the prior p(y)p(y) by the likelihood ratio p(x∣y)/p(x)p(x \mid y) / p(x). Every "Bayesian" calculation is this reweighting, and the only hard part is computing the marginal in the denominator.

import numpy as np

def bayes_predict(prior: np.ndarray, likelihood: np.ndarray) -> np.ndarray:
    """Posterior p(y | x) given prior p(y) (shape (k,)) and likelihood p(x | y) (shape (n, k)).

    Each column j is the n-vector of p(x | y=j). Returns posterior of shape (n, k).
    """
    joint = likelihood * prior[None, :]                    # shape (n, k), elementwise
    marginal = joint.sum(axis=1, keepdims=True)            # shape (n, 1)
    return joint / marginal                                  # shape (n, k), normalised

# Toy: 3 classes, 5 input bins.
prior     = np.array([0.5, 0.3, 0.2])                     # p(y)
likelihood = np.array([[0.10, 0.20, 0.30],
                       [0.30, 0.20, 0.10],
                       [0.40, 0.30, 0.20],
                       [0.10, 0.20, 0.30],
                       [0.10, 0.10, 0.10]])               # p(x | y)
posterior = bayes_predict(prior, likelihood)
print("posterior row sums (should all be 1):", posterior.sum(axis=1).round(6))

The intractable marginal is the reason variational methods exist. When yy is continuous, the sum becomes an integral, and ∫p(x∣y)p(y) dy\int p(x \mid y) p(y)\, dy has no closed form for almost any model of practical interest. The expectation Ep(y)[f(y)]\mathbb{E}_{p(y)}[f(y)] under that integral is what the sampler or the variational approximation is computing. The derivation is one line; the work is the integral.

The assumption whose violation breaks Bayes' theorem is p(x)=0p(x) = 0 for the observed xx. If the support of p(x)p(x) does not contain the observation, then p(x∣y)p(x \mid y) is undefined on that xx for every yy, and the conditional p(y∣x)p(y \mid x) is not a probability at all. In practice this is rare; in theory it matters, because a model whose likelihood vanishes on the test set is a model that cannot be evaluated on the test set. The 101-level mistake is to compute p(y∣x)p(y \mid x) by plugging in xx without checking that xx is in the support; the 201-level fix is to assert the support assumption explicitly.

The five shape rules that catch every bug

The chain rule in matrix form has five shape rules that, memorised once, catch every "shape mismatch" bug in every later derivation in ML-201.

ComputationShape ruleFailure mode if violated
y=Wxy = W xW∈Rn×m,x∈Rm⇒y∈RnW \in \mathbb{R}^{n \times m}, x \in \mathbb{R}^m \Rightarrow y \in \mathbb{R}^nMismatched inner dimension; multiplication undefined
∂L/∂W\partial L / \partial W for y=Wxy = W x∂L/∂y∈Rn,x∈Rm⇒∂L/∂W∈Rn×m\partial L / \partial y \in \mathbb{R}^{n}, x \in \mathbb{R}^m \Rightarrow \partial L / \partial W \in \mathbb{R}^{n \times m}Wrong broadcast rule; off-by-one in axis argument
∂L/∂x\partial L / \partial x for y=Wxy = W x∂L/∂y∈Rn,W∈Rn×m⇒∂L/∂x∈Rm\partial L / \partial y \in \mathbb{R}^{n}, W \in \mathbb{R}^{n \times m} \Rightarrow \partial L / \partial x \in \mathbb{R}^mForget the transpose; gradient against WW
∂L/∂x\partial L / \partial x for y=x⊙xy = x \odot x (Hadamard)∂L/∂y∈Rn⇒∂L/∂x∈Rn\partial L / \partial y \in \mathbb{R}^n \Rightarrow \partial L / \partial x \in \mathbb{R}^nMultiply instead of Hadamard; shapes can match but math is wrong
∂L/∂x\partial L / \partial x for y=W⊤xy = W^\top x∂L/∂y∈Rn,W⊤∈Rn×m⇒∂L/∂x∈Rm\partial L / \partial y \in \mathbb{R}^n, W^\top \in \mathbb{R}^{n \times m} \Rightarrow \partial L / \partial x \in \mathbb{R}^mConfuse WW and W⊤W^\top direction of multiplication

These five rules are stated here as a reference; the lesson 4 derivation of backprop uses every one of them. A learner who can read a derivation and verify each rule against the table is a learner who will not need a debugger to find the shape mismatch. A learner who cannot is a learner who will spend a working day on what is actually a one-minute check.

The deeper statement, which is not on the table but which the table makes concrete, is that the chain rule is always the same chain rule. Every "advanced" gradient — through attention, through convolution, through a recurrent cell — is the same matrix product along the path of the computation, with the same shape rules. There is no special gradient for attention; the attention gradient is the chain rule applied to a particular factorisation of the matrix product. ML-201 lesson 4 makes this explicit by deriving backprop for a two-layer network and then generalising to arbitrary graphs.

Key Takeaways

  • A matrix A∈Rn×mA \in \mathbb{R}^{n \times m} is a linear function A:Rm→RnA: \mathbb{R}^m \to \mathbb{R}^n, not a grid of numbers. Read it as a function and the rest of the lesson follows.
  • The Jacobian is the matrix form of the derivative, and the chain rule is the matrix product. Every backprop step is one matrix product along one path in the computational graph.
  • The gradient is the Riesz representer of the differential, and points uphill only under the Euclidean norm. Mirror descent uses a different norm and gets a different "steepest" direction.
  • Bayes' theorem is the reweighting of a prior by a likelihood ratio, with a marginal in the denominator that is intractable for almost any model of practical interest. The integral is the work.
  • Memorise the five shape rules. They catch every "shape mismatch" bug in every later derivation, and they are the only piece of memorisation the lesson asks for.

Check your understanding

7 questions · 80% to complete the lesson

1 / 7

6 correct to pass

A matrix A∈Rn×mA \in \mathbb{R}^{n \times m} is best understood as what kind of mathematical object?

0 of 7 answered

Pick a lesson to start the audio.