←Home KnowML
FoundationsChapter 01

Math & Stats Foundations

Every model you train runs one loop: predict, score the error, find which way is downhill, take a step. This chapter builds that loop by hand on a two-parameter model, and picks up the linear algebra, calculus, probability and information theory each stage needs.

28 min read Assumes: none. This is the base layer the rest of the site builds on
Start reading

Say you're building the arrival estimate for a delivery app. You have three past orders: 1 km took 12 minutes, 2 km took 15, and 3 km took 20.

You guess a rule: minutes = 3 × km + 5. That's a model with two numbers in it, a slope and an intercept. It predicts 8, 11 and 14 minutes, and every one of those is too short. What now?

Three questions come up, in this order:

  • How wrong is it, as one number? You can't tell whether a change helped unless you can score it. Square each miss and average: (16 + 16 + 36) / 3 ≈ 22.67.
  • Which way should the 3 and the 5 move? You could nudge each one and watch the score, but a model with a billion parameters would need a billion extra evaluations per step.
  • How far should they move? Too little and training crawls. Too far and the next guess is worse.

A quieter question hides behind the first. Why square the misses at all? If the target were yes or no ("will this order be late?"), would squaring still be a good score? It isn't, and seeing why takes probability.

Each question belongs to a branch of math you may have met separately. Linear algebra holds the data and computes every prediction at once. Calculus finds the direction that lowers the score. Probability says what "wrong" should mean for your kind of target, and information theory turns that into a loss. Optimization decides the step, and explains why some problems take three steps and others take three hundred.

The same stages train a linear regression in scikit-learn and a GPT-style language model. Section 01 lays out the loop, sections 02 to 06 build each piece on the delivery model with numbers you can check on paper, and section 07 covers what goes wrong on data the model hasn't seen.

What you'll be able to do

Take a gradient step by hand, explain why classifiers train with cross-entropy, get a base-rate Bayes question right, and trace a bad loss curve back to its cause.

01One loop, five toolkits

Here's the loop, run once on the delivery model. Every number in it gets derived later.

1.1 One training step

One step of training, starting from slope 3 and intercept 5
  1. Linear algebra · predictOne matrix product gives all three predictions: 8, 11 and 14 minutes.
  2. Probability · choose the scoreAssume Gaussian noise on the minutes. That assumption turns into squared error.
  3. ScoreThe loss is 22.67. For a yes/no target the same reasoning gives cross-entropy, information theory's price for surprise.
  4. Calculus · differentiateThe gradient is −20 for the slope, −9.33 for the intercept. Both negative, so both should rise.
  5. Optimization · stepWith a learning rate of 0.05, the slope becomes 4.0, the intercept 5.47, and the loss drops to 5.06.
  6. RepeatAfter 300 steps the loss is 0.223. The best possible is 0.222.
A language model runs the same stages. The matrix is bigger, the score is cross-entropy over a vocabulary, and the step is Adam.

Why does the score have to be a single number?

Because "downhill" needs one hill. Score a model on accuracy and speed at once and a change can help one and hurt the other, with no single direction to move in. So training collapses its goals into one scalar, the loss. If you care about two things, you add them with a weight, and picking that weight is your call.

1.2 Where these ideas came from

None of this was invented for deep learning. The field borrowed each piece from older math.

YearIdeaUsed for
1763Bayes' theorem, published after Thomas Bayes' death, communicated to the Royal Society by Richard PriceUpdating beliefs; priors as regularizers
1847Cauchy's method of steepest descent, for solving systems of equationsThe ancestor of gradient descent
1948Shannon's "A Mathematical Theory of Communication" defines entropyEntropy, cross-entropy, mutual information
1986Rumelhart, Hinton & Williams popularize backpropagation (the chain rule is centuries older)Every gradient in a network from one backward pass
2014Kingma & Ba publish AdamWith AdamW, the optimizer behind most large models

02Linear algebra: holding the data and the model

Three orders fit in your head. A million don't, and a GPU is only fast on numbers laid out in regular arrays. Linear algebra is the bookkeeping for those arrays, plus a few facts about them that turn out to control training.

2.1 Vectors, matrices, and one product

A vector is a list of numbers, a matrix is a table of them, and a tensor has any number of axes. A batch of colour images is a 4-D tensor of shape (batch, height, width, channels).

Here's the delivery data as a matrix $X$, one row per order, times the parameters $\theta$:

$$X\theta = \begin{bmatrix} 1 & 1 \\ 2 & 1 \\ 3 & 1 \end{bmatrix} \begin{bmatrix} 3 \\ 5 \end{bmatrix}$$ $$= \begin{bmatrix} 1\cdot 3 + 1\cdot 5 \\ 2\cdot 3 + 1\cdot 5 \\ 3\cdot 3 + 1\cdot 5 \end{bmatrix} = \begin{bmatrix} 8 \\ 11 \\ 14 \end{bmatrix}$$

Each prediction is a dot product, one row times $\theta$, multiplied entry by entry and summed. The column of ones folds the intercept into the product, so it's one more weight and every formula below treats both parameters alike.

2.2 Norms: the size of a miss

Predictions minus targets gives the error vector $e = (-4, -4, -6)$. A norm measures a vector's size, and two come up constantly:

  • L2, $\|e\|_2 = \sqrt{\sum_i e_i^2}$, the ordinary length: $\sqrt{68} \approx 8.25$.
  • L1, $\|e\|_1 = \sum_i |e_i|$, the sum of absolute values: 14.

Mean squared error is the squared L2 norm over the number of examples, $68/3 \approx 22.67$. Put the parameters inside the same norms and you get L2 and L1 regularization; section 04 shows where each comes from.

Dot products also measure alignment. Divided by both lengths, $\frac{a\cdot b}{\|a\|\,\|b\|}$ is the cosine similarity, from −1 to 1. A projection uses the same number to ask how much of one vector lies along another. Attention (08) is built on this: a large query-key dot product means "this token is relevant to me".

2.3 Eigenvectors, SVD and PCA

Most matrices rotate and stretch. An eigenvector is a direction a matrix only stretches, $Av = \lambda v$, and the eigenvalue $\lambda$ is the stretch factor. For the delivery data, the matrix that matters later is $X^\top X$:

