同一份数据加 ℓ2 罚项,λ 从 1e-6 到 1e3: 测试误差先降到 0.1832(λ 等于 1),再升到 11.4672(λ 等于 1000)。 同时条件数从 170 掉到 1.5,系数范数从 2.06 压到 0.56。 岭回归不做选择,它只做收缩——所有系数都变小,没有一个是零。
4.1 的约束是硬的:某些方向直接禁止。这节换成软的:所有方向都允许,但用罚项让大的变小。 好处是解变成连续的:λ 从 0 到无穷,解平滑地从最小二乘滑到全零。 代价是它永远不能让某个系数精确等于零——想要稀疏,得等第 5 章的 ℓ1。
一、从「不许去」到「少去一点」
ℓ2 约束的写法是:在最小二乘的目标后面加一项 λ 乘系数平方和。 λ 越大,系数越被压向零。 它有一个等价的几何说法:在「系数平方和不超过 R」这个球里找误差最小的点。 球的边界是光滑的,所以最优点一般落在球的内部或者切点上,坐标不会恰为零。 这就是它做不了稀疏的原因——第 5 章会把球换成菱形(ℓ1),棱角才会让坐标归零。 求导之后得到闭式解:θ 等于 (A 转置 A 加 λ 乘单位阵) 的逆乘 A 转置 y。 只比无约束版本多了一个 λI,代码里就是一行改动。 但它带来的性质变化很大:加了对角项,矩阵一定可逆,条件数一定下降。 「一定可逆」这一点常被忽略。 无约束解在 A 转置 A 奇异时有无穷多解,岭回归永远有唯一解。 所以它同时是「正则化」和「数值稳定化」两种工具。
二、λ 到底在做什么
把 A 做奇异值分解,岭回归的解可以写成:对每个方向,系数等于「无约束系数」乘一个收缩因子。 这个因子是 s 的平方除以 (s 的平方加 λ),s 是那个方向的奇异值。 看这个因子:奇异值远大于 λ 时,因子接近 1,几乎不收缩; 奇异值远小于 λ 时,因子接近 0,几乎压没。 所以 λ 事实上在按「数据在那个方向的把握程度」分级收缩。 这解释了 4.1 和 4.2 的关系:子空间约束是「前 k 个因子 1、其余 0」; 岭回归是「因子从 1 平滑降到 0」。 前者是阶梯,后者是斜坡。 也解释了为什么共线时岭回归特别有效:共线意味着某个方向的奇异值很小, 而那个方向的无约束系数往往极大。 收缩因子一乘,正好把它按下去。
三、实测:U 形与条件数
| λ | 训练 MSE | 测试 MSE | 系数范数 | 条件数 |
|---|---|---|---|---|
| 1e-06 | 0.1341 | 0.1931 | 2.06 | 1.7e+02 |
| 1e-01 | 0.1341 | 0.1918 | 2.05 | 1.7e+02 |
| 1 | 0.1361 | 0.1832 | 1.99 | 1.3e+02 |
| 10 | 0.2105 | 0.1981 | 1.72 | 4.2e+01 |
| 100 | 0.9802 | 0.9797 | 1.34 | 6.2e+00 |
| 1000 | 9.9899 | 11.4672 | 0.56 | 1.5e+00 |
| 最优在 λ 等于 1,测试 0.1832,比无约束的 0.1931 好 5 个百分点。 | ||||
| 提升不大,因为这份数据还不算病态:60 个点对 10 维,比例是 6 比 1。 | ||||
| λ 到 100 时训练误差从 0.1341 涨到 0.9802,翻了七倍。 | ||||
| 这就是偏差开始咬人的地方:系数被压得太小,模型连真值的形状都描不出来。 | ||||
| 系数范数那一列最直观:2.06、1.99、1.72、1.34、0.56。 | ||||
| 它一路降,没有跳变——这就是「收缩」这个词的来历。 | ||||
| 注意它永远不等于零。 | ||||
| λ 到 1000 时范数还有 0.56,每个系数都还在,只是都很小。 | ||||
| 如果你的目的是「挑出几个重要变量」,岭回归帮不了你。 |
四、什么时候必须用,什么时候没用
必须用的情况:特征数接近或超过样本数、特征之间高度相关。 这两条中任何一条成立,无约束解的方差都会大到不可用。 没用的情况:特征少、彼此正交、样本充足。 这时候 λ 的最优值会非常小,加了也没变化——Demo 里 1e-6 和 1e-1 的结果几乎一样。 所以「先看条件数,再决定要不要正则化」是个好习惯。 另一个常见误用:把 λ 当超参调到「训练误差最小」。 那会得到 λ 接近 0,等于没用。 λ 必须用交叉验证或者留出集选,这是下一节的内容。 还有一点:岭回归的系数不能直接拿来做解释。 它是有偏的,而且偏向「把所有系数按比例压小」,这个压缩比例依赖于特征的尺度。 所以用岭回归之前,必须先把特征标准化——否则量纲大的特征被压得更狠,这是纯粹的伪影。
五、动手 Demo:岭回归:λ 从 1e-6 到 1e3,测试误差先降到 0.183 再升到 11.467
同一份 60 点、10 维、高度相关的数据。 对每个 λ,解 (A 转置 A 加 λ 乘单位阵) 乘 θ 等于 A 转置 y,记录训练与测试均方误差、系数范数、 以及加了 λ 之后的条件数。
A = _XC.T @ _XC
b = _XC.T @ _Y
for lam in (1e-6, 1e-3, 1e-1, 1.0, 10.0, 100.0, 1000.0):
w = np.linalg.solve(A + lam * np.eye(D), b) # 只多了一个 λI
print(lam,
np.mean((_XC @ w - _Y) ** 2),
np.mean((_XTC @ w - _YT) ** 2),
np.linalg.norm(w),
np.linalg.cond(A + lam * np.eye(D)))
实跑输出:
--------------------------------------------------------------------
岭回归:λ 从 1e-6 到 1e3,测试误差先降到 0.183 再升到 11.467
--------------------------------------------------------------------
数据 60 个训练点,10 维,各列共享一个大公共因子
真值系数范数 1.94
无约束解 测试 0.1931,系数范数 2.06
条件数 不加 λ 时 1.7e+02,λ 等于 100 时 6.2e+00
λ 训练 MSE 测试 MSE 系数范数 条件数
-----------------------------------------------
1e-06 0.1341 0.1931 2.06 1.7e+02
1e-03 0.1341 0.1931 2.06 1.7e+02
1e-01 0.1341 0.1918 2.05 1.7e+02
1e+00 0.1361 0.1832 1.99 1.3e+02
1e+01 0.2105 0.1981 1.72 4.2e+01
1e+02 0.9802 0.9797 1.34 6.2e+00
1e+03 9.9899 11.4672 0.56 1.5e+00
**无约束解:测试 0.1931,系数范数 2.06,真值只有 1.94。**
**范数只大了 6 个百分点,但请注意它是 10 个分量凑出来的:**
**真值只有 2 个非零分量,解出来的 10 个分量全都不是零,靠互相抵消凑出同一个预测。**
**所以每个系数单独拿出来都不可信,而预测值还算对——这正是共线的代价。**
**加 λ 之后两件事同时发生:条件数从 1.7e+02 掉到 6.2e+00,系数范数从 2.06 压到 1.34。**
**条件数掉下来意味着求解稳定,系数被压小意味着方差小。**
**代价是偏差:λ 到 1e+03 时训练误差已经从 0.1341 升到 9.9899。**
**最优在 λ 等于 1e+00,测试 0.1832——比无约束解的 0.1931 好一点点。**
**只好了这么一点,是因为这份数据本来就不算病态:60 个点对 10 维。**
**如果样本再少一半,无约束解会更糟,岭回归的优势会明显得多。**
**第 4.2 节的全部内容就是这个 U 形:岭回归不做选择,它只做收缩。**
要说明:**λ 是我在测试集上挑的,真实项目里不允许**,该用交叉验证(下一节 Demo 12 会演示这件事)。
solve 而不是 inv 再乘。
虽然 A 加 λI 一定可逆,但显式求逆会把条件数平方,多丢一倍有效数字。
这类细节在 λ 很小时尤其要紧。
条件数那一列是本 Demo 最值得看的东西。
它从 1.7e+02 一路掉到 1.5,说明「加 λ」这个动作同时在做两件事:稳定求解、降低方差。
很多教材把它们当两件事讲,其实是一件事的两个说法。
系数范数从 2.06 压到 0.56,而真值是 1.94。
所以最优 λ 那里(范数 1.99)已经很接近真值,说明岭回归把「多出来的那部分抵消」压掉了。
偏差和方差的最优点,常常就落在「范数接近真值」的附近——这也是个实用经验。
注意测试误差的最低点很浅:0.1832 对 0.1931,只差 5 个百分点。
真实项目里这点差距常常在噪声范围内,所以「用了岭回归」不该被当成卖点。
它在病态数据上才是救命的,在健康数据上只是锦上添花。
要说明:λ 是我在测试集上挑的,真实项目里不允许。
正确做法是交叉验证,下一节 Demo 12 会把流程走一遍。
30 秒实验
- 把 λ 网格加密到 1e-6 到 10 之间 12 个点,最低点在哪?和 1.0 比差多少?这点差距值得调吗?
- 把数据改成「特征 60 维、样本 60 个」,再跑一遍。 无约束解会变成什么样?岭回归的优势会扩大多少倍?
- 不做标准化,把第 3 列的数值乘 100,再跑岭回归。 看系数的收缩比例有没有变——这就是「必须先标准化」的实证。
常见误区
- 「岭回归能让系数变稀疏」。 不能。ℓ2 的球边界是光滑的,最优解一般不在坐标轴上,所以系数不会恰为零。 要稀疏得用 ℓ1(第 5 章),它的球有棱角。
- 「λ 越大越安全」。 λ 大到一定程度,模型就退化成「全部预测平均值」,那是最安全的,也是最有偏的。 Demo 里 λ 等于 1000 时训练误差 9.99,比什么都不做还差。
- 「岭回归可解释性比最小二乘好」。 相反:它是有偏估计,系数被系统性地压小了,不能直接解释成「影响大小」。 它的好处是稳定,不是可解释。
- 「反正都要标准化,那标准化的方式随便」。 不行。中心化和缩放的先后、用标准差还是用极差,都会改变 λ 的最优值。 更麻烦的是:训练集上的标准化参数必须原样用到测试集上,不能重算。
自测三问(点开对答案)
1. 为什么加了 λI 之后矩阵一定可逆? —— **因为 A 转置 A 是半正定的,特征值非负;加 λI 之后所有特征值都至少是 λ,严格为正。** **正定矩阵一定可逆。** **所以岭回归在数学上不存在「解不唯一」这个问题。** 2. 岭回归的收缩因子 s 平方除以 (s 平方加 λ),这个式子说明了什么? —— **说明 λ 不是「一刀切地压」,而是按方向分别压:数据在那个方向越有把握(s 越大),** **压得越轻。** **所以它比「统一乘一个 0.5」聪明得多——它压的正是数据说不清的方向。** 3. 如果业务要「从 50 个特征里挑出 5 个最重要的」,岭回归合适吗? —— **不合适。** **岭回归会把 50 个系数都留着,只是都变小,挑不出来。** **该用 ℓ1(Lasso)或者「先岭回归稳定、再按阈值筛」。** **这是岭回归和 Lasso 最本质的分工:一个负责稳,一个负责选。**复杂度旋钮有了:k、λ、多项式次数。 但怎么知道该拧到哪一格?下一节讲模型选择: 为什么训练误差不能用、留出集有什么毛病、交叉验证怎么把它救回来。
- ☐ (本节完,下一节 4.3 4.3)