高斯核在七个带宽上的测试误差是 U 形:0.254、0.254、0.107、0.058、0.056、0.065、0.181。 两头都坏:带宽 0.05 时训练误差 0.0001、测试 0.254,它把每个点都穿过去了; 带宽 3.2 时核矩阵有效秩掉到 7,模型被抹成一条粗线。 而 α 的个数七行全是 20,一动没动——核模型的复杂度不在参数个数里。
2.1 的 sigmoid 基已经是「局部小台阶」,唯一的问题是中心得由人铺。这一节把这一步也交出去: 每个训练点放一个,宽度用一个参数统管。 所以核模型不是新数学,是线性模型的一次极端化。 它仍然是「对参数线性」,仍然一次闭式解,只是基的个数变成了样本数。
一、把中心交给数据
2.1 里 sigmoid 基的 7 个中心是我用 linspace 铺的。
这在 1 维、30 个点的玩具问题上没问题,到了 256 维就完全没法铺——维数一高,
网格的点数按指数爆炸。
核模型的做法很干脆:中心不用铺,每个训练点就是一个中心。
b 等于 n,基函数是 K(x, x_i)——只跟两个点的距离有关。
于是模型写成:f(x) 等于 Σ α_i 乘 K(x, x_i),i 从 1 到 n。
注意参数从 θ 换成了 α,个数从 b 变成 n。
这个改动看着朴素,效果很猛:不需要知道数据长什么样,只要有一个「像不像」的度量 K,就能拟合。
而「像不像」这件事在高维空间里比「在哪儿」好定义得多。
二、高斯核和它的带宽
最常用的核是高斯核:K(u, v) 等于 exp(负 (u 减 v) 的平方 除以 2h 的平方)。 h 是带宽,控制「多近才算近」。 h 很小时,只有几乎重合的两点才互相认亲,核矩阵接近单位阵。 h 很大时,所有点互相认亲,核矩阵接近「全 1」,秩接近 1。 所以带宽是核模型唯一的复杂度旋钮。 它不像多项式次数那样「加一项」,而是连续地调「多模糊」。 这是它比线性模型好用的地方:复杂度可以微调,不用重选基。 代价是:h 一旦调错,模型会以两种完全不同的方式坏掉。 太小就记噪声,太大就抹细节,而两种坏法的训练误差表现相反——这个后面看表。
三、α 的个数等于样本数
这是核模型最反直觉的一点:参数个数不随特征维数变,随样本数变。 30 个训练点是 30 个 α,100 万个训练点就是 100 万个 α。 教材特意强调了这条,因为它决定了核模型的适用边界: 样本几万以内好用,样本上百万就要换方法(第 3.3 节的随机梯度下降、或者干脆回到参数化模型)。 它的内存也是 O(n 的平方)——核矩阵是 n 乘 n。一万个点就是 1 亿个数,八字节一个,800 MB。 这就是核方法在大数据时代退居二线的直接原因,不是精度不够,是存不下。 还有个好用的性质:求 α 只需要核矩阵 K 本身,不需要知道 φ 是什么。 这叫「核技巧」——K 隐含地把 x 映射到了一个高维(甚至无穷维)空间, 而你永远不用真的算那个映射。 这是第 8.4 节支持向量机能做非线性分类的根基。
四、实测:带宽的 U 形
还是那 30 个点、20 训 10 测,高斯核,加一个极小的岭项 0.01 防病态。
| 带宽 h | α 个数 | 有效秩 | 训练 MSE | 测试 MSE |
|---|---|---|---|---|
| 0.05 | 20 | 20 | 0.0001 | 0.254 |
| 0.10 | 20 | 20 | 0.0003 | 0.254 |
| 0.20 | 20 | 20 | 0.0011 | 0.107 |
| 0.40 | 20 | 19 | 0.0165 | 0.058 |
| 0.80 | 20 | 15 | 0.0206 | 0.056 |
| 1.60 | 20 | 10 | 0.0265 | 0.065 |
| 3.20 | 20 | 7 | 0.1210 | 0.181 |
| 先看第一行:训练 0.0001,测试 0.254。 | ||||
| 训练误差比测试小两千倍,这是最典型的过拟合形态。 | ||||
| 注意有效秩那一列:带宽 0.05 时是 20,满秩。 | ||||
| 满秩听起来像「信息充足」,其实相反—— | ||||
| 核矩阵几乎是单位阵,每个训练点只认它自己,所以它把每个点都穿过去了。 | ||||
| 再看最后一行:带宽 3.2,有效秩掉到 7,测试反弹到 0.181。 | ||||
| 所有点互相认亲,模型被抹平,连正弦的弯都糊掉了。 | ||||
| 中间三行(0.4 到 1.6)的测试误差都在 0.06 左右,贴着噪声方差 0.04。 | ||||
| 这就是 U 形的底。 | ||||
| 而 α 的个数七行全是 20——所以「调带宽」调的不是参数量,是「这 20 个参数之间怎么分工」。 |
五、核模型的位置
它比线性模型灵活:不用猜基的形状,只要给一个距离度量。 它比层级模型简单:一次闭式解,没有初值、没有学习率、没有局部极小。 它的短板是规模和维度。 样本多,存不下核矩阵; 特征维数高,核的「远近」就失去意义——高维空间里所有点两两距离都差不多大,这叫距离集中。 所以核方法的主场是「样本几千到几万、特征几十到几百」的中等规模问题。 文本分类、小分子性质预测、基因数据,都是它的传统地盘。 工程上还有一招:先用核模型打基线,再上神经网络。 核模型的调参只有一个 h 加一个 λ,半天就能跑完;神经网络的调参是无底洞。 如果核模型的精度已经够用,就别上深度模型。
六、动手 Demo:高斯核:带宽 0.05 时训练 0.0001、测试 0.25;0.8 时 0.056
同一份 30 个点、20 训 10 测的数据。 七个带宽,每个都解一次(核矩阵加 0.01 的岭项防病态),算训练与测试均方误差, 并用奇异值数出核矩阵的有效秩(大于最大奇异值一亿分之一的个数)。
for h in (0.05, 0.1, 0.2, 0.4, 0.8, 1.6, 3.2):
def K(A_, B_):
return np.exp(-((A_[:, None] - B_[None, :]) ** 2) / (2 * h * h))
Ktr = K(X[TR], X[TR]) # 20 乘 20 的核矩阵
alpha = np.linalg.solve(Ktr + 0.01 * np.eye(len(X[TR])), Y[TR])
mtr = np.mean((K(X[TR], X[TR]) @ alpha - Y[TR]) ** 2)
mte = np.mean((K(X[TE], X[TR]) @ alpha - Y[TE]) ** 2)
s = np.linalg.svd(Ktr, compute_uv=False) # 有效秩
rank = int(np.sum(s > 1e-8 * s[0]))
实跑输出:
--------------------------------------------------------------------
高斯核:带宽 0.05 时训练 0.0001、测试 0.25;0.8 时 0.056
--------------------------------------------------------------------
模型 f(x) 等于 Σ α 乘 K(x, x_i),α 由核矩阵解出
核 高斯核 exp(-(u-v)^2 / 2h^2)
α 的个数 20 个,等于训练点数,与 x 的维数无关
岭项 λ 等于 0.01,不加这一项核矩阵病态时会发散
最优带宽 h 等于 0.8(测试 0.056)
带宽 h α 个数 有效秩 训练 MSE 测试 MSE
---------------------------------------------
0.05 20 20 0.0001 0.254
0.10 20 20 0.0003 0.254
0.20 20 20 0.0011 0.107
0.40 20 19 0.0165 0.058
0.80 20 15 0.0206 0.056
1.60 20 10 0.0265 0.065
3.20 20 7 0.1210 0.181
**h 等于 0.05 那一行:训练 MSE 是 0.0001,测试 0.25。**
**有效秩 20,等于满秩——但这不是「信息多」,恰恰相反:**
**核矩阵几乎是单位阵,每个训练点只认它自己,所以它把每个点都穿过去了。**
**这就是核模型的过拟合:不是参数太多,是「每个点都有自己的自由度」。**
**另一头 h 等于 3.2:有效秩掉到 7,测试反弹到 0.181。**
**带宽太宽,所有点互相认亲,模型被抹成一条粗线。**
**所以带宽是 U 形旋钮:太小记噪声,太大抹细节,中间才有 0.056。**
**而 α 的个数七行全是 20,一动没动。**
**这就是核模型和线性模型最根本的差别:线性模型靠加基变复杂,核模型靠收紧带宽变复杂,参数量始终等于样本数。**
**推论很直接:样本越多,核模型要存的东西越多——它的内存是随数据线性涨的。**
要说明:**带宽是拿测试集挑的,偏乐观;书里本该用交叉验证,第 4.3 节补。**
这段代码的全部内容就一件事:解一个 20 乘 20 的线性方程组。 没有迭代、没有初值、没有随机性——换个带宽重解一次,结果完全可复现。 这是核模型在工程上最讨喜的地方。 「有效秩」这个量要会读。 它数的是核矩阵里「互相独立的方向」有多少个。 带宽小时它等于 n(每个点自成一派),带宽大时它变小(点被合并成几团)。 所以它反映的是「模型实际用了几个自由度」,而不是名义参数个数。 U 形两端的原因完全不同,别混: 左端是「每个点一个自由度」,模型把噪声当信号;右端是「自由度不够」,正弦的弯曲被抹平。 一个是容量过剩,一个是容量不足,都表现为测试误差变大。 这个 U 形在机器学习里无处不在。 第 4 章会把它写成「测试误差等于偏差平方加方差加噪声」——左端是方差大,右端是偏差大。 记住这张表的形状,比记住任何公式都有用。 要说明:带宽是在测试集上挑的,偏乐观。 另外这里的岭项 0.01 只是数值稳定用,不是正经的正则化——正经的 λ 要用交叉验证选,第 4.3 节讲。
30 秒实验
- 把 h 从 0.8 拉到 1.2 之间细分五档,测试误差的最低点在哪? 和 0.8 比差多少?想想这点差距值不值得调。
- 把岭项从 0.01 改成 1.0,再看第一行(h 等于 0.05)的测试误差。 它会从 0.254 掉下来吗?为什么强岭项能救「过窄带宽」?
- 把样本数从 30 加到 200,带宽的最优值会往哪边走? 想清楚「点变密了,同样的带宽覆盖的点更多」这件事。
常见误区
- 「核模型是非线性模型」。 它对 x 是非线性的,对 α 是线性的。 求解它的方法还是最小二乘,还是闭式解。 「非线性」这个词要看修饰谁。
- 「核模型参数无限多」。 参数就是 n 个 α,有限且明确。 「无穷维」说的是核隐含的映射空间,不是参数个数。 这两个概念经常被混着说。
- 「带宽越小越精确」。 带宽小到一定程度,模型就在插值,训练误差归零而测试误差飙升。 Demo 第一行就是证据:0.0001 对 0.254。
- 「核方法已经过时了」。 在小样本、低维、需要可复现的场合,它仍然是性价比最高的选择。 深度模型赢在数据量大的场景,不是在所有场景。
自测三问(点开对答案)
1. 为什么核模型的参数个数等于训练点数,而不是特征维数? —— **因为基的个数被人为定成了 n——每个训练点放一个基。** **参数是这些基的系数 α,所以自然也是 n 个。** **特征维数只影响 K 怎么算,不影响有多少个 α。** 2. 带宽 0.05 时核矩阵满秩,为什么反而是坏事? —— **因为满秩的来源是「每个点只认自己」。** **核矩阵接近单位阵,意味着 20 个基互不重叠,模型有 20 个独立自由度去穿过 20 个点。** **训练集被完美拟合,连噪声一起——这就是过拟合。** **有效秩高不等于模型好,要看这些自由度用在了信号上还是噪声上。** 3. 如果有一百万条数据,你会用核模型吗? —— **不会。**核矩阵是 100 万乘 100 万,存不下也算不动。 **该换参数化模型加随机梯度下降(第 3.3 节),或者用随机傅里叶特征把核近似成有限维。** **核方法的天花板是内存,不是精度。**核模型把「基的中心」交给了数据,但基本身还是固定的形状(高斯核)。 下一节再往前一步:连基的形状也交给训练。这就是层级模型——它自己长出基,而代价是非凸优化。
- ☐ (本节完,下一节 2.3 2.3)