$$X^\top X = \begin{bmatrix} 1+4+9 & 1+2+3 \\ 1+2+3 & 1+1+1 \end{bmatrix}$$ $$= \begin{bmatrix} 14 & 6 \\ 6 & 3 \end{bmatrix}$$ $$\lambda = \frac{17 \pm \sqrt{17^2 - 4\cdot 6}}{2} \approx 16.64,\ 0.36$$

(A 2×2 matrix's eigenvalues come from its trace, 17, and determinant, $14\cdot3 - 6\cdot6 = 6$.) One direction is stretched 46 times more than the other. Section 06 shows that ratio is why this tiny model needs hundreds of steps.

SVD extends the idea to any matrix: $A = U\Sigma V^\top$, a rotation, a scaling, and another rotation. PCA is SVD on mean-centred data. The top eigenvectors of the covariance matrix are the directions the data varies along most, so projecting onto the first few gives the best linear summary in fewer dimensions.

Design implication

Subtract the mean distance (2 km) from every input and $X^\top X$ becomes $\begin{bmatrix} 2 & 0 \\ 0 & 3 \end{bmatrix}$, a ratio of 1.5 instead of 46, and this one preprocessing line is why pipelines standardize their features. Section 06 shows it cutting convergence from 90 steps to 3.

03Calculus: which way is downhill

You have a score and two knobs. Calculus tells you how the score changes when you turn each knob slightly, without trying every setting.

3.1 Derivatives and the gradient

A derivative is a local slope. You can measure one: raise $w$ from 3 to 3.001 and the loss goes from 22.66667 to 22.64667. That's −0.02 per 0.001, so the loss falls about 20 for each unit of $w$. The exact version, with $e_i = wx_i + b - y_i$ and $L = \frac{1}{n}\sum_i e_i^2$:

$$\begin{aligned}\frac{\partial L}{\partial w} &= \frac{2}{n}\sum_i e_i x_i \\ &= \frac{2}{3}\big((-4)(1) + (-4)(2) + (-6)(3)\big) = -20\end{aligned}$$ $$\frac{\partial L}{\partial b} = \frac{2}{n}\sum_i e_i = \frac{2}{3}(-14) \approx -9.33$$

A partial derivative holds every other input fixed. Stack them and you have the gradient, $\nabla L = (-20, -9.33)$. In matrix form it's $\frac{2}{n}X^\top e$, and $X^\top e = (-30, -14)$ gives the same numbers.

Why walk against the gradient?

The gradient points where the loss rises fastest, so its negative is where it falls fastest, at least for a small step. Both components are negative here, so both parameters should go up. That fits: every prediction was too short.

3.2 One gradient step by hand

The update subtracts the gradient times a learning rate $\eta$. With $\eta = 0.05$:

$$w = 3 - 0.05 \times (-20) = 4.0, \qquad b = 5 - 0.05 \times (-9.33) \approx 5.47$$

The predictions become 9.47, 13.47 and 17.47, and the loss falls from 22.67 to 5.06. One step removed 78% of the error. That pace doesn't last:

StepSlope wIntercept bLoss
03.005.0022.67
14.005.475.06
54.745.900.67
504.456.650.37
3004.027.620.223
best fit4.007.670.222

Watch the slope: it hits the best value, 4.0, after one step, climbs to 4.74, and takes hundreds of steps to come back. The parameters are coupled: while the intercept is too low, a steeper slope is the fastest way to lengthen predictions. Section 06 explains the slow tail.

3.3 The chain rule is backpropagation

A neural network is formulas nested inside formulas, and the chain rule, $\frac{d}{dx}f(g(x)) = f'(g(x))\cdot g'(x)$, says how to differentiate through the nesting. For one weight, through whatever sits between it and the loss, it's a product of local derivatives:

$$\frac{\partial L}{\partial w} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial z} \cdot \frac{\partial z}{\partial w}$$

Here $\hat y$ is the output and $z$ the pre-activation of the layer $w$ lives in. Each layer in between adds one factor. On the delivery model it looks like this:

Forward and backward through the delivery model, for the slope w
  1. ForwardCompute and keep each value. Order 1: ŷ = 3·1 + 5 = 8, error e = −4.
  2. ForwardLoss from all three errors: (16 + 16 + 36) / 3 = 22.67.
  3. Backward · loss → errorThe derivative of e²/3 is 2e/3: −2.67 for order 1.
  4. Backward · error → predictione = ŷ − y, so this link is 1.
  5. Backward · prediction → weightŷ = wx + b, so this link is x = 1. Order 1 contributes −2.67.
  6. Sum over examplesOrders 2 and 3 add −2.67 × 2 and −4 × 3. Total: −20, matching the direct formula.
Backprop is this pattern applied to every weight at once: the chain rule, layer by layer, reusing what the forward pass computed.

Why keep the forward values around?

Every local derivative needs them: the first backward step needs $e$, and a sigmoid layer's derivative needs its own output. Caching them keeps the backward pass cheap. It's also why training needs far more memory than inference, since every layer's activations must survive until the backward pass reaches them.

3.4 Jacobians, Hessians and curvature

For a function that outputs a vector, the derivative is a matrix, the Jacobian. One derivative further, the matrix of second derivatives is the Hessian, and it describes curvature: all eigenvalues positive is a bowl, mixed signs a saddle, all negative a peak.

The delivery loss has a constant Hessian, $H = \frac{2}{n}X^\top X = \begin{bmatrix} 9.33 & 4 \\ 4 & 2 \end{bmatrix}$, with eigenvalues of about 11.09 and 0.24. Both positive, so it's one bowl, but a long, narrow one.

3.5 Why deep chains vanish or explode

The chain rule multiplies one factor per layer. Factors a bit below 1 shrink the product toward zero on its way back to the first layers; factors above 1 blow it up.

A sigmoid's derivative is never larger than 0.25, so across ten sigmoid layers the activation derivatives alone multiply a gradient by at most $0.25^{10} \approx 9.5 \times 10^{-7}$. A factor of 1.5 per layer gives $1.5^{10} \approx 58$ instead. That's why plain deep networks and long unrolled RNNs were hard to train. Residual connections, careful initialization and normalization are the fixes, covered in 04 · Neural Network Fundamentals.

04Probability: what "wrong" should mean

Squaring the misses was a guess, if a pretty reasonable one. Probability tells you when it's the right guess, what to use when it isn't, and how to reason about a model's outputs once it exists.

4.1 A loss is a likelihood in disguise

Suppose the real delivery time is your line plus Gaussian noise with spread $\sigma$. Then the likelihood is how probable the observed times are under a given $\theta$, and maximum likelihood estimation (MLE) picks the $\theta$ that makes them most probable. The negative log of one Gaussian density is:

