Skip to content
The Lumenary
Early undergraduateUndergraduate (first or second year) 120 min

Statistical inference

Probability runs from a model to the data; statistics runs back from the data to the model — estimators, likelihood, confidence intervals, tests, regression and Bayes, with honest accounting of uncertainty.

Formally verified · 17 LeanComputationally tested · 3 PythonAI-drafted · awaiting human reviewMathematically reviewed: Awaiting human review
MotivationH

From data back to the world

In a trial of a malaria vaccine in West Africa, some children receive the vaccine and some a control injection, and the numbers of malaria cases in the two groups are counted. The counts are data; the question is about the world: how well does the vaccine protect children in general? A soil scientist in Punjab measures wheat yields on forty plots treated with a new fertiliser. A survey team in Nairobi asks four hundred households whether they use mobile money. In each case we see a finite, random sample and want to say something about an unknown quantity — a protection rate, a mean yield, a population proportion — with an honest statement of how uncertain we are.

Probability theory goes forwards: given the model (a coin with P(heads)=pP(\text{heads}) = p), what data should we expect? Statistical inference goes backwards: given the data, what can we say about pp? It does so by imagining the study repeated: an estimate computed from the data is itself a random variable, and its distribution across hypothetical repetitions — its sampling distribution — tells us how far to trust it.

This lesson builds on probability theory (expectation, variance, the law of large numbers and the central limit theorem) and on the school-level ideas of samples, bias and margins of error in statistical inference: first steps. Matrix notation from linear algebra appears in the section on regression.

IntuitionH

Which parameter makes the data least surprising?

Suppose 77 of 2020 seeds germinate. If the germination probability were p=0.9p = 0.9, seeing only 77 would be astonishing; if it were p=0.05p = 0.05, also astonishing. The likelihood L(p)=p7(1−p)13L(p) = p^7(1 - p)^{13} measures, for each candidate pp, how probable the observed data would be. It is largest at p=7/20=0.35p = 7/20 = 0.35: the maximum likelihood estimate.

Relative likelihood of a success probability

Both curves peak at the observed proportion. With four times as much data the likelihood is about half as wide: more data, less uncertainty.

MLE
  • n = 20 trials
  • n = 80 trials, same proportion
  • n = 20 trials: y = 0
  • n = 80 trials, same proportion: y = 0

Two features of the picture carry the whole subject. The peak is our estimate. The width tells us how well the data pin the parameter down; with nn observations it shrinks like 1/n1/\sqrt n, the same square-root law as the standard deviation of a sample mean. Confidence intervals, tests and Bayesian posteriors are different ways of turning that width into a statement of uncertainty.

DefinitionsH

Models, estimators, intervals and tests

Definition— statistical model, statistic, estimator

A parametric statistical model is a family of distributions {Pθ:θ∈Θ}\{P_\theta : \theta \in \Theta\} for the data X=(X1,…,Xn)X = (X_1, \dots, X_n); often the XiX_i are independent and identically distributed (an i.i.d. sample) from a density or mass function f(x;θ)f(x; \theta). A statistic is any function T(X)T(X) of the data (not of θ\theta). An estimator of θ\theta (or of a function g(θ)g(\theta)) is a statistic used to estimate it; its value on the observed data is an estimate.

Definition— bias, mean squared error, standard error, consistency

The bias of an estimator TT is bias⁡θ(T)=Eθ[T]−θ\operatorname{bias}_\theta(T) = E_\theta[T] - \theta; TT is unbiased if this is 00 for every θ\theta. Its mean squared error is MSE⁡θ(T)=Eθ[(T−θ)2]\operatorname{MSE}_\theta(T) = E_\theta[(T - \theta)^2], and its standard error is its standard deviation Var⁡θT\sqrt{\operatorname{Var}_\theta T} (or an estimate of it). A sequence of estimators TnT_n is consistent if Pθ(∣Tn−θ∣≥ε)→0P_\theta(|T_n - \theta| \ge \varepsilon) \to 0 for every ε>0\varepsilon > 0 and every θ\theta.

Definition— likelihood and maximum likelihood

For observed data xx, the likelihood is L(θ)=f(x;θ)L(\theta) = f(x; \theta) — the probability or density of the data, regarded as a function of the parameter. For an i.i.d. sample L(θ)=∏if(xi;θ)L(\theta) = \prod_i f(x_i; \theta), and the log-likelihood is ℓ(θ)=∑ilog⁡f(xi;θ)\ell(\theta) = \sum_i \log f(x_i; \theta). A maximum likelihood estimate (MLE) θ^\hat\theta maximises LL (equivalently ℓ\ell) over Θ\Theta.

Definition— confidence interval

A (1−α)(1 - \alpha) confidence interval for θ\theta is a pair of statistics C(X)=[A(X),B(X)]C(X) = [A(X), B(X)] such that Pθ(A(X)≤θ≤B(X))≥1−αP_\theta\big(A(X) \le \theta \le B(X)\big) \ge 1 - \alpha for every θ\theta. The probability is over the data, with θ\theta fixed: it is the interval that is random.

Definition— hypothesis test, errors, p-value

A test of a null hypothesis H0:θ∈Θ0H_0 : \theta \in \Theta_0 against an alternative H1:θ∈Θ1H_1 : \theta \in \Theta_1 rejects H0H_0 when a test statistic T(X)T(X) falls in a rejection region RR. A type I error is rejecting a true H0H_0; a type II error is failing to reject a false one. The test has level α\alpha if Pθ(T∈R)≤αP_\theta(T \in R) \le \alpha for all θ∈Θ0\theta \in \Theta_0, and its power at θ∈Θ1\theta \in \Theta_1 is Pθ(T∈R)P_\theta(T \in R). If large values of TT count against H0H_0 and tt is the observed value, the p-value is PH0(T≥t)P_{H_0}(T \ge t): the probability, computed assuming the null hypothesis, of a result at least as extreme as the one observed.

ProofH

Good estimators: bias, variance and Bessel's correction

Theorem— Theorem (bias–variance decomposition)

If TT has finite variance, then MSE⁡θ(T)=Var⁡θ(T)+bias⁡θ(T)2\operatorname{MSE}_\theta(T) = \operatorname{Var}_\theta(T) + \operatorname{bias}_\theta(T)^2.

Proof

Write m=Eθ[T]m = E_\theta[T] and T−θ=(T−m)+(m−θ)T - \theta = (T - m) + (m - \theta). Squaring and taking expectations, the cross term 2(m−θ)E[T−m]2(m - \theta)E[T - m] vanishes because E[T−m]=0E[T - m] = 0, leaving E[(T−m)2]+(m−θ)2E[(T - m)^2] + (m - \theta)^2.

∎

So an estimator can be bad in two ways — systematically off (bias) or erratic (variance) — and reducing one may increase the other.

Theorem— Theorem (the sample mean)

Let X1,…,XnX_1, \dots, X_n have common mean μ\mu. Then Xˉ=1n∑iXi\bar X = \frac1n\sum_i X_i is unbiased for μ\mu. If moreover they are pairwise uncorrelated with common variance σ2\sigma^2, then Var⁡Xˉ=σ2/n\operatorname{Var}\bar X = \sigma^2/n, and Xˉ\bar X is consistent: P(∣Xˉ−μ∣≥ε)≤σ2/(nε2)P(|\bar X - \mu| \ge \varepsilon) \le \sigma^2/(n\varepsilon^2).

Proof

Unbiasedness is linearity of expectation. The variance of a sum of uncorrelated variables is the sum of the variances, so Var⁡Xˉ=1n2⋅nσ2\operatorname{Var}\bar X = \frac{1}{n^2}\cdot n\sigma^2. Consistency is Chebyshev's inequality applied to Xˉ\bar X (this is the weak law of large numbers).

∎

The standard error of a mean is therefore σ/n\sigma/\sqrt n: to halve it, quadruple the sample.

How should we estimate σ2\sigma^2? The natural guess 1n∑(Xi−Xˉ)2\frac1n\sum(X_i - \bar X)^2 is too small on average, because the data are closer to their own mean Xˉ\bar X than to the true mean μ\mu. The key is an algebraic identity.

Theorem— Lemma (shift identity)

For any numbers x1,…,xnx_1, \dots, x_n with mean xˉ\bar x, and any cc,   ∑i=1n(xi−xˉ)2=∑i=1n(xi−c)2−n(xˉ−c)2.\;\displaystyle\sum_{i=1}^n (x_i - \bar x)^2 = \sum_{i=1}^n (x_i - c)^2 - n(\bar x - c)^2. In particular xˉ\bar x minimises c↦∑i(xi−c)2c \mapsto \sum_i (x_i - c)^2.

Proof

Expand (xi−xˉ)2=((xi−c)−(xˉ−c))2=(xi−c)2−2(xˉ−c)(xi−c)+(xˉ−c)2(x_i - \bar x)^2 = \big((x_i - c) - (\bar x - c)\big)^2 = (x_i - c)^2 - 2(\bar x - c)(x_i - c) + (\bar x - c)^2 and sum, using ∑i(xi−c)=n(xˉ−c)\sum_i (x_i - c) = n(\bar x - c): the middle terms give −2n(xˉ−c)2-2n(\bar x - c)^2 and the last ones +n(xˉ−c)2+n(\bar x - c)^2.

∎

