Polynomial Regression & Overfitting
Bend a straight line into a curve with polynomial features, and meet the overfitting trap — plus how validation error tells you when to stop.
Linear regression draws straight lines, but the world is full of curves: diminishing returns, saturation effects, U-shaped costs. Polynomial regression lets the same linear machinery fit curves — and in doing so introduces machine learning's most important dial: model complexity. Turn it too low and the model can't learn; turn it too high and it memorizes noise. This lesson is where you learn to feel that trade-off in your hands.
When a line isn't enough
Play with the degree slider below. Watch both curves: at degree 1 the line misses the shape entirely, around degree 3–4 the fit hugs the data's true pattern, and at high degrees the curve contorts itself through every training point while the test error climbs back up.
Polynomial degree vs. overfitting
The curve is fit only on the filled train points. Past degree ~6 it starts memorizing noise: train error keeps dropping while test error explodes — the classic U-shape below.
That U-shaped test-error curve is the single most important picture in this module. Keep it in mind as we rebuild it in code.
The trick: manufacture new features
Polynomial regression doesn't change the algorithm — it changes the inputs.
Instead of feeding the model just x, we feed it x, x², x³, … and let
plain linear regression find a weight for each:
ŷ = w₁·x + w₂·x² + w₃·x³ + b
scikit-learn's PolynomialFeatures manufactures those columns, and a
Pipeline chains it with LinearRegression so the whole thing behaves like
one model:
Polynomial regression is still LINEAR regression
The model is nonlinear in x but linear in the weights — it's still a
weighted sum of (transformed) inputs, so the same closed-form solution,
gradient descent, and everything from the previous lesson apply unchanged.
"Linear model" refers to the weights, not the shape of the curve.
Degree is a complexity dial
Each extra degree gives the curve one more way to bend. A degree-1 model has two parameters; a degree-15 model has sixteen — enough to wiggle through nearly every training point. More flexibility always reduces training error, but past some point it stops modeling the signal and starts modeling the noise. That's overfitting, and you can only detect it by checking data the model never saw.
Train vs test: rebuilding the U-curve
Let's reproduce exactly what the playground showed you, in code. We fit every degree from 1 to 12 and track both errors:
The two curves tell the whole story:
- Training error only goes down. More degrees can never hurt the fit on data the model is allowed to see.
- Test error is a U. It falls while extra flexibility captures real structure, bottoms out, then rises as the model starts fitting noise.
- The gap between the curves is your overfitting meter — a small gap at the U's bottom, a chasm at high degrees.
Choosing the degree with validation
The rule is simple: pick the degree by performance on held-out data, never on training data — and among models with similar validation scores, prefer the simplest. In the source course's words: if degree 3 gives the best test score, use degree 3, not the flashier degree 10 that ties it.
One refinement: if you compare many degrees against the same test set, you slowly overfit to that test set too. The standard fix is cross-validation — split the training data into folds, average the score across them, and keep the test set untouched for a final honest estimate:
from sklearn.model_selection import cross_val_score
for d in range(1, 9):
model = Pipeline([
("poly", PolynomialFeatures(d, include_bias=False)),
("lr", LinearRegression()),
])
scores = cross_val_score(model, X_train, y_train, cv=5)
print(f"degree {d}: CV R2 = {scores.mean():.3f} +/- {scores.std():.3f}")You'll formalize this workflow (and automate it with grid search) later in the course; for now the principle is what matters.
High-degree polynomials get wild fast
Beyond the data's range, a high-degree polynomial shoots off to ±infinity —
extrapolation with degree 9 is fiction. And because x¹⁰ for x = 3 is
59,049, feature magnitudes explode, which is one more reason feature scaling
(two lessons ahead) matters.
Check your understanding
Q1.Why is polynomial regression still considered a linear model?
Q2.As you increase the polynomial degree, what always happens to training error?
Q3.Train MSE = 0.1, test MSE = 9.5. What's the diagnosis?
Q4.Degrees 3 and 10 achieve nearly identical validation scores. Which should you deploy?
Exercise: Find the best degree for a taxi-fare curve
Simulate a simplified taxi-fare problem (inspired by this module's original
NYC taxi exercise): generate 120 trips with distance uniform between 0.5 and
10 km, and fare = 3 + 2.5·distance − 0.12·distance² + noise (Gaussian,
σ = 1). Split 70/30 into train/test. For degrees 1 through 6, fit a
PolynomialFeatures + LinearRegression pipeline and print train and test
MSE. Which degree wins on the test set — and does the training error agree
with that choice?
You've now seen overfitting with your own eyes — next we give it a proper theory: the bias–variance tradeoff.