$$-\log p(y_i \mid x_i, \theta) = \frac{(y_i - \hat{y}_i)^2}{2\sigma^2} + \tfrac{1}{2}\log(2\pi\sigma^2)$$

The second term has no $\theta$ in it. So mean squared error is maximum likelihood under Gaussian noise, and that's the assumption you make whenever you use it.

Why take the log?

A dataset's likelihood is a product, one probability per example. A thousand examples at 0.5 each give $0.5^{1000} \approx 9.3 \times 10^{-302}$, near the bottom of what a 64-bit float can hold, and two thousand underflow to zero. The log turns the product into a sum, $1000 \log 0.5 \approx -693$, that differentiates term by term. Log only increases, so the maximum doesn't move.

4.2 Yes-or-no targets

Now ask "will this order be late?". The label is 0 or 1, and the model outputs a probability through a sigmoid, $p = \sigma(z) = 1/(1+e^{-z})$. Gaussian noise around a 0/1 label makes no sense. The natural model is a Bernoulli, and its negative log-likelihood is:

$$-\log p(y \mid x) = -\big[\,y \log p + (1-y)\log(1-p)\,\big]$$

That is binary cross-entropy, which falls out of maximum likelihood once the target is binary. Section 05 shows how differently it behaves from squared error when the model is confidently wrong.

4.3 The distributions you'll meet

A random variable maps outcomes to numbers, and its distribution says how likely each value is.

DistributionDescribesWhere you meet it
BernoulliOne yes/no trialA binary label; a sigmoid output
CategoricalOne trial, K outcomesA softmax output; next-token prediction
MultinomialCounts over many categorical trialsBag-of-words counts
GaussianA continuous value around a meanThe default continuous assumption (Central Limit Theorem), and the one behind MSE
PoissonCounts of rare, independent events per intervalRequests per second on a server
ExponentialWaiting time between those eventsMemoryless: waiting five more minutes doesn't depend on how long you've waited

4.4 Expectation, variance, covariance

Expectation is a probability-weighted average. Variance, $\mathrm{Var}(X) = \mathbb{E}[(X-\mathbb{E}[X])^2]$, is spread around it. Covariance is positive when two variables move together and negative when they move apart.

On the delivery data, distance has variance $\frac{1+0+1}{3} \approx 0.67$, and its covariance with time is $\frac{(-1)(-3.67) + 0 + (1)(4.33)}{3} \approx 2.67$. Divide: $2.67/0.67 = 4$, the best-fit slope. Least-squares regression is covariance over variance. Correlation divides covariance by both standard deviations to remove the units; here it's about 0.99.

4.5 Bayes' theorem and the base rate

Conditional probability, $P(A\mid B) = P(A \cap B)/P(B)$, is how likely A is once you know B happened. Bayes' theorem turns one conditional into the other, and it's where intuition fails most often.

Predict before you read on

Suppose 1% of card transactions are fraud, and your model flags 90% of fraudulent ones and wrongly flags 5% of legitimate ones. A transaction gets flagged. Roughly how likely is it to be fraud?

  1. About 90%
  2. About 50%
  3. About 15%
  4. About 5%
Show the answer

C, about 15%. Count 10,000 transactions: 100 are fraud and 90 of those get flagged, while 9,900 are legitimate and 5% of those, 495, get flagged too. Of 585 flags, 90 are fraud: $90/585 \approx 15.4\%$.

Bayes' theorem is that count written as a formula. The numerator is $0.9 \times 0.01 = 0.009$, the fraud that gets flagged; the extra term below it is $0.05 \times 0.99 = 0.0495$, the false alarms.

$$P(\theta \mid D) = \frac{P(D \mid \theta)\,P(\theta)}{P(D)}$$ $$P(\text{fraud}\mid\text{flag}) = \frac{0.009}{0.009 + 0.0495} \approx 0.154$$
  • P(θ) the prior, belief before the evidence: 1% fraud.
  • P(D|θ) the likelihood of the evidence if the hypothesis holds: a 90% flag rate.
  • P(θ|D) the posterior, the updated belief you want.
  • P(D) the evidence, summed over every hypothesis: 5.85% of transactions get flagged. Over a model's parameters it is usually intractable, which is why approximate Bayesian inference exists.

Why so low, when the model catches 90%?

Legitimate transactions outnumber fraud 99 to 1, and 5% of a large pile beats 90% of a small one. A flag is 18 times likelier on fraud (0.9 against 0.05), which turns prior odds of 1 to 99 into 18 to 99. Raise the prior to 10% fraud and the same flag means 67%. The model didn't change; the population did.

Design implication

Precision depends on the base rate and recall doesn't. A fraud model tested on a balanced set will report far higher precision than it gets in production. Evaluate at the class balance you'll deploy into.

4.6 MLE, MAP, and where regularization comes from

What people call "training" is one of three amounts of Bayes' theorem:

  • MLE ignores the prior and maximizes $P(D\mid\theta)$. Unregularized loss minimization is MLE.
  • MAP (maximum a posteriori) maximizes $P(D\mid\theta)P(\theta)$. A Gaussian prior on the weights gives L2 regularization; a Laplace prior gives L1.
  • Full Bayesian inference keeps the whole posterior, so predictions carry uncertainty, at a much higher computing cost.

The L2 link takes two lines. A zero-mean Gaussian prior with spread $\tau$ has $-\log P(\theta) = \frac{\|\theta\|^2}{2\tau^2} + \text{const}$. Add it to the negative log-likelihood from 4.1 and multiply through by $2\sigma^2$:

$$\sum_i (y_i - \hat y_i)^2 \;+\; \frac{\sigma^2}{\tau^2}\,\|\theta\|^2$$

That's weight decay with $\lambda = \sigma^2/\tau^2$. A narrower prior, a stronger belief that weights are small, means a bigger penalty.

4.7 Intervals and tests

A confidence interval is a range of plausible values built from data at a chosen confidence level. Hypothesis testing asks whether an effect is surprising enough to reject a "nothing's going on" baseline.

Common mistake

Reading a 95% interval as "a 95% probability the true value is in this range". The 95% describes the procedure: repeat the experiment many times and about 95% of the intervals would contain the true value. Any single interval either does or doesn't.

05Information theory: pricing surprise

