Chapter 0 · Section 0.4 · 65 min

Probability for machine learning

A language model is a probability distribution. Given the text so far, it assigns a probability to every possible next token, and generating text means drawing from that distribution, one token at a time. Training it means choosing parameters that make the real text in the training set as probable as possible. Evaluating it means asking how probable it finds text it has never seen.

So probability is not background material for modern AI. It is the language the models are written in. This section covers the parts you will use constantly (expectation and variance, the three distributions that do most of the work, Bayes rule, maximum likelihood, priors as regularizers, and sampling), and it ends with a numerical trick, the log-sum-exp, that every loss function in this book depends on.

Random variables, expectation, and variance

A random variable is a quantity whose value is uncertain, described by a distribution. A discrete one, like the next token, has a probability mass function p(x)=P(X=x)p(x) = \mathbb{P}(X = x) that sums to 1. A continuous one, like a weight drawn at initialization, has a density p(x)p(x) that integrates to 1. (A density can exceed 1. Only its integral over an interval is a probability.)

The expectation is the probability-weighted average,

E[X]=∑xx p(x)or∫x p(x) dx,E[f(X)]=∑xf(x) p(x).\mathbb{E}[X] = \sum_x x\, p(x) \quad\text{or}\quad \int x\, p(x)\, dx, \qquad \mathbb{E}[f(X)] = \sum_x f(x)\, p(x) .

In plain words, the expectation is the long-run average value, and to average a function of XX you weight the function's values by the probabilities, with no need to work out the distribution of f(X)f(X) first.

The most useful property is linearity. E[aX+bY]=a E[X]+b E[Y]\mathbb{E}[aX + bY] = a\,\mathbb{E}[X] + b\,\mathbb{E}[Y] always, whether or not XX and YY are independent. Most expectation calculations in machine learning are linearity plus bookkeeping.

The variance measures spread around the mean, Var⁡(X)=E[(X−EX)2]=E[X2]−(EX)2\operatorname{Var}(X) = \mathbb{E}[(X - \mathbb{E}X)^2] = \mathbb{E}[X^2] - (\mathbb{E}X)^2, and its square root is the standard deviation. Three rules carry most of the weight.

  • Var⁡(aX+b)=a2Var⁡(X)\operatorname{Var}(aX + b) = a^2 \operatorname{Var}(X). Shifting does nothing, and scaling by aa scales the variance by a2a^2.
  • If XX and YY are independent, Var⁡(X+Y)=Var⁡(X)+Var⁡(Y)\operatorname{Var}(X + Y) = \operatorname{Var}(X) + \operatorname{Var}(Y). In general there is an extra 2Cov⁡(X,Y)2\operatorname{Cov}(X, Y), where Cov⁡(X,Y)=E[(X−EX)(Y−EY)]\operatorname{Cov}(X, Y) = \mathbb{E}[(X - \mathbb{E}X)(Y - \mathbb{E}Y)].
  • If XX and YY are independent with mean zero, Var⁡(XY)=E[X2Y2]=E[X2] E[Y2]=Var⁡(X)Var⁡(Y)\operatorname{Var}(XY) = \mathbb{E}[X^2 Y^2] = \mathbb{E}[X^2]\,\mathbb{E}[Y^2] = \operatorname{Var}(X)\operatorname{Var}(Y).

Worked example, the variance argument behind attention

Here is a calculation you will use twice in this book. Draw two vectors q,k∈Rd\mathbf{q}, \mathbf{k} \in \mathbb{R}^d with independent entries of mean 0 and variance 1. What is the variance of their dot product q⊤k=∑j=1dqjkj\mathbf{q}^\top\mathbf{k} = \sum_{j=1}^d q_j k_j?

Each term qjkjq_j k_j has mean E[qj]E[kj]=0\mathbb{E}[q_j]\mathbb{E}[k_j] = 0 and, by the third rule, variance 1⋅1=11 \cdot 1 = 1. The dd terms are independent, so by the second rule the variances add, and Var⁡(q⊤k)=d\operatorname{Var}(\mathbf{q}^\top\mathbf{k}) = d. The typical size of a dot product is therefore d\sqrt{d}, which for d=512d = 512 is about 23. Dividing by d\sqrt{d} brings the variance back to 1, by the first rule. That division is exactly the scaling in scaled dot-product attention (§4.3), where unscaled scores would push the softmax into saturation. The same three rules, applied to a layer's pre-activations, give the Xavier and He initializations of §0.7.

Python · cell 1

Averages get more precise, at a rate of one over root n

