Part I: Foundations of Sensory AI
Chapter 4: Probability, Estimation, and Uncertainty Primer

Estimators, bias-variance, and maximum likelihood

"Every number I report is a guess with a track record. My job is to know how good the track record is before you trust the guess."

A Self-Aware AI Agent

The Big Picture

A sensor never hands you the quantity you actually want. A photodiode gives counts, not lux; an accelerometer gives voltage, not acceleration; a thermistor gives resistance, not degrees. Between the raw reading and the number you report sits an estimator: a rule that turns noisy data into a best guess of a hidden parameter. This section is about how to build those rules, how to judge them, and why the single most useful decomposition in all of applied statistics, the split of error into bias and variance, governs everything from how many samples you average to how large a neural network you can afford. We then meet maximum likelihood, the workhorse recipe that produces most of the estimators you will ever deploy, and the Cramer-Rao bound, which tells you when to stop trying to do better.

This section assumes you are comfortable with random variables, expectation, and variance from Section 4.1, and with the sensor noise models introduced in Chapter 2. Everything here is frequentist: the parameter is a fixed unknown and the data is random. The complementary Bayesian view, where the parameter itself carries a distribution, arrives in Section 4.3.

What an estimator is, and how to grade one

An estimator \(\hat\theta\) is any function of the data \(X_1,\dots,X_n\) that we use to guess an unknown parameter \(\theta\). Because the data is random, \(\hat\theta\) is a random variable with its own distribution, called the sampling distribution. We grade an estimator by properties of that distribution, not by any single run.

The sampling distribution is precisely the probability distribution of the estimator \(\hat\theta\) taken over hypothetical repetitions of the entire experiment, each run supplying fresh random data. It matters because every quality we care about, bias, variance, and confidence intervals alike, is a feature of this distribution rather than of the one number you happened to compute. Mechanically you can approximate it without any repeated experiments through the bootstrap: resample your existing data with replacement many times, recompute \(\hat\theta\) on each resample, and read the spread off the resulting histogram. Reach for the sampling distribution whenever you need to attach honest error bars to a reported value; a lone point estimate carrying no sense of its own sampling distribution is a guess with no track record. Figure 4.2.2 illustrates the estimation pipeline: from noisy sensor data to a graded estimate via its sampling distribution.

The estimation pipeline: from noisy sensor data to a graded estimate via its sampling distribution
Figure 4.2.2: A single noisy sensor recording is turned into an estimate by an estimator rule; imagining the experiment repeated many times traces out the estimator's sampling distribution, whose offset from the true parameter is bias, whose width is variance, and whose combined error is the mean squared error.

Bias measures systematic error: \(\operatorname{Bias}(\hat\theta) = \mathbb{E}[\hat\theta] - \theta\). An estimator is unbiased if, averaged over infinitely many experiments, it lands on the truth. Variance measures spread: how far a single estimate typically strays from its own average. The quantity that actually matters for a deployed system combines both, the mean squared error (MSE):

$$\operatorname{MSE}(\hat\theta) = \mathbb{E}\big[(\hat\theta - \theta)^2\big] = \operatorname{Bias}(\hat\theta)^2 + \operatorname{Var}(\hat\theta).$$

This identity is the spine of the whole section. It says total error has exactly two ingredients, and they trade against each other. A thermostat that always reads two degrees high has bias but no variance; a cheap sensor that jitters wildly around the true value has variance but no bias. Both are wrong, and MSE counts them on the same scale.

Checkpoint

So far: an estimator is a random variable with its own sampling distribution, and we grade that distribution with three numbers, bias (systematic error) and variance (spread) and the mean squared error that combines them, which is the single score a deployed system actually cares about.

Consistency and efficiency