Section 04 said the loss for a yes/no target is $-\log p$ of the right answer. Information theory explains why that's a natural price for being wrong, and how to compare two distributions.

5.1 Entropy: average surprise

Shannon measured the surprise of an outcome with probability $p$ as $-\log p$. A certain outcome costs nothing; a one-in-a-hundred outcome costs about 6.6 bits. Entropy is the average surprise, $H(p) = -\sum_i p_i \log p_i$:

  • A coin that always lands heads: 0 bits.
  • A 90/10 coin: $-(0.9\log_2 0.9 + 0.1\log_2 0.1) \approx$ 0.47 bits.
  • A fair coin: 1 bit, the maximum for two outcomes.

With $\log_2$ the unit is bits. Deep learning libraries use the natural log, so their losses are in nats (one nat is about 1.44 bits), and the minimum doesn't move.

5.2 Cross-entropy and KL divergence

$$H(p,q) = -\sum_i p_i \log q_i$$ $$D_{KL}(p \,\|\, q) = \sum_i p_i \log \frac{p_i}{q_i} = H(p,q) - H(p)$$

Cross-entropy $H(p,q)$ is the average surprise when outcomes come from $p$ but you score them with your model's $q$. The extra over $H(p)$ is the KL divergence. On the 90/10 coin with a model that believes 80/20, $H(p,q) \approx 0.522$ bits against $H(p) \approx 0.469$, so the model's mistake costs 0.053 bits per flip.

$H(p)$ is a property of the data that no model changes. So minimizing cross-entropy and minimizing KL are the same optimization problem, which is the case for cross-entropy as a loss.

KL is asymmetric: on the same coins, $D_{KL}(q\|p) \approx 0.064$ bits, where the other direction gave 0.053. So it is not a true distance, and which side you call "true" changes what gets penalized. The project in section 09 makes that visible.

Derivation Where cross-entropy comes from, and why it equals KL

Cross-entropy is what maximum likelihood turns into once your model outputs a distribution over classes.

  1. $$\theta^\star = \arg\max_\theta \prod_{n=1}^{N} q_\theta(y_n \mid x_n)$$
    Where we start: maximum likelihood. Two things are assumed, not derived: that MLE is the right principle, and that examples are independent, which licenses writing the joint probability as a product.
  2. $$= \arg\max_\theta \sum_{n=1}^{N} \log q_\theta(y_n \mid x_n)$$
    Why this is legal: $\log$ is strictly increasing, so it can't move a maximum. The product becomes a sum, which doesn't underflow and differentiates term by term. That's what makes mini-batch gradients possible.
  3. $$\theta^\star = \arg\min_\theta \; -\frac{1}{N}\sum_{n=1}^{N} \log q_\theta(y_n \mid x_n)$$
    Why: negating turns a maximisation into a minimisation, because optimisers descend. The $1/N$ is convention; it makes the number comparable across batch sizes and doesn't move the argmin.
  4. $$-\log q_\theta(y_n \mid x_n) = -\sum_i p_n(i) \log q_\theta(i \mid x_n)$$
    Why this changes nothing numerically: $p_n$ is the one-hot label. Every term but the true class is multiplied by zero, so the right side collapses to the left. The point is to rewrite it in a shape you recognise.
  5. $$\mathcal{L} = \frac{1}{N}\sum_{n} H\big(p_n,\; q_\theta(\cdot \mid x_n)\big)$$
    Why: that's the definition of $H(p,q)$. Cross-entropy was never chosen as a loss. It's what maximum likelihood already was, written out.
  6. $$H(p,q) = H(p) + D_{KL}(p \,\|\, q)$$
    Why: expand KL. $\sum_i p_i \log \frac{p_i}{q_i} = \sum_i p_i \log p_i - \sum_i p_i \log q_i = -H(p) + H(p,q)$. Rearrange.
  7. $$\arg\min_\theta H(p, q_\theta) \;=\; \arg\min_\theta D_{KL}(p \,\|\, q_\theta)$$
    Why: $H(p)$ contains no $\theta$. Adding a constant to an objective shifts its value but never its argmin.
Maximising likelihood, minimising cross-entropy, and minimising KL from the labels to your model are one procedure. With one-hot labels $H(p) = 0$, so cross-entropy equals KL. With soft labels, from label smoothing or distillation, $H(p)$ is non-zero but still constant, so the argmin is unchanged.
Derivation Why KL divergence can never be negative

Everything above leans on $D_{KL} \geq 0$. The same fact makes the ELBO on 12 a true lower bound and not just an approximation.

  1. $$D_{KL}(p \,\|\, q) = \sum_i p_i \log \frac{p_i}{q_i} = -\,\mathbb{E}_{p}\!\left[\log \frac{q_i}{p_i}\right]$$
    Why: $\log(a/b) = -\log(b/a)$, and a sum weighted by $p_i$ is an expectation under $p$.
  2. $$\mathbb{E}_p\!\left[\log \frac{q_i}{p_i}\right] \;\leq\; \log\, \mathbb{E}_p\!\left[\frac{q_i}{p_i}\right]$$
    Why: Jensen's inequality. $\log$ is concave (its second derivative, $-1/x^2$, is negative), and for a concave function the expectation of the function is at most the function of the expectation.
  3. $$\log\, \mathbb{E}_p\!\left[\frac{q_i}{p_i}\right] = \log \sum_i p_i \frac{q_i}{p_i} = \log \sum_i q_i = \log 1 = 0$$
    Why: the $p_i$ cancel, leaving the total mass of $q$. This is the one step that needs $q$ to be a normalised distribution.
  4. $$-D_{KL}(p \,\|\, q) \leq 0 \quad\Longrightarrow\quad D_{KL}(p \,\|\, q) \geq 0$$
    Why: steps 1 to 3 say the negative of the divergence is at most zero. Multiply by $-1$ and the inequality flips.
  5. $$D_{KL}(p \,\|\, q) = 0 \iff p = q$$
    Why: Jensen is tight only when the quantity inside is constant. Here that forces $q_i/p_i$ to be the same for every $i$, and since both sum to one, the constant is one.
KL has a hard floor at zero, reached only when the distributions agree. That's what makes it usable as a "how wrong am I" score, and why the ELBO is a lower bound: the KL term it drops can't be negative. One quiet assumption: $q_i > 0$ wherever $p_i > 0$. Give zero probability to something that then happens and the divergence is infinite.