Average nn independent copies of XX, each with variance σ2\sigma^2. By the rules above, the average has variance nσ2/n2=σ2/nn\sigma^2 / n^2 = \sigma^2/n, so its standard deviation, the standard error, is σ/n\sigma/\sqrt{n}. The law of large numbers says the average converges to E[X]\mathbb{E}[X], and the central limit theorem says its fluctuations around the mean look Gaussian with that standard deviation, whatever the distribution of XX (as long as its variance is finite).

That 1/n1/\sqrt n rate shows up all over machine learning. A minibatch gradient over BB examples has noise that shrinks like 1/B1/\sqrt{B} (§0.6). An accuracy measured on 1,000 test questions has a standard error of about 0.5⋅0.5/1000≈1.6\sqrt{0.5 \cdot 0.5/1000} \approx 1.6 percentage points near 50%, so a 1-point gap between two models on that benchmark is noise. Confidence intervals, paired comparisons between two models, and how many test questions you need are developed in §0.11, and applied to model evaluations in §14.7.

The distributions that do most of the work

Bernoulli. A single yes-or-no outcome, X∈{0,1}X \in \{0, 1\}, with P(X=1)=p\mathbb{P}(X = 1) = p. Its mean is pp and its variance is p(1−p)p(1 - p). Binary classifiers, reward models comparing two answers, and dropout masks are all Bernoulli. A classifier usually outputs a logit zz and sets p=σ(z)=1/(1+e−z)p = \sigma(z) = 1/(1 + e^{-z}), where in this section σ(⋅)\sigma(\cdot) with an argument is the sigmoid and a bare σ\sigma is a standard deviation.

Categorical. One of KK outcomes, with probabilities p=(p1,…,pK)\mathbf{p} = (p_1, \dots, p_K) summing to 1. Every softmax output is a categorical distribution, and every language model's next-token prediction is one with K=VK = V, the vocabulary size. If you encode the outcome as a one-hot vector eX\mathbf{e}_X, its mean is p\mathbf{p} and its covariance is diag⁡(p)−pp⊤\operatorname{diag}(\mathbf{p}) - \mathbf{p}\mathbf{p}^\top. That is exactly the softmax Jacobian from §0.2, which is no coincidence. For every distribution in this family (the exponential families), the derivative of the mean with respect to the natural parameters, which for the categorical are the logits, is the covariance.

Gaussian (normal). A continuous value with mean μ\mu and variance σ2\sigma^2, written N(μ,σ2)\mathcal{N}(\mu, \sigma^2), with density

