A model that aces the training set but fails on new users, new tickets, or next week’s traffic is not “smart” — it memorized. The whole point of learning is generalization: good predictions on data the model has never seen. Underfitting and overfitting are the two classic failure modes, and the bias–variance tradeoff is the language we use to reason about the capacity sweet spot between them. Every GenAI practitioner hits this when a fine-tune looks perfect on the demo set and collapses in production.
Imagine studying for an exam. Underfitting is only reading the chapter titles: you miss detail, so you score poorly on practice and on the real test. Overfitting is memorizing the answer key for last year’s quiz: practice scores soar, but a reworded question on exam day wrecks you.
In ML terms:
Bias is error from wrong assumptions (too simple a model). Variance is error from sensitivity to the particular training sample (too wiggly a model). Irreducible noise remains even with a perfect learner. Roughly:
Expected error ≈ Bias^2 + Variance + Noise
You rarely minimize bias and variance at once. Bigger models and longer training cut bias but can inflate variance unless you regularize, add data, or stop early.
Detect with curves, not vibes. Plot training loss/metric and validation loss/metric over epochs (or model complexity).
| Pattern | Train error | Val error | Diagnosis |
|---|---|---|---|
| Both high, gap small | High | High | Underfitting |
| Train low, val high, gap growing | Low | High | Overfitting |
| Both low, gap modest | Low | Low | Healthy fit |
A rising validation loss while training loss still falls is the classic overfit signal. In LLMs and classifiers, watch validation perplexity or F1 the same way.
Capacity knobs. More parameters, deeper trees, higher polynomial degree, longer fine-tuning → more capacity → lower bias risk, higher overfit risk. Less capacity or stronger constraints → opposite.
What helps.
Bias–variance is a lens, not a single number you compute daily. In deep learning the picture is richer: double descent can show test error rising then falling again as models grow past the interpolation threshold, and large models sometimes fit train data near-perfectly yet still generalize (benign overfitting). Those phenomena refine the classical U-shaped curve; they do not retire the practical checklist. Still compare train vs held-out metrics, still react when the gap balloons on your task and data regime, and still prefer a locked evaluation set when you claim a win.
Fit polynomials of increasing degree to a noisy sine wave. Low degree underfits; high degree overfits the noise.
import numpy as np
rng = np.random.default_rng(0)
n = 30
x = np.linspace(0, 1, n)
y_true = np.sin(2 * np.pi * x)
y = y_true + 0.3 * rng.normal(size=n)
# Hold out last 8 points as "validation"
x_train, y_train = x[:22], y[:22]
x_val, y_val = x[22:], y[22:]
def mse(y_hat, y):
return float(np.mean((y_hat - y) ** 2))
print(f"{'degree':>6} {'train MSE':>10} {'val MSE':>10}")
for degree in [1, 3, 9, 15]:
# Vandermonde design matrix
Phi_tr = np.vander(x_train, N=degree + 1, increasing=True)
Phi_va = np.vander(x_val, N=degree + 1, increasing=True)
# Least squares
coef, *_ = np.linalg.lstsq(Phi_tr, y_train, rcond=None)
tr = mse(Phi_tr @ coef, y_train)
va = mse(Phi_va @ coef, y_val)
print(f"{degree:6d} {tr:10.4f} {va:10.4f}")
Expect degree 1: both MSEs mediocre (underfit). Mid degrees: both improve. Very high degree: train MSE near zero while validation MSE blows up (overfit). That gap is the lesson.
Underfitting is a model too simple for the pattern (high bias); overfitting is a model that memorizes training quirks (high variance) — watch the train/validation gap and aim for the capacity sweet spot.