Both run through modern ML. GPT-style pretraining is cross-entropy on the next token. KL is the VAE's pull toward its prior (12), the penalty that keeps an RLHF policy near its reference model (15), and the target in knowledge distillation.

5.3 Cross-entropy against squared error at p = 0.01

Back to the late-delivery classifier. An order was late ($y = 1$) and the model said $p = 0.01$. The model is confidently wrong, so which loss pushes harder? Differentiate each with respect to the score $z$, using the sigmoid's derivative $\frac{dp}{dz} = p(1-p)$. Cross-entropy first, then squared error:

$$\frac{\partial}{\partial z}\big(-\log p\big) = -\frac{1}{p}\cdot p(1-p) = p - 1$$ $$\frac{\partial}{\partial z}(p-1)^2 = 2(p-1)\cdot p(1-p)$$

At $p = 0.01$, cross-entropy gives $-0.99$. Squared error gives $2(-0.99)(0.01)(0.99) \approx -0.0196$. Cross-entropy pushes roughly 50 times harder, exactly when the model most needs it.

p on the true classCross-entropyIts gradientSquared errorIts gradient
0.01 (confidently wrong)4.61−0.990.98−0.020
0.12.30−0.900.81−0.162
0.5 (unsure)0.69−0.500.25−0.250
0.90.105−0.100.010−0.018
0.99 (confidently right)0.010−0.010.0001−0.0002

Squared error's gradient is largest at $p = 1/3$ (about −0.30) and fades toward both ends. Cross-entropy's gradient is the size of the miss. With a softmax over many classes it has the same form, $\partial L/\partial z = \hat{y} - y$.

Where squared error loses its gradient

The sigmoid's derivative $p(1-p)$ is nearly zero when $p$ is near 0 or 1. Squared error keeps that factor, so its gradient vanishes when the model is confidently wrong. The $1/p$ from the log in cross-entropy cancels it, and only the miss is left.

Cross-entropy loss as a function of the probability assigned to the true class
loss predicted probability on the true class → p=0.05 confident & wrong → huge loss p=0.9 confident & correct → tiny loss
The curve is $-\log(p)$. At $p = 0.9$ the loss is 0.105 nats; at $p = 0.05$ it's 3.0, and it grows without limit as $p$ approaches 0.

5.4 Computing it without overflowing

Softmax, $\hat y_i = e^{z_i} / \sum_j e^{z_j}$, uses exponentials. Feed it scores of 1000 and 999 and $e^{1000}$ overflows: a 64-bit float tops out near $e^{709.8}$, a 32-bit float near $e^{88.7}$.

Shifting every score by the same amount doesn't change softmax, so subtract the largest first. (1000, 999) becomes (0, −1), giving probabilities of 0.731 and 0.269. Log-softmax does this and takes the log in one fused step, returning −0.313 and −1.313 directly, so it never computes $\log 0$.

Common mistake

Passing probabilities to a loss that expects scores. PyTorch's F.cross_entropy takes raw logits and applies log-softmax itself. Put a softmax layer in front of it and you apply softmax twice: the model still trains, but its gradients are squashed and the reported loss is wrong.

5.5 Mutual information

Mutual information, $I(X;Y)$, is how much observing $Y$ reduces your uncertainty about $X$, and it's zero for independent variables. A good representation, roughly speaking, keeps high mutual information with what you care about and drops nuisance variation. Self-supervised objectives (03) are different ways of chasing that.

06Optimization: taking good steps

Calculus gives a direction but doesn't say how far to walk, or what to do when the direction keeps changing. The delivery model already shows each problem.

6.1 How big a step?

$$\theta_{t+1} = \theta_t - \eta \, \nabla_\theta L(\theta_t)$$
Predict before you read on

Section 3.2 used η = 0.05. Run the delivery model again with η = 0.17, then with η = 0.19. What happens to the loss?

  1. Both converge, and 0.19 converges faster
  2. 0.17 converges; 0.19 bounces forever at the same height
  3. 0.17 converges after zigzagging; 0.19 grows without limit
  4. Both diverge
Show the answer

C. At η = 0.17 the slope bounces 6.4, 3.3, 6.0, 3.6 while the loss falls from 22.7 to 7.1 in five steps, and reaches 0.23 by step 50. At η = 0.19 the loss goes 27.6, 33.7, 41.1 and passes 600,000 by step 50. The cut-off is 0.180.

On a bowl-shaped loss, the error along each eigenvector of the Hessian is multiplied by $(1 - \eta\lambda)$ every step. If that factor's size is below 1 the error shrinks; above 1 it grows.

The steep direction of the delivery loss has $\lambda \approx 11.09$. At $\eta = 0.17$ the factor is about −0.89: the sign flips every step (the zigzag) but the size shrinks. At $\eta = 0.19$ it's about −1.11, and the error grows 11% per step. Divergence starts at $\eta = 2/\lambda_{max} \approx 0.180$.

Why not pick a tiny learning rate and wait?

Because the flattest direction sets the wait. Its eigenvalue is 0.24, so at $\eta = 0.05$ the error there shrinks by only $1 - 0.05 \times 0.24 \approx 0.988$ per step, roughly 83 steps per factor of e. The steepest direction caps the learning rate, and the flattest one sets the pace.

6.2 Why the valley zigzags

The ratio of largest to smallest curvature is the condition number: $11.09/0.24 \approx 46$, the same 46 as in $X^\top X$. A large one means a long, narrow valley, and 46 is already a bit of one. The gradient there points mostly across the valley, toward the steep walls, so each step overshoots sideways and barely moves forward.

Gradient descent zigzagging down a poorly conditioned loss surface
global minimum start (random init)
Contours are curves of equal loss, and the elongated ellipses are what poor conditioning looks like. Plain gradient descent (pink) overshoots across the narrow axis and undershoots along the long one. Momentum and Adam exist to damp that zigzag.

Here's what it costs on the delivery model, counting steps until the loss is within 0.01 of its best:

InputsCondition numberSteps at η = 0.05Steps at the best fixed η
Raw distance4616290 (η ≈ 0.177)
Distance minus its mean1.5393 (η = 0.6)

Same data, same final predictions. Centring the input changed only the shape of the bowl. Normalization layers apply a similar rescaling to activations inside a network (04).

6.3 Stochastic gradients and momentum

With a billion examples, one exact gradient per step is far too slow. Stochastic gradient descent (SGD) estimates it from a random minibatch: noisy, much cheaper, and right on average. The noise seems to help a bit, too, by jostling parameters out of shallow irregularities.

