Chapter 5 · Rethinking Statistics with Bayesian Methods
Section 5.3 · Chapter 5 · Learning Statistics with Python
Rethinking Statistics with Bayesian Methods
Prof. Xuhu Wan
ISOM, HKUST Business School · 2026 Edition
Three planted outliers will drag an OLS slope from 5 to 4.4. You will predict the direction, then swap the likelihood for a Student-t and watch the slope come back — first on simulated data, then on GOOG’s market beta.
\(y = 0.5 + 5x + N(0, 0.5^2)\) on 100 points, plus three points at \((0.1, 8), (0.15, 6), (0.2, 9)\) — far above the line on the left.
How will OLS respond to three high points at small \(x\)?
OLS [1.033, 4.403] — intercept doubled, slope off by 0.6. Under a normal likelihood a residual of 7 costs \(7^2/2 = 24.5\) log-units; the fit bends to reduce that at everyone else’s expense.
In Colab
with pm.Model() as model:
beta0 = pm.Normal("b0", 0.0, 1.0); beta1 = pm.Normal("b1", 0, 1.2)
std = pm.Exponential("sd", 1.0)
output = pm.Normal("y", mu=beta0 + beta1 * data2["x"], sigma=std, observed=data2["y"])
# robust version: replace the last line by
likelihood = pm.StudentT("y", mu=mu, sigma=std, nu=3, observed=data2["y"].values)Same priors, one word changed: Normal → StudentT. Let’s see what that word does.
No sampler needed to see the effect: minimise the negative t log-likelihood with scipy.optimize.minimize, \(\nu = 3\).
Robust [0.492, 5.167], scale 0.457 — the truth is 0.5, 5, 0.5. The green dashed line goes through the cloud; the red one is tugged up-left by three points.
The t log-density’s derivative gives each point an implicit weight \(w_i = \dfrac{\nu + 1}{\nu + r_i^2}\), where \(r_i\) is the standardised residual.
The outlier at \((0.2, 9)\) has standardised residual ≈ 16.5 under the robust fit. With \(\nu = 3\), what is its weight (3 dp)?
0.015
Outliers get weights 0.017, 0.036, 0.015; a typical point gets 1.13. The t-likelihood is a self-weighting least squares — it down-weights exactly the points that do not fit. Nobody chose which points to drop.
Same sampler as §5.1, new log-posterior: Prior II from §5.2, \(\sigma \sim \text{Exponential}(1)\), t(3) likelihood.
Slope posterior mean 5.06, credible interval [4.64, 5.41]. OLS’s 4.40 lies outside it. The model is telling you the outliers are not from the same process.
Daily returns 2015-10 to 2020-10, 1 258 days including the March 2020 crash. Two likelihoods, one question: what is \(\beta\)?
OLS gives \(\beta \approx 1.06\). What will a Student-t likelihood give?
OLS β 1.064, robust β 1.094, \(\nu = 3.35\) — close to the 2.7 the return model found in §5.1. The point estimates differ by 0.03; the difference in inference is larger: a normal model with kurtosis-11 residuals reports standard errors that are fiction.
Twelve days with \(|r_{SP}| > 5\%\), nine of them in March 2020. Those twelve points — 1 % of the sample — carry 37 % of \(\sum x^2\), the leverage that drives OLS. The t model weights each by its surprise, not by its size.
250-day windows, stepped every 25 days. The OLS beta is done; replace the placeholder so b_rob is the t(3) slope from minimize (hint: mimic nll_t with xx, yy). Then compare the two paths.
Normal → StudentT) is the whole robust model; minimize or Metropolis fits it in under a second.Next: §5.4 — stop refitting from scratch; let yesterday’s posterior become today’s prior.
Prof. Xuhu Wan · HKUST ISOM · Learning Statistics with Python