p(x)=12πσ2exp⁡ ⁣(−(x−μ)22σ2),log⁡p(x)=−(x−μ)22σ2−12log⁡(2πσ2).p(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\!\left(-\frac{(x - \mu)^2}{2\sigma^2}\right), \qquad \log p(x) = -\frac{(x-\mu)^2}{2\sigma^2} - \tfrac12 \log(2\pi\sigma^2) .

In plain words, the log-density is a downward parabola centered at the mean, and its curvature is set by the variance. Gaussians appear for three reasons. The central limit theorem makes sums of many small effects Gaussian. They are the maximum-entropy distribution for a given mean and variance (§0.5), the "least assuming" choice. And they are algebraically convenient, since sums and linear maps of Gaussians stay Gaussian.

Multivariate Gaussian. A vector x∈Rd\mathbf{x} \in \mathbb{R}^d with mean μ∈Rd\boldsymbol{\mu} \in \mathbb{R}^d and covariance matrix Σ∈Rd×d\boldsymbol{\Sigma} \in \mathbb{R}^{d \times d} (symmetric and positive definite), with density

p(x)=1(2π)ddet⁡Σexp⁡ ⁣(−12(x−μ)⊤Σ−1(x−μ)).p(\mathbf{x}) = \frac{1}{\sqrt{(2\pi)^d \det \boldsymbol{\Sigma}}} \exp\!\left(-\tfrac12 (\mathbf{x} - \boldsymbol{\mu})^\top \boldsymbol{\Sigma}^{-1} (\mathbf{x} - \boldsymbol{\mu})\right) .

The quadratic form in the exponent is the squared Mahalanobis distance, a distance that accounts for correlations and different scales. Its level sets are ellipsoids (ellipses in 2-D) whose axes point along the eigenvectors of Σ\boldsymbol{\Sigma}, with half-lengths proportional to the square roots of its eigenvalues. (Eigenvectors of symmetric matrices, and what positive definite means geometrically, are the subject of §0.10.) To sample, factor Σ=LL⊤\boldsymbol{\Sigma} = \mathbf{L}\mathbf{L}^\top with the Cholesky decomposition (L\mathbf{L} lower triangular), draw z∼N(0,I)\mathbf{z} \sim \mathcal{N}(\mathbf{0}, \mathbf{I}), and set x=μ+Lz\mathbf{x} = \boldsymbol{\mu} + \mathbf{L}\mathbf{z}. Its covariance is E[Lzz⊤L⊤]=LIL⊤=Σ\mathbb{E}[\mathbf{L}\mathbf{z}\mathbf{z}^\top\mathbf{L}^\top] = \mathbf{L}\mathbf{I}\mathbf{L}^\top = \boldsymbol{\Sigma}, as required.

Python · cell 2

Joint, marginal, and conditional probability

Most questions worth asking involve two or more random variables at once, such as a word and the word that follows it. Their joint distribution p(x,y)=P(X=x,Y=y)p(x, y) = \mathbb{P}(X = x, Y = y) gives the probability of every combination. Summing out one variable gives the marginal distribution of the other, p(x)=∑yp(x,y)p(x) = \sum_y p(x, y). Dividing the joint by a marginal gives the conditional distribution, the probability of xx once you know yy,

p(x∣y)=p(x,y)p(y),equivalentlyp(x,y)=p(x∣y) p(y).p(x \mid y) = \frac{p(x, y)}{p(y)}, \qquad\text{equivalently}\qquad p(x, y) = p(x \mid y)\, p(y) .

In plain words, to condition on Y=yY = y, keep only the slice of the joint table where Y=yY = y and rescale it so it sums to 1. The second form, the product rule, builds a joint out of a marginal and a conditional.

A small table makes this concrete. Let XX be whether it rained and YY whether the grass is wet, with joint probabilities p(rain,wet)=0.30p(\text{rain}, \text{wet}) = 0.30, p(rain,dry)=0.02p(\text{rain}, \text{dry}) = 0.02, p(none,wet)=0.08p(\text{none}, \text{wet}) = 0.08, and p(none,dry)=0.60p(\text{none}, \text{dry}) = 0.60 (sprinklers explain the 0.08).

Python · cell 3

Rain makes wet grass very likely, p(wet∣rain)=0.30/0.32=0.94p(\text{wet} \mid \text{rain}) = 0.30/0.32 = 0.94. Wet grass makes rain likely but less so, p(rain∣wet)=0.30/0.38=0.79p(\text{rain} \mid \text{wet}) = 0.30/0.38 = 0.79, because the sprinklers also wet the grass. The two conditionals are different numbers, and confusing them is one of the most common errors in reasoning about evidence. Bayes rule, below, is the bridge between them. We will meet this same table again in §0.5, where we measure how much the grass tells us about the rain.

Two variables are independent when the joint factors into its marginals, p(x,y)=p(x) p(y)p(x, y) = p(x)\,p(y), which is the same as p(x∣y)=p(x)p(x \mid y) = p(x) for every yy. Knowing one tells you nothing about the other. Rain and wet grass are not independent (0.32×0.38=0.120.32 \times 0.38 = 0.12, not 0.30). Independence is the assumption that makes the variance rules above work, and it is what turns the probability of a whole data set into a product, as we will use for maximum likelihood.

Applying the product rule over and over factors the joint distribution of any sequence,

p(x1,x2,…,xT)=p(x1) p(x2∣x1) p(x3∣x1,x2)⋯=∏t=1Tp(xt∣x<t),p(x_1, x_2, \dots, x_T) = p(x_1)\, p(x_2 \mid x_1)\, p(x_3 \mid x_1, x_2) \cdots = \prod_{t=1}^{T} p(x_t \mid x_{<t}) ,

where x<tx_{<t} means all the elements before position tt. This is the chain rule of probability, and it holds for any distribution, with no assumptions at all. An autoregressive language model is this identity with a neural network supplying each factor, predicting every token from the ones before it (§3.1).

Bayes rule

Bayes rule turns a model of how data arise from causes into a belief about the causes given the data. It follows in one line from the product rule, because the joint can be factored either way, P(H,D)=P(D∣H) P(H)=P(H∣D) P(D)\mathbb{P}(H, D) = \mathbb{P}(D \mid H)\,\mathbb{P}(H) = \mathbb{P}(H \mid D)\,\mathbb{P}(D). Divide by P(D)\mathbb{P}(D). For a hypothesis HH and observed data DD,

P(H∣D)=P(D∣H) P(H)P(D),P(D)=∑H′P(D∣H′) P(H′).\mathbb{P}(H \mid D) = \frac{\mathbb{P}(D \mid H)\, \mathbb{P}(H)}{\mathbb{P}(D)}, \qquad \mathbb{P}(D) = \sum_{H'} \mathbb{P}(D \mid H')\, \mathbb{P}(H') .

In plain words, the posterior is the prior times the likelihood, renormalized. The denominator is the marginal probability of the data, the joint summed over every hypothesis (sometimes called the law of total probability). The names matter. P(H)\mathbb{P}(H) is the prior (belief before the data), P(D∣H)\mathbb{P}(D \mid H) is the likelihood (how well the hypothesis predicts the data), and P(H∣D)\mathbb{P}(H \mid D) is the posterior.

The classic worked problem shows why the prior cannot be ignored. A disease affects 1% of people. A test catches 99% of cases and has a 1% false-positive rate. You test positive. How likely are you to have the disease? The numerator is 0.99×0.01=0.00990.99 \times 0.01 = 0.0099. The denominator adds the false positives, 0.0099+0.01×0.99=0.01980.0099 + 0.01 \times 0.99 = 0.0198. The posterior is 0.0099/0.0198=0.50.0099/0.0198 = 0.5. A "99% accurate" test gives a coin flip, because the disease is rare, so the healthy people's false positives are as numerous as the true positives. Make the disease ten times rarer (0.1%) and the posterior drops to 9%.

This is the reasoning behind any detector of rare events, including the safety classifiers of §19.7. A classifier with a low false-positive rate can still produce mostly false alarms if what it detects is rare enough. In the language of §0.11, the posterior here is the classifier's precision, and it depends on the base rate in a way that recall and the false-positive rate do not.

Warm-up

A posterior that survives thousands of observations

Implement posterior(prior, lik) for KK hypotheses. prior has shape (K,). lik has shape (K,) for one observation, or (M, K) for M independent observations, where lik[m, k] is the probability of observation m under hypothesis k. Return the posterior, shape (K,). With thousands of observations the product of likelihoods underflows to 0 in float64, so work in log space.

Hidden tests, hints, and AI help, from $1.99 a month.

Maximum likelihood, where losses come from

Suppose a model with parameters θ\theta assigns probability pθ(x)p_\theta(x) to each possible data point, and we observe independent data x1,…,xNx_1, \dots, x_N. The likelihood is the probability of the whole data set as a function of θ\theta, and maximum likelihood estimation (MLE) picks the θ\theta that makes it largest,

θ⋆=arg⁡max⁡θ∏n=1Npθ(xn)=arg⁡min⁡θ  −1N∑n=1Nlog⁡pθ(xn).\theta^\star = \arg\max_\theta \prod_{n=1}^N p_\theta(x_n) = \arg\min_\theta \; -\frac1N\sum_{n=1}^N \log p_\theta(x_n) .

In plain words, choose the parameters under which the data you actually saw are as probable as possible, which is the same as minimizing the average negative log-probability. We take logs for two reasons. A product of thousands of probabilities underflows (you just saw this), while a sum of logs does not. And sums are much easier to differentiate.

Almost every loss in this book is a negative log-likelihood in disguise.

Bernoulli gives binary cross-entropy. With pθ(y∣x)=p^ y(1−p^)1−yp_\theta(y \mid \mathbf{x}) = \hat p^{\,y}(1 - \hat p)^{1-y} where p^=σ(zθ(x))\hat p = \sigma(z_\theta(\mathbf{x})), the negative log-likelihood is −[ylog⁡p^+(1−y)log⁡(1−p^)]-[y\log\hat p + (1-y)\log(1-\hat p)], the binary cross-entropy. Reward models (§16.3) and DPO (§17.2) are trained with exactly this loss.

Categorical gives cross-entropy. With pθ(y∣x)=softmax⁡(z)yp_\theta(y \mid \mathbf{x}) = \operatorname{softmax}(\mathbf{z})_y, the negative log-likelihood is −log⁡softmax⁡(z)y-\log \operatorname{softmax}(\mathbf{z})_y, the cross-entropy of §0.2. Language-model pretraining is maximum likelihood on next tokens, nothing more.

Gaussian gives squared error. With y=fθ(x)+noisey = f_\theta(\mathbf{x}) + \text{noise} and Gaussian noise of fixed variance σ2\sigma^2, the negative log-likelihood is 12σ2(y−fθ(x))2\frac{1}{2\sigma^2}(y - f_\theta(\mathbf{x}))^2 plus a constant. Minimizing it is least squares. So "use MSE" is secretly the assumption "my errors are Gaussian", which tells you when it is a bad idea (heavy-tailed noise, where one outlier dominates).

Worked example, the MLE of a Gaussian

Given samples x1,…,xNx_1, \dots, x_N, maximize ℓ(μ,σ2)=∑nlog⁡N(xn;μ,σ2)=−12σ2∑n(xn−μ)2−N2log⁡(2πσ2)\ell(\mu, \sigma^2) = \sum_n \log \mathcal{N}(x_n; \mu, \sigma^2) = -\frac{1}{2\sigma^2}\sum_n (x_n - \mu)^2 - \frac N2\log(2\pi\sigma^2). Setting the derivatives to zero,

∂ℓ∂μ=1σ2∑n(xn−μ)=0  ⇒  μ^=1N∑nxn,∂ℓ∂σ2=12σ4∑n(xn−μ)2−N2σ2=0  ⇒  σ^2=1N∑n(xn−μ^)2.\frac{\partial\ell}{\partial\mu} = \frac{1}{\sigma^2}\sum_n (x_n - \mu) = 0 \;\Rightarrow\; \hat\mu = \frac1N\sum_n x_n, \qquad \frac{\partial\ell}{\partial\sigma^2} = \frac{1}{2\sigma^4}\sum_n (x_n - \mu)^2 - \frac{N}{2\sigma^2} = 0 \;\Rightarrow\; \hat\sigma^2 = \frac1N\sum_n (x_n - \hat\mu)^2 .

In plain words, the MLE of the mean is the sample mean, and the MLE of the variance is the average squared deviation from it.

That variance estimate is biased. Its expectation is N−1Nσ2\frac{N-1}{N}\sigma^2, slightly too small, because μ^\hat\mu was fitted to the same data and sits closer to the samples than the true mean does. Dividing by N−1N - 1 instead (Bessel's correction) removes the bias. With N=5N = 5, the MLE underestimates the variance by 20% on average. For the large NN of machine learning it hardly matters, but it is a favorite interview question, and you will meet the 1/N1/N versus 1/(N−1)1/(N-1) choice again inside BatchNorm (§0.7).

Python · cell 4
Interview

Fit a multivariate Gaussian and score points stably

Implement fit_gaussian(X) returning the MLE (mu, Sigma) for data X of shape (N, d) (divide by NN), and mvn_logpdf(X, mu, Sigma) returning the log-density of each row, shape (N,). Do not call np.linalg.inv or np.linalg.det. Use a Cholesky factor Σ=LL⊤\boldsymbol{\Sigma} = \mathbf{L}\mathbf{L}^\top for both the quadratic form and the log-determinant, which keeps it accurate in high dimensions where det⁡Σ\det\boldsymbol{\Sigma} underflows.

Hidden tests, hints, and AI help, from $1.99 a month.

MAP, and priors as regularizers

Maximum likelihood trusts the data completely. With little data and a flexible model, that is a problem. Flip a coin three times, see three heads, and the MLE says the coin always lands heads. Fit a degree-9 polynomial to 10 points and the MLE passes through every point while oscillating wildly between them.

The Bayesian fix is to put a prior on the parameters and maximize the posterior instead, which is called maximum a posteriori (MAP) estimation. By Bayes rule, p(θ∣D)∝p(D∣θ) p(θ)p(\theta \mid \mathcal{D}) \propto p(\mathcal{D} \mid \theta)\, p(\theta), so

θMAP=arg⁡min⁡θ[−log⁡p(D∣θ)−log⁡p(θ)].\theta_{\text{MAP}} = \arg\min_\theta \Big[ -\log p(\mathcal{D} \mid \theta) - \log p(\theta) \Big] .

In plain words, MAP is maximum likelihood plus a penalty, and the penalty is the negative log-prior.

Now look at what common priors become.

  • A Gaussian prior θj∼N(0,τ2)\theta_j \sim \mathcal{N}(0, \tau^2) has −log⁡p(θ)=12τ2∥θ∥2+const-\log p(\theta) = \frac{1}{2\tau^2}\lVert\theta\rVert^2 + \text{const}. That is the L2 penalty, called weight decay in deep learning (§0.6 and §0.7).
  • A Laplace prior p(θj)∝e−∣θj∣/bp(\theta_j) \propto e^{-|\theta_j|/b} has −log⁡p(θ)=1b∥θ∥1+const-\log p(\theta) = \frac1b\lVert\theta\rVert_1 + \text{const}, the L1 penalty, which drives many weights to exactly zero.

Here is the derivation for linear regression, which is worth doing once in full. Let y=Xw+ϵ\mathbf{y} = \mathbf{X}\mathbf{w} + \boldsymbol{\epsilon} with X∈RN×d\mathbf{X} \in \mathbb{R}^{N \times d}, noise ϵn∼N(0,σ2)\epsilon_n \sim \mathcal{N}(0, \sigma^2), and prior wj∼N(0,τ2)w_j \sim \mathcal{N}(0, \tau^2). The negative log-posterior, dropping constants, is

12σ2∥y−Xw∥2+12τ2∥w∥2.\frac{1}{2\sigma^2}\lVert\mathbf{y} - \mathbf{X}\mathbf{w}\rVert^2 + \frac{1}{2\tau^2}\lVert\mathbf{w}\rVert^2 .

Its gradient is −1σ2X⊤(y−Xw)+1τ2w-\frac{1}{\sigma^2}\mathbf{X}^\top(\mathbf{y} - \mathbf{X}\mathbf{w}) + \frac{1}{\tau^2}\mathbf{w}. Setting it to zero and multiplying by σ2\sigma^2,

wMAP=(X⊤X+λI)−1X⊤y,λ=σ2τ2.\mathbf{w}_{\text{MAP}} = \big(\mathbf{X}^\top\mathbf{X} + \lambda\mathbf{I}\big)^{-1}\mathbf{X}^\top\mathbf{y}, \qquad \lambda = \frac{\sigma^2}{\tau^2} .

In plain words, MAP with a Gaussian prior is ridge regression, and the regularization strength is the ratio of noise variance to prior variance. A tight prior (small τ\tau) or noisy data (large σ\sigma) means strong regularization. As τ→∞\tau \to \infty the prior becomes flat and you recover least squares. A bonus is that X⊤X+λI\mathbf{X}^\top\mathbf{X} + \lambda\mathbf{I} is always invertible for λ>0\lambda > 0, even when d>Nd > N.

Python · cell 5

The MLE fit needs enormous coefficients (the largest is about 370,000) to thread every point, and it generalizes badly. A modest prior, λ=0.001\lambda = 0.001, shrinks the largest coefficient to about 10 and cuts the test error by more than half. A stronger one, λ=0.1\lambda = 0.1, already flattens the fit too much and the error rises again. That is the bias side of the trade-off you'll meet in §0.7.

The coin makes the same point with a prior you can see. For a coin with heads probability θ\theta, the Beta distribution Beta(a,b)\text{Beta}(a, b), with density proportional to θa−1(1−θ)b−1\theta^{a-1}(1-\theta)^{b-1}, is a convenient prior. After hh heads and tt tails the posterior is Beta(a+h,b+t)\text{Beta}(a + h, b + t), so the prior acts like aa imaginary heads and bb imaginary tails added to the data (for the MAP estimate, the most probable value, it is a−1a - 1 and b−1b - 1). The MLE is h/(h+t)h/(h + t), and the MAP estimate is (h+a−1)/(h+t+a+b−2)(h + a - 1)/(h + t + a + b - 2). Try three heads and no tails with a weak prior, then add data and watch the prior's influence fade.

How does a prior pull an estimate, and when does the data win?
A coin with unknown heads probability θ and a Beta(a, b) prior. After h heads and t tails the posterior is Beta(a + h, b + t). Compare the MLE with the MAP estimate.
Loading interactive figure…
Core

MAP linear regression

Implement map_linear_regression(X, y, sigma2, tau2) returning wMAP\mathbf{w}_{\text{MAP}} for Gaussian noise variance sigma2 and Gaussian prior variance tau2 on every weight. Use np.linalg.solve, not an explicit inverse. It must work when there are more features than examples.

Hidden tests, hints, and AI help, from $1.99 a month.

Sampling

Generating from a model means sampling, and several of the most important gradient estimators in machine learning are really facts about sampling.

Inverse CDF. If UU is uniform on [0,1][0, 1] and FF is a cumulative distribution function, then F−1(U)F^{-1}(U) has distribution FF. For a categorical distribution, FF is the running sum of the probabilities, and inverting it is a binary search. The word2vec negative sampler of §1.5 is built exactly this way.

The Gumbel-max trick. To sample from softmax⁡(z)\operatorname{softmax}(\mathbf{z}) without computing the softmax, add independent Gumbel noise gk=−log⁡(−log⁡Uk)g_k = -\log(-\log U_k) to every logit and take the argmax,

arg⁡max⁡k (zk+gk)  ∼  softmax⁡(z).\arg\max_k \,(z_k + g_k) \;\sim\; \operatorname{softmax}(\mathbf{z}) .

In plain words, perturb every logit with the right kind of noise and pick the largest. It never exponentiates, so it cannot overflow. It parallelizes trivially, and it underlies the Gumbel-softmax (or Concrete) relaxation that makes discrete choices differentiable (Jang et al., 2017, and Maddison, Mnih & Teh, 2017). The trick itself is much older, a consequence of the extreme-value statistics named after Emil Gumbel.

∂ Why Gumbel noise gives exactly the softmax

A standard Gumbel variable has CDF F(g)=exp⁡(−e−g)F(g) = \exp(-e^{-g}) and density f(g)=e−gexp⁡(−e−g)f(g) = e^{-g}\exp(-e^{-g}). Category kk wins if zk+gk>zj+gjz_k + g_k > z_j + g_j for all j≠kj \neq k, that is, gj<zk+gk−zjg_j < z_k + g_k - z_j. Condition on gk=gg_k = g. The other noises are independent, so

P(k wins∣gk=g)=∏j≠kF(zk+g−zj)=exp⁡ ⁣(−e−g∑j≠kezj−zk).\mathbb{P}(k \text{ wins} \mid g_k = g) = \prod_{j \neq k} F(z_k + g - z_j) = \exp\!\Big(-e^{-g} \sum_{j \neq k} e^{z_j - z_k}\Big) .

Multiply by the density of gkg_k and integrate. Writing S=∑jezj−zkS = \sum_{j} e^{z_j - z_k} (now including j=kj = k, which contributes the exp⁡(−e−g)\exp(-e^{-g}) from the density),

P(k wins)=∫−∞∞e−gexp⁡ ⁣(−Se−g) dg.\mathbb{P}(k \text{ wins}) = \int_{-\infty}^{\infty} e^{-g} \exp\!\big(-S e^{-g}\big)\, dg .

Substitute u=e−gu = e^{-g}, so du=−e−g dgdu = -e^{-g}\,dg and the limits become ∞\infty to 00. The integral is ∫0∞e−Su du=1/S=ezk/∑jezj\int_0^\infty e^{-Su}\, du = 1/S = e^{z_k}/\sum_j e^{z_j}, the softmax. ∎

Temperature. Divide the logits by a temperature τ>0\tau > 0 before the softmax and sample from softmax⁡(z/τ)\operatorname{softmax}(\mathbf{z}/\tau). (In this paragraph τ\tau is a temperature, not the prior scale of the MAP discussion.) A temperature below 1 sharpens the distribution toward the argmax, and one above 1 flattens it toward uniform. This is the main knob of text generation (§6.4).

Core

Sample from logits with the Gumbel-max trick

Implement gumbel_max_sample(logits, n, rng) that returns n independent samples (an int array of shape (n,)) from softmax⁡(logits)\operatorname{softmax}(\texttt{logits}) using the Gumbel-max trick, without computing a softmax or calling rng.choice. It must work for logits like [1000, 1000] where a naive softmax overflows.

Hidden tests, hints, and AI help, from $1.99 a month.

Two ways to differentiate through randomness

Often we need the gradient of an expectation, ∇θ Ex∼pθ[f(x)]\nabla_\theta\, \mathbb{E}_{x \sim p_\theta}[f(x)], where the distribution itself depends on θ\theta. Reinforcement learning needs this (the expected reward of a policy), and so do variational autoencoders. There are two standard estimators, and the contrast between them is a classic interview topic.

The score-function estimator, also called REINFORCE or the log-derivative trick, uses ∇θpθ=pθ∇θlog⁡pθ\nabla_\theta p_\theta = p_\theta\nabla_\theta\log p_\theta,

∇θ Epθ[f(x)]=∫f(x) ∇θpθ(x) dx=∫f(x) pθ(x) ∇θlog⁡pθ(x) dx=Epθ ⁣[f(x) ∇θlog⁡pθ(x)].\nabla_\theta\, \mathbb{E}_{p_\theta}[f(x)] = \int f(x)\, \nabla_\theta p_\theta(x)\, dx = \int f(x)\, p_\theta(x)\, \nabla_\theta \log p_\theta(x)\, dx = \mathbb{E}_{p_\theta}\!\big[f(x)\,\nabla_\theta\log p_\theta(x)\big] .

In plain words, sample, then weight each sample's log-probability gradient by how good the sample was. It works for any ff, even a non-differentiable one like a reward from a human or a unit test, which is why it is the foundation of policy gradients (§15.3). Its weakness is high variance.

The reparameterization estimator writes the sample as a differentiable function of θ\theta and fixed noise. For a Gaussian, x=μ+σϵx = \mu + \sigma\epsilon with ϵ∼N(0,1)\epsilon \sim \mathcal{N}(0, 1), so ∇μE[f(x)]=Eϵ[f′(μ+σϵ)]\nabla_\mu \mathbb{E}[f(x)] = \mathbb{E}_\epsilon[f'(\mu + \sigma\epsilon)]. It needs ff to be differentiable and the distribution to be reparameterizable, but its variance is usually far lower. It is the trick that lets variational autoencoders train by backpropagation through a random sampling step.

Python · cell 6

Both are unbiased. But with μ=1\mu = 1 the per-sample variance of the score-function estimator is exactly 30 (expand (1+ϵ)2ϵ(1 + \epsilon)^2\epsilon and use the Gaussian moments E[ϵ4]=3\mathbb{E}[\epsilon^4] = 3 and E[ϵ6]=15\mathbb{E}[\epsilon^6] = 15), against 4 for the reparameterized one. So it needs about 7.5 times as many samples for the same precision. The cell's per-sample standard deviations, about 5.8 and 2.0, are close to the theoretical 30≈5.5\sqrt{30} \approx 5.5 and 22. Much of §15.4 is about cutting that variance with baselines.

The log-sum-exp trick and the stable softmax

Every softmax, every cross-entropy, and every log-likelihood of a categorical model computes log⁡∑kezk\log\sum_k e^{z_k}, the log-sum-exp, which we write LSE⁡(z)\operatorname{LSE}(\mathbf{z}) for logits z∈RK\mathbf{z} \in \mathbb{R}^K. You met it, and the trick that makes it safe, in §0.2. This section completes the story, with the limits of each floating-point format, the two facts that make LSE a friendly function, and the edge cases (masked rows, infinities) that production code must handle. Computed naively, it breaks. eze^{z} overflows to infinity once zz exceeds about 88.7 in float32 or 709.8 in float64, and in float16 it overflows once zz passes about 11, so in low precision perfectly ordinary logits already break it. In the other direction, if every zkz_k is very negative, every ezke^{z_k} underflows to 0 and the log returns −∞-\infty.

As in §0.2, the fix factors out the largest term. Let m=max⁡kzkm = \max_k z_k. Then

log⁡∑kezk=log⁡(em∑kezk−m)=m+log⁡∑kezk−m.\log\sum_k e^{z_k} = \log\Big(e^{m}\sum_k e^{z_k - m}\Big) = m + \log\sum_k e^{z_k - m} .

In plain words, subtract the maximum before exponentiating and add it back after the log. Now every exponent is at most 0, so nothing overflows, and the largest term is exactly e0=1e^0 = 1, so the sum is at least 1 and the log is safe.

The same shift gives the stable softmax, since softmax⁡(z)=softmax⁡(z−m1)\operatorname{softmax}(\mathbf{z}) = \operatorname{softmax}(\mathbf{z} - m\mathbf{1}) (softmax is shift invariant, as we saw from its Jacobian in §0.2). And it gives the stable log-softmax, log⁡softmax⁡(z)k=zk−LSE⁡(z)\log\operatorname{softmax}(\mathbf{z})_k = z_k - \operatorname{LSE}(\mathbf{z}), which you should always use instead of taking the log of a softmax, because a probability that underflowed to 0 has a log of −∞-\infty.

Two more facts make log-sum-exp a friendly function. It is a smooth maximum, since max⁡kzk≤LSE⁡(z)≤max⁡kzk+log⁡K\max_k z_k \le \operatorname{LSE}(\mathbf{z}) \le \max_k z_k + \log K. And its gradient is the softmax, ∇zLSE⁡(z)=softmax⁡(z)\nabla_{\mathbf{z}}\operatorname{LSE}(\mathbf{z}) = \operatorname{softmax}(\mathbf{z}), which is the one-line derivation of p−y\mathbf{p} - \mathbf{y} from §0.2.

Python · cell 7

The same idea, carried out in blocks so the maximum can be updated as new scores arrive, is the online softmax at the heart of FlashAttention (§12.2).

Core

A log-sum-exp you can trust

Implement logsumexp(z, axis=-1, keepdims=False) and log_softmax(z, axis=-1) for arrays of any shape. They must not overflow for huge values, must return -inf (not NaN) for a slice whose entries are all -inf (which happens with fully masked attention rows), and must return inf for a slice that contains +inf, all without floating-point warnings. (A log_softmax of a slice that is entirely -inf is undefined, and may return NaN.) Do not use scipy.special.logsumexp.

Hidden tests, hints, and AI help, from $1.99 a month.

In PyTorch

torch.distributions packages densities, sampling, and both gradient estimators. sample() draws without a gradient path, rsample() uses reparameterization, and log_prob gives what the score-function estimator needs.

🔥 In PyTorchfor a machine with PyTorch

Read more

Watch next

🎬 Bayes theorem, the geometry of changing beliefs · 3Blue1BrownBayes rule as a picture, with the base-rate puzzle this section also solves.
🎬 Maximum Likelihood, clearly explained!!! · StatQuest with Josh StarmerA gentle picture of what maximizing the likelihood means.
🎬 But what is the Central Limit Theorem? · 3Blue1BrownWhy sums of many small random effects look Gaussian.