Two more properties matter in practice. An estimator is consistent if \(\hat\theta \to \theta\) as \(n\to\infty\): more data eventually crushes the error. It is efficient if, among unbiased estimators, it has the smallest possible variance. Consistency is the minimum bar for a sensor calibration routine; efficiency tells you whether spending money on a better algorithm can help, or whether you have already hit the physics-imposed floor. In short: an estimator is a promise made under uncertainty, and bias, variance, and Fisher information (defined later in this section, once we reach the Cramer-Rao bound) are the three numbers that tell you how much that promise is worth.

Key Insight: unbiased is not the goal, low MSE is

Beginners chase unbiasedness as if it were sacred. It is not. Because MSE adds squared bias and variance, you can often reduce total error by accepting a little bias in exchange for a large drop in variance. This is exactly why we regularize models (deliberately constrain a model so it cannot chase noise), why we shrink noisy estimates toward a prior, and why averaging a slightly-biased-but-stable sensor beats a perfectly-calibrated-but-jittery one. The estimator that typically wins in the field is the one with the smallest MSE at your actual sample size, not the one that looks purest on a whiteboard.

The bias-variance tradeoff as a design dial

The tradeoff is not an abstraction; it is a knob you turn every day. Consider estimating a slowly-drifting quantity, say the resting heart rate baseline of a wearer, by averaging the last \(n\) beats. A long window (large \(n\)) drives variance down like \(1/n\) because averaging cancels independent noise. But a long window also reaches back into stale data. If the true baseline is drifting, the average lags behind reality and picks up bias. A short window tracks the drift faithfully (low bias) but barely averages anything (high variance). There is an optimal window length that minimizes MSE, and it depends on the noise level and the drift rate. This same shape recurs in filter bandwidth choices in Chapter 6 and in model capacity choices for the neural sensor models of Chapter 13.

The model-complexity version is identical in spirit. A tiny model is too rigid to capture the signal, so it is biased (underfitting). A huge model bends to fit the noise in your particular training set, so it has high variance and generalizes poorly (overfitting). Every regularization technique, weight decay, dropout, early stopping, is a device for buying variance reduction with a controlled dose of bias. Figure 4.2.1 plots this decomposition directly: as complexity rises, squared bias falls while variance climbs, and their sum, the mean squared error, bottoms out at an intermediate optimum rather than at either extreme.

Bias-variance decomposition of mean squared error against model complexity Error Model complexity (or shorter averaging window) → Bias² Variance MSE = Bias² + Variance MSE minimum (optimal complexity)
Figure 4.2.1: As model complexity grows (equivalently, as the averaging window shortens), squared bias (orange) falls while variance (blue) rises. Their sum, the mean squared error (purple), is U-shaped and is minimized at an intermediate sweet spot, marked by the dashed line, rather than at either extreme.

Practical Example: calibrating a microelectromechanical systems (MEMS) gas sensor on the line

An industrial air-quality startup ships a low-cost metal-oxide CO2 sensor. Each unit's raw resistance-to-ppm curve varies with manufacturing tolerances, so every device gets a one-point factory calibration against a reference gas. The engineers first tried estimating each device's offset from a single 5-second reference reading. Result: unbiased, but the per-device offset estimate had huge variance because 5 seconds of a noisy sensor is barely any information, and field accuracy was terrible.

The fix was pure bias-variance thinking. They shrank each device's raw offset estimate toward the fleet-average offset, a deliberately biased move, weighting the shrinkage by how noisy that unit's reference reading was. Devices with clean readings kept their own estimate; devices with noisy readings borrowed strength from the fleet. MSE of the deployed calibration dropped by roughly forty percent with zero hardware change. The lesson: a biased estimator that leans on a good prior beat the unbiased one that trusted five noisy seconds.

Maximum likelihood: one recipe for almost every estimator

Nearly every calibrated number a modern sensor system reports, from your phone's step count to a spacecraft's position fix, is produced by one estimation recipe; choose it badly and the error leaks silently into every downstream decision that trusts the reading. Where do good estimators come from? Most of the time, from maximum likelihood estimation (MLE). The recipe has three moves. Write down a probabilistic model \(p(x \mid \theta)\) for how your sensor produces data given the parameter. Given the actual data you observed, treat that probability as a function of \(\theta\), the likelihood \(L(\theta) = \prod_i p(x_i \mid \theta)\), and pick the \(\theta\) that makes the observed data most probable:

$$\hat\theta_{\text{MLE}} = \arg\max_\theta \; \sum_{i=1}^n \log p(x_i \mid \theta).$$

Common Misconception

The trap is reading the likelihood \(L(\theta)\) as "the probability that \(\theta\) is the true value," so that maximizing it supposedly returns the most probable parameter. It does not. \(L(\theta) = p(\text{data}\mid\theta)\) is the probability of the observed data for a candidate parameter; it is not a probability distribution over \(\theta\) at all, and it need not even integrate to one as \(\theta\) varies. Maximum likelihood picks the \(\theta\) under which your data would have been most probable, which is a strictly weaker and different claim than "the most probable \(\theta\)"; turning the story around to get the probability of \(\theta\) itself requires a prior and the Bayesian machinery of Section 4.3.

We maximize the log-likelihood because sums are numerically kinder than products and because the logarithm turns the exponentials in most noise models into tidy quadratics. Here is the payoff that connects a whole thread of the book: if your sensor noise is Gaussian, maximum likelihood is exactly least squares. Maximizing \(\sum_i \log p(x_i\mid\theta)\) for \(p = \mathcal{N}(\mu(\theta), \sigma^2)\) is the same as minimizing \(\sum_i (x_i - \mu(\theta))^2\). The sample mean, linear regression, and the Kalman filter update of Chapter 9 are all maximum-likelihood estimators under a Gaussian assumption in disguise.

MLE earns its dominance because, under mild conditions, it is asymptotically unbiased (unbiased in the limit of large sample size), consistent, and efficient: with enough data it reaches the lowest variance any unbiased estimator can achieve. That floor has a name.

Key Insight: the Cramer-Rao bound tells you when to stop optimizing

For any unbiased estimator, the variance cannot go below the reciprocal of the Fisher information \(I(\theta)\): \(\operatorname{Var}(\hat\theta) \ge 1/I(\theta)\). Fisher information measures how sharply the log-likelihood peaks around the true parameter, that is, how much each sample actually tells you. The practical consequence is liberating: compute the Cramer-Rao bound for your problem, and if your current estimator already sits near it, no cleverer algorithm will save you. Your only levers left are more data, a better sensor (higher \(I(\theta)\) per sample), or accepting bias to trade against variance. This is how good sensing teams decide between "write a smarter filter" and "buy a quieter sensor."

Mental Model

Picture searching for the highest point of a hill in thick fog, feeling only the slope under your feet. If the summit is a sharp peak, a step in any direction drops away steeply and you can pin the top to within a meter. If instead it is a broad, flat plateau, you can wander a long way and still feel almost level ground, so your best guess of the exact top stays vague. Fisher information is the sharpness of that peak in the log-likelihood: sharp curvature means each sample gives crisp feedback and the parameter is nailed down tightly, while flat curvature leaves you drifting. The Cramer-Rao bound simply states that your uncertainty can never be smaller than the flatness of the hill permits, no matter how clever your walking strategy.

Computing a maximum-likelihood estimate

With that floor now in hand as a yardstick, the natural next step is to compute an actual maximum-likelihood estimate and hold it up against the bound. Consider a common sensor-modeling task: your accelerometer sits still, and you want to estimate the noise standard deviation \(\sigma\) of its output so you can feed it to a downstream filter. Assume readings are Gaussian around a fixed (also unknown) bias \(\mu\). The code below fits both by maximum likelihood and compares against the Cramer-Rao lower bound on the variance of \(\hat\sigma\), so you can see whether your estimate is as good as physics allows.

import numpy as np

