04 Β· Probability: reasoning under uncertainty
Every model you will ever train reads a number that is not quite true (a label, a sensor reading, a click) and outputs a number that is a guess. This module gives you the language for both: distributions for the noise, Bayes' rule for updating beliefs, and likelihood for turning data into parameters. It is also the module that reveals why your favourite loss functions are not arbitrary choices.
By the end you can
- State the axioms, use conditional probability and independence correctly, including the uncorrelated-vs-independent trap.
- Apply Bayes' rule to a base-rate problem without a calculator and get the right order of magnitude.
- Name the nine distributions that cover almost all classical ML and say where each one appears.
- Derive maximum likelihood for Gaussian and Bernoulli data, and say what loss each one produces.
- Explain how a Gaussian prior turns into ridge regression's $\lambda\lVert w\rVert^2$ term.
- Use simulation (Monte Carlo) to estimate a probability you cannot compute in closed form.
Why this module exists
Software engineers are trained to think in booleans: the request succeeded or it did not, the disk is up or down. That habit is fatal in machine learning, because nothing there is a boolean. A label can be wrong, a feature can be missing, a prediction can be 0.6. If you keep reasoning as if the data were exact, you will build systems that are confidently wrong β and you will have no vocabulary to describe how wrong they might be.
Probability gives you that vocabulary, and it does double duty. It is a modelling tool (this is the noise I assume in the world), a decision tool (given these beliefs and these costs, this is the action I should take), and a learning tool (given this data, these are the parameters I should pick). Most of what looks like "just optimisation" in ML β squared error, cross-entropy, regularisation, Naive Bayes, Kalman filters β is one of those three in disguise.
Remember β retrieve before you read
Six questions. Write your answers before opening the cardsWarm-up: answer from memory
No notes, no scrolling. These six cover exactly the machinery the rest of the module builds on; if two or three come out shaky, that is normal and it tells you where to slow down in Pass 2.
- If $A$ and $B$ are independent with $P(A)=0.3$ and $P(B)=0.4$, what is $P(A \cap B)$?
- Write Bayes' rule from memory. Name each of the four quantities in plain English.
- What are the mean and the variance of a fair six-sided die?
- What does a probability density function integrate to? Over what interval?
- What is the difference between the law of large numbers and the central limit theorem?
- Why do we maximise the log-likelihood rather than the likelihood itself?
1. $P(A \cap B)$ for independent $A$, $B$?
2. Bayes' rule, with the four terms named
3. Mean and variance of a fair die
4. What does a PDF integrate to, and over what?
5. LLN vs CLT
6. Why log the likelihood?
Understand β the shape of the idea
Ten sections: axioms, conditioning, Bayes, distributions, MLE and MAP1 Β· Why probability, and why ML cannot do without it
Before probability, the honest description of an uncertain situation was prose: "it will probably rain, but I'm not sure." Prose cannot be composed. You cannot average it, invert it, or put it inside an algorithm. Kolmogorov's move in 1933 was to make uncertainty arithmetic β three axioms, and everything else is derivation.
Machine learning uses that arithmetic in three distinct roles, and it is worth keeping them apart:
- Noise model. The world is stochastic and your labels are imperfect. A photo of a cat labelled "dog", a sensor reading with Β±0.3Β° of jitter, a click that depends on mood. Writing $y = f(x) + \varepsilon$ with $\varepsilon \sim \mathcal{N}(0,\sigma^2)$ is a probability statement, and it decides your loss function (see section 8).
- Decision theory. A probability alone never tells you what to do; a probability plus a cost matrix does. Two teams with the same fraud model should ship different thresholds if their costs differ.
- Learning itself. "Which parameters best explain this data?" is a probability question, and maximum likelihood and MAP are the answers β dressed up as optimisation problems, but probability statements underneath (sections 8 and 9).
Concrete version of role 2. A model scores a transaction: $P(\text{fraud} \mid x) = 0.09$. Two systems see exactly this number and must decide "flag or ignore":
| System | Cost of a false alarm | Cost of a missed fraud | Flag if $p$ exceeds | Decision at $p = 0.09$ |
|---|---|---|---|---|
| Back-office review queue | 5 (analyst minutes) | 100 (stolen money) | $\frac{5}{5+100} \approx 0.048$ | Flag |
| Real-time alert that pages on-call | 60 (woken engineer) | 10 (reversed later) | $\frac{60}{60+10} \approx 0.857$ | Ignore |
Same classifier, same score, opposite decisions β and both are correct. The threshold $\frac{C_{FP}}{C_{FP} + C_{FN}}$ is derived in the exercise at the end of the module; internalise it now. This is the "decision theory" role of probability in one table.
In 1654 Blaise Pascal wrote to Pierre de Fermat about gambling disputes β how to split stakes when a game is interrupted, and why a gambler's intuition about "fair" bets was wrong. That correspondence is usually counted as the birth of probability as a field: it forced people to define expectation as a probability-weighted average. Laplace formalised the calculus of probabilities around 1774 (and gave us the rule of succession). Two and a half centuries later, in 1933, Andrey Kolmogorov packaged all of it into three axioms, and probability became a branch of measure theory β which is why the definition starts with sets and ends with machine learning.
2 Β· Axioms, sample space, events
Start with the sample space $\Omega$ β the set of all possible outcomes (every length-1000 sequence of click/no-click a user could produce). An event is a subset of $\Omega$. A probability is a function from events to real numbers obeying three rules:
Almost everything you will use is a consequence: $P(\emptyset) = 0$; $P(A \cup B) = P(A) + P(B) - P(A \cap B)$ for events that overlap; $0 \le P(A \cap B) \le \min(P(A), P(B))$. Note what the axioms do not say: they never tell you how to set $P$ in the first place. That gap is the frequentistβBayesian divide.
| Reading | What $P(A) = 0.3$ means | Strength | Where ML uses it |
|---|---|---|---|
| Frequentist | If I repeat the experiment forever, $A$ happens in 30% of the runs. $P$ is a long-run frequency of something repeatable. | No subjectivity: two observers of the same repeatable process must agree. | Maximum likelihood, confidence intervals, hypothesis tests β most of classical ML evaluation. |
| Bayesian | I am 30% confident that $A$ is true, given what I know. $P$ is a degree of belief, allowed for one-off events. | Can quantify uncertainty about unique things β this model, these parameters, tomorrow's traffic. | MAP, Bayesian neural nets, credible intervals, A/B testing with priors, Kalman filters. |
Both are legitimate; the argument between them is mostly about where information enters. What matters for you: MLE is the frequentist reading (the parameters are fixed, the data is random), MAP and credible intervals are the Bayesian reading (the data is fixed, the parameters are random). Both produce numbers, and in practice both are used in the same codebase.
The operational meaning of a probability is this: if you say 0.7, and you say 0.7 for many different events, then roughly 70% of those events should come true. A weather model that says "90% rain" and it rains nine times out of ten across thousands of such predictions is calibrated; one that says 90% and rains twice out of ten is broken even though it may still be right more often than not. This is why "the model outputs 0.6" is not yet a probability β you have to check calibration. Module 06 puts a number on being wrong (log-loss); Module 05 teaches you how to test calibration honestly.
3 Β· Conditional probability and the rules
Almost nothing in a real dataset is independent of anything else, so we need the notion of "probability of $A$ given that $B$ happened". It is defined by one line, which you should read as "restrict the world to $B$, then ask what fraction of it is $A$":
Work it on a table you could build in SQL. Take 2000 people, 1% of whom have a disease ($P(D)=0.01$). The test catches 95% of the sick ($P(+ \mid D) = 0.95$) and falsely alarms on 5% of the healthy ($P(+ \mid \neg D) = 0.05$). Every entry is a count:
| Test + | Test β | Total | |
|---|---|---|---|
| Diseased | 19 | 1 | 20 |
| Healthy | 99 | 1881 | 1980 |
| Total | 118 | 1882 | 2000 |
Now read the quantities straight off the rows and columns. $P(D) = 20/2000 = 0.01$. $P(+ \mid D) = 19/20 = 0.95$. $P(+ \mid \neg D) = 99/1980 = 0.05$. And $P(D \mid +) = 19/118 \approx 0.161$ β the diseased people among those who tested positive. Three related-looking fractions: 0.01, 0.95, 0.161. Keeping them straight is most of applied probability.
Three rules follow from the definition, and you will use all three constantly:
The law of total probability is the one people forget, and it is the denominator of Bayes' rule: to know how common a positive test is, average over "sick" and "healthy" weighted by how many of each there are.
Independence, and the trap
Events $A$ and $B$ are independent when $P(A \cap B) = P(A)P(B)$ β equivalently, $P(A \mid B) = P(A)$: knowing $B$ changes nothing about $A$. For random variables the analogous (weaker) statement is uncorrelated: $\mathrm{cov}(X,Y) = 0$. Here is why that is not the same thing:
Let $X$ be uniform on $\{-1, 0, 1\}$ and $Y = X^2$. Then $\mathbb{E}[X] = \frac{1}{3}(-1 + 0 + 1) = 0$, $\mathbb{E}[XY] = \mathbb{E}[X^3] = \frac{1}{3}(-1 + 0 + 1) = 0$, so $\mathrm{cov}(X,Y) = \mathbb{E}[XY] - \mathbb{E}[X]\mathbb{E}[Y] = 0 - 0 \cdot \tfrac{1}{3} = 0$: uncorrelated. Yet $Y$ is a deterministic function of $X$ β tell me $X$ and I know $Y$ with certainty, which is the opposite of "tells you nothing". Zero correlation only says the linear relationship is empty; any nonlinear dependence survives it untouched.
Independence implies zero correlation (when variances exist); the reverse fails, and the counterexample above is the cheapest one to memorise. In production this bites through feature selection and correlation matrices: "these two features have correlation 0.01, so I can treat them as independent" is wrong whenever the relationship is non-monotone, periodic, or threshold-like β which is a lot of the time. Correlation is a statement about the joint linear structure, nothing more.
Conditional independence: the assumption that makes Naive Bayes work
$X$ and $Y$ are conditionally independent given $C$ when $p(x, y \mid c) = p(x \mid c)\,p(y \mid c)$. This is a modelling assumption, not a fact about the world β and it is the entire content of the Naive Bayes classifier: assume the features are independent given the class, and a 1000-dimensional joint distribution collapses into 1000 one-dimensional tables you can estimate from a handful of examples each. Conditional independence given a class is even compatible with the features being strongly marginally dependent (they are usually correlated through the class), which is why the "naive" assumption survives contact with reality surprisingly often.
4 Β· Bayes' rule β the whole reason this module exists
Apply the definition twice to $P(H \cap D)$, once as $P(H \mid D)P(D)$ and once as $P(D \mid H)P(H)$, and divide:
Read the formula as a machine, and note the direction flip: it converts $P(D \mid H)$ β which you can get from a physical model of the world or from data β into $P(H \mid D)$, which is what you actually want. That flip is the only hard part, and it is why the base-rate error below is so persistent.
The base-rate computation, with real numbers
Disease prevalence $P(D) = 0.01$. Sensitivity $P(+ \mid D) = 0.95$. False positive rate $P(+ \mid \neg D) = 0.05$. You test positive. Step by step:
- Evidence. How common are positive results overall? Apply the law of total probability over "sick" and "healthy": $$P(+) = P(+ \mid D)P(D) + P(+ \mid \neg D)P(\neg D) = 0.95 \times 0.01 + 0.05 \times 0.99 = 0.0095 + 0.0495 = 0.0590$$
- Posterior. Of the 5.90% who test positive, how many are actually sick? $$P(D \mid +) = \frac{P(+ \mid D)\,P(D)}{P(+)} = \frac{0.0095}{0.0590} \approx 0.161$$
- Interpret. About 16%, not 95%. The 99 healthy people per 1000 swamp the 10 sick ones, so false positives dominate the positive pile β exactly what the 2000-person table showed as $19/118$.
Notice the arithmetic asymmetry that produced the surprise: the sick contributed $0.0095$ and the healthy contributed $0.0495$ β five times as many false alarms as true hits, even though the test is "95% accurate". Nothing exotic happened; the prior was simply small, and a small prior is hard to move.
Where machine learning runs Bayes' rule
- Naive Bayes classification. Replace $H$ with a class $c$ and conditionally independent features $x_j$: $$\hat{c} = \arg\max_c \; P(c) \prod_{j=1}^{d} P(x_j \mid c) = \arg\max_c \; \Big[ \ln P(c) + \sum_{j=1}^{d} \ln P(x_j \mid c) \Big]$$ The denominator $P(x)$ is dropped because it does not depend on $c$ β the argmax is unaffected. Products become sums, exactly as in section 8.
- Bayesian A/B testing. Put a prior on each variant's conversion rate, update with the observed clicks, and report $P(\text{B better than A})$ directly β no p-value ritual.
- Kalman filtering. Predict β observe β correct, repeatedly. A linear-Gaussian belief update is Bayes' rule with a closed-form posterior, which is why Kalman filters are cheap enough to run on a microcontroller.
- Posterior predictive checks. Draw parameters from the posterior, simulate data, compare with the real data. The cheapest honest test of "does my model's assumption survive contact with reality?"
Dashboards, alerting rules and "model confidence" readouts commit the same crime daily: they report $P(\text{signal} \mid \text{positive})$ as if it were $P(\text{positive} \mid \text{signal})$, or simply drop the prior. An anomaly detector with a 95% hit rate and a 5% false-alarm rate, watching a stream that is 1% anomalous, does not deliver 95% precision β it delivers 0.0095/0.059 β 16%, and on-call engineers read the "95%" off the dashboard anyway. Whenever you see a "confidence" number in a metric, ask: which conditional probability is this, and what prior was folded in or silently ignored?
What exactly does Naive Bayes assume β and why does it still work?
5 Β· Random variables and their distributions
A random variable is a function from outcomes to numbers β "how many clicks", "is it spam", "latency in ms". It is discrete if its values form a countable set, described by a PMF $p(x) = P(X = x)$ that sums to 1. It is continuous if its values fill an interval, described by a PDF $f(x) \ge 0$ that integrates to 1.
$f(x) = 0.3$ does not mean "the probability of $X = x$ is 0.3" β for a continuous variable, $P(X = x) = 0$ at every single point, because a point has zero width. Densities can even exceed 1: a variable uniform on $(0, 0.1)$ has density $10$ everywhere on that interval. Only an integral over a region is a probability: $P(a \le X \le b) = \int_a^b f(x)\,dx \le 1$. The unit check for a PDF is "does it integrate to 1", never "is every value below 1".
The CDF $F(x) = P(X \le x)$ is the third face of the same object: for continuous variables $F(x) = \int_{-\infty}^{x} f(t)\,dt$, so the PDF is the derivative of the CDF. CDFs work for discrete and continuous variables alike, are non-decreasing, and run from 0 to 1 β which makes them the safe choice when you are unsure of the type.
Here is the cast you will meet in classical ML. Almost every model uses one of these as its noise model, its prior, or its output layer.
| Distribution | PMF / PDF | Mean | Variance | Where it shows up in ML |
|---|---|---|---|---|
| Bernoulli$(p)$ | $p^k(1-p)^{1-k}$, $k \in \{0,1\}$ | $p$ | $p(1-p)$ | A binary label; the sigmoid output is a Bernoulli parameter |
| Categorical / multinomial$(\boldsymbol{\pi})$ | $\pi_k$ for $k = 1..K$ | β | β | A $K$-class label; softmax output layer, language-model token draw |
| Binomial$(n,p)$ | $\binom{n}{k} p^k (1-p)^{n-k}$ | $np$ | $np(1-p)$ | Count of successes in $n$ tries: clicks, conversions, defectives |
| Poisson$(\lambda)$ | $e^{-\lambda}\lambda^k / k!$ | $\lambda$ | $\lambda$ | Event counts per window: requests, arrivals, faults per day |
| Uniform$(a,b)$ | $\frac{1}{b-a}$ on $[a,b]$ | $\frac{a+b}{2}$ | $\frac{(b-a)^2}{12}$ | Random initialisation, Monte Carlo proposals, "no information" prior |
| Gaussian$(\mu,\sigma^2)$ | $\frac{1}{\sqrt{2\pi\sigma^2}} e^{-(x-\mu)^2/2\sigma^2}$ | $\mu$ | $\sigma^2$ | Noise model, weight prior, activations, and the CLT's limit shape |
| Exponential$(\lambda)$ | $\lambda e^{-\lambda x}$, $x \ge 0$ | $1/\lambda$ | $1/\lambda^2$ | Time until an event: churn, survival, retry delays, TTLs |
| Beta$(\alpha,\beta)$ | $\frac{x^{\alpha-1}(1-x)^{\beta-1}}{B(\alpha,\beta)}$ on $[0,1]$ | $\frac{\alpha}{\alpha+\beta}$ | $\frac{\alpha\beta}{(\alpha+\beta)^2(\alpha+\beta+1)}$ | Prior over a probability; conjugate to Bernoulli, so the posterior stays Beta |
| Log-normal$(\mu,\sigma^2)$ | $\frac{1}{x\sigma\sqrt{2\pi}} e^{-(\ln x - \mu)^2/2\sigma^2}$, $x \gt 0$ | $e^{\mu + \sigma^2/2}$ | $(e^{\sigma^2}-1)e^{2\mu+\sigma^2}$ | Heavy-tailed positive quantities: revenue, file sizes, latency |
Ask three questions in order. (1) What are the possible values? Binary β Bernoulli; a category β Categorical; a non-negative count β Poisson or Binomial; a positive real β log-normal or Gamma; any real β Gaussian or Student-$t$. (2) Is the mean roughly equal to the variance? For counts, Poisson forces that equality; if your data violates it badly, use a negative binomial instead. (3) Are there heavy tails? If a few outliers dominate, the Gaussian assumption behind squared error will hate you β Student-$t$ or log-transform instead. Picking a distribution is picking a loss function; Module 06 makes that correspondence exact.
6 Β· Joint, marginal, conditional
Three ways to describe how variables hang together, and they convert into each other:
For continuous variables the sum becomes an integral: $p(x) = \int p(x,y)\,dy$. The chain rule is the joint distribution written as a sequence of conditionals β it is an identity, no assumptions needed:
A GPT-style model is the chain rule: it models the probability of a text as $p(\text{tokens}) = \prod_i p(\text{token}_i \mid \text{tokens}_{\lt i})$, one conditional at a time, with a neural network approximating each conditional. "Autoregressive" is just the name for $p(x_i \mid x_{\lt i})$. And training such a model by minimising the average negative log of each conditional is exactly maximum likelihood (section 8), with cross-entropy as its loss (Module 06). One identity, three of the biggest ideas in modern ML.
Two summaries of a joint distribution that you will use constantly β covariance and its normalised twin, correlation:
Covariance is the off-diagonal content of the covariance matrix you met in Module 02 β the object PCA
diagonalises, and the one that must be positive semidefinite for the Gaussian below to exist.
Stacking covariances gives $\Sigma$ with $\Sigma_{jj} = \mathrm{Var}(X_j)$ on the diagonal and
$\Sigma_{jk} = \mathrm{cov}(X_j, X_k)$ off it. Sample estimate:
np.cov(X, rowvar=False).
Multivariate Gaussian in one paragraph
The multivariate Gaussian is the Gaussian with a mean vector $\boldsymbol{\mu} \in \mathbb{R}^d$ and a covariance matrix $\Sigma$ instead of a single $\sigma^2$:
Picture it: a blob centred at $\boldsymbol{\mu}$; its constant-density contours are ellipses whose axes point along the eigenvectors of $\Sigma$ and whose lengths are the square roots of the eigenvalues β the same eigen-decomposition PCA uses, which is why PCA on Gaussian-looking data works so cleanly. The volume scales with $|\Sigma|^{1/2}$ (that is the normalising constant: tilt the correlations and you must squeeze the blob to keep the total probability at 1). And the punchline for independence: for a Gaussian, uncorrelated βΊ independent, because off-diagonal zeros in $\Sigma$ make the exponent split into a sum of one-dimensional terms. That is the exception that makes the trap in section 3 survivable β but only when your data really is close to Gaussian.
7 Β· Expectation, variance, and the two limit theorems
Expectation is the probability-weighted average β the value the quantity settles at if you could repeat the experiment forever:
Variance measures the spread around that average, and the standard deviation is its square root (back in the original units, which is why it is the one you quote):
$\mathbb{E}[aX + bY] = a\,\mathbb{E}[X] + b\,\mathbb{E}[Y]$ β and this holds even when $X$ and $Y$ are dependent, even when you cannot write their joint distribution at all. Variance does not have that luxury: $\mathrm{Var}(X+Y) = \mathrm{Var}(X) + \mathrm{Var}(Y)$ only for independent $X, Y$, plus a covariance term otherwise. This asymmetry is why "expected number of defects = sum of expected defects" is always safe, while "expected spread = sum of spreads" silently needs an independence assumption. It also gives the cheapest trick in the book: $n$ Bernoulli$(p)$ trials sum to a Binomial$(n,p)$, whose mean $np$ follows from adding $n$ copies of $p$.
Law of large numbers vs central limit theorem
The LLN says your sample average gets closer to $\mu$ as $n$ grows β the estimate improves. The CLT says the shape of that average's sampling distribution becomes Gaussian, whatever shape the individual $X_i$ had: sum 50 exponentials and you get something symmetric, even though a single exponential is anything but. The rate of both is $1/\sqrt{n}$ β halve the standard deviation and you need four times the data, which is the single most budget-relevant fact in this module.
That rate, applied to the mean, has a name you will use from here on:
Worked: a fair die has $\sigma = \sqrt{35/12} \approx 1.708$. Average 100 rolls and the standard error is $1.708/\sqrt{100} \approx 0.171$, so "I rolled an average of 3.4" out of 100 rolls is well within noise, while an average of 3.0 is not. Module 05 is built on exactly this quantity β confidence intervals, effect sizes and hypothesis tests are all $\sigma/\sqrt{n}$ in a trench coat.
(1) "More data makes my data Gaussian." No. The CLT is about the distribution of the average, not about your dataset; a million exponential samples are still exponentially distributed. (2) "The average converges, so it equals the mean once n is large." The LLN is about the limit; at any finite $n$ the average is still random with standard deviation $\sigma/\sqrt{n}$, and the CLT tells you how wrong it can be. If you find yourself saying "with enough data this difference is negligible", the honest version is "this difference is $\sigma/\sqrt{n}$ standard errors β here is the number."
Standard error, in one sentence β and how it scales
8 Β· Maximum likelihood estimation, derived properly
Here is the question that generates all of supervised learning: given data, which parameters made it most probable? Flip your point of view β the data is what you have, so treat it as fixed and ask how plausible each parameter value is. The likelihood is that plausibility as a function of $\theta$, with independence assumed across samples:
Two things to be precise about, because textbooks blur them. First, $p(y \mid \theta)$ is a density in $y$; once you substitute your data it becomes a function of $\theta$ β a different object with a different name, even though it is the same expression. Second, $\arg\max_\theta L(\theta) = \arg\max_\theta \ell(\theta)$ exactly, because $\ln$ is strictly monotone: it never reorders the candidates, so the winner is unchanged. You take the log because products of a million small numbers underflow, and because sums differentiate nicely.
Gaussian MLE, line by line
Assume $y_i \stackrel{iid}{\sim} \mathcal{N}(\mu, \sigma^2)$ and write the log-likelihood of the sample. Each sample contributes $-\tfrac12\ln(2\pi\sigma^2) - \frac{(y_i-\mu)^2}{2\sigma^2}$, so:
Differentiate with respect to $\mu$, set to zero (the first-order condition), and read off the estimator:
Now with respect to the variance $v = \sigma^2$, treating $S = \sum_i (y_i-\mu)^2$ as a constant. Write $\ell = -\frac{n}{2}\ln(2\pi v) - \frac{S}{2v}$, differentiate, and solve:
That is the punchline of the whole section. Squared error is not a friendly default someone picked because it is easy to differentiate β it is the statement "my noise is Gaussian, symmetric, and constant-variance". Change the noise assumption and the loss changes with it.
The same move on Bernoulli data gives the other loss you use daily. With $y_i \in \{0,1\}$ and $P(y_i = 1) = p$:
Module 06 completes that second half: with $p$ produced by a sigmoid of a linear score, $-\ell$ becomes
the binary cross-entropy loss you know from sklearn.linear_model.LogisticRegression.
Every loss function is a likelihood in disguise. Squared error β Gaussian noise; absolute error β Laplace noise (heavier tails, so outliers hurt less); binary cross-entropy β Bernoulli noise; Huber β a Gaussian core with Laplace tails. When you choose a loss you are choosing a noise model, and when a model trained with squared error fails on your data, the honest diagnosis is often "my noise is not Gaussian", not "my model is not expressive enough".
Which loss for which noise? Four pairs.
9 Β· MAP: priors turn estimation into belief revision
Maximum likelihood treats every parameter value as equally plausible a priori. Often you know more than that β weights should be small, a conversion rate should sit near last quarter's, a positive quantity should not be negative. Maximum a posteriori estimation folds that knowledge in as a prior and maximises the posterior:
This is Bayes' rule with the evidence $P(D)$ dropped β it does not depend on $\theta$, so the argmax is unaffected. And a special case worth naming explicitly: if the prior is uniform, $\ln P(\theta)$ is a constant and MAP coincides with MLE. (For a finite candidate set that is exact. Be careful with "uniform" on continuous parameter spaces: uniform on $[0,1]$ is not uniform on the logit of the parameter, and MAP β unlike full Bayesian inference β changes when you reparameterise. That is a real wart, and one reason Bayesian purists prefer integrating over the posterior to maximising it.)
Worked: Gaussian prior + Gaussian likelihood β ridge regression
Take a linear model $y_i = x_i^\top w + \varepsilon_i$ with Gaussian noise $\varepsilon_i \sim \mathcal{N}(0, \sigma_y^2)$, and a Gaussian prior $w \sim \mathcal{N}(0, \sigma_w^2 I)$ (a strong preference for small weights). The log-posterior, up to terms that do not depend on $w$:
The whole of ridge regression falls out of two Gaussian assumptions in four lines β and note what $\lambda$ is: the ratio of how much you trust the data ($\sigma_y^2$, noise in the observations) to how much you trust your prior ($\sigma_w^2$, expected weight size). A small $\lambda$ means "the data is clean, let the fit follow it"; a large one means "the data is noisy, shrink the weights". That is exactly the tuning dial Module 07 will exercise, now with a meaning instead of a ritual.
Swap the Gaussian prior for a Laplace prior $P(w_j) \propto e^{-|w_j|/b}$, whose log is $-\frac{1}{b}\sum_j |w_j|$, and the same three lines give $\lambda\lVert w\rVert_1$ β lasso. Same framework, different prior, different regulariser, different sparsity behaviour. Whenever you see $\lambda\Omega(\theta)$ in a paper, your first question should now be: "which prior does this correspond to?"
MAP gives you a point estimate plus a regulariser. The full Bayesian move goes one step further and integrates over the posterior, $P(y \mid x, D) = \int P(y \mid x, \theta) P(\theta \mid D)\,d\theta$, which gives you a prediction with an honest uncertainty band β but usually no closed form, hence MCMC and variational inference. Deep learning uses the MAP idea constantly (weight decay is a Gaussian prior) and the full-Bayesian idea rarely, because the integrals are intractable at scale.
10 Β· Sampling and Monte Carlo
Sometimes the expectation or the probability you need has no closed form, but you can draw samples from the distribution. Then stop integrating and start counting: Monte Carlo estimation replaces a hard integral with an average over $N$ samples. Formally, for $x_1, \dots, x_N$ drawn independently from $p$:
It always converges β at rate $1/\sqrt{N}$, the CLT again, which is also why you should report a standard error alongside any Monte Carlo number: $\hat{\sigma}/\sqrt{N}$.
- Estimating an intractable probability: $P(\text{two queues empty simultaneously})$ has no formula for a real system, but a simulator plus 100 000 runs gives it to you with error bars.
- Reproducibility: set the seed (
np.random.default_rng(0)) and a stochastic experiment becomes a deterministic, reviewable artifact. Never report a simulated number without its seed. - Importance sampling: when samples from the distribution you care about are hard to get, sample somewhere easier and reweight each sample by the density ratio β you are buying rare events with weights instead of with compute.
- MCMC: when you cannot sample directly from the posterior, construct a random walk whose stationary distribution is the posterior, throw away the first stretch, and keep the rest. This is how full Bayesian models are fitted when the integral has no closed form.
Implement β make it move
Four blocks: simulation, CLT, MLE by hand, Bayes by handBlock 1 Β· Monte Carlo: estimate $\pi$ with darts
The classic. Throw random points at the unit square; those with $x^2 + y^2 \le 1$ land in the quarter disc. The fraction inside converges to the disc's area $\pi/4$, so four times that fraction estimates $\pi$. Watch the standard deviation fall like $1/\sqrt{n}$ β and never reach zero.
import numpy as np, matplotlib.pyplot as plt
rng = np.random.default_rng(0)
def estimate_pi(n, runs=200):
# one run = n darts; 4 * (share landing inside the quarter disc) -> pi
out = np.empty(runs)
for r in range(runs):
x, y = rng.random(n), rng.random(n)
out[r] = 4.0 * (x * x + y * y <= 1.0).mean()
return out
# Monte Carlo error falls like 1/sqrt(n), never to zero: sd = 1.642/sqrt(n)
for n in [10, 100, 1000, 100000]:
est = estimate_pi(n)
print(f"n={n:>7} mean={est.mean():.4f} sd={est.std():.4f} theory={1.6423/np.sqrt(n):.4f}")
# n= 10 mean=3.1440 sd=0.5060 theory=0.5193
# n= 100 mean=3.1404 sd=0.1605 theory=0.1642
# n= 1000 mean=3.1403 sd=0.0559 theory=0.0519
# n= 100000 mean=3.1418 sd=0.0051 theory=0.0052
# the running estimate: the wiggle shrinks as 1/sqrt(n), it never stops
pts = rng.random((20000, 2))
run = 4.0 * ((pts ** 2).sum(axis=1) <= 1.0).cumsum() / np.arange(1, 20001)
print("running estimate at 20000 darts:", round(float(run[-1]), 4)) # 3.1468 (pi = 3.1416)
plt.plot(run); plt.axhline(np.pi, ls="--"); plt.show()
Two lessons to carry: a Monte Carlo estimate is a random variable (hence the 200 repeats and the standard deviation column), and its error bars shrink as $1/\sqrt{n}$ β the price of one more digit is a hundred times more samples.
Block 2 Β· The CLT, on a distribution that is not remotely Gaussian
Exponential samples are heavily right-skewed (theoretical skewness 2). Average 50 of them and the distribution of that average is nearly Gaussian β at rate $1/\sqrt{n}$, visible by comparing $n=2$ with $n=50$.
import numpy as np, matplotlib.pyplot as plt
rng = np.random.default_rng(1)
raw = rng.exponential(1.0, 200000) # mean 1, variance 1, very skewed
print("raw skewness:", round(float(((raw - 1.0) ** 3).mean()), 3)) # 1.922, theory 2
fig, axes = plt.subplots(1, 2, figsize=(9, 3.4))
for ax, n in zip(axes, [2, 50]): # same n repetitions, only the averaging window changes
avgs = rng.exponential(1.0, size=(4000, n)).mean(axis=1)
print(f"n={n:>3} mean={avgs.mean():.4f} sd={avgs.std(ddof=1):.4f} "
f"theory={1/np.sqrt(n):.4f} skew={((avgs - avgs.mean())**3).mean()/avgs.std()**3:.3f}")
sd = avgs.std(ddof=1) # the 1/sqrt(n) narrowing, measured
ax.hist(avgs, bins=40, density=True, alpha=.7, label=f"averages of n={n}")
xs = np.linspace(0, 4, 300)
ax.plot(xs, np.exp(-xs), "k--", alpha=.5, label="the original exponential")
ax.plot(xs, np.exp(-((xs - avgs.mean())**2) / (2*sd**2)) / np.sqrt(2*np.pi*sd**2), "r-",
label="Gaussian with the same mean and sd")
ax.legend(fontsize=8)
plt.tight_layout(); plt.show()
# n= 2 mean=0.9879 sd=0.6902 theory=0.7071 skew=1.387
# n= 50 mean=0.9989 sd=0.1433 theory=0.1414 skew=0.257
Read the two printed rows against each other. The mean stays at 1 (LLN), the standard deviation drops from 0.69 to 0.14 (the $1/\sqrt{n}$ rate, matching $1/\sqrt{n}$ to three digits), and the skewness collapses from 1.39 to 0.26 (CLT). Three facts, three different theorems, one script.
Block 3 Β· Maximum likelihood from scratch
No library, just the two first-order conditions derived in section 8 β then check them against NumPy and against the closed-form log-likelihood to confirm the fit really is the maximum.
import numpy as np
rng = np.random.default_rng(3)
y = rng.normal(5.0, 2.0, size=200) # "data from a device we cannot open"
mu_hat = y.mean() # d ell / d mu = 0
sigma2_hat = ((y - mu_hat) ** 2).mean() # d ell / d sigma^2 = 0
print(f"mu_hat={mu_hat:.4f} sigma_hat={np.sqrt(sigma2_hat):.4f}")
print(f"np.mean={y.mean():.4f} np.std(ddof=0)={y.std():.4f} np.std(ddof=1)={y.std(ddof=1):.4f}")
# mu_hat=5.0966 sigma_hat=2.0602 -- np.std(ddof=0) matches the MLE, ddof=1 does not
def avg_nll(mu, s2): # mean negative log-likelihood of the sample
return 0.5 * np.log(2 * np.pi * s2) + ((y - mu) ** 2).mean() / (2 * s2)
print(f"avg NLL at MLE ({mu_hat:.2f}, {sigma2_hat:.2f}) = {avg_nll(mu_hat, sigma2_hat):.6f}")
print(f"avg NLL at true (5.00, 4.00) = {avg_nll(5.0, 4.0):.6f}")
print(f"avg NLL at (0.00, 1.00) = {avg_nll(0.0, 1.0):.6f}")
# 2.141735 2.143799 16.028969 -- lowest at the MLE, by construction
Look closely at the middle line: the MLE fitted to this particular sample (variance 4.24) beats the true parameter (variance 4.00) at explaining the sample. That is not a bug β the MLE explains the data you have, not the process that generated it, and that gap is exactly what Module 05 quantifies. The third line shows how strongly the likelihood discriminates: far-away parameters are not slightly worse, they are astronomically worse.
Block 4 Β· Bayes by hand, and Naive Bayes in three lines
First the base-rate computation of section 4, as code, so the β16% is a number you have seen come out of a
machine. Then the same rule at scale, with GaussianNB.
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# --- the base-rate example, as a two-line Bayes update ---
prior = np.array([0.01, 0.99]) # P(diseased), P(healthy)
lik = np.array([0.95, 0.05]) # P(+|diseased), P(+|healthy)
post = prior * lik
post /= post.sum() # divide by the evidence P(+)
print("P(diseased | +) =", round(float(post[0]), 6)) # 0.161017
flat = np.array([0.5, 0.5]) * lik # the same test with the prior "forgotten"
flat /= flat.sum()
print("with a flat prior =", round(float(flat[0]), 6)) # 0.95 -- the base-rate error
# --- Naive Bayes on a synthetic feature dataset ---
X, y = make_classification(n_samples=1000, n_features=8, n_informative=6,
n_redundant=0, class_sep=1.2, random_state=0)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25, random_state=0)
nb = GaussianNB().fit(Xtr, ytr) # argmax_c [ log pi_c + sum_j log N(x_j; mu_cj, s_cj) ]
lr = LogisticRegression(max_iter=1000).fit(Xtr, ytr)
print("GaussianNB :", accuracy_score(yte, nb.predict(Xte))) # 0.832
print("LogisticRegression :", accuracy_score(yte, lr.predict(Xte))) # 0.844
Two things to note. The Naive Bayes number (0.832) is close to logistic regression (0.844) despite the conditional-independence assumption being false β the argmax ranking survives. And the flat-prior line prints 0.95: the difference between 0.95 and 0.161 is entirely the prior, which is the whole argument of section 4 in four lines of NumPy.
- Derive the flagging threshold. A classifier outputs $P(\text{spam} \mid x) = 0.7$. Flagging a real email costs $C_{FP} = 5$ (an angry customer); not flagging spam costs $C_{FN} = 1$ (a nuisance). Write the expected cost of "flag" and of "don't flag" as functions of $p$, set them equal, and solve for the threshold $p^\star$. Then decide, for $p = 0.7$.
- Sanity-check with arithmetic. At $p = 0.7$: flagging costs $5 \times 0.3$, ignoring costs $1 \times 0.7$. Which is smaller? It must agree with your threshold.
- Predict the flip. Now the costs swap: false positives cost 1, false negatives cost 5. Recompute $p^\star$ and predict what happens to $p = 0.7$ before you calculate it. Then check.
- Extend. What happens to $p^\star$ as $C_{FN} \to \infty$? Say in one sentence what that means for a medical screening tool vs a spam filter.
Prove it
Answer first, then open the feedbackMultiple choice β instant feedback
1. $X$ is a continuous random variable with density $f$. Which statement is true?
2. $X$ is uniform on $\{-1, 0, 1\}$ and $Y = X^2$. Which is correct?
3. Which statement about maximum likelihood and MAP is correct?
4. You average 1000 draws from a heavily skewed distribution. Which statement is the central limit theorem?
5. Your model systematically over-predicts by a roughly constant amount β a bias caused by too simple a model class. Collecting 10Γ more training data willβ¦
6. A screening test has 1% prevalence, 95% sensitivity and a 5% false positive rate. A randomly chosen person tests positive. $P(\text{disease} \mid +)$ is closest toβ¦
Open questions β answer aloud, without notes
- Write the three axioms and derive $P(\emptyset) = 0$ from them in one line.
- Frequentist vs Bayesian: one sentence each on what "$P(A) = 0.3$" means, and one sentence on which reading maximum likelihood uses.
- Compute, showing every number: prevalence 1%, sensitivity 95%, false positive rate 5%. What is $P(\text{disease} \mid +)$? Why is it not 95%?
- $X$ uniform on $\{-1,0,1\}$, $Y = X^2$: compute $\mathbb{E}[XY]$ and $\mathbb{E}[X]\mathbb{E}[Y]$. What does their equality prove about "zero correlation implies independence"?
- Three reasons for taking the log of a likelihood. Which of the three matters most at a million samples?
- Derive $\hat\mu = \bar{y}$ from the Gaussian log-likelihood in two lines. What loss function does that derivation justify?
- A Gaussian prior on the weights turns into which regulariser, and what is $\lambda$ as a ratio of two variances?
- LLN and CLT in one sentence each. Then: $\sigma = 10$, $n = 25$ β what is the standard error of the mean?
Re-answer these in 1 day, 3 days, and 7 days from memory. In particular, question 3 (the base-rate computation) and question 8 ($10/\sqrt{25} = 2$) should become reflexes β they are the two numbers this module wants you to own.
The algorithms that use this module most directly live in ML module 08 Β· Distance & probabilistic models β Naive Bayes, Gaussian mixtures and k-means are this material assembled into estimators, and that module rebuilds each one from the math you now have. Then ML module 06 Β· Logistic regression takes the Bernoulli likelihood of section 8 and turns it into a classifier you will actually ship: the cross-entropy loss, the sigmoid, and the decision threshold you derived in the exercise above.