Classical ML Phase B · Lecture 4 of 12
Part II — Linear Models · Lecture 4

Where Loss Functions Come From

You do not choose a loss function. You choose a noise model, and the loss is whatever its negative log-likelihood turns out to be. One principle generates squared error, absolute error, cross-entropy and Poisson loss — and tells you exactly when each is the wrong choice.

By the end you can

  • Turn any noise model into a loss by writing down its negative log-likelihood
  • Derive squared, absolute, Huber, cross-entropy and Poisson losses this way
  • Recognise the exponential family and why every gradient looks like \(\mX^\top(\hat{\vy}-\vy)\)
  • State the asymptotic properties of the MLE and what the Fisher information measures
  • Choose a robust loss when the Gaussian assumption fails, and know what it costs

Assumed

  • Phase A, Lecture 14: MLE, MAP, Bayes
  • Phase A, Lecture 2: logs, the argmax theorem, numerical stability
  • Phase B, Lecture 2: linear regression and residual diagnostics

1The recipe

Phase A Lecture 14 established the pattern. It is worth stating once as a procedure, because every loss in this course is an instance of it.

The four-step recipe
  1. Write down a conditional distribution \(p(y \mid \vx;\vt)\) — your claim about how the world generates \(y\) given \(\vx\).
  2. Form the likelihood \(L(\vt)=\prod_i p(y_i\mid\vx_i;\vt)\).
  3. Take \(-\log\): \(\;\mathcal{L}(\vt) = -\sum_i \log p(y_i\mid \vx_i;\vt)\). This is your loss.
  4. Discard any term that does not depend on \(\vt\), and any positive multiplicative constant. Neither can move the minimiser (Phase A Lecture 2).
Intuition

The loss is a measure of surprise. \(-\log p\) is large when the model assigned low probability to what actually happened, and zero when it assigned probability 1. Training minimises total surprise. That reading also explains why the units are called nats (base \(e\)) or bits (base 2), and why a language model's loss is reported as perplexity \(e^{\mathcal{L}}\) — the effective number of equally-likely options the model was choosing between.

2The catalogue

\[\begin{array}{lll} \textbf{noise model} & \textbf{negative log-likelihood} & \textbf{known as} \\[4pt] y \sim \mathcal{N}(\hat y, \sigma^2) & \tfrac{1}{2\sigma^2}(y-\hat y)^2 + \text{const} & \text{squared error} \\[4pt] y \sim \mathcal{N}(\hat y, \sigma_i^2) & \tfrac{1}{2\sigma_i^2}(y-\hat y)^2 & \text{weighted least squares} \\[4pt] y \sim \text{Laplace}(\hat y, b) & \tfrac1b|y-\hat y| + \text{const} & \text{mean absolute error} \\[4pt] y \sim \text{Student-}t_\nu(\hat y) & \tfrac{\nu+1}{2}\log\!\big(1+\tfrac{(y-\hat y)^2}{\nu}\big) & \text{robust regression} \\[4pt] y \sim \text{Bernoulli}(\hat p) & -y\log\hat p - (1-y)\log(1-\hat p) & \text{binary cross-entropy} \\[4pt] y \sim \text{Categorical}(\hat{\boldsymbol\pi}) & -\sum_k y_k\log\hat\pi_k & \text{cross-entropy} \\[4pt] y \sim \text{Poisson}(\hat\lambda) & \hat\lambda - y\log\hat\lambda + \text{const} & \text{Poisson loss} \end{array}\]

Every one of those is derived the same way — write the density, take the log, drop constants. Two of them are worth doing in full because their consequences are large.