rng = np.random.default_rng(0)
true_mu, true_sigma, n = 0.02, 0.15, 500          # bias (g), noise std (g), samples
x = rng.normal(true_mu, true_sigma, size=n)        # a still accelerometer axis

# Maximum-likelihood estimates for a Gaussian: closed form.
mu_hat = x.mean()                                  # MLE of the mean
sigma_hat = x.std(ddof=0)                           # MLE of std (divides by n, biased low)
sigma_unbiased = x.std(ddof=1)                      # Bessel-corrected (divides by n-1)

# Cramer-Rao lower bound on Var(sigma_hat) for a Gaussian: sigma^2 / (2n).
crlb_var_sigma = true_sigma**2 / (2 * n)

print(f"mu_hat      = {mu_hat:+.4f}  (true {true_mu:+.4f})")
print(f"sigma_hat   = {sigma_hat:.4f}  MLE, biased low by ~sigma/(2n)")
print(f"sigma_unbi. = {sigma_unbiased:.4f}  (true {true_sigma:.4f})")
print(f"CRLB std of sigma_hat = {np.sqrt(crlb_var_sigma):.4f} g")
Maximum-likelihood estimation of an accelerometer's bias and noise from a still recording. The MLE of \(\sigma\) divides by \(n\) and is slightly biased low; the Bessel-corrected version (divide by \(n-1\)) is the unbiased choice. The printed Cramer-Rao bound is the smallest standard error any unbiased estimator of \(\sigma\) could achieve at this sample size, so it tells you whether collecting more stillness data would meaningfully help.

Notice the concrete appearance of bias-variance in the output: the plain MLE of \(\sigma\) is biased low (it divides by \(n\)), while the Bessel-corrected estimate is unbiased (it divides by \(n-1\)). At \(n=500\) the gap is tiny, which is exactly the point, the bias of MLE vanishes as data grows, so we tolerate it in exchange for the recipe's generality.

Step-Through: Gaussian maximum likelihood by hand

Trace the closed-form MLE with a four-sample still-accelerometer recording (units of g): \(x = [0.10,\ -0.05,\ 0.20,\ 0.15]\). No optimizer needed; the log-likelihood for a Gaussian is maximized analytically.

  1. Estimate the mean (bias). \(\hat\mu = \tfrac{1}{4}(0.10 - 0.05 + 0.20 + 0.15) = \tfrac{0.40}{4} = 0.10\) g.
  2. Form the residuals. Subtract \(\hat\mu\) from each sample: \([0.00,\ -0.15,\ 0.10,\ 0.05]\).
  3. Sum their squares. \(0.00^2 + (-0.15)^2 + 0.10^2 + 0.05^2 = 0 + 0.0225 + 0.0100 + 0.0025 = 0.0350\).
  4. Divide by \(n\) for the MLE of variance. \(\hat\sigma^2_{\text{MLE}} = 0.0350 / 4 = 0.00875\), so \(\hat\sigma_{\text{MLE}} = \sqrt{0.00875} = 0.0935\) g. This divides by \(n\) and is biased low.
  5. Divide by \(n-1\) for the unbiased estimate. \(\hat\sigma^2_{\text{unb}} = 0.0350 / 3 = 0.01167\), so \(\hat\sigma_{\text{unb}} = 0.1080\) g. The two differ by fifteen percent here at \(n=4\); at \(n=500\) that gap would shrink to about a tenth of a percent.

The whole recipe of the previous code block is exactly these five arithmetic lines, run on four numbers instead of five hundred, and the visible gap between the two \(\sigma\) estimates is the bias of MLE made concrete.

Library Shortcut: let SciPy fit the whole distribution

Writing the log-likelihood and its maximizer by hand is instructive but rarely necessary. For any of dozens of noise families, scipy.stats.<dist>.fit(x) returns the maximum-likelihood parameters in one line, handling the optimization, the log-sum-exp stability (the numerical trick that keeps sums of many exponentials from overflowing or underflowing to zero), and the parameter constraints for you:

from scipy import stats
mu_hat, sigma_hat = stats.norm.fit(x)        # MLE, one line
df, loc, scale   = stats.t.fit(x)            # heavy-tailed? swap the family
One-line maximum-likelihood fits with SciPy: stats.norm.fit returns the Gaussian bias and noise standard deviation, and swapping to stats.t.fit refits the exact same data under a heavy-tailed Student-t model, changing the entire noise family with a single word.

That replaces roughly 20 to 40 lines of hand-rolled likelihood, gradient, and bounded-optimizer code per distribution, and switching noise models (Gaussian to Student-t for a sensor with outliers) becomes a one-word edit. Reserve the from-scratch version for when your measurement model is custom enough that no library distribution fits it.

When maximum likelihood misleads you

MLE is powerful, not infallible, and sensor data breaks its assumptions in predictable ways. First, model misspecification: MLE finds the best parameter within the family you assumed. If you assume Gaussian noise but your accelerometer occasionally emits large spike outliers, the fitted \(\sigma\) inflates to cover the spikes. Every downstream estimate then suffers. The remedy is a heavier-tailed likelihood (Student-t, Huber) so a few outliers no longer dominate. Second, small samples: MLE's beautiful efficiency is asymptotic, and with a handful of points it can be badly biased or even undefined. That is precisely the regime where borrowing strength from a prior pays off, which motivates the Bayesian treatment in Section 4.3. Third, MLE gives you a point estimate; it does not, by itself, tell you how much to trust that point. Quantifying that trust, and separating noise you cannot reduce from ignorance you can, is the subject of Section 4.4 on aleatoric versus epistemic uncertainty.

Research Frontier

When the sensor's data-generating process is a complex simulator with no writable likelihood \(p(x\mid\theta)\), classical maximum likelihood cannot even be evaluated. Simulation-based inference sidesteps this by training a neural network on many simulated (parameter, data) pairs to output an estimate, or a full posterior, directly. Gloeckler et al.'s "All-in-one Simulation-Based Inference" (the Simformer, ICML 2024) uses a single transformer to amortize inference across arbitrary conditioning patterns, and the open-source sbi toolkit (Boelts et al., Journal of Open Source Software, 2025) puts these neural estimators one import away. Together they extend the estimator toolkit of this section to measurement models where the likelihood is intractable and only forward simulation is available.

Exercise

You estimate a wearable's skin-temperature offset by averaging \(n\) readings taken over a window during which the true skin temperature is slowly rising at rate \(r\) degrees per sample. Model the per-sample noise as zero-mean with variance \(\sigma^2\). (a) Write the MSE of the windowed-average estimate as a function of \(n\), \(r\), and \(\sigma^2\), identifying which term is bias and which is variance. (b) Differentiate to find the window length \(n^\star\) that minimizes MSE. (c) Explain in one sentence what happens to \(n^\star\) as the sensor gets noisier, and as the drift gets faster. This is the bias-variance dial made numerical.

Self-Check

  1. An estimator has zero bias but enormous variance, and a second has a small constant bias but tiny variance. Under MSE at a fixed sample size, which can be the better choice, and why does "unbiased" not settle the question?
  2. Your sensor-noise fit sits right at the Cramer-Rao lower bound. A colleague proposes a more elaborate estimation algorithm. What do you tell them, and what are the two remaining ways to actually reduce the error?
  3. Why is maximum-likelihood estimation under Gaussian noise identical to least-squares fitting, and what changes the moment you switch to a Student-t noise model?

Try It: watch bias and variance trade off