Plain SGD treats each step independently, which is what makes the zigzag. Momentum steps along a running sum of past gradients:

$$v_{t} = \beta v_{t-1} + \nabla_\theta L(\theta_{t}), \qquad \theta_{t+1} = \theta_t - \eta\, v_t$$

With the usual $\beta = 0.9$, velocity along the valley floor, where the gradient keeps its sign, builds toward $1/(1-\beta) = 10$ gradients' worth. Across the valley the sign flips each step and the terms cancel. Momentum is a low-pass filter on the gradient.

6.4 Adam and AdamW

Adam keeps an average of the gradient and of its square, and uses the second to scale each parameter's step:

$$m_t = \beta_1 m_{t-1} + (1-\beta_1)g_t, \qquad v_t = \beta_2 v_{t-1} + (1-\beta_2)g_t^2$$ $$\hat{m}_t = \frac{m_t}{1-\beta_1^t}, \qquad \hat{v}_t = \frac{v_t}{1-\beta_2^t}, \qquad \theta_{t+1} = \theta_t - \eta\,\frac{\hat{m}_t}{\sqrt{\hat{v}_t}+\epsilon}$$

$m_t$ is the momentum term. $v_t$ tracks how large each parameter's gradient has been lately, so dividing by its root gives large gradients smaller steps. Both averages start at zero, and the hats correct for that early bias.

Take the first step on the delivery model with $\beta_1 = 0.9$, $\beta_2 = 0.999$. After one gradient, $\hat m_1 = 0.1\,g / 0.1 = g$ and $\hat v_1 = g^2$, so the step is $\eta\, g/|g|$: exactly $\eta$ per parameter, whatever the gradient's size. At $\eta = 0.1$, Adam raises both slope and intercept by 0.1. Plain gradient descent would move them by 2.0 and 0.93. Adam has discarded the scale difference between parameters, which is much of why it's forgiving on badly scaled problems.

AdamW changes one thing: standard L2 adds $\lambda\theta$ to the gradient before the adaptive division, which warps the regularization strength per parameter. AdamW subtracts $\eta\lambda\theta$ from the weights directly, and it is the default in most modern recipes.

Why not always use Adam?

Adam tolerates a poorly tuned learning rate, which matters when a model is too big for much hyperparameter search. That's why transformers and LLMs default to it. But well-tuned SGD with momentum often matches or beats it on final accuracy for some vision architectures, and why that happens is still argued about. The practical trade: Adam gets a working model faster; tuned SGD sometimes gets a slightly better one.

SGDMomentumAdamAdamW
Core ideaStep against the raw minibatch gradientStep against a running average, damping the zigzagMomentum plus a per-parameter step size from squared gradientsAdam, with weight decay applied to the weights directly
Per-parameter stepNoNoYesYes
Learning-rate sensitivityHigh; needs a scheduleLowerLowLow
Typical homeConvex problems, tuned CNN recipesThe standard upgrade in visionTransformers, sparse or noisy gradientsMost large-model training

6.5 Local minima and saddle points

The delivery loss is convex, one bowl, so going downhill always finds the global minimum. Neural network losses are non-convex, with no such guarantee, but that matters less than it seems. A true local minimum needs every Hessian eigenvalue positive, and across millions of directions that's rare. Saddle points, curving up in some directions and down in others, are far more common.

Common mistake

Saying training "got stuck in a bad local minimum". Slow progress across saddles and plateaus is the likelier cause of a flat loss curve. Experiments on overparameterized networks also find that the minima SGD reaches have similar loss and generalize comparably. Why SGD lands in minima that generalize well is still an open question.

07Generalization, and what breaks

Everything so far fitted three orders. The fourth is the one that matters, and a model can fit the first three perfectly and still miss it badly.

7.1 A perfect fit is the wrong goal

The best line has a loss of 0.222. The curve $\text{minutes} = \text{km}^2 + 11$ passes through all three orders exactly (12, 15, 20), so its loss is zero.

Ask both about a 10 km order: the line says $4 \times 10 + 7.67 \approx 48$ minutes, the curve says 111. Three points can't say which is right, though the line is probably the safer bet. The curve has enough freedom to fit whatever those points happened to be, noise included, and the next equation calls that freedom variance.

7.2 The bias-variance decomposition

$$\mathbb{E}\big[(y-\hat{f}(x))^2\big] = \underbrace{\big(\mathbb{E}[\hat{f}(x)] - f(x)\big)^2}_{\text{Bias}^2} + \underbrace{\mathrm{Var}[\hat{f}(x)]}_{\text{Variance}} + \sigma^2$$
  • Bias is error from a model too simple for the pattern, wrong the same way even with infinite data, and it looks like underfitting.
  • Variance is error from a model too sensitive to its training sample, so predictions swing when you retrain on fresh data, and it looks like overfitting.
  • σ² the noise in the data itself. No model gets below it.
Derivation Splitting squared error into bias, variance, and noise

Assume $y = f(x) + \varepsilon$, with $\mathbb{E}[\varepsilon] = 0$ and $\mathrm{Var}(\varepsilon) = \sigma^2$. The estimator $\hat f$ is random too, because it depends on which training sample you drew. Every expectation runs over both sources of randomness.

  1. $$\mathbb{E}\big[(y - \hat f(x))^2\big]$$
    Where we start: expected squared error at one point $x$. Keeping the two kinds of randomness apart (noise in the label, noise in the training set) is most of the difficulty.
  2. $$= \mathbb{E}\Big[\big(\underbrace{f(x) - \mathbb{E}[\hat f(x)]}_{A} \;+\; \underbrace{\varepsilon}_{B} \;+\; \underbrace{\mathbb{E}[\hat f(x)] - \hat f(x)}_{C}\big)^2\Big]$$
    Why this is legal: substitute $y = f(x) + \varepsilon$, then add and subtract $\mathbb{E}[\hat f(x)]$. Choosing that quantity is the pivot: it separates how far the average prediction is from the truth, from how far this prediction is from the average.
  3. $$\begin{aligned} =\;& \mathbb{E}[A^2] + \mathbb{E}[B^2] + \mathbb{E}[C^2] \\[2pt] &+\; 2\,\mathbb{E}[AB] + 2\,\mathbb{E}[AC] + 2\,\mathbb{E}[BC] \end{aligned}$$
    Why: expand the squared trinomial and use linearity of expectation.
  4. $$\mathbb{E}[AB] = \mathbb{E}[AC] = \mathbb{E}[BC] = 0$$
    Why, each for its own reason: $A$ isn't random, since $f(x)$ and $\mathbb{E}[\hat f(x)]$ are fixed numbers. So $\mathbb{E}[AB] = A\,\mathbb{E}[\varepsilon] = 0$ and $\mathbb{E}[AC] = A\big(\mathbb{E}[\hat f] - \mathbb{E}[\hat f]\big) = 0$. The third differs in kind: $\varepsilon$ is noise on the test label and $C$ depends only on the training sample, so they're independent with mean zero.
  5. $$= \underbrace{\big(\mathbb{E}[\hat{f}(x)] - f(x)\big)^2}_{\text{Bias}^2} + \underbrace{\mathrm{Var}[\hat{f}(x)]}_{\text{Variance}} + \underbrace{\sigma^2}_{\text{irreducible}}$$
    Why: $\mathbb{E}[A^2] = A^2$ because $A$ is deterministic. $\mathbb{E}[C^2]$ is the definition of the variance of $\hat f(x)$. And $\mathbb{E}[B^2] = \mathrm{Var}(\varepsilon) = \sigma^2$, since $\mathbb{E}[\varepsilon] = 0$.