Laplace noise gives absolute error, and why that is robust0 / 5
\[p(y\mid\hat y) = \frac{1}{2b}\exp\!\left(-\frac{|y-\hat y|}{b}\right)\]
The Laplace density. Compare the Gaussian: the exponent has \(|{\cdot}|\) rather than \((\cdot)^2\), so the tails decay exponentially rather than as \(e^{-x^2}\). Far more probability mass far from the centre.
\[-\log p = \frac{|y-\hat y|}{b} + \log(2b) \quad\Longrightarrow\quad \mathcal{L} = \sum_i |y_i-\hat y_i|\]
Take the log and drop constants. Mean absolute error, exactly.
\[\frac{\partial}{\partial \hat y}|y-\hat y| = -\operatorname{sign}(y-\hat y) \in \{-1,+1\}\]
The bounded gradient is the whole story. A residual of 100 contributes exactly the same gradient as a residual of 1. Squared error contributes \(2\times100=200\) versus \(2\) — a hundred times more. That is why one outlier can drag an OLS line across the plot and cannot drag an MAE line.
\[\text{squared error} \to \text{conditional MEAN}, \qquad \text{absolute error} \to \text{conditional MEDIAN}\]
Different losses estimate different things. Phase A Lecture 13 showed the mean minimises expected squared deviation; the same argument with \(|{\cdot}|\) gives the median. So MAE is not \"a more robust way to estimate the mean\" — it estimates a different quantity, which happens to be more robust. On a symmetric distribution they coincide; on a skewed one they do not, and you should decide which you actually want.
\[\ell_\delta(r) = \begin{cases}\tfrac12 r^2 & |r|\le\delta\\ \delta\big(|r|-\tfrac12\delta\big) & |r|>\delta\end{cases}\]
Huber: quadratic near zero, linear far out. It behaves like squared error for ordinary residuals (so it is smooth and estimates something close to the mean) and like absolute error for large ones (so outliers cannot dominate). The pieces are chosen to match in value and slope at \(|r|=\delta\), making \(\ell_\delta\) continuously differentiable — check it: both give \(\tfrac12\delta^2\) and slope \(\delta\) at \(r=\delta\).
Four losses, and what one outlier does to each fitInteractive
squaredabsoluteHuberthe true line
2.5
1.00
0
View 0: 30 clean points plus one you control. Drag its value upward and watch the blue squared-error line chase it while the orange absolute-error line barely moves. View 1: the loss functions themselves — the reason is visible immediately, since squared error grows without bound while the other two grow linearly. Huber's δ sets where it switches from one behaviour to the other.

3Classification: Bernoulli and Categorical

For \(y\in\{0,1\}\) the Bernoulli gives binary cross-entropy, derived in Phase A Lecture 14. For \(K\) classes the generalisation is immediate.

Softmax and multiclass cross-entropy0 / 5
\[\vz = \mW\vx \in\RR^K \qquad \text{(one score, or ``logit'', per class)}\]
Produce K unconstrained numbers. These cannot be probabilities — they are any reals. We need a map from \(\RR^K\) to the probability simplex.
\[\hat\pi_k = \operatorname{softmax}(\vz)_k = \frac{e^{z_k}}{\sum_{j=1}^{K} e^{z_j}}\]
Softmax. Exponentiate to make everything positive (Phase A Lecture 2: \(e^z>0\) always), then normalise so the total is 1. Note it is the natural multiclass generalisation of the sigmoid: with \(K=2\) and \(z_2=0\), \(\hat\pi_1 = \frac{e^{z_1}}{e^{z_1}+1}=\sigma(z_1)\).
\[-\log L = -\sum_{i=1}^{n}\sum_{k=1}^{K} y_{ik}\log\hat\pi_{ik} = -\sum_{i=1}^{n}\log\hat\pi_{i,c_i}\]
Categorical negative log-likelihood. With one-hot \(\vy_i\), only the true class \(c_i\) survives the inner sum. So cross-entropy is simply minus the log probability the model assigned to the correct answer — nothing more.
\[\log\hat\pi_k = z_k - \log\sum_j e^{z_j} = z_k - \operatorname{logsumexp}(\vz)\]
Never compute softmax then log. Phase A Lecture 2's log-sum-exp identity applies verbatim: computing \(\hat\pi\) first can underflow to exactly zero, and \(\log 0=-\infty\) poisons the whole batch. Every framework fuses these into log_softmax / CrossEntropyLoss for this reason.
\[\frac{\partial \mathcal{L}}{\partial \vz_i} = \hat{\boldsymbol\pi}_i - \vy_i \quad\Longrightarrow\quad \grad_{\mW}\mathcal{L} = \sum_i (\hat{\boldsymbol\pi}_i-\vy_i)\vx_i^\top\]
The same clean gradient again. Prediction minus target, times the input — identical in form to least squares and to binary logistic regression. Lecture 05 proves this for the binary case and the general one is the same computation. The \(\hat\pi(1-\hat\pi)\) factors from the softmax Jacobian cancel exactly against the \(1/\hat\pi\) from the log, just as they did for the sigmoid in Phase A Lecture 5.