Using only NumPy and Matplotlib, make the bias-variance tradeoff appear on a single plot in about twenty minutes.

  1. Simulate a slowly drifting signal over 2000 steps: build truth = 0.01 * np.arange(2000), then add noise once per Monte Carlo trial (one simulated run with a fresh batch of random draws) with x = truth + rng.normal(0, 0.5, 2000).
  2. For each window length n in [1, 2, 5, 10, 20, 50, 100, 200], estimate the signal at every time step as the trailing mean of the previous n noisy samples.
  3. Repeat step 2 across a few hundred trials, and at each n compute the squared bias (mean estimate minus truth, squared, averaged over time) and the variance of the estimate across trials, then their sum (the MSE).
  4. Plot bias\(^2\), variance, and MSE against n on a log-scaled x-axis, and confirm that variance falls like \(1/n\) while bias\(^2\) climbs as the window reaches back into stale, drifting data.
  5. Read off the n that minimizes the MSE curve; then rerun with double the noise and half the drift and watch the optimum shift, exactly the dial you derived in the exercise above.

Real-World Application: Global Positioning System (GPS) receivers

Every consumer GPS chip is a maximum-likelihood estimator in disguise: it picks the receiver position and clock offset that make the observed satellite pseudoranges (each a satellite-to-receiver distance inferred from signal travel time, offset by the receiver's own clock error) most probable under a Gaussian model of ranging noise, which reduces to the weighted least-squares fix your phone reports. The receiver also propagates the Cramer-Rao geometry of the visible constellation into the "dilution of precision" number, telling you when the satellites are too clustered for any algorithm to sharpen the fix. That is why an open-sky lock is meters-accurate while an urban canyon leaves you drifting across the street.

Fisher Rediscovered a Century-Old Idea, Then Made It Rigorous Enough to Bear His Name

Ronald Fisher championed maximum likelihood in the 1920s as if it were new, but the essential move, choosing the parameter that maximizes the probability of the observed data, had already been written down by Carl Friedrich Gauss around 1809 and hinted at even earlier by Daniel Bernoulli and Lagrange. What Fisher genuinely did add was the machinery that made it rigorous: consistency, efficiency, and the information measure that now carries his name. The delicious twist is that Fisher information, the sharpness of the likelihood peak that bounds every unbiased estimator through Cramer-Rao, quantifies exactly why the century-old recipe works so well, so the newcomer's proof ended up explaining the veteran's guess.

Lab: measure your own estimator against the Cramer-Rao floor

Goal. See empirically that the maximum-likelihood estimator of a Gaussian mean actually reaches the Cramer-Rao lower bound, and watch what breaks when the noise stops being Gaussian.

Tools. Python with NumPy, SciPy, and Matplotlib (about 15 to 25 minutes). No hardware needed; you will simulate a still sensor.

  1. Set up. Fix a true mean mu = 0.02 and noise sigma = 0.15. For each sample size n in [10, 30, 100, 300, 1000], run 2000 Monte Carlo trials, each drawing x = rng.normal(mu, sigma, n) and recording x.mean().
  2. Measure. At each n, compute the empirical variance of your 2000 mean-estimates and compare it against the Cramer-Rao bound sigma**2 / n. Plot both against n on log-log axes.
  3. Vary. Replace the Gaussian draw with a heavy-tailed one, x = mu + sigma/np.sqrt(3) * rng.standard_t(3, n) (same variance, fatter tails), keeping the sample mean as your estimator.
  4. Observe. Under Gaussian noise the empirical variance sits right on the Cramer-Rao line, the sample mean is efficient. Under the t-distributed noise the sample-mean variance floats above the bound because the mean is no longer the MLE; swap in a robust estimator (trimmed mean or scipy.stats.t.fit) and watch it drop back toward the floor.

The payoff: you will have proven, on your own machine, both halves of the section, that MLE hits the physics-imposed floor when its assumptions hold, and that a misspecified likelihood quietly leaves accuracy on the table.

What's Next

In Section 4.3, we let the parameter carry a distribution of its own instead of treating it as a fixed unknown. Treating \(\theta\) as random turns the gas-sensor shrinkage trick into a principled framework, injects prior knowledge when data is scarce, and returns a full posterior we can propagate through the sensing pipeline rather than a lone point estimate.