The clean split is a property of squared-error loss specifically, not a law of learning. Under 0-1 loss the equivalent identity is notoriously hard to obtain, and Domingos (2000) showed the natural definitions don't sum to the expected loss the way they do here. The tradeoff intuition carries over to classification. The equation doesn't.

7.3 Regularization is one trade

Weight decay, dropout, early stopping, augmentation and a smaller architecture all make the same bet: a little more bias for a larger cut in variance. So training loss usually gets slightly worse while validation loss improves. An interviewer is usually checking whether you see that trade, and no single technique matters as much.

7.4 Calibration

A model can be accurate and still overconfident, and modern deep nets probably are, straight out of training. If its "90% confident" predictions are right 70% of the time, those scores can't drive a threshold or a hand-off to a human. That's miscalibration, and accuracy can't see it.

Temperature scaling is the cheap fix: divide the logits by one scalar, fitted on held-out data, before the softmax. It doesn't change which class ranks first, only how confident the model sounds. 25 · Evaluation, Reliability & Safety goes further.

7.5 Symptom, cause, fix

Most training failures show up first in the loss curve, and each row traces back to an earlier section.

SymptomLikely causeFix
Loss grows or turns NaN within a few stepsη above $2/\lambda_{max}$ (6.1), or overflow and $\log 0$ in a hand-written softmax (5.4)Lower η or add warmup; clip gradients; use the fused log-softmax loss
Loss drops fast, then crawlsPoor conditioning (6.2)Standardize inputs; momentum or Adam; normalization layers
Early layers barely changeVanishing gradients (3.5)ReLU-family activations, residual connections, careful init
Classifier learns slowly from its worst mistakesSquared error on a sigmoid (5.3)Cross-entropy on logits
Training and validation error both highHigh bias (7.2)Bigger model, better features, less regularization
Training error low, validation much higherHigh variance (7.1)More data, augmentation, weight decay, dropout, early stopping
Confidence scores don't match hit ratesMiscalibration (7.4)Temperature scaling on a held-out set
99% accuracy, rare class never caughtImbalanced data; base rates (4.5)Precision and recall on the rare class, at the production base rate

08Summary

  1. Training is one loop. Predict with a matrix product, score with a loss, differentiate with the chain rule, step against the gradient.
  2. The loss is one number because "downhill" needs one direction. Weighing two goals is your decision.
  3. Gradients are cheap. For squared error it's $\frac{2}{n}X^\top e$; in a network, backprop multiplies local derivatives and reuses the forward pass.
  4. A loss is a noise assumption. Squared error is maximum likelihood under Gaussian noise; binary cross-entropy is maximum likelihood for a yes/no label.
  5. Cross-entropy keeps its gradient when the model is confidently wrong, about 50 times squared error's at $p = 0.01$.
  6. Base rates dominate Bayes. A detector that catches 90% of fraud at a 5% false-alarm rate is right 15% of the time it fires when fraud is 1%.
  7. Regularization is a prior. L2 is MAP with a Gaussian prior; L1 is a Laplace prior.
  8. Curvature sets the learning rate. Gradient descent diverges above $2/\lambda_{max}$, and the flattest direction sets the pace.
  9. Conditioning is often a preprocessing problem. Centring one input took the delivery model from 90 steps to 3.
  10. A perfect training fit proves little. Test error is bias, variance and noise, and every regularizer trades the first for the second.

09Build this

Section 05 says KL is asymmetric and that the direction you pick changes what gets penalized, which is easy to nod at and hard to believe. Two plots settle it.

Project Fit one Gaussian to two bumps, in both KL directions ~2 hours · PyTorch

Build a target $p$ with two separated bumps. Fit a single Gaussian $q$ to it twice: once minimizing $D_{KL}(p\|q)$, once minimizing $D_{KL}(q\|p)$. Same target, optimizer and initialization; only the argument order changes. Stay in one dimension, where the fitted Gaussian has nowhere to hide.

  1. Lay a grid of a few hundred points across the real line. Define $p$ on it as a mixture of two well-separated Gaussians, normalized to sum to 1.
  2. Parameterize $q$ by a mean and a log standard deviation, evaluated on the same grid and normalized the same way.
  3. Write the KL sum by hand from section 05, $\sum_i p_i \log(p_i/q_i)$. No kl_div, no distribution class. Add a small floor inside the log, since the derivation needs $q_i > 0$ wherever $p_i > 0$.
  4. Minimize $D_{KL}(p\|q)$ with Adam and plot the fitted $q$ on top of $p$.
  5. Swap to $D_{KL}(q\|p)$, refit from the same initialization, and plot it on the same axes. Then refit starting near the other bump.
  6. Replace the two-bump target with a single Gaussian and fit both directions again.
You'll know it worked when the two fitted curves are visibly different. Forward KL spreads one wide Gaussian across both bumps, with real mass in the empty valley between them. Reverse KL narrows onto one bump, and which one depends on where you started.
What the breakage teaches. Against a single-Gaussian target, both directions land in the same place. The asymmetry only bites when $q$ can't represent $p$, and then it decides how the model fails: cover everything badly, or commit to one region. That choice sits inside every KL term on this site.

