Machine learningLoading progress…

L1 and feature selection

Compare model flexibility, regularization and validation procedures without using the test set for tuning.

Absolute values instead of squares

The L1 penalty adds the absolute sizes of the weights instead of their squares: J(w) = MSE(w) + lambda * (|w1| + |w2| + ...). This is the lasso. It looks like a small change and behaves very differently: it can set weights exactly to 0. A weight of exactly 0 means the feature is not used, so the lasso doubles as feature selection. For w = [2, -1] the L1 norm is 2 + 1 = 3 (the squared L2 norm is 5), so the L1 objective with lambda 0.2 and MSE 0.1 is 0.1 + 0.2 · 3 = 0.7.

MSE (fixed for this demo)0.1
squared L2 norm, w1² + w2²5
L1 norm, |w1| + |w2|3
L2 objective, MSE + lambda · squared L21.1
L1 objective, MSE + lambda · L10.7

With w = [2, -1] and lambda = 0.2 the L2 objective is 0.1 + 0.2 · 5 = 1.1 and the L1 objective is 0.1 + 0.2 · 3 = 0.7. They are different objectives, not two scores of one model to compare.

The same arithmetic as before; drag the weights and compare the two objectives.

Diamonds have corners

Here is the geometric reason. Instead of adding a penalty, think of limiting the weights to a budget: the L1 budget |w1| + |w2| ≤ t is a diamond, the L2 budget w1² + w2² ≤ t² is a disc. The orange ovals are lines of equal loss around the best unconstrained weights; the answer is where an oval first touches the blue region. A disc is smooth, so the touch point is a typical spot on its rim. A diamond has sharp corners that sit exactly on the axes, and ovals often hit a corner first, which gives a weight of exactly 0.

L1 (lasso): |w1| + |w2| ≤ t

-202-202unconstrained best

solution w = (1, 0) exact zero

L2 (ridge): w1² + w2² ≤ t²

-202-202unconstrained best

solution w = (0.906, 0.423)

The orange ovals are lines of equal loss around the unconstrained best point. The answer is the first point of the blue region that an expanding oval touches. A circle has no corners, so the touch point is almost never on an axis. A diamond has corners on the axes, and a tilted oval often reaches a corner first.

Move the unconstrained best point and the budget. In the diamond picture a green dot means a weight landed on an axis. The default setting is one where it does.

Not every setting gives a zero. Move the best point close to the diagonal, or raise the budget until the best point is allowed, and the L1 answer leaves the corner. It is a tendency that grows with the strength of the penalty, not a guarantee.

The soft-threshold rule

With the data scaled, the L1 problem can be solved one weight at a time. For a single weight the answer is the soft threshold: take the plain least squares value z, move it towards 0 by lambda, and stop at 0 if you would cross it:

lambda = 1
z =   -3  ->  -2
z =   -2  ->  -1
z =   -1  ->  0
z = -0.5  ->  0
z =  0.5  ->  0
z =    1  ->  0
z =    2  ->  1
z =    3  ->  2

Everything with |z| up to lambda becomes exactly 0, and the rest is shrunk by exactly lambda. Ridge instead divides: z becomes z / (1 + lambda) for an orthogonal, scaled problem, which is never exactly 0. Cycling through the weights and applying this rule repeatedly (coordinate descent) solves the full lasso, as you will code in practice.

Paths: L1 against L2

Lasso (L1): paths hit exact zero

-3-2-10-1012strength (log10 of lambda / lambda max)

Ridge (L2): paths only approach zero

-3-2-10-1012strength (log10 of lambda / lambda max)
featurex1x2x3x4x5x6x7x8non-zerovalidation error
lasso0.791.061.2-0.78-0.07-0.06-0.10.0281.112
ridge0.880.981.24-0.79-0.17-0.13-0.170.1281.147

x1 and x2 are near copies (correlation about 0.95) and both feed y; x3 and x4 also matter; x5 to x8 are pure noise (dashed). Lowest lasso validation error on this grid: strength 10^-1.5, error 1.112.

Eight features: x1 and x2 are near copies, x3 and x4 matter too, x5 to x8 are noise (dashed). Left: lasso. Right: ridge. Raise the strength and watch the table: the lasso weights turn into exact zeros, the ridge weights never do.

On this sample, once the strength reaches lambda max (the largest correlation between a feature and y, 1.948 here) every lasso weight is exactly 0; just below it the first feature enters. As the strength falls, features join one by one, and the noise features enter last. Ridge at the same strengths keeps all eight weights non-zero.

Predict first. Two features are near copies of each other and both help predict y. What does the lasso tend to do?

Chapter context

A model should capture reusable structure without chasing accidental patterns in the training sample. Model selection compares this tradeoff using validation data that resembles future use.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

A possible objective is

J(w)=MSE⁡(w)+λ∑jwj2.J(w)=\operatorname{MSE}(w)+\lambda\sum_jw_j^2.

For L1 replace the squared-weight sum by ∑j∣wj∣\sum_j|w_j|. Here lambda is nonnegative and the bias convention must be specified. Different libraries normalize objectives differently.

Worked example

If MSE=0.1, w=[2,−1] and lambda=0.2, the stated L2 objective is 0.1+0.2×5=1.1. The corresponding L1 objective is 0.1+0.2×3=0.7. These values come from different objectives and should not be compared as if they were the same validation metric.

Reference code

The following example uses the Python standard library and does not call a remote service.

from math import isclose
w, mse, penalty = [2,-1], .1, .2
assert isclose(mse + penalty*sum(x*x for x in w), 1.1)
assert isclose(mse + penalty*sum(abs(x) for x in w), .7)
assert isclose(sum([.7,.8,.9])/3, .8)

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

Cross-validation does not repair leakage introduced before folding. More regularization can increase bias. A chosen validation result is not an unbiased final test result.