Skip to content
Machine Learning
Regression 9 min read

Regularization: Ridge, Lasso & ElasticNet

Tame exploding coefficients with L1 and L2 penalties — shrink weights with Ridge, select features with Lasso, and blend both with ElasticNet.

Download notebook Open Google ColabIn Colab: File → Upload notebook → pick the downloaded file.

You've seen that flexible models overfit, and that one cure is "regularize." This lesson delivers on that promise. Regularization adds a penalty for large weights to the loss function, so the optimizer must balance fitting the data against keeping the model tame. It's the practical answer to a real dilemma: you rarely know the right polynomial degree or feature set in advance — so use a generous model and let the penalty rein it in.

The symptom: exploding coefficients

When features are strongly correlated (or plentiful and noisy), ordinary least squares becomes unstable. If two columns carry nearly the same information, the model can put a huge positive weight on one and a huge negative weight on the other — the two nearly cancel, training error looks fine, and the coefficients are meaningless and fragile:

Python — runs in your browser

Both models fit equally well — but OLS invented enormous, opposite-signed weights (rerun mentally with a different noise seed and they'd be completely different), while Ridge quietly spread a sensible total of ~3 across the three near-identical columns. That stability is what the penalty buys.

How the penalty works

Regularized regression minimizes loss = MSE + α · penalty(w), and the two classic penalties differ in one exponent:

  • L2 (Ridge): penalty = Σ wᵢ² — the squared sizes. Big weights are punished quadratically, so Ridge shrinks all weights smoothly toward zero but almost never exactly to zero.
  • L1 (Lasso): penalty = Σ |wᵢ| — the absolute sizes. The pressure on a weight doesn't fade as it approaches zero, so Lasso pushes unhelpful weights exactly to zero — it sparsifies.

The mnemonic from the source course: L2 for simplicity (smooth, stable, keeps everything a little), L1 for feature selection (keeps a few, kills the rest). The bias term b is not penalized — only the weights.

Scale before you regularize

The penalty compares raw coefficient sizes. An unscaled feature measured in tiny units needs a huge coefficient just to participate — and gets crushed by the penalty for reasons that have nothing to do with usefulness. Always put a scaler before Ridge/Lasso/ElasticNet in your pipeline. (This is why the previous lesson came first.)

Alpha: the strength dial

alpha sets how loudly the penalty speaks. At α = 0 you recover plain OLS; as α grows toward infinity every weight is forced to zero (predicting only the mean). Tracing each coefficient as α grows produces the coefficient path — and it makes the L1/L2 difference visible:

Python — runs in your browser

Read the difference: Ridge coefficients glide smoothly toward zero together but stay alive until enormous α. Lasso coefficients hit exactly zero one by one — by moderate α only a handful of features survive. Reading which features survive longest is a legitimate (and popular) form of feature selection: fit Lasso, keep the features with non-zero coefficients.

Choose α the same way you chose polynomial degree: cross-validation. Small α = complex model (variance risk); large α = rigid model (bias risk) — it's the same U-curve, just with the dial reversed.

ElasticNet: why not both?

Lasso has quirks: with a group of correlated features it tends to pick one arbitrarily and zero the rest, and it can behave erratically when features outnumber samples. ElasticNet blends both penalties:

loss = MSE + α · ( l1_ratio · Σ|wᵢ| + (1 − l1_ratio) · Σwᵢ² / 2 )

l1_ratio slides from 0 (pure Ridge) to 1 (pure Lasso). Values in between give you sparsity and the stabilizing, group-friendly behavior of L2 — a sensible default when you suspect correlated features but still want selection.

from sklearn.linear_model import Ridge, Lasso, ElasticNet
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
 
# The pattern for all three — generous features, then a penalty:
model = Pipeline([
    ("scaler", StandardScaler()),
    ("poly", PolynomialFeatures(10, include_bias=False)),
    ("reg", ElasticNet(alpha=0.01, l1_ratio=0.5)),   # or Ridge(0.01) / Lasso(0.01)
])

Spotting multicollinearity before it bites

The exploding-coefficient problem has a name — multicollinearity — and a cheap early-warning system: the correlation matrix. Compute pairwise correlations between features (and the target) and look for near-±1 blocks:

Python — runs in your browser

The bright cell between s1 and s2 (two blood-serum measurements, correlation ≈ 0.9) is exactly the situation from our first demo: OLS coefficients for those two are untrustworthy, and regularization is the standard remedy. (Pearson measures linear relationships; Spearman and Kendall rank-based variants catch monotonic ones — df.corr(method="spearman").)

Rules of thumb

  • Default: Ridge with cross-validated α. Stable, smooth, rarely a bad idea.
  • Many features, suspect most are useless: Lasso — get a sparse, interpretable model for free.
  • Correlated feature groups + want sparsity: ElasticNet (tune l1_ratio ∈ 0.1–0.9).
  • Good feature engineering still beats brute-force regularization — a well-chosen degree-3 model can outscore a regularized degree-10 one. But when you don't know the right features, regularization is the practical path.
  • And always: scaler first, penalty second, α by cross-validation.

Check your understanding

5 questions · free
  1. Q1.Two features are near-duplicates of each other. Why does plain OLS often assign them huge opposite-signed coefficients?

  2. Q2.You want a model that automatically discards useless features by setting their weights to exactly zero. Which penalty?

  3. Q3.What happens as alpha grows toward infinity in Ridge regression?

  4. Q4.Why must features be scaled before applying Lasso or Ridge?

  5. Q5.ElasticNet with l1_ratio = 0 is equivalent to…

Exercise: Tune an ElasticNet end to end

Recreate this module's original capstone exercise on an offline dataset: load load_diabetes, split 75/25, and build a Pipeline of StandardScalerPolynomialFeatures(2)ElasticNet. Use GridSearchCV (cv=5) to tune alpha over 0.01–10 and l1_ratio over 0.1, 0.5, 0.9. Report the best parameters, cross-validated R², and test R² — and count how many of the polynomial features ElasticNet zeroed out.

That wraps up regression — next module, we switch from predicting numbers to predicting categories: classification, starting with logistic regression.