10Interview questions

BeginnerWalk me through gradient descent, step by step.

Start from some parameters, usually random. Compute the loss on a batch. Use the chain rule to get the gradient of the loss with respect to every parameter; it points toward steepest increase. Step the other way, scaled by the learning rate, and repeat until the loss stops improving. Stochastic gradient descent is the same loop with the gradient estimated from a random minibatch.

BeginnerWhat's the difference between a derivative, a gradient, and a Jacobian?

A derivative is the slope of a scalar function of one variable. A gradient is the vector of partial derivatives of a scalar function of several variables, one slope per input. A Jacobian is the matrix of partial derivatives of a function that outputs a vector: every output's sensitivity to every input.

BeginnerState Bayes' theorem and explain each term.

$P(\theta\mid D) = \dfrac{P(D\mid\theta)P(\theta)}{P(D)}$. $P(\theta)$ is the prior, the belief before the data. $P(D\mid\theta)$ is the likelihood of the data under that hypothesis. $P(\theta\mid D)$ is the posterior, the updated belief. $P(D)$ is the evidence, the data's probability summed over every hypothesis, and usually the hardest term to compute. The classic trap is the base rate: at 1% prevalence, a test that fires on 90% of positives and 5% of negatives is right only about 15% of the time it fires.

BeginnerWhy do we use cross-entropy loss for classification instead of mean squared error?

Cross-entropy is the maximum-likelihood loss for a categorical target, so minimizing it maximizes the probability of the correct class. MSE is maximum likelihood under Gaussian noise, the wrong assumption for a discrete label. It also keeps a strong gradient when the model is confidently wrong: at 0.01 on the true class, its gradient on the logit is −0.99, against about −0.02 for squared error through a sigmoid.

IntermediateExplain the bias-variance tradeoff and how regularization affects each term.

Expected squared test error splits into bias squared, variance and irreducible noise. Bias is systematic error from a model too simple for the pattern (underfitting). Variance is error from a model too sensitive to its training sample (overfitting). Regularization, such as weight decay, dropout, early stopping or a smaller architecture, accepts a little more bias for a larger drop in variance. That's why it usually makes training loss slightly worse and validation loss better.

IntermediateWhat problem does Adam solve that plain SGD doesn't? What does each of Adam's moving averages track?

Plain SGD uses one global learning rate and treats steps independently, so it zigzags on badly conditioned surfaces and needs careful tuning. Adam keeps two moving averages per parameter: $m_t$ of the gradient, like momentum, and $v_t$ of the squared gradient. Dividing the first by the square root of the second gives each parameter its own step size, larger for small steady gradients and smaller for large or noisy ones. On the first step every parameter moves by the learning rate, whatever its gradient's size.

IntermediateWhat's the difference between MLE, MAP, and full Bayesian inference?

MLE maximizes the likelihood $P(D\mid\theta)$ alone: unregularized loss minimization. MAP maximizes likelihood times prior, $P(D\mid\theta)P(\theta)$; L2 regularization is MAP with a Gaussian prior on the weights, and L1 with a Laplace prior. Full Bayesian inference keeps the whole posterior over $\theta$ instead of one point, so predictions carry uncertainty, at a much higher computing cost.

IntermediateWhat's the relationship between cross-entropy and KL divergence? Why does minimizing one minimize the other?

$D_{KL}(p\|q) = H(p,q) - H(p)$. The entropy of the data, $H(p)$, doesn't depend on the model and doesn't change during training. So minimizing $H(p,q)$ over the parameters and minimizing $D_{KL}(p\|q)$ are the same problem, differing by a constant. With one-hot labels $H(p) = 0$ and they're equal.

DeepWhy do saddle points matter more than local minima in high-dimensional non-convex optimization?

At a critical point, the Hessian's eigenvalues decide its type. A true local minimum needs every eigenvalue positive, curving up in each of possibly millions of directions. As dimension grows that gets unlikely, and a mixed-sign Hessian, a saddle, becomes the common case. So in high dimensions training mostly slows on saddles and the plateaus around them while it searches for a direction that still curves down. A bad basin is the rarer explanation.

DeepDerive the gradient of softmax plus cross-entropy with respect to the logits, and explain why the result matters.

With logits $z$, $\hat{y}=\mathrm{softmax}(z)$, one-hot target $y$ and $L=-\sum_i y_i \log \hat{y}_i$: the softmax Jacobian is $\partial \hat y_i/\partial z_j = \hat y_i(\delta_{ij} - \hat y_j)$. Multiply by $\partial L/\partial \hat y_i = -y_i/\hat y_i$ and sum over $i$. The $\hat y_i$ cancel and, since $\sum_i y_i = 1$, $\partial L/\partial z = \hat{y} - y$. The gradient is the size of the miss. It doesn't saturate the way squared error on a sigmoid does, so the model gets its strongest correction when it's most wrong.

DeepYour model has 99% accuracy on a fraud dataset but is badly miscalibrated. How would you diagnose and fix that, and why didn't accuracy catch it?

Accuracy only checks the top prediction and ignores confidence; when 99% of examples are legitimate, a model can score 99% by ignoring the input. Diagnose calibration with a reliability diagram (confidence against actual accuracy per bucket) or expected calibration error; overconfidence bows below the diagonal. Fix it with temperature scaling on a held-out set, which keeps the ranking, or with label smoothing or focal loss in training. Evaluate with precision, recall or PR-AUC on the minority class, at the production base rate.

DeepWhat does it mean, information-theoretically, for a learned representation to be "good"? Connect this to mutual information.

A representation $Z$ of input $X$ is good for predicting $Y$ if it keeps high mutual information $I(Z;Y)$, so knowing $Z$ cuts your uncertainty about $Y$, while discarding what in $X$ is irrelevant to $Y$. It can never hold more information about $Y$ than $X$ did (the data processing inequality). Contrastive objectives, masked prediction and next-token prediction can all be read as ways to raise the mutual information between a representation and some signal (another view, a masked patch, the next token) without hand-labelled targets.

11Go deeper

●Now write it yourself

Reading the derivation and being able to produce it are different skills. These are Deep-ML problems that exercise what this page covers — each one is checked against real test cases, not multiple choice.

Matched to this page from Deep-ML's catalogue of 1,380 problems. More at deep-ml.com, and Where to practise covers the other platforms and what each one trains.

My Notes — 01 Math & Stats Foundations

Free notes

Highlights on this page