我读研究生那会儿第一次接触 LASSO 回归,是在处理一个高维生物信息数据集的作业里。当时特征数量接近三千个,样本量只有一百出头,用普通线性回归一跑,训练集 R² 接近 1,测试集直接负数。导师看了一眼结果就说了句:你想办法把那些没用的特征砍掉,但不能手动一个一个删。那是我第一次意识到,模型不仅要会拟合,还得会做减法。后来我系统过了一遍 LASSO 回归的原理和代码实现,才彻底理解它为什么能自动把无关特征的系数压成零,也才明白它和岭回归的本质差别到底在哪。
这篇笔记是《Python 应用机器学习:代码实战指南》系列的第 21 篇,不绕弯子,直接讲清楚 LASSO 回归从数学原理到 Python 实战的完整链路。内容包括:它到底解决了什么问题、为什么 L1 惩罚项会产生稀疏解、坐标下降的核心思想是怎么落到代码里的、alpha 这个超参数该怎么调、以及在真实项目里你会踩到哪些文档里根本没写明白的坑。无论你是正在复习机器学习期末考的学生,还是工作上第一次碰到高维数据的工程师,这篇都能给你省下不少查资料的时间。
1. 从线性回归的两个老大难问题说起
1.1 高维数据下为什么普通线性回归会失效
先回到全宇宙最简单的线性回归。假设我们有 n 个样本,每个样本有 p 个特征,模型长这样:
$$y = X\beta + \epsilon$$
普通最小二乘(OLS)做的事情就是最小化残差平方和:
$$\hat{\beta}{OLS} = \arg\min{\beta} \sum_{i=1}^n (y_i - x_i^T\beta)^2$$
它的闭式解高中数学竞赛都推过:
$$\hat{\beta} = (X^T X)^{-1}X^T y$$
问题就藏在这个公式里。想让 $(X^T X)$ 可逆,数据必须满足几个条件:特征之间不能高度相关(没有多重共线性)、样本量大于特征数($n > p$)、特征没有完全线性相关。
但现实项目里没这么理想。比如你做用户行为分析,后台埋点几百个事件,每个事件还要拆成近期频率、历史次数、最近一周是否有行为这样的衍生特征,轻轻松松破千维。再比如文本分类任务,用 TF-IDF 向量化之后,特征维度动辄几万。这时候 $p \gg n$,$X^T X$ 不满秩,是奇异矩阵,逆矩阵不存在,OLS 解直接算不出来。就算勉强用伪逆求出一个解,那个解的范数也大得离谱,对数据里的微小扰动极其敏感——你今天训练完的模型,明天换一批数据就崩了。
这个问题的本质是:信息量不够,却要估计太多参数。就好比你只有一个模糊的目击者描述,却要警察画出十个嫌疑人的全脸画像,这根本是欠定问题。数学上有一万种 $\beta$ 能让训练集误差为零,但没一种是真正学到了数据背后的规律。
1.2 理解偏差-方差困境和过拟合的关系
要透彻理解 LASSO 为什么有必要存在,得先把“偏差-方差分解”这个概念翻出来说清楚。
一个模型的期望预测误差可以拆成三部分:噪声(irreducible error)、偏差的平方(bias²)、方差(variance)。噪声是数据本身自带的、任何模型都消除不掉的随机波动。偏差是模型预测的期望与真实值的系统性偏离,说白了就是模型太简单、没学够。方差是模型对不同训练集的敏感程度,换一批数据结果就大变天。
普通线性回归在高维场景下的问题是:参数自由度太高,模型有充分的能力把训练数据里的每一个点都摸得透透的。这会导致训练误差逼近零,但方差被拉满到极致。模型过度适应了训练集里的噪声和异常值,把这些跟真实规律无关的细节也当成规律学进去了,这就是过拟合。
一句话总结:过拟合的本质不是模型“太努力”,而是模型自由度过高、在信息不足的数据上过度反应。正则化的思想根源,就是主动给模型的自由度戴上枷锁,牺牲一点点偏差,换取方差的大幅下降。LASSO 就是这个思路最经典的代表之一。
1.3 LASSO、岭回归和弹性网到底差在哪
LASSO 的完整名字是 Least Absolute Shrinkage and Selection Operator,直译是“最小绝对收缩和选择算子”。它的目标函数是:
$$\hat{\beta}{lasso} = \arg\min{\beta} \left{ \sum_{i=1}^n (y_i - x_i^T\beta)^2 + \lambda \sum_{j=1}^p |\beta_j| \right}$$
后面多出来的是 L1 惩罚项,也就是 $\beta$ 各个分量绝对值之和乘以正则化系数 $\lambda$。Ridge 回归用的是 L2 惩罚项:$\lambda \sum \beta_j^2$。
很多教材把两者的区别描述成“L1 会让系数变成零,L2 只会让系数变小”。这个说法是对的,但要讲得再深一点:因为它俩对应的惩罚项在参数空间的几何形状不同,导致最优解落在什么地方的行为不一样。
L2 惩罚项在二维平面上是一个以原点为中心的圆形。带约束的优化问题可以拉格朗日化,等价于在“$\beta_1^2 + \beta_2^2 \le t$”的圆形区域内找使残差平方和最小的点。椭圆等值线和圆的切点通常不会恰好落在坐标轴上,因为圆的边界处导数不为零,不太容易恰好让某个坐标卡死为零。所以 Ridge 的结果是:所有系数都被压缩到一个比较小的数值,但很少有系数会严格等于 0。
L1 惩罚项在二维平面上的约束区域是一个顶点在坐标轴上的菱形。菱形有尖角,这些角就落在轴上——也就是 $\beta_1 = 0$ 或 $\beta_2 = 0$ 的位置。椭圆等值线和菱形相交时,最优解落在顶点上的概率非常大。一旦落在顶点上,另一个维度的系数就已经被压成零了。高维情况下,这个特性放大得非常明显:L1 惩罚会把一大批无关特征的系数精确地变成 0,只留下一小部分“真正有用”的特征。
Elastic Net(弹性网)则是把 L1 和 L2 按比例混合:
$$\hat{\beta}{enet} = \arg\min{\beta} \left{ \sum_{i=1}^n (y_i - x_i^T\beta)^2 + \lambda_1 \sum_{j=1}^p |\beta_j| + \lambda_2 \sum_{j=1}^p \beta_j^2 \right}$$
为什么要混着来?因为 LASSO 有两个不完美的地方:一是当特征之间存在强相关时,它倾向于只随机挑其中一个,而不是把一组相关特征都保留下来;二是当 $p > n$ 的时候,它最多只能选出 $n$ 个非零特征。弹性网加了个 L2 项进去,能让高度相关的特征组以“组”的形式被选中或剔除,实际效果在很多场景下比纯 LASSO 更稳。如果你的特征里有明显的分组结构(比如几个 one-hot 编码出来的变量其实来自同一个类别变量),弹性网是比 LASSO 更好的起点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 把数学原理说人话:L1 惩罚、软阈值与坐标下降
2.1 KKT 条件与稀疏性的来源
只停留在几何直觉还不够,面试或者期末考试很可能会问到这一步:为什么 L1 规范会产生精确的零解?
回到带约束形式的拉格朗日对偶视角,LASSO 等价于在球形约束域内做最小化,它的 KKT(Karush-Kuhn-Tucker)条件可以写成:最优解 $\hat{\beta}$ 满足,对于每一个分量 $j$,存在次梯度条件(因为 $|\beta_j|$ 在零处不可导,要引入次梯度的概念):
$$\frac{\partial RSS}{\partial \beta_j} + \lambda \cdot s_j = 0$$
其中 $s_j$ 是 $|\beta_j|$ 在 $\hat{\beta}_j$ 处的次梯度。当 $\hat{\beta}_j > 0
