1. 从最小二乘说起:线性回归为什么需要正则化
1.1 线性回归的损失函数与参数求解
线性回归、岭回归和LASSO回归,这三个模型放到一起,几乎就是入门机器学习第一道分水岭。很多人线性回归学得很顺,一到岭回归和LASSO就开始犯迷糊:好好的最小二乘为什么不用,非要加惩罚项?加了惩罚项之后,参数解出来的意义是不是就变了?这篇文章我就结合自己实际做项目的经历,把三个模型从头到尾捋一遍——从损失函数构造逻辑、正则化项的数学原理,到实际调参和选型的操作细节,一次性讲清楚。
线性回归的任务,本质上是找一组权重 w 和一个偏置 b,让预测值 ŷ = Xw + b 与真实值 y 之间的误差尽可能小。最经典的做法是最小二乘法,损失函数写成:
L(w) = Σ(y_i - ŷ_i)² = ||y - Xw||²
这个形式看起来简单,但它背后有一个重要假设:误差服从正态分布,且各样本独立同分布。对损失函数求导并令导数为零,可以直接得到闭式解:
w = (XᵀX)⁻¹Xᵀy
这个解在教科书里写得漂漂亮亮,但实际项目里你会遇到几个很现实的问题。第一,特征之间高度相关时,XᵀX 可能接近奇异矩阵,求逆结果极不稳定,参数估计值方差大到离谱。第二,特征维度很多时,模型会把训练数据里的噪声也当成规律学进去,造成严重过拟合。我刚做项目时踩过一个典型的坑,当时建模用了几十个原始特征,训练集上 R² 高到 0.98,换一批数据直接掉到 0.6,这种“训练漂亮、上线惨”的症状,几乎都是过拟合。
注意:线性回归的闭式解不是任何时候都能直接用的。特征数量超过样本数量时,XᵀX 不可逆,闭式解直接失效,这也是后面引入正则化的现实原因之一。
1.2 过拟合的实质:最小二乘的方差为什么失控
要理解正则化,先得理解过拟合是怎么来的。模型复杂度高,等价于模型参数的自由度大,而自由度大的模型,对训练样本中的每一点抖动都很敏感。最小二乘的目标就是纯粹拟合训练误差,它不会管参数值大小,结果就是权重可以变得非常大,正负穿插,试图精确“描”出每一个训练样本点。
这里可以用一个直观类比:你请了一个记忆力超强的学生,他考试前把练习题答案逐字背下来,题目稍微换个数字他就不会了。最小二乘就是这个“死记硬背”的学生。岭回归和 LASSO 要做的,就是给这个学生定规矩:你可以记,但不能毫无节制地记,对每个知识点(参数)都要付出一定“代价”。
于是“正则化惩罚项”就登场了。它的本质是在原始损失函数后面加一项,用参数大小来约束模型复杂度。参数太大,即使训练误差很小,整体损失也会变大,这样优化过程就会自动在“拟合得更好”和“参数更小”之间找平衡点。至于这个惩罚项是用 L1 范数还是 L2 范数,就衍生出了岭回归和 LASSO 两条完全不同的技术路线。
2. 岭回归:L2 正则化如何稳住参数估计
2.1 岭回归的损失函数与闭式解
岭回归的损失函数写成:
L_ridge(w) = ||y - Xw||² + λ||w||²
后面加的是 L2 范数的平方,λ 是正则化强度,也可以叫岭参数。对 w 求导并令其为零,解变成:
w_ridge = (XᵀX + λI)⁻¹Xᵀy
XᵀX 加上 λI 之后,原来可能接近奇异甚至不可逆的矩阵,变成了严格正定矩阵,求逆问题被稳稳地解决了。这就是“岭”这个名字的来源——在矩阵对角线上加了一条“山脊”,让它变得数值稳定。
从参数估计的角度看,L2 惩罚把权重整体往零的方向压缩,但它不会直接让某个权重变成绝对的零。什么意思呢?如果原始最小二乘解是 w=3,加上岭惩罚之后,解可能是 2.7,但它还是一个非零的数。每个特征对预测仍然有微小贡献,只是整体幅度被压住了。这就决定了岭回归擅长处理“特征都多少有用、且相关性较强”的场景。
实操心得:我刚开始用岭回归时,最大的误解是以为它能做特征选择。它其实做的是特征“压缩”,不是“删除”。你想让模型自动挑出几个最重要的特征,岭回归做不到,得交给 LASSO。
2.2 岭参数 λ 的调参逻辑与交叉验证
λ 的大小直接决定惩罚力度。λ=0 时,岭回归退化成普通最小二乘;λ 趋向无穷大时,所有权重都被压向 0,模型退化成一条水平线,只保留偏置。实际操作中,λ 的选择几乎都是用交叉验证完成的,常见做法是:
- 将训练集分成 K 折(我一般用 5 折或 10 折)
- 在一组对数均匀分布的候选 λ 上依次训练
- 记录每一折的验证误差,取平均值
- 选择平均验证误差最小的 λ
这里有个细节容易被忽略:λ 的取值范围最好用对数刻度,比如 10⁻⁴ 到 10⁴,而不是线性从 0.001 到 1 均匀取数。因为正则化对 λ 的响应在数量级层面变化,线性取值会浪费大量计算在几乎没区别的区间。
选择最小验证误差对应的 λ 时,我习惯再加一个“邻近选择”原则。最小误差对应的 λ 往往偏小,模型复杂度偏高,泛化风险仍在。我会在误差-λ 曲线比较平坦的区域里,选一个稍微大一点的 λ,让模型参数压缩得更多一些,换取更好的稳定性。代价是验证误差可能上升一点点,但换来的是实打实的泛化能力提升。
3. LASSO 回归:L1 惩罚带来的稀疏解与特征选择
3.1 LASSO 的损失函数与几何直觉
LASSO(Least Absolute Shrinkage and Selection Operator)的损失函数是:
L_lasso(w) = ||y - Xw||² + λ||w||₁
这里的 ||w||₁ 是绝对值和。与 L2 惩罚不同,L1 惩罚有一个非常独特的性质:在最优解处,部分参数会被精确压缩到 0。这意味着 LASSO 天然能做特征选择,保留下来的特征就是模型认为真正有用的变量。
为什么 L1 能让参数归零而 L2 不能?画个二维参数空间图就明白了。L2 约束是一个圆,目标函数等高线与圆周相切的位置,基本不会落在坐标轴上;L1 约束是一个菱形,菱形的角尖就长在坐标轴上,等高线一碰到角尖,对应的参数就是 0。维度越高,这种稀疏效应越明显。
从另一种角度看,稀疏解等价于模型在诸多特征里做了一次“硬决策”——有些特征直接不要了。这在特征维度几千上万的项目里特别有价值,特征少了,模型解释性变强,部署时的存储和计算成本也降下来了。我当时做一个信息筛选类的模型,几百个候选特征里最后 LASSO 只保留了二十几个,解释业务时省了太多力气。
3.2 坐标下降法与正则化路径
LASSO 的损失函数虽然在 0 点不可导,没法直接用梯度下降处理所有位置,但有一个非常高效的标准算法叫坐标下降法。它的思路是:固定其他所有参数,只优化当前这个参数,然后逐个循环,直到收敛。因为每一步的优化都有解析解,实际运行速度非常快。
坐标下降的推导中有个软阈值操作:
w_j = S(z_j, λα_j)
其中 S 是软阈值函数,它做的事情很简单:当 z_j 的绝对值小于阈值 λα 时,直接把 w_j 置为 0;否则把 z_j 往零的方向缩一段距离。这个“要么归零、要么收缩”的行为,正是 LASSO 稀疏解的直接来源。
实操中我一般不手写坐标下降,直接用现成库里的实现,但理解它仍然有价值。你可以通过调节 λ 得到一条正则化路径,观察每个特征系数在 λ 从小到大过程中的变化轨迹。特征系数从非零变成零的那个 λ 值,可以作为判断特征重要性的参考依据。这个可视化在业务汇报中特别加分,比直接甩一个最终特征列表好理解得多。
4. 三种模型怎么选:从数据特征到业务场景
4.1 模型对比与适用场景
先放一张我在项目里经常用来给团队讲清楚的三模型对照表:
| 模型 | 惩罚项 | 能否特征选择 | 适合场景 | 参数解释性 |
|---|---|---|---|---|
| 线性回归 | 无 | 否 | 特征少、样本充足、无明显共线性 | 最直观 |
| 岭回归 | L2 | 否(只压缩) | 特征相关性强、维度中等、所有特征都可能有用 | 尚可,权重被压缩需说明 |
| LASSO | L1 | 是 | 特征维度高、存在大量冗余特征、需要模型可解释 | 稀疏后解释性强 |
选择逻辑上,我的经验是先用一个快速基线判断。特征数量远小于样本量、共线性不严重、模型不加正则化也能稳定,用普通线性回归甚至更好,参数直接就是业务分析里需要的“边际效应”。但大多数真实数据没这么干净,特征一多,正则化基本就是默认项。
如果特征是业务逻辑确认过都有效的,比如价格、促销、库存这些核心变量,你不能把任何一个剔除掉,那岭回归是稳妥的。如果特征里有大量噪音、候选特征成千上万,你需要一个自动筛选机制,那就用 LASSO。当特征数量特别大或者共线性非常明显时,很多人会选择 ElasticNet——它是 L1 和 L2 惩罚的线性组合,兼顾稀疏性和稳定性。这个正文里不展开,但它在实际工业项目中非常常见。
4.2 评估指标与模型对比的完整流程
三种模型不能只看训练集误差来对比,评估流程必须统一。我在项目中一般这样做:
- 先把数据拆成训练集、验证集和测试集,三者比例大致 7:2:1
- 训练集上做交叉验证,确定每个模型各自的 λ
- 在所有模型都确定 λ 后,在测试集上统一计算 RMSE、MAE、R²
- 如果需要解释模型,还要额外看稀疏度、特征保留情况、系数符号是否符合业务常识
这里尤其要提醒一个经验:不同模型的 RMSE 差异如果小于 5%,我会倾向于选择解释性更好的那个,而不是数值上略优的那个。因为回归模型在工业项目里往往不只做预测,还要给业务同事讲清楚“哪些因素在起作用、方向是什么、影响有多大”。LASSO 能给出一个简洁的特征集合,很多时候比那 5% 的精度提升更有价值。
注意:不要用同一个固化的数据预处理流程去套所有模型。比如对是否标准化,三种模型的态度是不同的。线性回归对特征尺度敏感,但不是由于数学上不能算,而是由于系数的可解释性;岭回归和 LASSO 由于惩罚项直接作用在系数上,特征不标准化会造成不公平的压缩。这个细节直接影响选型结果。
5. 实操流程:从数据预处理到调参落地的完整记录
5.1 数据清洗与标准化
我常用一个任务来演示三种模型的完整实操。任务背景是预测某地区房屋价格,原始数据有 20 个特征,包含面积、房龄、周边配套评分、交通便利指数等,还掺杂着一些噪声特征,比如房源编号、录入员代号这种理论上有唯一性的变量。这种数据是典型的需要正则化处理的场景:维度不算特别多,但噪声特征和相关性都有一点。
预处理顺序上,我习惯按“清洗 → 编码 → 标准化 → 切分”来走。清洗阶段要处理缺失值和异常值,尤其是房龄这种明显违背常识的数值,比如出现负值或者 300 年以上,这种记录直接删除或按边界值替换。编码阶段处理类别变量,比如朝向、装修档次,转为 one-hot。标准化阶段特别关键,因为岭回归和 LASSO 的惩罚项对每个特征系数都敏感,如果面积以“平方米”为单位、交通指数以“分”为单位,数值范围差几个数量级,λ 对它们的作用就会失衡。
具体标准化我会用 sklearn 的 StandardScaler,先 fit 训练集,再 transform 测试集。注意这里一定要用同一个 scaler 去处理测试集,绝不能在测试集上重新 fit,否则相当于把测试集的信息泄露给了训练过程。这是我看到很多新手反复犯的错。
5.2 三种模型的构建与调参
以 Python 生态为例,核心代码大致是这个框架:
from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.linear_model import LinearRegression, Ridge, Lasso import numpy as np X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42) scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_val_scaled = scaler.transform(X_val) # 线性回归 lr = LinearRegression() lr.fit(X_train_scaled, y_train) # 岭回归,用交叉验证选择 lambda ridge_params = {'alpha': np.logspace(-4, 4, 50)} ridge = GridSearchCV(Ridge(), ridge_params, cv=5, scoring='neg_mean_squared_error') ridge.fit(X_train_scaled, y_train) # LASSO lasso_params = {'alpha': np.logspace(-4, 2, 30)} lasso = GridSearchCV(Lasso(max_iter=10000), lasso_params, cv=5, scoring='neg_mean_squared_error') lasso.fit(X_train_scaled, y_train) # 统一在验证集上评估 from sklearn.metrics import mean_squared_error, r2_score for name, model in [('LinearRegression', lr), ('Ridge', ridge), ('Lasso', lasso)]: pred = model.predict(X_val_scaled) print(name, 'RMSE:', np.sqrt(mean_squared_error(y_val, pred)), 'R2:', r2_score(y_val, pred))代码非常简单,真正有讲究的是几个点。第一,LASSO 的 max_iter 需要设得大一点,默认 1000 在某些数据上可能还没收敛,直接导致结果不稳定。第二,岭回归的候选 alpha 范围不需要取到 10⁴ 那么高,因为 L2 惩罚对极端大值的响应太强,很容易把所有系数都压成接近 0。第三,GridSearchCV 的 scoring 参数要明确指定,千万别用默认的 R²,否则你选出来的参数跟用 RMSE 选的完全不是一回事。
调参跑完之后,我还会做一个稳定性确认:把随机种子换几个不同的值重新切分数据,看选出来的最优 α 是否在同一个数量级内。如果换一次切分最优 α 就跳跃两三个数量级,说明模型对数据划分极度敏感,这时我会回头检查数据本身的质量,而不是继续调参。这是个很多人没意识到的问题。
5.3 结果解读与特征重要性的视角
模型跑完,别急着写报告。拿到三个模型的系数之后,我会按这样一组步骤来解读:
- 看 LASSO 保留下来哪些非零系数,这些特征就是模型认为的“硬核”变量
- 对比岭回归中同一批特征的系数排序,验证方向和相对大小是否一致
- 把线性回归的系数也列出来,观察正负号是否与业务认知相符
如果岭回归和 LASSO 对某个特征的系数方向不一致,我会立刻标记为“需要人工核查”。这种不一致往往意味着特征本身有异常或者与其他特征存在强相关,导致系数符号翻转、稳定性变差,而不是模型错了。这种对比工作,价值远高于单纯比较 RMSE 数字。
对于特征重要性,LASSO 的系数绝对值可以当成初步排序依据,但不要把它当成严格重要性度量。原因在于 L1 惩罚会系统性地缩小系数,而且特征共线时谁被保留、谁被剔除存在随机性。想得到更可靠的重要性排序,我会再做一次基于置换的特征重要性评估,或者用交叉验证中不同折里 LASSO 保留特征的频次来判断。
6. 常见问题与排查技巧实录
6.1 特征尺度不一致导致正则化失衡
症状:加了 L1/L2 惩罚之后,模型表现还不如不加,或者某些大数值特征被强制压成 0 但业务上它们明明很重要。
原因几乎都是没做标准化。想象一下,房龄单位是“年”,数值通常 0 到 100;交通指数是 0 到 1 的浮点数,同时还有个“房源面积”是几十到几百平方米。L1 惩罚对参数绝对值加总,一个面积对应的系数只要稍微被压缩一点点,损失就变化巨大;而交通指数对应的系数缩到 0 的成本小得多,模型就会优先把标度小的特征砍掉,这不是特征本身不重要,而是量纲在捣乱。
解决方式很简单:对每个特征做标准化,让它们处在同一量级。标准化之后再做模型,系数的大小才真正反映特征对目标的贡献强度。这一条是所有正则化模型使用的前提,没有例外。
6.2 λ 选得过大导致欠拟合
症状:训练集误差明显高于普通线性回归,验证集误差也没有变好,模型输出近似于一条水平线。
原因很直接:λ 太大,所有系数都被压向 0 了。我见过有人直接用默认的 α=1 去跑 LASSO,结果特征全被删光,模型只剩一个 intercept。用交叉验证的目的就是避免这种情况,但交叉验证也不是无脑套用,候选 λ 的范围要覆盖到相对小的区域,比如从 0.001 起步,而不是一律从 1 起步。
排查时我会把正则化路径画出来,横轴是 log(λ),纵轴是系数值,一眼就能看到系数从非零到归零的临界点。如果最优 λ 恰好在临界点右侧很远,说明正则化过度;如果在临界点左侧太远,说明正则化几乎没有作用,模型接近最小二乘。合理值应该落在临界点附近偏右一点点的区域。
6.3 LASSO 在特征高度相关时的表现不稳定
症状:多次运行中,LASSO 保留的特征集合变化很大,这次留下 A 特征删掉 B,下次反过来。或者 A 和 B 明明高度相关,模型却只选其中一个,导致业务解释困难。
这是 LASSO 的固有缺陷。L1 惩罚在特征存在高度共线性时,会随机选择从一组强相关特征里挑一个,因为它对“选谁”的过程并不敏感——只要损失差不多,路径就会摇摆。对于这种情况,我通常有两种处理:一是先用相关性分析把强相关特征聚类,每组只保留一个代表特征,再进 LASSO;二是直接换 ElasticNet,用 L2 项稳定相关特征组的系数估计,再用 L1 项做稀疏化。
经验上,在典型业务数据里,特征之间几乎不可能完全独立,所以我现在做 LASSO 时从不只看一次结果,而是结合多次交叉验证的保留频次来下结论。一个特征如果在大多数折里都被保留了,我才认定它稳定重要。
6.4 对线性回归的一个常见误判:共线性不等于必须用正则化
很多人一看到特征相关性强,就无条件认为必须上岭回归。其实共线性的危害主要在参数估计方差的增大,但如果你的目标是做预测而不是解释参数,共线性对预测精度的影响没那么致命。样本量足够大时,普通线性回归的预测结果也可能完全可用,参数方差虽然大,但整体拟合效果照样稳定。
所以我的建议里有一条:先问业务目标。只做预测且特征不多,普通线性回归甚至更好,因为不用调 λ,模型简单直接。要做变量解释、梳理影响因子,再看共线性的严重程度决定要不要岭回归。这一点在面试交流中也常被问到,能分清楚“预测视角”和“解释视角”的差异,说明你对模型的理解已经不只是停留在公式层面。
最后分享一个个人项目里的体会。我最初上手这三个模型时,把大量时间花在调整代价函数的细节和比较验证误差数字上,后来才发现真正决定项目成败的两个前置问题:数据到底干不干净、业务上究竟需要预测还是解释。想清楚这两件事再选模型、调参数,事半功倍。
还有一个我后来固定下来的小习惯:把每一次跑出来的正则化路径图、系数对比表、验证误差曲线全都存档,哪怕当时觉得没用。项目周期一长,新需求来了要复用旧结论,这些存档就是最值钱的参考资料,比任何记忆都可靠。
如果你正要拿这三个模型做练习或上线,我的建议是别急着追求最优精度,先把每一个模型在一个简单数据集上完整跑通:线性回归打印系数、岭回归看不同 lambda 下系数收缩曲线、LASSO 观察特征从有到无的删除过程。把这三张图看明白了,你才算真正理解正则化到底在做什么。