Theorem— Theorem (Bessel's correction)

Let X1,…,XnX_1, \dots, X_n (n≥2n \ge 2) be pairwise uncorrelated with common mean μ\mu and variance σ2\sigma^2. Then E[∑i(Xi−Xˉ)2]=(n−1)σ2E\big[\sum_i (X_i - \bar X)^2\big] = (n - 1)\sigma^2, so the sample variance

S2=1n−1∑i=1n(Xi−Xˉ)2S^2 = \frac{1}{n - 1}\sum_{i=1}^n (X_i - \bar X)^2

is an unbiased estimator of σ2\sigma^2.

Proof

By the shift identity with c=μc = \mu, ∑i(Xi−Xˉ)2=∑i(Xi−μ)2−n(Xˉ−μ)2\sum_i (X_i - \bar X)^2 = \sum_i (X_i - \mu)^2 - n(\bar X - \mu)^2. Taking expectations, E[(Xi−μ)2]=σ2E[(X_i - \mu)^2] = \sigma^2 and E[(Xˉ−μ)2]=Var⁡Xˉ=σ2/nE[(\bar X - \mu)^2] = \operatorname{Var}\bar X = \sigma^2/n, so the expectation is nσ2−n⋅σ2/n=(n−1)σ2n\sigma^2 - n \cdot \sigma^2/n = (n - 1)\sigma^2.

∎

Geometrically, the residual vector (Xi−Xˉ)i(X_i - \bar X)_i is confined to the (n−1)(n - 1)-dimensional subspace of vectors whose entries sum to zero: one "degree of freedom" was used up in estimating μ\mu (see the viewpoints).

Example— Unbiased is not the same as best

For a normal sample, Var⁡(S2)=2σ4n−1\operatorname{Var}(S^2) = \frac{2\sigma^4}{n - 1} (a fact about the χ2\chi^2 distribution), so MSE⁡(S2)=2σ4n−1\operatorname{MSE}(S^2) = \frac{2\sigma^4}{n - 1}. The biased estimator σ^2=n−1nS2\hat\sigma^2 = \frac{n-1}{n}S^2 has bias −σ2/n-\sigma^2/n and variance 2(n−1)σ4n2\frac{2(n-1)\sigma^4}{n^2}, so MSE⁡(σ^2)=(2n−1)σ4n2\operatorname{MSE}(\hat\sigma^2) = \frac{(2n - 1)\sigma^4}{n^2}, which is smaller than 2σ4n−1\frac{2\sigma^4}{n - 1} for every n≥2n \ge 2. A little bias can buy a larger reduction in variance — the idea behind shrinkage estimators and much of modern statistics.

ProofH

Maximum likelihood

Theorem— Proposition (the Bernoulli MLE)

If kk of nn independent trials succeed, with 0<k<n0 < k < n, the log-likelihood ℓ(p)=klog⁡p+(n−k)log⁡(1−p)\ell(p) = k\log p + (n - k)\log(1 - p) on (0,1)(0, 1) is maximised exactly at p^=k/n\hat p = k/n.

Proof

With calculus: ℓ′(p)=kp−n−k1−p\ell'(p) = \frac kp - \frac{n - k}{1 - p} is positive for p<k/np < k/n and negative for p>k/np > k/n, so ℓ\ell increases and then decreases. Without calculus: write q=k/nq = k/n and use log⁡x≤x−1\log x \le x - 1 (with equality only at x=1x = 1):

ℓ(p)−ℓ(q)=klog⁡pq+(n−k)log⁡1−p1−q≤k(pq−1)+(n−k)(1−p1−q−1)=np−k+n(1−p)−(n−k)=0,\ell(p) - \ell(q) = k\log\frac pq + (n - k)\log\frac{1 - p}{1 - q} \le k\Big(\frac pq - 1\Big) + (n - k)\Big(\frac{1 - p}{1 - q} - 1\Big) = np - k + n(1 - p) - (n - k) = 0,

using k/q=nk/q = n and (n−k)/(1−q)=n(n - k)/(1 - q) = n. Equality forces p/q=1p/q = 1. (The second proof is the one formalised in Lean, and it is Gibbs' inequality from information theory in disguise.)

∎

Example— A gallery of maximum likelihood estimators

  • Poisson(λ)(\lambda): ℓ(λ)=∑xilog⁡λ−nλ−∑log⁡xi!\ell(\lambda) = \sum x_i \log\lambda - n\lambda - \sum\log x_i!, so ℓ′(λ)=∑xi/λ−n=0\ell'(\lambda) = \sum x_i/\lambda - n = 0 gives λ^=xˉ\hat\lambda = \bar x.
  • Exponential with rate λ\lambda: ℓ(λ)=nlog⁡λ−λ∑xi\ell(\lambda) = n\log\lambda - \lambda\sum x_i, so λ^=1/xˉ\hat\lambda = 1/\bar x. It is biased: since ∑Xi\sum X_i has a Gamma(n,λ)(n, \lambda) distribution, E[1/Xˉ]=nλn−1E[1/\bar X] = \frac{n\lambda}{n - 1} for n≥2n \ge 2. (An MLE need not be unbiased; it is invariant under reparametrisation — the MLE of the mean 1/λ1/\lambda is xˉ\bar x, which is unbiased.)
  • Normal(μ,σ2)(\mu, \sigma^2): setting both partial derivatives of ℓ=−n2log⁡(2πσ2)−12σ2∑(xi−μ)2\ell = -\frac n2\log(2\pi\sigma^2) - \frac{1}{2\sigma^2}\sum(x_i - \mu)^2 to zero gives μ^=xˉ\hat\mu = \bar x and σ^2=1n∑(xi−xˉ)2\hat\sigma^2 = \frac1n\sum(x_i - \bar x)^2, which is the biased n−1nS2\frac{n-1}{n}S^2.
  • Uniform on [0,θ][0, \theta]: L(θ)=θ−nL(\theta) = \theta^{-n} if θ≥max⁡ixi\theta \ge \max_i x_i and 00 otherwise. It is not differentiable at its maximum, which is at the boundary: θ^=max⁡ixi\hat\theta = \max_i x_i. Since max⁡iXi\max_i X_i has density nyn−1/θnny^{n-1}/\theta^n on [0,θ][0, \theta], E[θ^]=nn+1θE[\hat\theta] = \frac{n}{n+1}\theta; the estimator n+1nmax⁡iXi\frac{n+1}{n}\max_i X_i is unbiased.

How good can an estimator be? Define the score U(θ)=ℓ′(θ)=∑i∂θlog⁡f(Xi;θ)U(\theta) = \ell'(\theta) = \sum_i \partial_\theta \log f(X_i; \theta) and the Fisher information I(θ)=Eθ[(∂θlog⁡f(X1;θ))2]I(\theta) = E_\theta\big[(\partial_\theta \log f(X_1; \theta))^2\big].

Theorem— Theorem (Cramér–Rao inequality)

Let X1,…,XnX_1, \dots, X_n be i.i.d. with density (or mass function) f(x;θ)f(x; \theta), θ\theta in an open interval, and assume the regularity conditions: the set where f>0f > 0 does not depend on θ\theta, 0<I(θ)<∞0 < I(\theta) < \infty, and differentiation in θ\theta may be taken under the integral (or sum) sign in the identities below. If TT is an unbiased estimator of θ\theta with finite variance, then

Var⁡θ(T)≥1n I(θ).\operatorname{Var}_\theta(T) \ge \frac{1}{n\,I(\theta)}.

Proof

Write L(x;θ)=∏if(xi;θ)L(x; \theta) = \prod_i f(x_i; \theta), so U=∂θL/LU = \partial_\theta L / L. Differentiating ∫L dx=1\int L\,dx = 1 gives Eθ[U]=∫∂θL dx=0E_\theta[U] = \int \partial_\theta L\,dx = 0. The nn terms of UU are i.i.d. with mean 00, so Var⁡θU=nI(θ)\operatorname{Var}_\theta U = nI(\theta). Differentiating ∫T(x)L(x;θ) dx=θ\int T(x) L(x; \theta)\,dx = \theta gives Eθ[TU]=1E_\theta[TU] = 1, hence Cov⁡θ(T,U)=1\operatorname{Cov}_\theta(T, U) = 1. By the Cauchy–Schwarz inequality for covariances, 1=Cov⁡(T,U)2≤Var⁡(T)Var⁡(U)=Var⁡(T)⋅nI(θ)1 = \operatorname{Cov}(T, U)^2 \le \operatorname{Var}(T)\operatorname{Var}(U) = \operatorname{Var}(T)\cdot nI(\theta).

∎

For the Bernoulli model, ∂plog⁡f(x;p)=xp−1−x1−p\partial_p \log f(x; p) = \frac xp - \frac{1 - x}{1 - p} and I(p)=1p(1−p)I(p) = \frac{1}{p(1 - p)}, so the bound is p(1−p)n=Var⁡p^\frac{p(1-p)}{n} = \operatorname{Var}\hat p: the sample proportion is efficient. The uniform model violates the regularity conditions (its support depends on θ\theta), and indeed its unbiased estimator has variance of order 1/n21/n^2, beating the "bound". Under regularity conditions the MLE is consistent and asymptotically normal: n(θ^n−θ)→N(0,1/I(θ))\sqrt n(\hat\theta_n - \theta) \to N\big(0, 1/I(\theta)\big) in distribution (Fisher, 1925; made rigorous by Cramér, 1946) — it attains the Cramér–Rao bound in the limit, which is the main justification for using it.

ProofH

Confidence intervals

Theorem— Theorem (the z-interval)

If X1,…,XnX_1, \dots, X_n are i.i.d. N(μ,σ2)N(\mu, \sigma^2) with σ\sigma known, and z=1.96z = 1.96 (so that P(∣Z∣≤z)=0.95P(|Z| \le z) = 0.95 for Z∼N(0,1)Z \sim N(0, 1)), then Xˉ±zσ/n\bar X \pm z\sigma/\sqrt n is a 95%95\% confidence interval for μ\mu.

Proof

Xˉ\bar X is normal (a sum of independent normals is normal) with mean μ\mu and variance σ2/n\sigma^2/n, so Z=Xˉ−μσ/n∼N(0,1)Z = \frac{\bar X - \mu}{\sigma/\sqrt n} \sim N(0, 1) for every μ\mu. The event μ∈[Xˉ−zσ/n,Xˉ+zσ/n]\mu \in [\bar X - z\sigma/\sqrt n, \bar X + z\sigma/\sqrt n] is the event ∣Z∣≤z|Z| \le z, which has probability 0.950.95.

∎

The pattern — find a pivot, a function of the data and θ\theta whose distribution does not depend on θ\theta, and invert it — gives most classical intervals:

  • Unknown σ\sigma, normal data. Replacing σ\sigma by SS changes the pivot to T=Xˉ−μS/nT = \frac{\bar X - \mu}{S/\sqrt n}, which has Student's tt distribution with n−1n - 1 degrees of freedom (Gosset, writing as "Student", 1908; proved by Fisher). The interval Xˉ±tn−1 S/n\bar X \pm t_{n-1}\,S/\sqrt n has exact coverage; tn−1>1.96t_{n-1} > 1.96 (for example t4=2.776t_4 = 2.776) accounts for the extra uncertainty of estimating σ\sigma.
  • Large samples. By the central limit theorem, Xˉ±1.96 S/n\bar X \pm 1.96\,S/\sqrt n has coverage approximately 95%95\% for large nn, for any distribution with finite variance.
  • A proportion. The Wald interval p^±1.96p^(1−p^)/n\hat p \pm 1.96\sqrt{\hat p(1 - \hat p)/n} comes from the CLT. Its actual coverage can be far below 95%95\% when np^n\hat p is small (with n=10n = 10 and p=0.05p = 0.05 it is 40%40\%); the Wilson interval (1927), obtained by inverting the test rather than plugging in p^\hat p, behaves much better. The first experiment below computes these coverages exactly.

Example— A survey of mobile-money use

Suppose 260260 of 400400 randomly chosen households in a city report using mobile money. Then p^=0.65\hat p = 0.65, the estimated standard error is 0.65⋅0.35/400≈0.024\sqrt{0.65 \cdot 0.35/400} \approx 0.024, and the Wald interval is 0.65±0.047=[0.603,0.697]0.65 \pm 0.047 = [0.603, 0.697]; the Wilson interval is [0.602,0.695][0.602, 0.695]. The honest report is "about 65%65\%, give or take 55 percentage points" — together with how the households were sampled, since no interval repairs a biased sample.

What "95% confidence" means. Before the data are collected, the procedure has a 95%95\% chance of producing an interval that covers pp. After the data are in, [0.603,0.697][0.603, 0.697] either contains pp or it does not; pp is not random in this framework, so "P(0.603≤p≤0.697)=0.95P(0.603 \le p \le 0.697) = 0.95" is not a frequentist statement. If the survey were repeated many times, about 95%95\% of the intervals would cover the true pp. (The Bayesian credible interval below does support a probability statement about pp, at the price of a prior.)

ProofH

Hypothesis tests and p-values

Example— Is the die loaded?

A die is rolled 600600 times and shows 120120 sixes; a fair die would give 100100 on average. Take H0:p=16H_0 : p = \tfrac16 against H1:p>16H_1 : p > \tfrac16, with test statistic SS = number of sixes. Under H0H_0, SS has mean 100100 and standard deviation 600⋅16⋅56≈9.13\sqrt{600 \cdot \tfrac16 \cdot \tfrac56} \approx 9.13, and the p-value is PH0(S≥120)≈0.018P_{H_0}(S \ge 120) \approx 0.018 (exactly, from the binomial distribution; the normal approximation with continuity correction gives 0.0160.016). At level α=0.05\alpha = 0.05 we reject H0H_0. This does not mean P(H0 true)=0.018P(H_0 \text{ true}) = 0.018: it means that a fair die would produce 120120 or more sixes in about 1.8%1.8\% of such experiments.

Theorem— Theorem (p-values are uniform under the null)

Suppose that under H0H_0 the test statistic TT has a continuous distribution function FF, and the p-value is P=1−F(T)P = 1 - F(T). Then PH0(P≤α)=αP_{H_0}(P \le \alpha) = \alpha for every α∈[0,1]\alpha \in [0, 1]: the test "reject when P≤αP \le \alpha" has type I error exactly α\alpha.

Proof

It suffices to show that F(T)F(T) is uniform on [0,1][0, 1], since then P(1−F(T)≤α)=P(F(T)≥1−α)=αP(1 - F(T) \le \alpha) = P(F(T) \ge 1 - \alpha) = \alpha. Let u∈(0,1)u \in (0, 1). Because FF is continuous, non-decreasing and tends to 00 and 11 at ∓∞\mp\infty, the set {x:F(x)≤u}\{x : F(x) \le u\} is a closed half-line (−∞,xu](-\infty, x_u] with F(xu)=uF(x_u) = u (intermediate value theorem). Hence P(F(T)≤u)=P(T≤xu)=F(xu)=uP(F(T) \le u) = P(T \le x_u) = F(x_u) = u.

∎

The power of a test depends on the true effect, the noise and the sample size. For a one-sided zz-test of H0:μ=0H_0 : \mu = 0 at level 0.050.05 with known σ\sigma, we reject when n Xˉ/σ>1.645\sqrt n\,\bar X/\sigma > 1.645; if the true mean is μ=δσ\mu = \delta\sigma, the power is 1−Φ(1.645−δn)1 - \Phi(1.645 - \delta\sqrt n). For an effect of half a standard deviation (δ=0.5\delta = 0.5), the power is 0.470.47 with n=10n = 10, 0.800.80 with n=25n = 25 and 0.950.95 with n=44n = 44.

Type I error, type II error and power

Shaded: the 5% chance of rejecting a true null (type I error). The part of the second curve to the left of 1.645 is the type II error; to the right, the power. Increase d by increasing n.

reject →
  • test statistic if H₀ is true
  • test statistic if the effect is d
  • Signed area: above the axis counts as positive, below (hatched) as negative
  • test statistic if H₀ is true: y = 0.242
  • test statistic if the effect is d: y = 0.1295
  • Signed area from 1.645 to 8 ≈ 0.05 (numerical integration)

Three facts complete the picture.

  1. Tests and intervals are two views of one thing. The two-sided zz-test rejects H0:μ=μ0H_0 : \mu = \mu_0 at level α\alpha exactly when μ0\mu_0 lies outside the (1−α)(1 - \alpha) zz-interval. A confidence interval is the set of parameter values that the data do not reject — and it shows the size of the effect, which a p-value alone hides.
  2. Not rejecting is not accepting. A study with low power will usually fail to reject even when the effect is real. "p=0.3p = 0.3" means the data are compatible with no effect; they may be equally compatible with a large one. Report the interval.
  3. Significance is not importance. With enough data, a trivially small effect becomes "significant"; with too little, an important one does not.
ProofH

Multiple testing

Run 2020 independent tests of true null hypotheses at level 0.050.05. The chance that at least one is "significant" is 1−0.9520≈0.641 - 0.95^{20} \approx 0.64. Search through enough variables, subgroups or outcome measures, and a spurious discovery is almost guaranteed — and if only the significant results are reported, the literature fills with false positives. The family-wise error rate (FWER) is the probability of at least one false rejection.

Theorem— Theorem (Bonferroni correction)

If each of mm tests is carried out at level α/m\alpha/m, the family-wise error rate is at most α\alpha, whatever the dependence between the tests.

Proof

Let AiA_i be the event that test ii falsely rejects; for true nulls P(Ai)≤α/mP(A_i) \le \alpha/m (for false nulls there is nothing to count). By the union bound P(A1∪⋯∪Am)≤∑iP(Ai)≤m⋅α/m=αP(A_1 \cup \cdots \cup A_m) \le \sum_i P(A_i) \le m \cdot \alpha/m = \alpha. The union bound itself follows from additivity: A1∪⋯∪AmA_1 \cup \cdots \cup A_m is the disjoint union of the sets Ai∖(A1∪⋯∪Ai−1)A_i \setminus (A_1 \cup \cdots \cup A_{i-1}), each contained in AiA_i.

∎

For independent tests the exact FWER is 1−(1−α/m)m1 - (1 - \alpha/m)^m, and Bernoulli's inequality (1−a)m≥1−ma(1 - a)^m \ge 1 - ma shows how close the union bound is. Bonferroni is safe but conservative: with many tests it loses power. The Benjamini–Hochberg procedure (1995) controls instead the false discovery rate, the expected proportion of false discoveries among all discoveries: sort the p-values p(1)≤⋯≤p(m)p_{(1)} \le \cdots \le p_{(m)}, find the largest kk with p(k)≤kα/mp_{(k)} \le k\alpha/m, and reject the kk smallest. For independent tests it guarantees false discovery rate at most αm0/m≤α\alpha m_0/m \le \alpha, where m0m_0 is the number of true nulls (stated here without proof). The second experiment compares both procedures by simulation.

Multiplicity also hides in choices that are never written down — which outcome, which subgroup, which covariates, when to stop collecting data. Pre-registering the analysis, reporting every test performed, and publishing code, data and random seeds so that others can rerun the analysis (see computational reproducibility) are the practical defences.

ProofH

Linear regression and the normal equations

In the linear model y=Xβ+εy = X\beta + \varepsilon, the n×pn \times p matrix XX holds the explanatory variables (a first column of ones gives an intercept), β∈Rp\beta \in \R^p is unknown, and ε\varepsilon is random noise. The least-squares estimate minimises the residual sum of squares ∥y−Xβ∥2=∑i(yi−(Xβ)i)2\|y - X\beta\|^2 = \sum_i \big(y_i - (X\beta)_i\big)^2.

Theorem— Theorem (normal equations)

A vector β^\hat\beta minimises ∥y−Xβ∥2\|y - X\beta\|^2 if and only if it satisfies the normal equations X⊤Xβ^=X⊤yX^\top X\hat\beta = X^\top y. If the columns of XX are linearly independent, X⊤XX^\top X is invertible and the unique minimiser is β^=(X⊤X)−1X⊤y\hat\beta = (X^\top X)^{-1}X^\top y.

Proof

If. Let r=y−Xβ^r = y - X\hat\beta, so the normal equations say X⊤r=0X^\top r = 0: the residual is orthogonal to every column of XX. For any β\beta, put w=β^−βw = \hat\beta - \beta; then y−Xβ=r+Xwy - X\beta = r + Xw and

∥y−Xβ∥2=∥r∥2+2 r⊤Xw+∥Xw∥2=∥r∥2+2 (X⊤r)⊤w+∥Xw∥2=∥r∥2+∥Xw∥2≥∥r∥2.\|y - X\beta\|^2 = \|r\|^2 + 2\,r^\top X w + \|Xw\|^2 = \|r\|^2 + 2\,(X^\top r)^\top w + \|Xw\|^2 = \|r\|^2 + \|Xw\|^2 \ge \|r\|^2 .

Only if. If β^\hat\beta is a minimiser, let g=X⊤rg = X^\top r and t∈Rt \in \R. The same expansion gives ∥y−X(β^+tg)∥2=∥r∥2−2t∥g∥2+t2∥Xg∥2\|y - X(\hat\beta + tg)\|^2 = \|r\|^2 - 2t\|g\|^2 + t^2\|Xg\|^2, which must be at least ∥r∥2\|r\|^2 for every tt. If g≠0g \ne 0, small t>0t > 0 make −2t∥g∥2+t2∥Xg∥2-2t\|g\|^2 + t^2\|Xg\|^2 negative; so g=0g = 0. Uniqueness. If X⊤Xv=0X^\top Xv = 0 then ∥Xv∥2=v⊤X⊤Xv=0\|Xv\|^2 = v^\top X^\top Xv = 0, so Xv=0Xv = 0, and v=0v = 0 when the columns are independent; thus X⊤XX^\top X is invertible.

∎

The fitted values y^=Xβ^\hat y = X\hat\beta are the orthogonal projection of yy onto the column space of XX — the viewpoints section takes this picture further. For a straight line y=β0+β1xy = \beta_0 + \beta_1 x, the two normal equations ∑i(yi−β0−β1xi)=0\sum_i(y_i - \beta_0 - \beta_1x_i) = 0 and ∑ixi(yi−β0−β1xi)=0\sum_i x_i(y_i - \beta_0 - \beta_1x_i) = 0 give

β^1=∑i(xi−xˉ)(yi−yˉ)∑i(xi−xˉ)2=r sysx,β^0=yˉ−β^1xˉ,\hat\beta_1 = \frac{\sum_i (x_i - \bar x)(y_i - \bar y)}{\sum_i (x_i - \bar x)^2} = r\,\frac{s_y}{s_x}, \qquad \hat\beta_0 = \bar y - \hat\beta_1\bar x,

so the line passes through (xˉ,yˉ)(\bar x, \bar y), and the residuals sum to zero and are uncorrelated with xx.

Example— Hooke's law in a school laboratory

A physics class hangs masses of 0,100,…,5000, 100, \dots, 500 g on a spring and records the extensions 0.1,2.0,4.1,5.9,8.2,9.90.1, 2.0, 4.1, 5.9, 8.2, 9.9 cm (illustrative numbers). With xx in hundreds of grams, the normal equations give exactly β^0=8105≈0.076\hat\beta_0 = \frac{8}{105} \approx 0.076 cm and β^1=347175≈1.983\hat\beta_1 = \frac{347}{175} \approx 1.983 cm per 100100 g, with R2=0.999R^2 = 0.999. The third experiment below solves the normal equations in exact arithmetic and checks the residuals.

Statistical properties. If XX is fixed with independent columns, E[ε]=0E[\varepsilon] = 0 and Cov⁡(ε)=σ2I\operatorname{Cov}(\varepsilon) = \sigma^2 I, then E[β^]=(X⊤X)−1X⊤Xβ=βE[\hat\beta] = (X^\top X)^{-1}X^\top X\beta = \beta (unbiased) and Cov⁡(β^)=σ2(X⊤X)−1\operatorname{Cov}(\hat\beta) = \sigma^2(X^\top X)^{-1}. The Gauss–Markov theorem (stated without proof) says β^\hat\beta has the smallest variance among all linear unbiased estimators. The residual sum of squares divided by n−pn - p is unbiased for σ2\sigma^2 — Bessel's correction is the special case p=1p = 1, XX a column of ones. When an intercept is included, ∑(yi−yˉ)2=∑(y^i−yˉ)2+∑(yi−y^i)2\sum(y_i - \bar y)^2 = \sum(\hat y_i - \bar y)^2 + \sum(y_i - \hat y_i)^2 (Pythagoras), and R2=1−∑(yi−y^i)2∑(yi−yˉ)2R^2 = 1 - \frac{\sum(y_i - \hat y_i)^2}{\sum(y_i - \bar y)^2} is the fraction of variation "explained"; for a straight line, R2=r2R^2 = r^2.

Check the residuals. Every one of these properties rests on assumptions — linearity, constant variance, independence, and for intervals and tests often normality of the noise. They are checked by looking at the residuals yi−y^iy_i - \hat y_i: plotted against the fitted values they should show no pattern (a curve signals non-linearity, a funnel signals non-constant variance); a normal quantile plot checks normality; and points with large leverage hiih_{ii} (the diagonal of the projection matrix X(X⊤X)−1X⊤X(X^\top X)^{-1}X^\top) deserve scrutiny, because they pull the line towards themselves. Anscombe's quartet (1973) makes the point unforgettable: four data sets with the same means, variances, correlation (0.8160.816) and fitted line y=3.00+0.500xy = 3.00 + 0.500x — one roughly linear, one a smooth curve, one linear with a single outlier, and one where a single point determines the slope. And no residual check turns correlation into causation: that needs design, such as randomisation.

ProofH

Bayesian inference

The Bayesian approach treats the unknown parameter as random, with a prior distribution π(θ)\pi(\theta) expressing what is believed before the data. Bayes' theorem gives the posterior

π(θ∣x)=L(θ) π(θ)∫L(ϑ) π(ϑ) dϑ  ∝  likelihood×prior,\pi(\theta \mid x) = \frac{L(\theta)\,\pi(\theta)}{\int L(\vartheta)\,\pi(\vartheta)\,d\vartheta} \;\propto\; \text{likelihood} \times \text{prior},

and all conclusions are read off it: a posterior mean as an estimate, an interval of posterior probability 0.950.95 (a credible interval) as a statement of uncertainty.

Theorem— Theorem (beta–binomial conjugacy)

If pp has the Beta(a,b)(a, b) prior, with density proportional to pa−1(1−p)b−1p^{a-1}(1 - p)^{b-1} on (0,1)(0, 1) (a,b>0a, b > 0), and kk successes are observed in nn independent trials, then the posterior is Beta(a+k,b+n−k)(a + k, b + n - k), with mean

a+ka+b+n=w⋅aa+b+(1−w)⋅kn,w=a+ba+b+n.\frac{a + k}{a + b + n} = w\cdot\frac{a}{a + b} + (1 - w)\cdot\frac kn, \qquad w = \frac{a + b}{a + b + n}.

Proof

The posterior density is proportional to pk(1−p)n−k⋅pa−1(1−p)b−1=pa+k−1(1−p)b+n−k−1p^k(1 - p)^{n-k}\cdot p^{a-1}(1 - p)^{b-1} = p^{a + k - 1}(1 - p)^{b + n - k - 1}, which is the Beta(a+k,b+n−k)(a + k, b + n - k) density up to its normalising constant; since both integrate to 11, the constants agree. The mean of Beta(α,β)(\alpha, \beta) is α/(α+β)\alpha/(\alpha + \beta), and the weighted-average form is a rearrangement.

∎

The posterior mean is a compromise between the prior mean and the data, and the data's weight 1−w1 - w tends to 11 as nn grows. With the uniform prior Beta(1,1)(1, 1) it is k+1n+2\frac{k + 1}{n + 2}, Laplace's rule of succession. For the survey above (260260 of 400400), the uniform prior gives the posterior Beta(261,141)(261, 141), with mean 0.6490.649 and central 95%95\% credible interval [0.602,0.695][0.602, 0.695] — numerically almost the same as the confidence intervals, with a different meaning: given the model and the prior, P(0.602≤p≤0.695∣data)=0.95P(0.602 \le p \le 0.695 \mid \text{data}) = 0.95. This agreement is no accident: under regularity conditions, the Bernstein–von Mises theorem says that for large nn the posterior is approximately N(θ^,1/(nI(θ^)))N\big(\hat\theta, 1/(nI(\hat\theta))\big), whatever the (smooth, positive) prior. With little data, or many parameters, the prior matters, and should be reported and examined like any other assumption.

Formal mathematicsF

Statistics in Lean and Mathlib

Mathlib has no "statistics" library as such, but its probability theory — random variables as functions X : Ω → ℝ, expectation μ[X], variance Var[X; μ], independence X ⟂ᵢ[μ] Y — is exactly what the theory of estimation needs, and its linear algebra handles least squares. Data sets are functions summed over a Finset.

Estimators. The sample mean as a definition; the shift identity; unbiasedness and the variance σ2/n\sigma^2/n of the sample mean; and Bessel's correction, proved as in the lesson. The hypotheses are pairwise independence (Mathlib's form of "uncorrelated" in IndepFun.variance_sum) with common mean and variance:

sampleMeanLean 4Formally verified
/-- The **sample mean** `x̄ = (∑ᵢ xᵢ)/|s|` of the data `xᵢ`, `i ∈ s`. (For the empty data set
Lean's convention `a / 0 = 0` gives `0`.) -/
noncomputable def sampleMean {ι : Type*} (s : Finset ι) (x : ι → ℝ) : ℝ :=
  (∑ i ∈ s, x i) / s.card
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
sum_eq_card_mul_meanLean 4Proved here from basic factsFormally verified
/-- The total of the data is `n · x̄`. -/
theorem sum_eq_card_mul_mean {ι : Type*} (s : Finset ι) (x : ι → ℝ) :
    ∑ i ∈ s, x i = s.card * sampleMean s x := by
  unfold sampleMean
  rcases Nat.eq_zero_or_pos s.card with h | h
  · rw [Finset.card_eq_zero.mp h]
    simp
  · have : (s.card : ℝ) ≠ 0 := Nat.cast_ne_zero.mpr h.ne'
    field_simp
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
sum_sq_dev_eqLean 4Proved here from basic factsFormally verified
/-- **The shift identity.** For any number `c`,
`∑ (xᵢ − x̄)² = ∑ (xᵢ − c)² − n (x̄ − c)²`. In particular (taking `c` arbitrary) the sample
mean minimises `c ↦ ∑ (xᵢ − c)²`, and (taking `c = μ`) it is the key step in Bessel's
correction. Proof: expand `((xᵢ − c) − (x̄ − c))²` and use `∑ (xᵢ − c) = n (x̄ − c)`. -/
theorem sum_sq_dev_eq {ι : Type*} (s : Finset ι) (x : ι → ℝ) (c : ℝ) :
    ∑ i ∈ s, (x i - sampleMean s x) ^ 2 =
      ∑ i ∈ s, (x i - c) ^ 2 - s.card * (sampleMean s x - c) ^ 2 := by
  set m := sampleMean s x
  have hsum : ∑ i ∈ s, (x i - c) = s.card * (m - c) := by
    rw [sum_sub_distrib, sum_eq_card_mul_mean s x, sum_const, nsmul_eq_mul]
    ring
  have hpt : ∀ i ∈ s, (x i - m) ^ 2 = (x i - c) ^ 2 - 2 * (m - c) * (x i - c) + (m - c) ^ 2 := by
    intro i _
    ring
  rw [sum_congr rfl hpt, sum_add_distrib, sum_sub_distrib, ← mul_sum, hsum, sum_const,
    nsmul_eq_mul]
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
sample_mean_unbiasedLean 4Proved here from basic factsFormally verified
/-- **The sample mean is unbiased:** if each `Xᵢ` has mean `m`, then `E[X̄ₙ] = m` (`n ≥ 1`).
Only linearity of expectation is used — no independence. -/
theorem sample_mean_unbiased (hint : ∀ i, Integrable (X i) μ) (hmean : ∀ i, μ[X i] = m)
    {n : ℕ} (hn : 0 < n) : μ[fun ω => sampleMean (range n) (fun i => X i ω)] = m := by
  have hnR : (n : ℝ) ≠ 0 := Nat.cast_ne_zero.mpr hn.ne'
  simp only [sampleMean, card_range]
  rw [integral_div, integral_finsetSum _ fun i _ => hint i]
  simp only [hmean, sum_const, card_range, nsmul_eq_mul]
  field_simp
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
variance_sample_meanLean 4Proved here from basic factsFormally verified
/-- **The variance of the sample mean is `σ²/n`** for pairwise independent observations with
common variance `σ² = v`: variances of independent variables add (`IndepFun.variance_sum`),
and `Var(X/n) = Var(X)/n²`. -/
theorem variance_sample_mean (hL2 : ∀ i, MemLp (X i) 2 μ)
    (hindep : Pairwise fun i j => X i ⟂ᵢ[μ] X j) (hvar : ∀ i, Var[X i; μ] = v) (n : ℕ) :
    Var[fun ω => sampleMean (range n) (fun i => X i ω); μ] = v / n := by
  have h : (fun ω => sampleMean (range n) (fun i => X i ω)) =
      fun ω => (n : ℝ)⁻¹ * (∑ i ∈ range n, X i) ω := by
    funext ω
    simp [sampleMean, Finset.sum_apply, div_eq_inv_mul]
  rw [h, variance_const_mul,
    IndepFun.variance_sum (fun i _ => hL2 i) (fun i _ j _ hij => hindep hij)]
  simp only [hvar, sum_const, card_range, nsmul_eq_mul]
  rcases Nat.eq_zero_or_pos n with rfl | hn
  · simp
  · have hnR : (n : ℝ) ≠ 0 := Nat.cast_ne_zero.mpr hn.ne'
    field_simp
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
sample_mean_memLpLean 4Proved here from basic factsFormally verified
/-- The sample mean of finitely many observations with finite variance has finite variance. -/
theorem sample_mean_memLp [IsProbabilityMeasure μ] (hL2 : ∀ i, MemLp (X i) 2 μ) (n : ℕ) :
    MemLp (fun ω => sampleMean (range n) (fun i => X i ω)) 2 μ := by
  have hsum : MemLp (∑ i ∈ range n, X i) 2 μ := memLp_finsetSum' _ fun i _ => hL2 i
  have := hsum.const_mul ((n : ℝ)⁻¹)
  convert this using 1
  funext ω
  simp [sampleMean, Finset.sum_apply, div_eq_inv_mul]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
besselLean 4Proved here from basic factsFormally verified
/-- **Bessel's correction.** For pairwise independent observations with common mean `m` and
common variance `v`, and `n ≥ 1`, `E[∑ (Xᵢ − X̄)²] = (n − 1) v`. Hence the sample variance
`S² = ∑ (Xᵢ − X̄)²/(n − 1)` is an unbiased estimator of `v` (for `n ≥ 2`), while dividing by
`n` underestimates it on average. Proof, as in the lesson: by the shift identity with `c = m`,
`∑ (Xᵢ − X̄)² = ∑ (Xᵢ − m)² − n (X̄ − m)²`; the expectations are `n v` and `n · v/n`. -/
theorem bessel [IsProbabilityMeasure μ] (hL2 : ∀ i, MemLp (X i) 2 μ) (hindep : Pairwise fun i j => X i ⟂ᵢ[μ] X j)
    (hmean : ∀ i, μ[X i] = m) (hvar : ∀ i, Var[X i; μ] = v) {n : ℕ} (hn : 0 < n) :
    ∫ ω, ∑ i ∈ range n, (X i ω - sampleMean (range n) (fun j => X j ω)) ^ 2 ∂μ =
      (n - 1) * v := by
  set Xbar : Ω → ℝ := fun ω => sampleMean (range n) (fun j => X j ω) with hXbar
  have hnR : (n : ℝ) ≠ 0 := Nat.cast_ne_zero.mpr hn.ne'
  -- Pointwise, the shift identity with `c = m`.
  have hpt : (fun ω => ∑ i ∈ range n, (X i ω - Xbar ω) ^ 2) =
      fun ω => ∑ i ∈ range n, (X i ω - m) ^ 2 - n * (Xbar ω - m) ^ 2 := by
    funext ω
    rw [hXbar]
    simp only
    rw [sum_sq_dev_eq (range n) (fun j => X j ω) m, card_range]
  -- Integrability of the two pieces.
  have hint_i : ∀ i, Integrable (fun ω => (X i ω - m) ^ 2) μ := fun i =>
    ((hL2 i).sub (memLp_const m)).integrable_sq
  have hint_bar : Integrable (fun ω => (Xbar ω - m) ^ 2) μ :=
    ((sample_mean_memLp hL2 n).sub (memLp_const m)).integrable_sq
  -- Each `E[(Xᵢ − m)²] = v`, and `E[(X̄ − m)²] = Var X̄ = v/n`.
  have hEi : ∀ i, ∫ ω, (X i ω - m) ^ 2 ∂μ = v := by
    intro i
    rw [← hvar i, variance_eq_integral (hL2 i).aestronglyMeasurable.aemeasurable, hmean i]
  have hEbar : ∫ ω, (Xbar ω - m) ^ 2 ∂μ = v / n := by
    have hm : μ[Xbar] = m :=
      sample_mean_unbiased (fun i => (hL2 i).integrable one_le_two) hmean hn
    rw [← variance_sample_mean hL2 hindep hvar n, ← hXbar,
      variance_eq_integral (sample_mean_memLp hL2 n).aestronglyMeasurable.aemeasurable, hm]
  show ∫ ω, (fun ω => ∑ i ∈ range n, (X i ω - Xbar ω) ^ 2) ω ∂μ = (n - 1) * v
  rw [hpt, integral_sub (integrable_finsetSum _ fun i _ => hint_i i) (hint_bar.const_mul _),
    integral_finsetSum _ fun i _ => hint_i i, integral_const_mul, hEbar]
  simp only [hEi, sum_const, card_range, nsmul_eq_mul]
  field_simp
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor

Consistency of the sample mean (Mathlib's Chebyshev inequality applied to Xˉn\bar X_n), the computing formula for the variance, and the bias–variance decomposition:

sample_mean_consistentLean 4Proved here from basic factsFormally verified
/-- **Consistency of the sample mean**, with a rate: `P(|X̄ₙ − m| ≥ ε) ≤ v / (n ε²)`. Proof:
Mathlib's Chebyshev inequality (`meas_ge_le_variance_div_sq`) applied to `X̄ₙ`, whose mean is
`m` and whose variance is `v/n`. As `n → ∞` the bound tends to `0`. -/
theorem sample_mean_consistent [IsProbabilityMeasure μ] (hL2 : ∀ i, MemLp (X i) 2 μ)
    (hindep : Pairwise fun i j => X i ⟂ᵢ[μ] X j) (hmean : ∀ i, μ[X i] = m)
    (hvar : ∀ i, Var[X i; μ] = v) {n : ℕ} (hn : 0 < n) {ε : ℝ} (hε : 0 < ε) :
    μ {ω | ε ≤ |sampleMean (range n) (fun i => X i ω) - m|} ≤
      ENNReal.ofReal (v / (n * ε ^ 2)) := by
  have h := meas_ge_le_variance_div_sq (sample_mean_memLp hL2 n) hε
  rw [sample_mean_unbiased (fun i => (hL2 i).integrable one_le_two) hmean hn,
    variance_sample_mean hL2 hindep hvar n, div_div] at h
  exact h
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
variance_computing_formulaLean 4Applies a library theoremFormally verified
/-- The computing formula `Var X = E[X²] − (E X)²`, for `X` with finite variance. This is
Mathlib's `ProbabilityTheory.variance_eq_sub`. -/
theorem variance_computing_formula [IsProbabilityMeasure μ] {X : Ω → ℝ} (hX : MemLp X 2 μ) :
    Var[X; μ] = μ[X ^ 2] - μ[X] ^ 2 :=
  variance_eq_sub hX
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
mse_decompositionLean 4Proved here from basic factsFormally verified
/-- **Mean squared error = variance + bias².** For an estimator `T` with finite variance and
a parameter value `θ`, `E[(T − θ)²] = Var T + (E T − θ)²`. Proof: write
`T − θ = (T − E T) + (E T − θ)`; the cross term has expectation `0`. -/
theorem mse_decomposition [IsProbabilityMeasure μ] {T : Ω → ℝ} (hT : MemLp T 2 μ) (θ : ℝ) :
    ∫ ω, (T ω - θ) ^ 2 ∂μ = Var[T; μ] + (μ[T] - θ) ^ 2 := by
  set a := μ[T]
  have hTi : Integrable T μ := hT.integrable one_le_two
  have hpt : (fun ω => (T ω - θ) ^ 2) =
      fun ω => (T ω - a) ^ 2 + (2 * (a - θ) * (T ω - a) + (a - θ) ^ 2) := by
    funext ω
    ring
  have h1 : Integrable (fun ω => (T ω - a) ^ 2) μ := (hT.sub (memLp_const a)).integrable_sq
  have h2 : Integrable (fun ω => 2 * (a - θ) * (T ω - a)) μ :=
    (hTi.sub (integrable_const a)).const_mul _
  have h3 : Integrable (fun ω => 2 * (a - θ) * (T ω - a) + (a - θ) ^ 2) μ :=
    h2.add (integrable_const _)
  rw [hpt, integral_add h1 h3, integral_add h2 (integrable_const _),
    integral_const_mul, integral_sub hTi (integrable_const a),
    variance_eq_integral hT.aestronglyMeasurable.aemeasurable]
  simp [a]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor

Likelihood. The calculus-free proof that k/nk/n maximises the Bernoulli log-likelihood, using Mathlib's Real.log_le_sub_one_of_pos:

bernoulli_mleLean 4Proved here from basic factsFormally verified
/-- **The Bernoulli maximum likelihood estimator is `k/n`.** With `k` successes in `n`
independent trials (`0 < k < n`), the log-likelihood `ℓ(p) = k log p + (n − k) log(1 − p)` is
largest at `p̂ = k/n`. Proof without calculus, as in the lesson: with `q = k/n`,
`ℓ(p) − ℓ(q) = k log(p/q) + (n − k) log((1 − p)/(1 − q))
  ≤ k (p/q − 1) + (n − k)((1 − p)/(1 − q) − 1) = 0`, using `log x ≤ x − 1`
(Mathlib's `Real.log_le_sub_one_of_pos`). -/
theorem bernoulli_mle {n k : ℕ} (hk : 0 < k) (hkn : k < n) {p : ℝ} (hp0 : 0 < p) (hp1 : p < 1) :
    k * Real.log p + (n - k) * Real.log (1 - p) ≤
      k * Real.log (k / n) + (n - k) * Real.log (1 - k / n) := by
  have hkR : (0 : ℝ) < k := by exact_mod_cast hk
  have hknR : (k : ℝ) < n := by exact_mod_cast hkn
  have hnR : (0 : ℝ) < n := hkR.trans hknR
  set q : ℝ := k / n with hq
  have hq0 : 0 < q := div_pos hkR hnR
  have hq1 : q < 1 := (div_lt_one hnR).mpr hknR
  have h1 : Real.log p - Real.log q ≤ p / q - 1 := by
    rw [← Real.log_div hp0.ne' hq0.ne']
    exact Real.log_le_sub_one_of_pos (div_pos hp0 hq0)
  have h2 : Real.log (1 - p) - Real.log (1 - q) ≤ (1 - p) / (1 - q) - 1 := by
    rw [← Real.log_div (by linarith) (by linarith)]
    exact Real.log_le_sub_one_of_pos (div_pos (by linarith) (by linarith))
  have hzero : (k : ℝ) * (p / q - 1) + (n - k) * ((1 - p) / (1 - q) - 1) = 0 := by
    have hnk : (n : ℝ) - k ≠ 0 := by linarith
    rw [hq]
    field_simp
    ring
  have e1 := mul_le_mul_of_nonneg_left h1 hkR.le
  have e2 := mul_le_mul_of_nonneg_left h2 (show (0 : ℝ) ≤ n - k by linarith)
  linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor

Least squares. Both directions of the normal-equations theorem, for any real matrix X : Matrix n p ℝ, with ⬝ᵥ the dot product and *ᵥ matrix–vector multiplication:

normal_equations_minimizeLean 4Proved here from basic factsFormally verified
/-- **Least squares via the normal equations.** If `b` satisfies `(XᵀX) b = Xᵀy`, then `b`
minimises the residual sum of squares `‖y − Xβ‖²` over all `β`. Proof (Pythagoras): with
`r = y − Xb` and `w = b − β`, `y − Xβ = r + Xw`, and the cross term `r · Xw = (Xᵀr) · w`
vanishes because `Xᵀr = Xᵀy − XᵀXb = 0`; so `‖y − Xβ‖² = ‖r‖² + ‖Xw‖² ≥ ‖r‖²`. -/
theorem normal_equations_minimize {n p : Type*} [Fintype n] [Fintype p] (X : Matrix n p ℝ)
    (y : n → ℝ) (b : p → ℝ) (hb : (Xᵀ * X) *ᵥ b = Xᵀ *ᵥ y) (β : p → ℝ) :
    (y - X *ᵥ b) ⬝ᵥ (y - X *ᵥ b) ≤ (y - X *ᵥ β) ⬝ᵥ (y - X *ᵥ β) := by
  set r := y - X *ᵥ b
  set w := b - β
  have hr : Xᵀ *ᵥ r = 0 := by
    simp only [r, mulVec_sub, mulVec_mulVec, hb, sub_self]
  have hcross : r ⬝ᵥ (X *ᵥ w) = 0 := by
    rw [dotProduct_mulVec, ← mulVec_transpose, hr, zero_dotProduct]
  have hsplit : y - X *ᵥ β = r + X *ᵥ w := by
    simp only [r, w, mulVec_sub]
    abel
  have hsq : 0 ≤ (X *ᵥ w) ⬝ᵥ (X *ᵥ w) :=
    Finset.sum_nonneg fun i _ => mul_self_nonneg _
  rw [hsplit, add_dotProduct, dotProduct_add, dotProduct_add, hcross, dotProduct_comm (X *ᵥ w) r,
    hcross]
  linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
minimizer_normal_equationsLean 4Proved here from basic factsFormally verified
/-- **Conversely, every least-squares solution satisfies the normal equations.** If `b`
minimises `‖y − Xβ‖²`, then `(XᵀX) b = Xᵀy`. Proof: for each direction `w` and real `t`,
`‖y − X(b + tw)‖² = ‖r‖² − 2t (Xᵀr)·w + t² ‖Xw‖²` must be at least `‖r‖²`; a quadratic
`−2ta + t²c` with `c ≥ 0` that is never negative has `a = 0`. Taking `w = Xᵀr` gives
`‖Xᵀr‖² = 0`. -/
theorem minimizer_normal_equations {n p : Type*} [Fintype n] [Fintype p] (X : Matrix n p ℝ)
    (y : n → ℝ) (b : p → ℝ)
    (hmin : ∀ β, (y - X *ᵥ b) ⬝ᵥ (y - X *ᵥ b) ≤ (y - X *ᵥ β) ⬝ᵥ (y - X *ᵥ β)) :
    (Xᵀ * X) *ᵥ b = Xᵀ *ᵥ y := by
  set r := y - X *ᵥ b
  set g := Xᵀ *ᵥ r
  -- Expand the residual sum of squares at `b + t g`.
  have hexp : ∀ t : ℝ, (y - X *ᵥ (b + t • g)) ⬝ᵥ (y - X *ᵥ (b + t • g)) =
      r ⬝ᵥ r - 2 * t * (g ⬝ᵥ g) + t ^ 2 * ((X *ᵥ g) ⬝ᵥ (X *ᵥ g)) := by
    intro t
    have hsplit : y - X *ᵥ (b + t • g) = r - t • (X *ᵥ g) := by
      simp only [r, mulVec_add, mulVec_smul]
      abel
    have hrg : r ⬝ᵥ (X *ᵥ g) = g ⬝ᵥ g := by
      rw [dotProduct_mulVec, ← mulVec_transpose]
    rw [hsplit]
    simp only [sub_dotProduct, dotProduct_sub, smul_dotProduct, dotProduct_smul, smul_eq_mul,
      hrg, dotProduct_comm (X *ᵥ g) r]
    ring
  set a := g ⬝ᵥ g
  set c := (X *ᵥ g) ⬝ᵥ (X *ᵥ g)
  have hc : 0 ≤ c := Finset.sum_nonneg fun i _ => mul_self_nonneg _
  have ha : 0 ≤ a := Finset.sum_nonneg fun i _ => mul_self_nonneg _
  -- Choose `t = a/(c + 1)`: the quadratic becomes `−a²(c + 2)/(c + 1)² ≤ 0`, so `a = 0`.
  have key := hmin (b + (a / (c + 1)) • g)
  rw [hexp] at key
  have hc1 : 0 < c + 1 := by linarith
  have hq : -2 * (a / (c + 1)) * a + (a / (c + 1)) ^ 2 * c = -(a ^ 2 * (c + 2)) / (c + 1) ^ 2 := by
    field_simp
    ring
  have h0 : 0 ≤ -(a ^ 2 * (c + 2)) / (c + 1) ^ 2 := by
    rw [← hq]
    linarith
  have h0' : a ^ 2 * (c + 2) ≤ 0 := by
    by_contra hneg
    have hpos : 0 < a ^ 2 * (c + 2) := not_le.mp hneg
    have : -(a ^ 2 * (c + 2)) / (c + 1) ^ 2 < 0 := div_neg_of_neg_of_pos (by linarith) (by positivity)
    linarith
  have ha0 : a = 0 := by
    have ha2 : a ^ 2 = 0 := by nlinarith [sq_nonneg a]
    exact pow_eq_zero_iff (two_ne_zero) |>.mp ha2
  -- `g · g = 0` forces `g = 0`, i.e. `Xᵀ(y − Xb) = 0`.
  have hg : g = 0 := by
    funext i
    have hsum : ∑ j, g j * g j = 0 := ha0
    have := (Finset.sum_eq_zero_iff_of_nonneg fun j _ => mul_self_nonneg (g j)).mp hsum i
      (Finset.mem_univ i)
    simpa using this
  have : Xᵀ *ᵥ y - (Xᵀ * X) *ᵥ b = 0 := by
    rw [← mulVec_mulVec, ← mulVec_sub]
    exact hg
  exact (sub_eq_zero.mp this).symm
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor

Multiple testing. The union bound from Mathlib, the Bonferroni correction, Bernoulli's inequality for independent tests, and the "twenty tests" number:

union_boundLean 4Applies a library theoremFormally verified
/-- **The union bound** (Boole's inequality): `P(A₁ ∪ ⋯ ∪ Aₘ) ≤ P(A₁) + ⋯ + P(Aₘ)`, for any
events, dependent or not. This is Mathlib's `measureReal_biUnion_finset_le`. -/
theorem union_bound [IsFiniteMeasure μ] {ι : Type*} (s : Finset ι) (A : ι → Set Ω) :
    μ.real (⋃ i ∈ s, A i) ≤ ∑ i ∈ s, μ.real (A i) :=
  measureReal_biUnion_finset_le s A
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
bonferroniLean 4Proved here from basic factsFormally verified
/-- **The Bonferroni correction controls the family-wise error rate.** If each of `m` tests
has probability at most `α/m` of a false rejection (event `Aᵢ`), then the probability of at
least one false rejection is at most `α` — whatever the dependence between the tests.
Proof: the union bound, then `m · (α/m) = α`. -/
theorem bonferroni [IsFiniteMeasure μ] {ι : Type*} (s : Finset ι) (A : ι → Set Ω) {α : ℝ}
    (hα : 0 ≤ α) (h : ∀ i ∈ s, μ.real (A i) ≤ α / s.card) :
    μ.real (⋃ i ∈ s, A i) ≤ α := by
  calc μ.real (⋃ i ∈ s, A i) ≤ ∑ i ∈ s, μ.real (A i) := union_bound s A
    _ ≤ ∑ _i ∈ s, α / s.card := sum_le_sum h
    _ = s.card * (α / s.card) := by rw [sum_const, nsmul_eq_mul]
    _ ≤ α := by
      rcases Nat.eq_zero_or_pos s.card with h0 | h0
      · rw [h0]
        simp [hα]
      · have : (s.card : ℝ) ≠ 0 := Nat.cast_ne_zero.mpr h0.ne'
        rw [mul_div_cancel₀ α this]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
fwer_independent_leLean 4Proved here from basic factsFormally verified
/-- For `m` **independent** tests each at level `α`, the family-wise error rate is exactly
`1 − (1 − α)ᵐ`, and this is at most `mα` — Bernoulli's inequality `(1 + a)ᵐ ≥ 1 + ma`
(Mathlib's `one_add_mul_le_pow`, valid for `a ≥ −2`) with `a = −α`; we only need `α ≤ 1`. So Bonferroni's union bound is close to exact
for independent tests with small `α`. -/
theorem fwer_independent_le {α : ℝ} (h1 : α ≤ 1) (m : ℕ) :
    1 - (1 - α) ^ m ≤ m * α := by
  have h := one_add_mul_le_pow (a := -α) (by linarith) m
  have : (1 + -α) = 1 - α := by ring
  rw [this] at h
  linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor
twenty_testsLean 4Proved here from basic factsFormally verified
/-- Twenty independent tests of true null hypotheses at level `0.05` produce at least one
"significant" result with probability `1 − 0.95²⁰ > 0.64`. Checked by exact arithmetic. -/
theorem twenty_tests : (1 : ℚ) - (95 / 100) ^ 20 > 64 / 100 := by
  norm_num
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Statistics.leanTry it in the Lean web editor

What is and is not formalised. Proved here: the shift identity, unbiasedness of the sample mean and of S2S^2, the variance of the sample mean and its consistency bound, the bias–variance decomposition, the Bernoulli MLE, the normal equations in both directions, Bonferroni's correction and the multiple-testing inequalities. Cited from Mathlib: the union bound and the computing formula for the variance (and, inside the consistency proof, Chebyshev's inequality and the additivity of variance). Not formalised: the Cramér–Rao inequality, the asymptotic normality of the MLE, the uniformity of p-values, Student's tt distribution and the coverage of the tt-interval, Gauss–Markov, Benjamini–Hochberg and beta–binomial conjugacy. The interval coverages, test sizes and powers in this lesson are computed numerically.

ComputationC

Coverage, false positives and residuals

Do confidence intervals deliver what they promise? First, the exact coverage of the Wald and Wilson intervals for a proportion, computed by summing binomial probabilities; then a simulation comparing the zz-interval, the tt-interval and the naive interval that plugs the sample standard deviation into the zz-formula.

How often do 95% confidence intervals really cover the truth?PythonExact computationStatistical evidenceComputationally tested
"""Do 95% confidence intervals cover the truth 95% of the time?

Part 1 is exact. For a binomial count X ~ Bin(n, p), the coverage of an
interval method is the sum of P(X = k) over the k whose interval contains p.
We compute it for the textbook Wald interval p_hat +- 1.96 sqrt(p_hat(1 -
p_hat)/n) and for the Wilson score interval. Part 2 is a seeded simulation:
for normal samples of size 5 we compare the z-interval with known sigma, the
Student t-interval, and the naive z-interval that plugs in the sample
standard deviation.
"""

import math
import random
import statistics

Z = 1.959963984540054  # the 97.5% point of N(0, 1)
T4 = 2.776445105197799  # the 97.5% point of Student's t with 4 degrees of freedom

def binomial_pmf(n, k, p):
    """P(X = k) for X ~ Bin(n, p), computed with logarithms (no overflow)."""
    if p in (0.0, 1.0):
        return float(k == round(n * p))
    log_c = math.lgamma(n + 1) - math.lgamma(k + 1) - math.lgamma(n - k + 1)
    return math.exp(log_c + k * math.log(p) + (n - k) * math.log(1 - p))

def wald_interval(k, n, z=Z):
    """The Wald interval p_hat +- z sqrt(p_hat (1 - p_hat) / n)."""
    p_hat = k / n
    half = z * math.sqrt(p_hat * (1 - p_hat) / n)
    return p_hat - half, p_hat + half

def wilson_interval(k, n, z=Z):
    """The Wilson score interval (Wilson, 1927)."""
    p_hat = k / n
    denom = 1 + z * z / n
    centre = (p_hat + z * z / (2 * n)) / denom
    half = z / denom * math.sqrt(p_hat * (1 - p_hat) / n + z * z / (4 * n * n))
    return centre - half, centre + half

def coverage(method, n, p):
    """Exact probability that the interval method(X, n) contains p."""
    total = 0.0
    for k in range(n + 1):
        low, high = method(k, n)
        if low <= p <= high:
            total += binomial_pmf(n, k, p)
    return total

def simulate_normal_intervals(n=5, reps=4000, seed=2024):
    """Coverage of three 95% intervals for the mean of N(10, 2^2) samples.

    Returns (z with known sigma, t with S, naive z with S) as proportions.
    """
    rng = random.Random(seed)
    mu, sigma = 10.0, 2.0
    hits = [0, 0, 0]
    for _ in range(reps):
        xs = [rng.gauss(mu, sigma) for _ in range(n)]
        mean, s = statistics.fmean(xs), statistics.stdev(xs)
        for j, half in enumerate([Z * sigma / math.sqrt(n),
                                  T4 * s / math.sqrt(n),
                                  Z * s / math.sqrt(n)]):
            hits[j] += abs(mean - mu) <= half
    return [h / reps for h in hits]

def main():
    print("Part 1 (exact): coverage of nominal 95% intervals for a proportion")
    print(f"{'n':>6} {'p':>6} {'Wald':>8} {'Wilson':>8}")
    for n in [10, 30, 100, 1000]:
        for p in [0.5, 0.2, 0.05]:
            print(f"{n:>6} {p:>6} {coverage(wald_interval, n, p):>8.3f}"
                  f" {coverage(wilson_interval, n, p):>8.3f}")
    print("The Wald interval can undercover badly when n p is small; the")
    print("Wilson interval stays much closer to 95%.")
    print()
    print("Part 2 (simulation, 4000 normal samples of size n = 5):")
    known, t_int, naive = simulate_normal_intervals()
    print(f"  z-interval, sigma known:         {known:.3f}")
    print(f"  t-interval, S and t(4) = 2.776:  {t_int:.3f}")
    print(f"  naive z-interval with S:         {naive:.3f}")
    print("Plugging S into the z-interval ignores the uncertainty in S;")
    print("Student's t-distribution corrects for it exactly for normal data.")
    print()
    print("Epistemic status: part 1 is an exact computation of coverage")
    print("probabilities (in floating point) for the listed n and p. Part 2 is")
    print("a seeded Monte Carlo estimate with standard error about 0.004; it")
    print("illustrates, but does not prove, that the t-interval has coverage")
    print("exactly 95% for normal samples (a theorem).")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Next, multiple testing by simulation: null p-values are uniform, twenty uncorrected tests produce a false positive about 64%64\% of the time, Bonferroni restores control, and Benjamini–Hochberg finds more real effects at the price of a controlled fraction of false ones.

Multiple testing: false positives, Bonferroni and Benjamini-HochbergPythonStatistical evidenceExact computationComputationally tested
"""Multiple testing: why twenty tests find a 'significant' effect that is not there.

We simulate many studies, each running m two-sided z-tests. Under a true null
hypothesis the test statistic is N(0, 1); under a real effect it is N(3, 1).
We check that null p-values are uniformly distributed, measure the family-wise
error rate (the chance of at least one false positive) with and without the
Bonferroni correction, and compare Bonferroni with the Benjamini-Hochberg
procedure, which controls the false discovery rate instead.
"""

import math
import random

def p_value(z):
    """Two-sided p-value of a standard normal test statistic z."""
    return math.erfc(abs(z) / math.sqrt(2))

def bonferroni(pvalues, alpha):
    """Indices rejected by Bonferroni: p <= alpha / m."""
    m = len(pvalues)
    return {i for i, p in enumerate(pvalues) if p <= alpha / m}

def benjamini_hochberg(pvalues, alpha):
    """Indices rejected by the Benjamini-Hochberg step-up procedure (1995).

    Sort the p-values; find the largest k with p_(k) <= k alpha / m and reject
    the k smallest.
    """
    m = len(pvalues)
    order = sorted(range(m), key=lambda i: pvalues[i])
    k_max = 0
    for rank, i in enumerate(order, start=1):
        if pvalues[i] <= rank * alpha / m:
            k_max = rank
    return set(order[:k_max])

def simulate(rng, m, effects, shift=3.0):
    """p-values for one study: the first ``effects`` tests have a real effect."""
    return [p_value(rng.gauss(shift if i < effects else 0.0, 1.0))
            for i in range(m)]

def main():
    rng = random.Random(1995)
    alpha, reps = 0.05, 2000
    deciles = [0] * 10
    any_raw = any_bonf = 0
    for _ in range(reps):
        ps = simulate(rng, 20, 0)
        for p in ps:
            deciles[min(int(p * 10), 9)] += 1
        any_raw += any(p <= alpha for p in ps)
        any_bonf += bool(bonferroni(ps, alpha))
    print(f"{reps} studies, each with 20 true null hypotheses, alpha = 0.05")
    print("Null p-values per tenth of [0, 1] (uniform means about 4000 each):")
    print("  " + " ".join(f"{c:>5}" for c in deciles))
    print(f"P(at least one p <= 0.05), uncorrected: {any_raw / reps:.3f}"
          f"  (exact 1 - 0.95^20 = {1 - 0.95 ** 20:.3f})")
    print(f"P(at least one rejection), Bonferroni:  {any_bonf / reps:.3f}"
          f"  (guaranteed <= 0.05)")
    print()
    print("Studies with 50 tests, of which 10 have a real effect (mean 3):")
    totals = {"Bonferroni": [0, 0], "Benjamini-Hochberg": [0, 0]}
    fdp_bh = 0.0
    for _ in range(reps):
        ps = simulate(rng, 50, 10)
        for name, rule in [("Bonferroni", bonferroni),
                           ("Benjamini-Hochberg", benjamini_hochberg)]:
            rejected = rule(ps, alpha)
            true_hits = sum(1 for i in rejected if i < 10)
            totals[name][0] += true_hits
            totals[name][1] += len(rejected) - true_hits
            if name == "Benjamini-Hochberg" and rejected:
                fdp_bh += (len(rejected) - true_hits) / len(rejected)
    for name, (hits, false) in totals.items():
        print(f"  {name:<19} real effects found {hits / reps:5.2f} of 10,"
              f" false positives {false / reps:4.2f}")
    print(f"  Average false discovery proportion for BH: {fdp_bh / reps:.3f}")
    print("  (BH guarantees at most 0.05 x 40/50 = 0.04 for independent tests)")
    print()
    print("Epistemic status: seeded Monte Carlo simulation (2000 studies per")
    print("scenario), so every proportion has sampling error of order 0.01.")
    print("The guarantees quoted (Bonferroni's union bound, the BH theorem for")
    print("independent tests) are theorems; the simulation only illustrates")
    print("them in two scenarios.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Finally, least squares: the normal equations solved exactly, residuals orthogonal to the columns of XX, and Anscombe's quartet — identical summaries, different residual stories.

Normal equations and Anscombe's quartet: fit, then check residualsPythonExact computationNumerical approximationComputationally tested
"""Least squares by the normal equations, and why you must look at residuals.

Part 1 fits a straight line to a small (illustrative) data set of spring
extensions by solving the normal equations X^T X b = X^T y exactly in
rational arithmetic, and checks the answer against numpy's least-squares
solver. Part 2 uses Anscombe's quartet (1973): four data sets with the same
means, variances, correlation and fitted line, but completely different
residual patterns - curvature, an outlier, and a single point of high
leverage.
"""

from fractions import Fraction

import numpy as np

#: Illustrative data: mass on a spring (hundreds of grams) and extension (cm).
MASS = [0, 1, 2, 3, 4, 5]
EXTENSION = ["0.1", "2.0", "4.1", "5.9", "8.2", "9.9"]

#: Anscombe, "Graphs in statistical analysis", The American Statistician (1973).
ANSCOMBE_X = [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]
ANSCOMBE = {
    "I": (ANSCOMBE_X, [8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84,
                       4.82, 5.68]),
    "II": (ANSCOMBE_X, [9.14, 8.14, 8.74, 8.77, 9.26, 8.10, 6.13, 3.10, 9.13,
                        7.26, 4.74]),
    "III": (ANSCOMBE_X, [7.46, 6.77, 12.74, 7.11, 7.81, 8.84, 6.08, 5.39,
                         8.15, 6.42, 5.73]),
    "IV": ([8, 8, 8, 8, 8, 8, 8, 19, 8, 8, 8],
           [6.58, 5.76, 7.71, 8.84, 8.47, 7.04, 5.25, 12.50, 5.56, 7.91, 6.89]),
}

def normal_equations_line(xs, ys):
    """Exact (intercept, slope) solving X^T X b = X^T y for X = [1, x].

    The 2 x 2 system [[n, Sx], [Sx, Sxx]] b = [Sy, Sxy] is solved by
    Cramer's rule in rational arithmetic.
    """
    xs = [Fraction(x) for x in xs]
    ys = [Fraction(y) for y in ys]
    n = len(xs)
    sx, sy = sum(xs), sum(ys)
    sxx = sum(x * x for x in xs)
    sxy = sum(x * y for x, y in zip(xs, ys))
    det = n * sxx - sx * sx
    if det == 0:
        raise ValueError("all x values are equal: the slope is not determined")
    return (sxx * sy - sx * sxy) / det, (n * sxy - sx * sy) / det

def residuals(xs, ys, intercept, slope):
    """y_i - (intercept + slope x_i)."""
    return [Fraction(y) - (intercept + slope * Fraction(x))
            for x, y in zip(xs, ys)]

def summary(xs, ys):
    """Mean of x, mean of y, slope, intercept, correlation r and R^2."""
    x, y = np.asarray(xs, float), np.asarray(ys, float)
    design = np.column_stack([np.ones_like(x), x])
    (b0, b1), *_ = np.linalg.lstsq(design, y, rcond=None)
    r = float(np.corrcoef(x, y)[0, 1])
    return float(x.mean()), float(y.mean()), float(b1), float(b0), r, r * r

def diagnostics(xs, ys):
    """Largest |residual|, its index, and the largest leverage h_ii."""
    x, y = np.asarray(xs, float), np.asarray(ys, float)
    design = np.column_stack([np.ones_like(x), x])
    hat = design @ np.linalg.inv(design.T @ design) @ design.T
    b = np.linalg.solve(design.T @ design, design.T @ y)
    res = y - design @ b
    i = int(np.argmax(np.abs(res)))
    return float(abs(res[i])), i, float(np.max(np.diag(hat)))

def curvature(xs, ys):
    """Correlation between residuals and (x - mean x)^2: large if curved."""
    x, y = np.asarray(xs, float), np.asarray(ys, float)
    _, _, b1, b0, _, _ = summary(xs, ys)
    res = y - (b0 + b1 * x)
    sq = (x - x.mean()) ** 2
    if np.std(sq) == 0:
        return 0.0
    return float(np.corrcoef(res, sq)[0, 1])

def main():
    b0, b1 = normal_equations_line(MASS, EXTENSION)
    res = residuals(MASS, EXTENSION, b0, b1)
    print("Part 1: spring extension (cm) against mass (100 g)")
    print(f"  exact normal-equation fit: y = {b0} + {b1} x"
          f" = {float(b0):.4f} + {float(b1):.4f} x")
    _, _, nb1, nb0, _, r2 = summary(MASS, [float(e) for e in EXTENSION])
    print(f"  numpy lstsq:               y = {nb0:.4f} + {nb1:.4f} x,"
          f" R^2 = {r2:.4f}")
    print(f"  sum of residuals = {sum(res)}, sum of x * residual ="
          f" {sum(Fraction(x) * e for x, e in zip(MASS, res))}")
    print()
    print("Part 2: Anscombe's quartet")
    print(" set  mean x  mean y  slope  intercept     r   R^2 | max|res|"
          " leverage curve")
    for name, (xs, ys) in ANSCOMBE.items():
        mx, my, s, c, r, r2 = summary(xs, ys)
        big, _, lev = diagnostics(xs, ys)
        print(f" {name:>3} {mx:7.2f} {my:7.2f} {s:6.3f} {c:10.2f} {r:5.3f}"
              f" {r2:5.2f} | {big:8.2f} {lev:8.2f} {curvature(xs, ys):5.2f}")
    print("Same summary statistics; different stories. II is curved (residuals")
    print("track (x - mean)^2), III has one outlier, and in IV a single point")
    print("with leverage 1 determines the slope by itself.")
    print()
    print("Epistemic status: part 1 is exact rational arithmetic, confirmed")
    print("numerically; part 2 is floating-point computation on published data.")
    print("The diagnostics illustrate what residual plots show; they are not")
    print("formal tests, and the spring data are illustrative, not measured.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Part 1 of the first experiment is an exact computation; its part 2 and the second experiment are statistical evidence (seeded simulations with sampling error of about 0.010.01); the third is exact and numerical. Simulations illustrate the theorems about coverage and error rates; they do not prove them.

Exercises

Exercises

1. Statistical inference

Warm-upHuman

A test of H0H_0: "the new fertiliser has no effect on mean yield" gives p=0.03p = 0.03. Which statement is correct?

Choose one

2. Statistical inference

Warm-upHuman

A health clinic records the number of patients arriving in five consecutive hours: 3,5,2,6,43, 5, 2, 6, 4. Modelling the counts as independent Poisson(λ)(\lambda), what is the maximum likelihood estimate of λ\lambda?

3. Statistical inference

Warm-upHuman

Compute the sample variance S2=1n−1∑i(xi−xˉ)2S^2 = \frac{1}{n-1}\sum_i (x_i - \bar x)^2 of the data 2,4,92, 4, 9.

4. Statistical inference

StretchHuman

For an i.i.d. sample X1,…,XnX_1, \dots, X_n from the uniform distribution on [0,θ][0, \theta], the MLE is M=max⁡iXiM = \max_i X_i, and E[M]=nn+1θE[M] = \frac{n}{n+1}\theta. Which estimator is unbiased for θ\theta?

Choose one

5. Statistical inference

CoreHuman

In the proof that the normal equations give the least-squares solution, we expand ∥y−Xβ∥2=∥r∥2+2 r⊤Xw+∥Xw∥2\|y - X\beta\|^2 = \|r\|^2 + 2\,r^\top Xw + \|Xw\|^2 with r=y−Xβ^r = y - X\hat\beta and w=β^−βw = \hat\beta - \beta. Why does the cross term vanish?

Choose one

6. Statistical inference

CoreHuman

A study tests 88 hypotheses and obtains the p-values 0.0004, 0.003, 0.006, 0.0071, 0.011, 0.02, 0.04, 0.30.0004,\ 0.003,\ 0.006,\ 0.0071,\ 0.011,\ 0.02,\ 0.04,\ 0.3. Using the Bonferroni correction with family-wise error rate 0.050.05, how many hypotheses are rejected?

7. Statistical inference

CoreHuman

A small trial of a new treatment (20 patients) finds a 95%95\% confidence interval of [−2,15][-2, 15] days for the reduction in recovery time, with p=0.13p = 0.13. What is the best conclusion?

Choose one

8. Statistical inference

CoreHuman

From 260260 of 400400 households, a 95%95\% confidence interval for the proportion pp is [0.603,0.697][0.603, 0.697], and with a uniform prior the Bayesian posterior is Beta(261,141)(261, 141) with 95%95\% credible interval [0.602,0.695][0.602, 0.695]. Which statements are correct? (Choose all that apply.)

Choose all that apply

9. Statistical inference

CoreFormal

Which Lean statement says that a solution b of the normal equations minimises the residual sum of squares? (Xᵀ is the transpose, *ᵥ multiplies a matrix by a vector, ⬝ᵥ is the dot product.)

Choose one

10. Statistical inference

StretchComputational

Write fit_line(xs, ys) returning the least-squares (intercept, slope) for the model y=β0+β1xy = \beta_0 + \beta_1 x, using β^1=∑(xi−xˉ)(yi−yˉ)∑(xi−xˉ)2\hat\beta_1 = \frac{\sum (x_i - \bar x)(y_i - \bar y)}{\sum (x_i - \bar x)^2} and β^0=yˉ−β^1xˉ\hat\beta_0 = \bar y - \hat\beta_1\bar x. Use Fraction so the answers are exact. The tests also check that the residuals sum to zero and are orthogonal to xx — the normal equations.

Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.
Common misconceptionsH

Common misconceptions

Misconception

"The p-value is the probability that the null hypothesis is true." The p-value is computed assuming H0H_0 is true: it is P(data at least this extreme∣H0)P(\text{data at least this extreme} \mid H_0), not P(H0∣data)P(H_0 \mid \text{data}). Turning one into the other needs Bayes' theorem and a prior probability for H0H_0 — the same base-rate reasoning as in diagnostic testing. A p-value of 0.010.01 can coexist with a high probability that H0H_0 is true if real effects are rare.

Misconception

"A non-significant result proves there is no effect." Failing to reject H0H_0 may simply reflect low power. A small trial with p=0.4p = 0.4 can be compatible both with no effect and with a large benefit; the confidence interval shows which effect sizes remain plausible. Absence of evidence is not evidence of absence — claims of "no effect" need high power or an equivalence test.

Misconception

"There is a 95% probability that the true value lies in this computed interval." For a frequentist confidence interval, the 95%95\% describes the procedure over repeated samples; a particular interval either contains the fixed true value or not. A Bayesian credible interval does carry a probability statement — conditional on the model and the prior.

Misconception

"An unbiased estimator is always better than a biased one." Mean squared error is variance plus squared bias, and a small bias can buy a large reduction in variance: for normal data, dividing ∑(Xi−Xˉ)2\sum(X_i - \bar X)^2 by nn (or n+1n + 1) gives a smaller mean squared error than dividing by n−1n - 1.

Misconception

"Each test is at the 5% level, so my conclusions are 95% reliable." With many tests, false positives accumulate: twenty independent true nulls give at least one "significant" result with probability 0.640.64. Correct for multiplicity (Bonferroni, Benjamini–Hochberg), and count the tests that were run but not reported.

Misconception

"A high R2R^2 means the model is right." R2R^2 measures how much variation a straight-line (or linear) fit captures, not whether the model's assumptions hold or whether xx causes yy. All four of Anscombe's data sets have R2=0.67R^2 = 0.67; only residual plots tell them apart. Causal conclusions need randomised design or careful causal reasoning.

ViewpointsH

Many ways of seeing

Geometry— Least squares is orthogonal projection; degrees of freedom are dimensions

Think of the data yy as a single point of Rn\R^n. The model's possible means XβX\beta fill the column space V=col⁡(X)V = \operatorname{col}(X), a pp-dimensional subspace, and least squares picks the point of VV nearest to yy: the orthogonal projection y^=Hy\hat y = Hy, with H=X(X⊤X)−1X⊤H = X(X^\top X)^{-1}X^\top a symmetric idempotent matrix (H2=HH^2 = H). The normal equations say that the residual y−y^y - \hat y is perpendicular to VV, and the decomposition ∥y−yˉ1∥2=∥y^−yˉ1∥2+∥y−y^∥2\|y - \bar y\mathbf 1\|^2 = \|\hat y - \bar y\mathbf 1\|^2 + \|y - \hat y\|^2 is Pythagoras' theorem; R2R^2 is cos⁡2\cos^2 of the angle between the centred data and the centred fit. "Degrees of freedom" are dimensions: if the noise is σ2\sigma^2 times a standard normal vector in Rn\R^n, its projection onto any kk-dimensional subspace WW has E∥PWε∥2=kσ2E\|P_W\varepsilon\|^2 = k\sigma^2, by the rotational symmetry of the normal distribution. The residual lives in the (n−p)(n - p)-dimensional orthogonal complement of VV — which is why the residual sum of squares is divided by n−pn - p, and why Bessel divides by n−1n - 1 (the complement of the line spanned by 1\mathbf 1). For normal data this geometry also explains why Xˉ\bar X and S2S^2 are independent (Cochran's theorem): they are built from projections onto orthogonal subspaces.

Analysis— Information as curvature

The Fisher information has an analytic meaning: under the regularity conditions, I(θ)=−Eθ[∂θ2log⁡f(X;θ)]I(\theta) = -E_\theta\big[\partial_\theta^2\log f(X; \theta)\big], the expected curvature of the log-likelihood at its peak. A sharply curved likelihood pins θ\theta down; a flat one does not — exactly the widths in the likelihood widget. The asymptotic normality of the MLE comes from a Taylor expansion of the score around θ^\hat\theta: 0=ℓ′(θ^)≈ℓ′(θ)+(θ^−θ)ℓ′′(θ)0 = \ell'(\hat\theta) \approx \ell'(\theta) + (\hat\theta - \theta)\ell''(\theta), where ℓ′(θ)/n→N(0,I(θ))\ell'(\theta)/\sqrt n \to N(0, I(\theta)) by the central limit theorem and ℓ′′(θ)/n→−I(θ)\ell''(\theta)/n \to -I(\theta) by the law of large numbers. The Cramér–Rao inequality is the Cauchy–Schwarz inequality in L2(Pθ)L^2(P_\theta), and the whole asymptotic theory is an exercise in limits, estimates and uniformity — Le Cam's theory of local asymptotic normality (1960s) makes it precise. See measure theory.

Probability— Two meanings of probability

The frequentist reads PP as long-run frequency in repetitions of the experiment, so only data are random; parameters are fixed unknowns, and guarantees are statements about procedures (coverage, error rates). The Bayesian reads PP as a coherent degree of belief, so parameters may have distributions and the posterior answers directly "how probable is it that p>0.6p > 0.6?". De Finetti's representation theorem (1931) connects the two: if a sequence of 0–1 observations is exchangeable (its probabilities are unchanged by permuting the order), then it is a mixture of i.i.d. Bernoulli sequences — mathematically, a prior over pp appears automatically. In practice the two schools usually agree when data are plentiful (Bernstein–von Mises) and differ instructively when they are not.

Computation— Resampling and simulation

When formulas are unavailable, computation substitutes for algebra. The bootstrap (Efron, 1979) estimates the sampling distribution of an estimator by recomputing it on many samples drawn with replacement from the data; permutation tests (Fisher's idea from the 1930s) obtain exact p-values by recomputing a statistic over rearrangements of group labels, which are equally likely under the null hypothesis of no difference; and Markov chain Monte Carlo (see Markov chains) samples from posterior distributions that cannot be computed in closed form, which made Bayesian methods practical from the 1990s. Each comes with its own conditions — the bootstrap, for example, can fail for the maximum of a uniform sample — so computation does not remove the need for theory.

History & global context

History and global context

  • Early data. John Graunt's analysis of London's bills of mortality (1662) is often called the beginning of statistics; in the 18th century Thomas Bayes' essay (published by Richard Price in 1763) and Pierre-Simon Laplace's "inverse probability" (1774 onwards) gave the first systematic methods of inference, including the rule of succession.
  • Least squares. Adrien-Marie Legendre published the method of least squares in 1805; Carl Friedrich Gauss (1809) justified it with the normal law of errors and claimed earlier use, and later (1821–23) proved the optimality now called the Gauss–Markov theorem. Francis Galton's studies of heredity (1886) gave "regression" its name — regression towards the mean — and Karl Pearson developed correlation and the χ2\chi^2 test (1900).
  • The 20th-century synthesis. William Sealy Gosset, a chemist at the Guinness brewery in Dublin, published the tt distribution as "Student" (1908) to analyse small samples. Ronald Fisher introduced maximum likelihood (1912–22), Fisher information, significance testing with p-values and the randomised design of experiments (Statistical Methods for Research Workers, 1925; The Design of Experiments, 1935). Jerzy Neyman and Egon Pearson formulated tests with two types of error and proved their optimal-test lemma (1933), and Neyman introduced confidence intervals (1937). Edwin Wilson's score interval dates from 1927.
  • A global discipline. Prasanta Chandra Mahalanobis founded the Indian Statistical Institute in Kolkata (1931) and pioneered large-scale sample surveys, used for India's National Sample Survey from 1950. C. R. Rao, working there, proved the information inequality in 1945; Harald Cramér proved it independently in Stockholm, and his Mathematical Methods of Statistics (1946) gave the subject its rigorous asymptotic theory. Bruno de Finetti in Italy (1931–37) and Harold Jeffreys in England (1939) developed Bayesian foundations.
  • Computers and many tests. Bradley Efron's bootstrap (1979) and Markov chain Monte Carlo methods transformed practice, and Yoav Benjamini and Yosef Hochberg's false discovery rate (1995) answered the needs of genomics and other fields where thousands of hypotheses are tested at once. Concerns about reproducibility led the American Statistical Association to issue a statement on the meaning and misuse of p-values in 2016.
Further reading

Further reading

  • George Casella and Roger L. Berger, Statistical Inference (2nd edition, 2002) — the standard rigorous course: sufficiency, likelihood, Cramér–Rao, tests and intervals.
  • Larry Wasserman, All of Statistics (2004) — a fast, modern tour, including the bootstrap, multiple testing and Bayesian inference.
  • John A. Rice, Mathematical Statistics and Data Analysis (3rd edition, 2007) — theory with real data sets.
  • David Freedman, Robert Pisani and Roger Purves, Statistics (4th edition, 2007) — the clearest non-technical account of what tests, intervals and regression mean, and how they are misused.
  • Andrew Gelman, John Carlin, Hal Stern, David Dunson, Aki Vehtari and Donald Rubin, Bayesian Data Analysis (3rd edition, 2013).
  • Bradley Efron and Trevor Hastie, Computer Age Statistical Inference (2016) — how computation reshaped the classical theory.