4Why every gradient looks the same

That recurring \(\mX^\top(\hat{\vy}-\vy)\) is not a coincidence. It is a theorem about a family of distributions.

Definition — exponential family, canonical link

A distribution is in the exponential family with natural parameter \(\theta\) if

\[ p(y\mid\theta) = h(y)\,\exp\big(\theta\, T(y) - A(\theta)\big), \]

where \(A\) is the log-partition function. Gaussian (fixed variance), Bernoulli, Categorical, Poisson, Exponential, Gamma and Beta are all members.

A generalised linear model sets \(\theta_i = \vw^\top\vx_i\) — the canonical link.

The universal GLM gradient0 / 5
\[\int h(y)e^{\theta T(y)-A(\theta)}\,dy = 1 \quad\text{for every }\theta\]
Start from normalisation. A density integrates to 1 — that is the only input to this whole derivation, which is why the conclusion is so general.
\[\frac{d}{d\theta}\int h(y)e^{\theta T(y)}\,dy = e^{A(\theta)}A'(\theta) \quad\text{and}\quad \int h(y)T(y)e^{\theta T(y)}\,dy = e^{A(\theta)}\E[T(Y)]\]
Differentiate the identity \(\int h e^{\theta T} = e^{A}\). The left side differentiates by bringing \(T(y)\) down from the exponent; the right by the chain rule. Both are legitimate given the usual regularity conditions permitting differentiation under the integral.
\[\boxed{A'(\theta) = \E[T(Y)]}\]
The key identity. The derivative of the log-partition function is the mean of the sufficient statistic. (Differentiating again gives \(A''(\theta)=\Var(T(Y))\), so \(A\) is convex — which is why GLM likelihoods are concave and their optimisation is well behaved.)
\[\mathcal{L}(\vw) = -\sum_i\Big[\theta_i T(y_i) - A(\theta_i)\Big] + \text{const}, \qquad \theta_i = \vw^\top\vx_i\]
Write the negative log-likelihood with the canonical link substituted in.
\[\grad_{\vw}\mathcal{L} = -\sum_i\Big[T(y_i) - A'(\theta_i)\Big]\vx_i = \sum_i\Big[\underbrace{\E[T(Y)\mid\vx_i]}_{\text{prediction}} - \underbrace{T(y_i)}_{\text{target}}\Big]\vx_i = \mX^\top(\hat{\vy}-\vy)\]
The theorem. Chain rule with \(\partial\theta_i/\partial\vw = \vx_i\), then substitute \(A'=\E[T]\). Every canonical-link GLM has gradient = design matrix transposed times prediction error. Gaussian gives \(\hat y=\vw^\top\vx\); Bernoulli gives \(\hat y=\sigma(\vw^\top\vx)\); Poisson gives \(\hat y=e^{\vw^\top\vx}\). Same code, different link. ∎
Check yourself
You are predicting the number of support tickets per hour. Counts range from 0 to about 40, and the variance visibly grows with the mean. Which loss, and why?
Correct. Correct, and for three distinct reasons that all point the same way.

Support. Counts are non-negative integers. The exponential link guarantees \(\hat\lambda>0\); a linear-Gaussian model will happily predict \(-3.2\) tickets.

Variance structure. A Poisson has \(\Var=\E\), so it expects larger counts to be noisier. That matches your observation exactly. Squared error assumes constant variance and therefore over-weights the busy hours, distorting the fit towards them.

Multiplicative effects. With a log link, coefficients are multiplicative: \(w_j=0.3\) means "a one-unit increase in feature \(j\) multiplies the expected count by \(e^{0.3}=1.35\)". For counts, that is almost always the more natural claim than "adds 0.3 tickets".

One caveat worth knowing: real count data is often over-dispersed — variance exceeding the mean. Check \(\Var/\E\) on your data; if it is well above 1, negative binomial is the next step up, and it has an extra dispersion parameter for exactly this.
Not quite. The approximation improves at large counts, but you said counts go down to 0, where it is worst. And the observation that variance grows with the mean is a direct statement that the constant-variance assumption behind squared error is violated — which is exactly the funnel-shaped residual plot from Lecture 02. Squared error will still run; it will just fit the high-count hours preferentially and occasionally predict negative tickets.
Not quite. Cross-entropy needs a fixed finite set of unordered classes. Counts are ordered and unbounded — treating 39 and 40 as two arbitrary unrelated labels throws away all the structure, and the model has no way to know that predicting 39 when the truth is 40 is nearly right. (Ordinal regression exists for the intermediate case of ordered categories with no meaningful spacing.)

5What maximum likelihood guarantees, and what it does not

Asymptotic properties of the MLE

Under regularity conditions (identifiability, smoothness, the true parameter in the interior of the space), as \(n\to\infty\):

  1. Consistency: \(\hat{\vt}_{\text{MLE}} \to \vt^\star\) in probability.
  2. Asymptotic normality: \(\sqrt n\big(\hat{\vt}-\vt^\star\big) \xrightarrow{d} \mathcal{N}\big(\vzero,\ \mathcal{I}(\vt^\star)^{-1}\big)\), where \(\mathcal{I}\) is the Fisher information \(\mathcal{I}(\vt) = \E\big[-\grad^2_{\vt}\log p(Y\mid\vt)\big]\).
  3. Efficiency: no unbiased estimator has smaller asymptotic variance — the MLE attains the Cramér–Rao lower bound.

The proofs are a chapter of a statistics course and are deferred; the statements are what you need.

Intuition

The Fisher information is the curvature of the log-likelihood at its peak — literally the expected Hessian, with a sign flip. A sharply peaked likelihood means the data strongly distinguishes nearby parameter values, so the estimate is precise; a flat one means many parameters explain the data almost equally well, so the estimate is uncertain. That is exactly the "peak sharpens as \(n\) grows" behaviour you dragged in Phase A Lecture 14's likelihood figure, and \(\mathcal{I}^{-1}/n\) is the variance of the estimate.

Fisher information: curvature at the peak IS precisionInteractive
log-likelihoodquadratic approximation at the peak±1 standard error
30
0.30
A Bernoulli log-likelihood. The green band is ±1 standard error, computed from the curvature alone as 1/√(n·I). The purple parabola is the second-order Taylor expansion at the peak — the Gaussian approximation that asymptotic normality promises. Raise n: the peak sharpens, the band narrows like 1/√n, and the parabola becomes an ever better fit to the true curve. That last point is asymptotic normality, visible.
Common trap

Three failures of maximum likelihood worth holding onto.

Same data, five losses — and what each one is estimatingPython · NumPy

6Exercises

★

Derive the loss implied by each noise model, simplifying and dropping constants.

(a) \(y\sim\text{Exponential}(\text{rate}=1/\hat y)\), i.e. mean \(\hat y\).
(b) \(y\sim\mathcal{N}(\hat y,\sigma_i^2)\) with known, varying \(\sigma_i\).
(c) \(y\sim\text{Bernoulli}(\hat p)\) but with label noise: the observed label is flipped with known probability \(\epsilon\).

(a) Density \(p(y)=\frac{1}{\hat y}e^{-y/\hat y}\) for \(y>0\). So

\[-\log p = \log\hat y + \frac{y}{\hat y}, \qquad \mathcal{L}=\sum_i\left(\log\hat y_i + \frac{y_i}{\hat y_i}\right).\]

Note it is scale-invariant: multiplying both \(y\) and \(\hat y\) by \(c\) changes the loss by the constant \(\log c\). Appropriate for durations and waiting times, where a 10% error matters equally at 1 second and 1 hour. (This is the Itakura–Saito divergence, used in audio spectrogram modelling for exactly that reason.)

(b) \(-\log p = \frac{(y_i-\hat y_i)^2}{2\sigma_i^2} + \log\sigma_i + \text{const}\). The \(\log\sigma_i\) does not involve \(\vw\), so

\[\mathcal{L}(\vw)=\sum_i \frac{(y_i-\hat y_i)^2}{\sigma_i^2} \qquad\text{— weighted least squares, weights } 1/\sigma_i^2.\]

Noisier observations are down-weighted, which is exactly right: they carry less information. In matrix form the solution is \(\hat{\vw}=(\mX^\top\mathbf{\Omega}\mX)^{-1}\mX^\top\mathbf{\Omega}\vy\) with \(\mathbf{\Omega}=\operatorname{diag}(1/\sigma_i^2)\).

(c) The observed label is 1 either when the true label is 1 and no flip occurs, or when the true label is 0 and a flip does:

\[P(\tilde y=1) = \hat p(1-\epsilon) + (1-\hat p)\epsilon = \epsilon + (1-2\epsilon)\hat p =: \tilde p.\]

So the loss is ordinary cross-entropy applied to \(\tilde p\):

\[\mathcal{L} = -\sum_i\big[\tilde y_i\log\tilde p_i + (1-\tilde y_i)\log(1-\tilde p_i)\big], \qquad \tilde p_i = \epsilon+(1-2\epsilon)\sigma(\vw^\top\vx_i).\]

Why this matters: \(\tilde p\) is confined to \([\epsilon, 1-\epsilon]\), so the model can never be asked to output a probability of 0 or 1. That caps the loss for any single example, which is precisely what stops noisy labels from producing unbounded gradients. This is the principled version of label smoothing — and knowing the derivation tells you the smoothing parameter should be your estimated label-noise rate, not an arbitrary 0.1.

★★

Prove that the Huber loss is continuously differentiable at \(|r|=\delta\), and find the value of \(\delta\) that makes it the negative log-likelihood of a specific density. Sketch that density and compare it with a Gaussian.

Continuity of value. At \(r=\delta\): the quadratic branch gives \(\tfrac12\delta^2\); the linear branch gives \(\delta(\delta-\tfrac12\delta)=\tfrac12\delta^2\). Equal ✓.

Continuity of derivative. Quadratic branch: \(\ell'(r)=r\), so \(\ell'(\delta^-)=\delta\). Linear branch (for \(r>\delta\)): \(\ell(r)=\delta r-\tfrac12\delta^2\), so \(\ell'(\delta^+)=\delta\). Equal ✓. So \(\ell_\delta\in C^1\) for every \(\delta\), which is why it is safe for gradient-based optimisation where absolute error is not.

(The second derivative is discontinuous — 1 inside, 0 outside — so \(\ell_\delta\notin C^2\). That is why Newton-type methods need care with Huber, and why log-cosh, which is smooth everywhere, is sometimes preferred.)

The implied density. Exponentiating \(-\ell_\delta\) and normalising:

\[p(r) \propto \begin{cases} e^{-r^2/2} & |r|\le\delta\\[3pt] e^{-\delta|r|+\delta^2/2} & |r|>\delta\end{cases}\]

This is the Huber density: Gaussian in the middle, Laplace in the tails, glued together smoothly at \(\pm\delta\). Any \(\delta\) gives a valid density (the normalising constant depends on \(\delta\)), so there is no single "correct" value — \(\delta\) parameterises a family interpolating between Gaussian (\(\delta\to\infty\)) and Laplace (\(\delta\to0\)).

Compared with a Gaussian: identical near the centre, but with far heavier tails — decaying like \(e^{-\delta|r|}\) rather than \(e^{-r^2/2}\). At \(r=6\delta\) the Huber density is larger by a factor of roughly \(e^{12.5\delta^2}\). That is the entire content of "robust": the model considers a large residual surprising but possible, rather than astronomically impossible, and so declines to distort itself to eliminate one.

Choosing \(\delta\): the standard is \(\delta=1.345\hat\sigma\), which gives 95% efficiency relative to OLS when the noise really is Gaussian while retaining robustness when it is not. Note \(\hat\sigma\) must be estimated robustly (e.g. from the median absolute deviation) or the outliers you are guarding against will inflate it.

★★

Compute the Fisher information and hence the asymptotic standard error for:

(a) Bernoulli\((p)\)    (b) Poisson\((\lambda)\)    (c) Gaussian mean with known \(\sigma^2\).

For (a), at which \(p\) is the estimate most precise, and at which least? Explain the practical consequence for measuring click-through rates.

(a) Bernoulli. \(\log p(y\mid p)=y\log p+(1-y)\log(1-p)\). \(\frac{\partial^2}{\partial p^2} = -\frac{y}{p^2}-\frac{1-y}{(1-p)^2}\). Taking \(-\E\) with \(\E[Y]=p\):

\[\mathcal{I}(p) = \frac{p}{p^2}+\frac{1-p}{(1-p)^2} = \frac1p+\frac1{1-p} = \frac{1}{p(1-p)}.\]

Standard error \(=\sqrt{p(1-p)/n}\) — the familiar formula, now derived rather than quoted.

(b) Poisson. \(\log p = y\log\lambda-\lambda-\log y!\), second derivative \(-y/\lambda^2\), so \(\mathcal{I}(\lambda)=\E[Y]/\lambda^2 = 1/\lambda\). Standard error \(=\sqrt{\lambda/n}\) — consistent with \(\Var=\lambda\).

(c) Gaussian mean. \(\log p = -\frac{(y-\mu)^2}{2\sigma^2}+\text{const}\), second derivative \(-1/\sigma^2\), so \(\mathcal{I}(\mu)=1/\sigma^2\), constant in \(\mu\). Standard error \(=\sigma/\sqrt n\) — Phase A Lecture 13, recovered.

Most and least precise. \(\text{se}=\sqrt{p(1-p)/n}\) is maximised at \(p=\tfrac12\) (value \(0.5/\sqrt n\)) and shrinks towards zero as \(p\to0\) or \(1\). So rare events are estimated with the smallest absolute error.

But that is the wrong way round for click-through rates, and this is the practically important point. What matters is relative precision:

\[\frac{\text{se}}{p} = \sqrt{\frac{1-p}{np}} \approx \frac{1}{\sqrt{np}} \quad\text{for small } p.\]

This blows up as \(p\to0\). At \(p=0.001\) you need \(n\approx10^6\) for a 3% relative error, and \(n\approx10^4\) gives you \(\pm32\%\). The absolute error is tiny and completely useless.

Hence the rule of thumb that you need on the order of \(1/p\) events, not observations: A/B tests on rare conversions need enormous samples, and a reported "CTR improved from 0.10% to 0.12%" on ten thousand impressions is roughly seven conversions against six. Always compute the interval.

★★★

Coding. Build a heteroscedastic regression that learns its own noise level.

  1. Generate data where \(y_i\sim\mathcal{N}(\vw^\top\vx_i,\ \sigma^2(\vx_i))\) with \(\sigma(\vx)=e^{\vv^\top\vx}\) — the noise depends on the input.
  2. Fit ordinary least squares. Show the residual plot funnels.
  3. Write the full negative log-likelihood in both \(\vw\) and \(\vv\), and minimise it jointly.
  4. Compare the recovered \(\vw\) and the predictive intervals against OLS. Which improves more, the point predictions or the uncertainty?

3. The objective. With \(\mu_i=\vw^\top\vx_i\) and \(\log\sigma_i=\vv^\top\vx_i\),

\[\mathcal{L}(\vw,\vv) = \sum_{i=1}^n\left[\vv^\top\vx_i + \frac{(y_i-\vw^\top\vx_i)^2}{2\exp(2\vv^\top\vx_i)}\right].\]

Note the structure: the first term penalises claiming large noise, the second rewards it (it shrinks the residual penalty). The model must trade them off, which is what stops it from declaring infinite noise everywhere and calling the job done.

import numpy as np
from scipy.optimize import minimize
rng = np.random.default_rng(0)
n, d = 600, 3
X = np.column_stack([np.ones(n), rng.normal(size=(n, d))])
w_true = np.array([1.0, 2.0, -1.0, 0.5])
v_true = np.array([-0.5, 0.9, 0.0, 0.0])          # noise grows with feature 1
sd = np.exp(X @ v_true)
y  = X @ w_true + sd*rng.normal(size=n)

w_ols, *_ = np.linalg.lstsq(X, y, rcond=None)
res = y - X @ w_ols
print("OLS  w:", np.round(w_ols, 3), " true:", w_true)
print("funnel check  corr(|res|, x1) =",
      round(np.corrcoef(np.abs(res), X[:,1])[0,1], 4), " (should be ~0 if homoscedastic)")

def nll(theta):
    w, v = theta[:d+1], theta[d+1:]
    ls = np.clip(X @ v, -8, 8)
    return np.sum(ls + (y - X@w)**2 / (2*np.exp(2*ls)))

opt = minimize(nll, np.concatenate([w_ols, np.zeros(d+1)]), method="L-BFGS-B")
w_h, v_h = opt.x[:d+1], opt.x[d+1:]
print("\\nHet  w:", np.round(w_h, 3))
print("Het  v:", np.round(v_h, 3), " true:", v_true)
print(f"\\n||w_ols - w_true|| = {np.linalg.norm(w_ols-w_true):.4f}")
print(f"||w_het - w_true|| = {np.linalg.norm(w_h  -w_true):.4f}")

# calibration of 90% intervals
z = 1.645
cov_ols = np.mean(np.abs(y - X@w_ols) <= z*res.std())
cov_het = np.mean(np.abs(y - X@w_h)   <= z*np.exp(X@v_h))
print(f"\\n90% interval coverage:  OLS {cov_ols:.3f}   heteroscedastic {cov_het:.3f}")

2. The OLS residual plot funnels visibly, and \(\operatorname{corr}(|r|, x_1)\) comes out around \(+0.35\) rather than 0 — the quantitative version of the funnel in Lecture 02's diagnostic figure.

4. The answer to "which improves more". The uncertainty, by a large margin.

  • Point predictions improve modestly. OLS remains unbiased under heteroscedasticity — the normal equations do not require constant variance for unbiasedness, only for efficiency. So \(\vw_{\text{OLS}}\) is right on average; it is merely noisier than it needs to be, because it weights the high-noise observations as heavily as the clean ones. Expect \(\|\vw-\vw^\star\|\) to fall by perhaps 20–40%.
  • Intervals improve dramatically. OLS produces one constant-width interval, which is simultaneously far too wide in the quiet region and far too narrow in the noisy one. Its 90% intervals typically cover around 93–95% overall — but that average hides the failure, since coverage is roughly 99% for low-noise points and 75% for high-noise ones. The heteroscedastic model gives per-point intervals with coverage near 90% uniformly.

The general lesson. Getting the mean right and getting the uncertainty right are separate problems, and modelling the noise fixes the second far more than the first. This is exactly why modern probabilistic regression predicts both \(\mu(\vx)\) and \(\sigma(\vx)\), why quantile regression exists, and why a model that outputs a point estimate cannot tell you when to distrust it.


Next: the classification case in full. Lecture 05 builds logistic regression and softmax from the Bernoulli likelihood, derives the decision boundary, and confronts the separable-data pathology head on.