系列 · 核方法 · 第 5 篇

核方法(五):核 SVM、核 PCA 与核岭回归

把经典算法核化——SVM 的对偶形式、核 PCA 在特征空间里的特征分解、核岭回归的闭式解。带 sklearn 代码与 worked example。

你的特征只有二维,数据明明是一个圆环套一个圆环,而 LinearSVC 在 50% 准确率上瞪着你——一副"我真心觉得直线就是答案"的天真神情。你盯着散点图,又盯着模型,脑子后台终于冒出"核 SVM"三个字。改成 kernel='rbf',准确率瞬间跳到 0.98,整个下午你都在琢磨:刚才那一手到底是什么魔法?为什么同样的招数还能让核 PCA 把瑞士卷展平,让核岭回归三行代码拟合一个正弦波?

三个核化算法在同一份非线性数据上

前四篇把机械搭起来了:线性方法的天花板(第 1 篇 )、什么是正定核(第 2 篇 )、RKHS 为什么让升维后的空间表现得像希尔伯特空间(第 3 篇 )、货架上的那些常用核(第 4 篇 )。

这一篇是兑现。我们拿三个教科书级别的线性算法——软间隔 SVM、PCA、岭回归——看它们如何用几乎相同的三步动作完成核化。最终它们都收敛到同一个形状的解:一个 $n \times n$ 的 Gram 矩阵替代了原本 $d \times d$ 的协方差矩阵,答案完全可以用内积表示。这不是巧合,是 representer theorem,读完这篇你应该体感到它。

你会带走三件东西。第一,SVM 对偶问题的完整推导——Lagrangian、KKT 分区每一步都讲清楚,包括为什么稀疏性是 KKT 互补松弛自动掉出来的,而不是人为加进去的。第二,核 PCA 作为中心化 Gram 矩阵的特征分解,附带那条没人愿意推、但人人偷偷查的中心化公式,以及为什么它在瑞士卷上能赢、在 t-SNE 想要的局部邻域结构上常常输。第三,核岭回归的闭式解,以及它与 GP 回归完全相等的事实——同一个公式两套语言。

三个算法套路完全一样:写出损失函数,搬出 representer theorem,把内积换成核求值,求解一个有限维线性代数问题。一个动作,三个算法,套路一旦看穿就再也忘不掉。

核 SVM:从 primal 到 dual#

$$\min_{w, b, \xi}\ \tfrac{1}{2}\|w\|^2 + C\sum_{i=1}^n \xi_i \quad \text{s.t.}\quad y_i\bigl(\langle w, x_i\rangle + b\bigr) \geq 1 - \xi_i,\ \ \xi_i \geq 0.$$

真正起作用的有两个参数。$\|w\|$ 控制间隔宽度——$\|w\|$ 小意味着间隔宽,因为几何间隔正是 $1/\|w\|$ ;最大化间隔等价于最小化 $\|w\|^2$ ,所以原问题里那个看似纯正则化的 $\tfrac{1}{2}\|w\|^2$ 项其实正是 SVM 的主目标

$C$ 控制模型"买"多少松弛——$C$ 小则容忍很多越界点,得到一个胖而平滑的间隔;$C$ 大则强迫边界围着每个困难点拐弯。两个参数的物理意义截然不同:$\|w\|$ 是模型一旦训完就读得出的几何量,$C$ 是你在训练前注入的偏好。

在原问题里,数据是以原始坐标 $x_i \in \mathbb{R}^d$ 嵌在 $w$ 里的。$d$ 小没事;$d$ 是百万,更糟——是无穷(用核的话),那 $w$ 这个变量就根本没法存。

核技巧就是那个$w$ 扔掉的重写。我们一次都不存权重向量,连定义都不定义,全程只跟 $n$ 个对偶系数 $\alpha_i$ 打交道——它们挂在 $n$ 个训练点上。输入空间的维度从代价里掉出去了,被训练点数 $n$ 取代。这是核方法能算的根本原因,也是为什么对偶形式才是 SVM 的正典写法。

请注意这个 trade-off:当 $d \gg n$ (文本、基因表达),对偶赢;当 $n \gg d$ (百万级表格数据),原问题反而赢,这就是 LinearSVC$n > d$ 时默认走原问题、$n < d$ 时走对偶的原因。

下手前还有一个值得说的观察:原问题是凸的。目标 $\tfrac{1}{2}\|w\|^2 + C\sum_i \xi_i$ 关于 $w$ 是凸二次、关于 $\xi$ 是线性的,约束是仿射的。强对偶成立,KKT 条件既必要又充分,全局最优解唯一。

这些性质神经网络一条都没有——这就是为什么 SVM 在 2026 年仍然作为基线方法被尊重:当它有效时,你确定它有效,没有局部极小、没有初始化敏感的疑虑。一个跑出来 91% 准确率的 SVM 和另一个同样配置、跑十次的 SVM 都会落在同一个 91% 上;一个 91% 的 ResNet 跑十次可能在 89% 到 93% 之间浮动。这种确定性在论文复现、A/B 测试、统计显著性检验里值钱。

凸性还买到第二个性质:可以证明泛化界。Vapnik 1998 的统计学习理论里 SVM 的 VC 维和间隔界是定理,不是经验观察。神经网络的"为什么它能泛化"到 2026 年仍然是开放问题,要靠 NTK、双重下降、彩票假设这些半经验半理论的框架去拼凑解释。SVM 的故事在这点上简短得多——三十年前的定理今天仍然原样适用,没有被任何"反例"动摇过。稳定性在论文复现、A/B 测试、统计显著性检验里值钱。

$$\mathcal{L}(w, b, \xi, \alpha, \mu) = \tfrac{1}{2}\|w\|^2 + C\sum_i \xi_i - \sum_i \alpha_i \bigl[y_i(\langle w, x_i\rangle + b) - 1 + \xi_i\bigr] - \sum_i \mu_i \xi_i.$$ $$\frac{\partial \mathcal{L}}{\partial w} = 0 \implies w = \sum_i \alpha_i y_i x_i,$$ $$\frac{\partial \mathcal{L}}{\partial b} = 0 \implies \sum_i \alpha_i y_i = 0,$$ $$\frac{\partial \mathcal{L}}{\partial \xi_i} = 0 \implies \alpha_i + \mu_i = C.$$

第一个等式值得反复看。它说最优权重向量是训练点的线性组合,权重为 $\alpha_i y_i$ 。这就是 representer theorem 从 SVM 推导里自然冒出来——我们没假设它,是推出来的。一旦有了它,剩下的机械就自动运转。

第二个等式($\sum_i \alpha_i y_i = 0$ )是"对偶解必须类别平衡"的代数表述:所有正类 SV 的 $\alpha$ 之和等于所有负类 SV 的 $\alpha$ 之和。当你拿到一个训完的 SVM 想"sanity check"它有没有跑歪,验证这条等式只要一行代码,不满足就说明求解器没收敛或数据预处理出了问题。

第三个等式提供了 $C$ 的另一个解读:它给单个点的 $\alpha$ 设了上界,所以没有任何一个训练点能贡献超过 $C$ 那么多的影响。把 $C$ 理解为"单点影响力的天花板",比把它理解为"违反间隔的惩罚强度"更接近实操直觉。

回代消元。$w = \sum_i \alpha_i y_i x_i$ 代回 $\mathcal{L}$ ,用 $\sum_i \alpha_i y_i = 0$ 干掉 $b$ 项,用 $\alpha_i + \mu_i = C$ 消掉 $\mu_i$ 同时把 $\alpha_i$ 约束在 $[0, C]$ 区间内。

$$\max_{\alpha}\ \sum_i \alpha_i - \tfrac{1}{2}\sum_{i, j} \alpha_i \alpha_j y_i y_j \langle x_i, x_j\rangle \quad \text{s.t.}\quad 0 \leq \alpha_i \leq C,\ \sum_i \alpha_i y_i = 0.$$

数据通过内积 $\langle x_i, x_j\rangle$ 出现。把每个这样的内积换成 $K(x_i, x_j)$ ,优化问题的形状根本没变——同样 $n$ 个变量、同样的约束、同样的二次规划求解器。非线性藏在 $K(x_i, x_j)$ 里,求解器对此一无所知,它眼里只看到一个 PSD 矩阵和一些线性约束。

这一点是核方法的精髓:算法和核完全解耦。同一个 QP 求解器可以喂线性核、RBF 核、多项式核、字符串核、图核,得到的优化问题在形式上完全一致,只是 Gram 矩阵的具体数字不同。这种解耦带来巨大的工程价值——你可以独立于算法换核来探索假设空间,独立于核换算法来比较套路。libsvm 的代码库就是这样组织的:求解器只接受一个 $K$ 矩阵和标签向量 $y$ ,连"什么是 RBF" 都不知道。

这种解耦在科研代码里很难复现——大多数研究者会把核计算和算法逻辑紧紧绑在一起,结果换核就要改几十行代码。如果你正在搭一个核方法实验框架,先想清楚 “Gram 矩阵作为算法的唯一输入” 这一接口,剩下的扩展(新核、新算法、组合核)就基本自由了。这是把 libsvm 当架构参考、不只是当库的理由。

$$f(x) = \sum_{i \in \text{SV}} \alpha_i y_i K(x_i, x) + b,$$

求和只跑支持向量——也就是 $\alpha_i > 0$ 的那些点。

KKT 互补松弛条件保证:只有恰好位于间隔上或间隔内的点才有非零 $\alpha$ ,其余全是稀疏的零。在一个干净的数据集上 RBF SVM 通常只保留 5%–20% 的训练点作为支持向量。这种稀疏性是核 SVM 在核化机制下仍能 scale 的根本原因:预测代价依赖 $n_{\text{SV}}$ 而不是 $n$

把它跟核岭回归对比一下立刻就显眼了——核岭的解里每个 $\alpha_i$ 一般都非零,预测代价始终 $\mathcal{O}(n)$ ,没有稀疏化的奢侈。SVM 的稀疏性不是工程优化,是 KKT 互补松弛白送的几何事实。

值得明确的是:稀疏性的程度$C$ 和数据的可分性共同决定,不是固定常数。$C \to \infty$ (硬间隔)极限下只有恰好落在间隔上的少数点是 SV,稀疏度极高;$C \to 0$ 极限下几乎所有点都成 SV 因为大家都"违反"了那个超宽间隔。数据噪声水平也影响:完全可分的干净数据上 SV 数极少(常常少于训练集大小的 5%),而高度重叠的数据上 SV 数可能逼近全集。看到训练完的 SVM 报告 support_vectors_.shape[0] 接近 $n$ ,几乎一定是噪声或可分性出了问题。

KKT 一句话。 这个问题的 KKT 条件把训练点切成三个 regime:

  • $\alpha_i = 0$ :点在间隔外,且在边界正确一侧。忽略。
  • $0 < \alpha_i < C$ :点恰好在间隔上。$\xi_i = 0$在线支持向量。
  • $\alpha_i = C$ :点 $\xi_i > 0$ ——在间隔内或被误分。违反间隔的支持向量。

阈值 $C$ 充当任何单一点能拥有的最大影响力的上限。这正是软间隔 SVM 对异常点鲁棒、硬间隔不鲁棒的根本原因:一个标签噪声点最多只能对决策边界施加 $C$ 那么多影响。硬间隔 SVM(相当于 $C = \infty$ )让一个异常点就能毁掉一切;软间隔优雅地吸收掉它。

值得 explicit 强调一下三 regime 的几何意义:第一类点是模型可以完全忘掉的"无信息样本"——丢掉它们重新训练得到同一个分类器;第二类是定义间隔的"边界样本";第三类是模型不得不放弃的"难点"。这种"点的等级分化"在其它分类算法里几乎找不到——logistic 回归对每个点都一样关心,决策树是按特征分割不按样本分级,神经网络则把所有梯度均匀混合。SVM 的"哪些点重要"信号在调试和数据清洗里特别有用:去看那些 $\alpha_i = C$ 的点,常常就是标签错的或者真正困难的边缘案例。

一个具体场景:训练 1000 个干净点加 5 个反标签的对抗样本。硬间隔会绕着 5 个对抗点拐弯,决策面被它们拽得扭曲;软间隔以 $C = 1$ 设上限,那 5 个点最多贡献 $5 \cdot 1 = 5$ 单位的影响力,被剩下 995 个干净点的几何主流压倒。Bartlett & Mendelson 2002 的 Rademacher 复杂度界把这件事正式化了:泛化误差以 $\|w\|/\sqrt{n}$ 衰减,而 $\|w\|$ 在软间隔下被 $C$ 控制。

这条界对核 SVM 的一个不直观推论是:训练集规模 $n$ 翻 4 倍,期望泛化误差只衰减 2 倍——因为 $\sqrt{n}$ 是平方根。所以数据效率上 SVM 跟简单线性模型同阶,没有 KNN 那种 $1/n^{2/(d+2)}$ 的诅咒,也没有深度网络在大数据上观测到的更快经验衰减。这套统计保证在小数据 regime 下尤其珍贵——$n < 1000$ 的实验里 SVM 经常比深度网络稳,原因就是这条界给的偏差—方差权衡是写死的。

$$b = y_i - \sum_{j \in \text{SV}} \alpha_j y_j K(x_j, x_i).$$

实际中你对每个在线 SV 算一遍 $b$ 再求平均,得到数值稳定的估计。如果没有在线 SV(罕见,但在 $C$ 很大时可能发生),就退而求其次,在所有 SV 上加权平均。

这是 sklearn 内部就是这么做的,所以你几乎不会自己去算这一步——但理解它能解释一类报错:当你的训练集线性可分到完全没有点处于间隔上时,求解器会偶尔抛出"无在线 SV"的告警,对应模型的 $b$ 数值不稳定。

值得明确一下:训完的 SVM 决策函数 $f(x) = \sum_i \alpha_i y_i K(x_i, x) + b$ 中,$b$ 不会通过 $\alpha$ 自动出现,它是真正"额外"的一个标量参数。这是 SVM 跟核岭、GP 的一个微小差别——后两者的解里没有截距项,因为它们的正则项 $\|w\|^2$ 不惩罚常数偏移,等价于自动隐含一个零均值假设。SVM 的间隔约束 $y_i(\langle w, x_i\rangle + b) \geq 1$$b$ 显式拉了进来,需要单独求解。

不同 gamma 下 RBF 核 SVM 在 circles 数据上的决策边界

核 SVM 实战#

对偶给你理论,sklearn 给你一行代码。核 SVM 的主力 API 是 sklearn.svm.SVC,90% 的调参精力都在两个旋钮上。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from sklearn.svm import SVC
from sklearn.datasets import make_moons
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline

X, y = make_moons(n_samples=400, noise=0.25, random_state=0)

pipe = make_pipeline(StandardScaler(), SVC(kernel="rbf"))
param_grid = {
    "svc__C": [0.1, 1, 10, 100],
    "svc__gamma": [0.01, 0.1, 1, 10],
}
grid = GridSearchCV(pipe, param_grid, cv=5)
grid.fit(X, y)
print(grid.best_params_, grid.best_score_)

$C$ 这个旋钮。 如前所述,$C$ 是松弛的代价。几何解释比代数解释更有用。$C$ 小则间隔变宽到许多训练点都掉到里面——边界看上去糊糊的,几乎像 logistic 回归的结果,泛化好是因为单点影响力小。

$C$ 大则间隔收紧到几乎没点在里面——边界绕着每个困难样本扭动,开始过拟合标签噪声。默认从 $C=1$ 开始,两边各乘除 10 试一试。

一个跟 logistic 回归的对比直觉:logistic 的 $L_2$ 正则化系数 $1/(2C)$ 跟 SVM 的 $C$ 在数学结构上是 dual 的——前者用 $1/C$ 惩罚权重大小,后者用 $C$ 加权 hinge 损失。结果是 logistic 的 $C$ 越大模型越复杂(弱正则化),SVM 的 $C$ 越大模型也越复杂(强拟合)。两边方向一致是好事,但量纲不同:logistic 的 $C = 1$ 跟 SVM 的 $C = 1$ 没有任何对应关系。如果你发现自己想要 $C > 100$ ,停一停问问:你是真要软间隔 SVM,还是该换个算法。

这背后是 SVM 适用场景的边界:$C$ 很大意味着你不愿意为噪声付任何代价,等价于在做硬间隔分类——而硬间隔分类在标签有噪声的现实数据上几乎总是错答案。“想要 $C > 100$ ” 的下一步通常是"数据有少量但严重的异常值",正确的修法是清洗数据或换成 logistic 回归,而不是把 $C$ 拉得更大。

一个常见误诊:$C$ 越调越大、训练精度上去、CV 精度反而下降,说明你已经把模型推到了把噪声当信号的区间,继续加 $C$ 不会救你,加更平滑的核(更小 $\gamma$ )或者更多数据才会。

工程上还有一个被忽略的细节:SVC$C$LogisticRegression$C$ 在 sklearn 里量纲不一样。前者是 hinge 损失项的权重,后者是对数似然项的权重,单位不同;从 logistic 迁移过来的人常常把 logistic 的最优 $C$ 直接当 SVM 的初值,结果差一两个数量级。一直从 $C = 1$ 起步搜,别复用其他模型的 $C$

$\gamma$ 这个旋钮。 用 RBF 核时,$\gamma$ 控制每个支持向量的"贡献锐度"。$\gamma$ 小则每个 SV 影响一大片邻域,决策边界平滑甚至呆板。$\gamma$ 大则每个 SV 只影响紧邻的一小片,边界变成围绕单个训练点的小岛集合,你就重新发明了 1-近邻。

把这两个极端连起来看,$\gamma$ 实际上是在 “线性 SVM” 和 “1-NN” 之间插值:$\gamma \to 0$ 时 RBF 核 $K \to 1$ (任意两点都"等同"),决策函数被均值主导,等价于一个偏置的常数预测器;$\gamma \to \infty$$K(x, y) \to \delta_{xy}$ (只有同一点相似),每个查询点只看最近的训练点投票,等价于 1-NN。中间的 $\gamma$ 就是在这条"复杂度梯度"上选位置。Schölkopf & Smola 2002 的第 7 章把这条等价讲得很彻底,能帮你从极限案例反推 $\gamma$ 应该往哪边调。

$$\gamma_0 = \frac{1}{2 \cdot \mathrm{median}(\|x_i - x_j\|^2)}.$$

然后在它周围对数网格扫一扫。如果最优值落在网格边缘,说明你网格范围扫得太窄了,要拓宽。

$C$$\gamma$ 的相互作用。 这两个参数不是独立的。小 $\gamma$ (平滑核)能容忍更大的 $C$ 而不过拟合,因为每个 SV 的"投票权"散得很开。大 $\gamma$ (尖锐核)需要小 $C$ 来补偿,否则模型会把决策权重集中在最噪声的点上。

你做网格搜索时通常会看到验证表面上有一条山脊,好的 $(C, \gamma)$ 大致沿对角线排列——一端是小 $\gamma$ + 大 $C$ ,另一端是大 $\gamma$ + 小 $C$ 。那条山脊就是模型的有效复杂度等高线,网格搜索本质上就是把它定位出来。两维网格搜索对大多数场景够用了;只有两个超参,贝叶斯优化带不来多大收益。

更精明的做法是用 $\log C - \log \gamma$ 作为搜索坐标——验证表面上的山脊在这套对数坐标下基本是直线,扫一条 1D 切片就可以覆盖。Chang & Lin 在 libsvm guide 里推荐先做粗对数网格定位山脊位置,再做细网格精修,这套两步流程比一刀切的密网格快 4–8 倍并且不丢精度。Hsu, Chang & Lin 的 “A Practical Guide to Support Vector Classification” 把这套流程写得最清楚,可以当 SVM 调参的速查手册。

一个简短的数值例子:在 make_moons(noise=0.25) 上扫 $C \in \{0.1, 1, 10, 100\}$$\gamma \in \{0.01, 0.1, 1, 10\}$ ,五折 CV 通常给出三到四个并列最佳的格点 $(C, \gamma) \in \{(1, 1), (10, 0.1), (10, 1), (100, 0.1)\}$ ,CV 精度都在 0.95–0.96,差异在标准误内。这就是山脊。

不同 C 下的支持向量与软间隔

一个常见错误。 大家会记得给 LogisticRegression 标准化特征,却经常忘记给 SVC 标准化。RBF 核算的是原始特征空间里的 $\|x - y\|^2$ ——如果一个特征量纲 $[0, 1]$ ,另一个 $[0, 10^6]$ ,第二个就完全压住核,第一个等于不存在。

在拟合任何核 SVM 之前务必先标准化(StandardScaler)。前面说的中位数启发式 $\gamma_0$ 也是假设特征已标准化才有意义;在原始量纲上它会算出一个废值。

同样的警告适用于所有基于距离或核的方法——KNN、k-means、高斯过程——但 SVM 是最容易翻车的地方,因为 SVM 长得太"高大上",人们反而忘了核眼里看到的只是原始坐标。

多分类。 SVM 本质上是二分类。sklearn 的 SVC 通过 one-vs-one 分解处理多分类(默认行为)——$K$ 类要训练 $\binom{K}{2}$ 个二分类 SVM。$K$ 大时这比 one-vs-rest 贵,但实际中 $K$ 极少大到让人在乎,而且 one-vs-one 通常精度更高。$K > 20$ 时考虑换 multinomial softmax 的 logistic 回归,或者树模型集成。

一个反直觉的事实:one-vs-one 训 $\binom{K}{2}$ 个分类器看起来吓人,但每个分类器只用两类的数据,所以总训练代价大约是 $\binom{K}{2} \cdot \mathcal{O}((2n/K)^3) \approx \mathcal{O}(n^3 / K)$ ,反而比 one-vs-rest 的 $K \cdot \mathcal{O}(n^3)$ 便宜。这是 libsvm 选 one-vs-one 当默认的隐藏原因。

但 one-vs-one 也有它的代价:预测时要查询 $\binom{K}{2}$ 个分类器再投票,预测延迟随 $K^2$ 增长;而 one-vs-rest 只要 $K$ 次。所以在实时系统上 $K$ 中等大(比如 30–50 类)时,one-vs-rest 反而更友好。这一类"训练 vs 推理"的不对称权衡贯穿整个 ML 工程,但在 SVM 多分类上尤其显眼,因为两个策略的精度差距小到经常可以接受任何一个,工程考虑就反而占主导。

另一个细节是投票策略:one-vs-one 默认用"赢票数"投票,但平局并不罕见。libsvm 用 Wu, Lin & Weng 2004 提出的成对耦合(pairwise coupling)从两两概率推全局概率,比简单投票更稳。SVC(decision_function_shape='ovr') 可以切到 one-vs-rest 形式的决策函数(注意不是训练形式),对下游需要单一分数排序的场景方便。

概率输出。 SVM 不原生输出概率。SVC(probability=True) 会在 SVM 得分上额外拟合一个 Platt 缩放的 logistic 回归,训练时多花一轮交叉验证,得到的概率通常校准良好,但分类精度稍有牺牲。如果你需要概率,干脆直接用 logistic 回归——SVM 的优势从来就是几何间隔,不是概率解释。

Platt 缩放本质是事后补救:先训 SVM 拿到 $f(x) = \langle w, \phi(x)\rangle + b$ ,再单独训一个 $P(y = 1 \mid x) = \sigma(A f(x) + B)$ ,两个标量参数 $A, B$ 用极大似然估计。当 SVM 得分的分布跟"反 sigmoid"假设差太远时(极端不平衡数据、或决策边界几何上很扭曲),Platt 缩放给出的概率会校准不良;这时 isotonic regression(CalibratedClassifierCV(method='isotonic'))通常更稳。

计算现实。 核 SVM 的训练代价大致 $\mathcal{O}(n^2)$$\mathcal{O}(n^3)$ ,与训练点数 $n$ 相关——构造 Gram 矩阵 $\mathcal{O}(n^2 d)$ ,求解 QP 在二次和三次之间(取决于求解器)。预测代价 $\mathcal{O}(n_{\text{SV}} \cdot d)$ 每次查询。

所以核 SVM 在 $n = 10^3$ 上是享受,$n = 10^4$ 上是忍受,$n = 10^6$ 上是不可行。第 7 篇 会讲那些把天花板顶上去的近似——Nyström、随机傅里叶特征、基于 SGD 的线性化。

一个工程经验:libsvm 在 $n = 5000$ 上的训练时间大约几十秒,到 $n = 20{,}000$ 上往往就是十几分钟到一小时——QP 求解的复杂度跳跃比理论曲线还陡,因为内存层级的 cache miss 在大 Gram 矩阵上突然恶化。

还有一个内存细节常被忽略:libsvm 默认 cache 大小是 200 MB(cache_size=200),$n$ 大时这点远远不够,Gram 矩阵的列被反复重算。把 cache_size 调到机器空闲 RAM 的 50%–70%(比如 4 GB 或 8 GB),训练时间常常能掉一半。这是个一行参数的 free lunch,但 sklearn 默认值是为小数据集设的,大家普遍忘了。

核 PCA:在特征空间里做特征分解#

教科书 PCA 拿一个中心化数据矩阵 $X \in \mathbb{R}^{n \times d}$ ,对 $d \times d$ 协方差矩阵 $C = \tfrac{1}{n} X^\top X$ 做特征分解。前 $k$ 个特征向量就是主方向,任何新点投影上去得到一个 $k$ 维编码。

标准 PCA 的全部要点是:这些方向在输入空间里是线性的——有时这是好事(数据真的住在线性子空间附近),有时是灾难(数据住在一个卷起来的流形上)。

核 PCA 把"对 $d \times d$ 协方差做特征分解"换成"对 $n \times n$ 中心化 Gram 矩阵做特征分解"。结果是特征映射 $\phi(X)$ 的主成分,尽管我们从头到尾没把 $\phi$ 写出来。这跟 SVM 是同一招——用内积和 $n \times n$ 矩阵替代显式特征——只是用在了一个无监督问题上。

它最早由 Schölkopf, Smola & Müller 1998 提出,标志着核方法从纯监督场景扩张到无监督的开端,后续的核 ICA、核 CCA、核 LDA 都遵循同一个套路。

$$C_\phi = \frac{1}{n}\sum_i \phi(x_i) \phi(x_i)^\top,$$

主方向 $v_k$ 满足 $C_\phi v_k = \lambda_k v_k$

这是一个在 $\mathcal{H}_K$ 上的特征问题,潜在无穷维,看上去无望。诀窍在于:任何非零特征值对应的特征向量 $v_k$ 一定在 $\{\phi(x_i)\}_{i=1}^n$ 的张成里——如果 $v_k$ 有任何与该张成正交的分量,那么 $C_\phi v_k$ 在该方向上也是零,特征方程强制 $\lambda_k = 0$

这条论证本质上是把无穷维特征值问题"压扁"到一个 $n$ 维子空间——所有有信息的方向都在 $\{\phi(x_i)\}$ 张成内,无穷维补空间只会贡献零特征值。这套塌缩论证在 RKHS 框架下出现过多次(第 3 篇 的 representer theorem 是同一个机制的另一面),但每次都值得重新走一遍,因为它解释了"为什么核方法计算上可行" 的根本原因。

$$v_k = \sum_i \alpha_i^{(k)} \phi(x_i).$$ $$K \alpha^{(k)} = n \lambda_k \alpha^{(k)},$$

其中 $K$$n \times n$ 的 Gram 矩阵,$K_{ij} = \langle \phi(x_i), \phi(x_j)\rangle = K(x_i, x_j)$

无穷维协方差算子上的特征问题,被压缩成有限维 Gram 矩阵上的特征问题。这就是核 PCA 的全部内容。

注意这个 $n$ 因子:$K$ 的特征值是协方差算子特征值的 $n$ 倍,所以解释方差时要除回去。sklearn 的 KernelPCA.eigenvalues_ 返回的是 $K$ 的特征值(已经按 $1/n$ 归一),但其它实现可能不一样——读源码看清楚再做"解释方差比"的可视化。

$$\tilde{K} = K - \mathbf{1}_n K - K \mathbf{1}_n + \mathbf{1}_n K \mathbf{1}_n,$$

其中 $\mathbf{1}_n$$n \times n$ 全为 $1/n$ 的矩阵。

这是核方法里少有的几条建议你背下来的公式——每个核 PCA 实现都要走这一步,符号错了就一堆垃圾分量。推导只需展开 $\tilde{K}_{ij} = \langle \tilde{\phi}(x_i), \tilde{\phi}(x_j)\rangle$ ,利用双线性和 $\tilde{\phi}$ 的定义,四个项就掉出来了。

一种快速记忆法:把 $\mathbf{1}_n K$ 想成"每行减去该行均值",$K \mathbf{1}_n$ 想成"每列减去该列均值",$\mathbf{1}_n K \mathbf{1}_n$ 是"全局均值的两次校正"。中心化在欧氏空间就是减均值;在 RKHS 里减均值要通过 Gram 矩阵的代数表达,这四项是同一件事的核版本。理解了这层对应,你就不会把符号写反——错号意味着你不是在中心化,而是在"反中心化",特征向量会指向相反方向但模长仍然正常,结果是图全反着画。

一个隐形坑:测试点也要用训练集的均值中心化——不能用测试集自己的均值,否则 train/test 不在同一个坐标系里。KernelPCA.transform() 内部会用训练时缓存的 $\mathbf{1}_n K$ 项补这个偏置,自己实现时要记得复用同一个偏置向量。

归一化。 eig(K) 解出的特征向量 $\alpha^{(k)}$$\mathbb{R}^n$ 上是单位范数,但对应的 $v_k = \sum_i \alpha_i^{(k)} \phi(x_i)$$\mathcal{H}_K$ 上一般不是单位范数。强加 $\|v_k\|^2 = \alpha^{(k)\top} K \alpha^{(k)} = 1$ 给出重新归一化 $\alpha^{(k)} \to \alpha^{(k)} / \sqrt{n \lambda_k}$

sklearn 的 KernelPCA 会替你做,但你要是自己撸一遍,记得这一步;没有它,投影坐标的尺度就是错的,下游接 SVM 或 logistic 回归时还会被无声地搞砸——因为线性模型对特征尺度敏感,错的尺度等同于错的正则化。

$$z_k(x) = \sum_i \alpha_i^{(k)} K(x_i, x).$$

注意它跟线性 PCA 的非对称性:这里投影系数 $\alpha_i^{(k)}$训练点上的权重,不是输入空间里的方向。你不能从 $z_k(x)$ 反向重构 $x$ ,除非去解一个 pre-image problem——这是核 PCA 最大的局限之一,也是一整片小文献的主题(Mika 等人,1998)。

这条非对称性还有一个实际后果:核 PCA 没有"特征加载(loading)“概念。线性 PCA 的第一个主成分有明确的特征系数,你能说"这个方向主要由特征 7 和特征 12 主导”;核 PCA 的"方向"是 $\sum_i \alpha_i^{(k)} \phi(x_i)$ ,每个 $\alpha_i^{(k)}$ 是某个训练点的权重,跟原始特征没有直接对应。这让核 PCA 在"特征重要性解释"上几乎不可用——你能可视化嵌入但解释不了为什么这个嵌入合理。在需要可解释性的场景(医疗、金融)这是个硬约束。

可视化用途下 pre-image 通常不需要;但任何需要回到输入空间的任务(去噪、生成),它就是主要的拦路虎。sklearn 用 fit_inverse_transform=True 训一个从 $z$$x$ 的核岭回归来近似 pre-image,这套近似在 MNIST 去噪上效果不错,但本质上是另一个 ML 模型套在 PCA 之上,不是 PCA 自身的反演。

为什么它能处理非线性流形。 如果你的数据是嵌在 3D 里的瑞士卷,数据其实住在一个二维流形上,线性 PCA 看不见——因为卷起来的薄片的主方向指向"错"的方向,PCA 只懂直线。

RBF 核的核 PCA 计算 $\phi(X)$ 的主成分——$\phi$ 隐式把每个点映射为它跟训练集的相似度概貌。在那个表示里,流形被"展开",前几个特征向量正确恢复瑞士卷的两个内在维度。

一种几何直觉是:RBF 核把每个训练点视为一个"高斯凸包",整个数据集变成这些凸包的并集;核 PCA 找的是这些凸包在 RKHS 里方差最大的方向。当数据沿一条曲线流形分布时,这些方向恰好沿流形展开,跟流形几何对齐。$\gamma$ 控制凸包的尺寸:太小则相邻凸包重叠覆盖整片空间、流形结构被抹平;太大则凸包退化成孤立点、邻接关系丢失。

这与谱嵌入方法 Isomap、Laplacian eigenmaps 关系密切——它们都可视为用特定数据相关核的核 PCA。Ham 等人 2004 给出了正式的统一框架:把 Isomap 的测地距离矩阵或 Laplacian eigenmaps 的归一化拉普拉斯矩阵当作"核"丢给核 PCA 算法,等价的结果就出来了。这是为什么这一整片"流形学习"算法实际上是同一台引擎换了不同的 Gram 矩阵。

反过来这也带来一个失败模式:用 RBF 核 PCA 看一个明显有"测地结构"的数据集(比如沿一条弯曲流形的传感器轨迹),结果常常不如 Isomap——因为 RBF 核度量的是欧几里得相似度,无视流形结构;而 Isomap 用图上的最短路距离构造核,认得流形上的"远"。判据:如果数据嵌在一个低维流形上、且流形本身有明显的几何(“测地距离"跟"欧几里得距离"差很多),优先考虑 Isomap / Laplacian eigenmaps;若数据只是非线性但相似度在局部欧氏意义下可信,RBF 核 PCA 更稳。

核 PCA 把瑞士卷展开

核 PCA 实战#

sklearn API 是 sklearn.decomposition.KernelPCA,几乎是 PCA 的即插即用替代品:

1
2
3
4
5
6
7
8
from sklearn.decomposition import KernelPCA, PCA
from sklearn.datasets import make_swiss_roll
import numpy as np

X, color = make_swiss_roll(n_samples=1000, noise=0.1, random_state=0)

pca = PCA(n_components=2).fit_transform(X)
kpca = KernelPCA(n_components=2, kernel="rbf", gamma=0.05).fit_transform(X)

怎么选 $\gamma$ 跟核 SVM 一样,$\gamma$ 控制带宽,是最重要的超参。不一样的地方在于:核 PCA 无监督,没有标签信号可拿来网格搜索。三个实用策略:

  • 中位数启发式。 用对距离算 $\gamma_0$ ,再在它周围几个数量级目视检查。如果核 PCA 作为下游任务的预处理,可以直接拿下游任务表现当信号网格搜索 $\gamma$
  • 重构误差。 投到 $k$ 个分量再用 KernelPCA(fit_inverse_transform=True) 重构,选最小化留出集平均重构误差的 $\gamma$ 。原理清晰但有局限,因为重构本身也依赖 $\gamma$ 和核。
  • 下游分类器精度。 如果核 PCA 是 SVM 或随机森林的预处理步骤,$\gamma$ 不过是另一个超参,并入下游模型的同一轮 CV。

一个具体瑞士卷数字:1000 个点上扫 $\gamma \in \{0.01, 0.05, 0.1, 0.5, 1\}$ ,目视检查二维嵌入跟"卷出来的真色带"的对齐程度。

$\gamma = 0.05$ 通常给出最干净的展开,$\gamma = 0.5$ 开始把卷压成一团,$\gamma = 1$ 完全失去结构。这种"目视判断"听起来很主观,但跟下游分类精度的 CV 结果高度一致——核 PCA 的好坏在 2D 散点图上肉眼可读,这本身是它相对深度自编码器的一个优势。

自编码器的潜在空间没有这种"看一眼就知道好不好"的可读性:你不知道 16 维瓶颈里前 2 维代表什么,常常要再套一个 t-SNE 才能可视化。核 PCA 的潜在空间天生是"按方差排序"的,第 1 个分量就是最重要的方向,第 2 个次之,依此类推。这条排序结构是 PCA 系算法独有的资产,自编码器和大多数神经降维方法都没有。

排序结构的另一个用途是$k$ :累计解释方差比作为 $k$ 的函数会画出一条"碎石图”(scree plot),肘部就是合理的 $k$ 值。自编码器要选潜在维度,要么靠 reconstruction loss 配 CV 网格搜索,要么靠下游任务表现——两者都比读一张 scree plot 麻烦。核 PCA 把"我应该保留多少维"这个问题降级成画一张图、找肘部,调试体验非常友好。

什么时候值得用。 核 PCA 在以下场景最有用:(a) 数据有非线性结构;(b) 你想在 2D 或 3D 里可视化这个结构;(c) 结构最适合用平滑的、局部的相似度来刻画。

瑞士卷、S 形曲线、moons、同心圆——这些是"核 PCA 大显身手"的经典数据。在高维、稀疏或本来就线性的数据上,标准 PCA 几乎总是同等好甚至更好——而且便宜得多:标准 PCA 是 $\mathcal{O}(d^2 n + d^3)$ ,核 PCA 是 $\mathcal{O}(n^3)$

什么时候翻车。 核 PCA 在两类场景下脆弱。一是噪声数据上,Gram 矩阵的前几个特征向量可能被噪声模式主导而不是信号——小 $\gamma$ 会缓解但也会糊掉结构。

二是数据有多个不连通流形(比如两个分隔很开各有曲率的 blob)时,前几个成分常常捕捉的是簇间变化而非簇内结构——这到底是不是你想要的就难说了。如果你偏要簇内结构,t-SNE 或 UMAP 更合适——它们优化的是保留局部邻域的损失,不是最大化方差。

这是一个根本性的目标差异:PCA 系(包括核 PCA)最大化全局方差解释,t-SNE/UMAP 最小化局部邻域的 KL 散度。两套损失会给出截然不同的二维投影——同一份数据用核 PCA 看像两团相距很远的 blob,用 UMAP 看是两团内部展开了各自精细结构的子簇。

标准 PCA vs 核 PCA 在同心圆上的对比

计算注记。 对 Gram 矩阵做特征分解 $\mathcal{O}(n^3)$ 是约束。当 $n > 5000$ 时用 eigen_solver='arpack' 只算前 $k$ 个特征向量,复杂度降到约 $\mathcal{O}(n^2 k)$ 。当 $n$ 真的很大时,得上 Nyström 近似——第 7 篇 见。

内存代价是另一个隐形约束:双精度 $n = 30{,}000$ 的 Gram 矩阵就要 7.2 GB,光是把它放进 RAM 就在 16 GB 笔记本上挤;$n = 50{,}000$ 直接爆。所以核 PCA 的"$\mathcal{O}(n^3)$ 上限"在实操中常常先撞 RAM 墙,再撞 CPU 墙。

一个工程妥协是用 float32 而不是 float64,立刻把内存减半,对核 PCA 的精度影响微乎其微(因为前几个主成分的能量集中在大特征值上,对舍入误差不敏感)。sklearn 0.24 起 KernelPCA 支持 eigen_solver='randomized',结合 float32 通常能把 $n = 50{,}000$ 拖进 16 GB 笔记本。再大就得换 incremental 或 streaming 算法,但那是另一篇文章的主题了。

vs. t-SNE 和 UMAP。 现代实操中非线性可视化通常先想到 t-SNE 或 UMAP,而不是核 PCA。原因:(i) t-SNE/UMAP 明确优化保留局部邻域,正是你肉眼在 2D 图里关心的;(ii) 实际上它们 scale 到大 $n$ 好得多(UMAP 接近线性);(iii) 不需要用户挑核。

核 PCA 相对 t-SNE/UMAP 的优势是:(i) 对新测试点有闭式、确定性的投影函数(t-SNE 没有,UMAP 有但近似);(ii) 它忠于方差结构而非邻域结构——这正是你若想下游接一个线性分类器时想要的;(iii) 只有一个超参,不是三个。探索式可视化用 UMAP;下游模型的预处理步骤用核 PCA。

一个简单的判据:如果你要把降维结果传给后续的 ML 模型,几乎一定选核 PCA 或 PCA;如果你要把它放进幻灯片给人看,几乎一定选 UMAP 或 t-SNE。

另一个常被遗漏的对比维度是超参敏感度。t-SNE 的 perplexity 改 5 和改 50 给出的图可能根本看不出来是同一份数据;UMAP 对 n_neighbors 同样敏感。核 PCA 在中位数启发式 $\gamma_0$ 附近一两个数量级内的图大体一致——核 PCA 的"稳健性"换来了"漂亮度"的损失。如果你的目标是给老板演示一张"看起来惊艳"的图,t-SNE 几乎一定赢;如果你的目标是写一篇可复现的论文图,核 PCA 几乎一定赢。

核岭回归:闭式解的优雅#

$$\min_w\ \tfrac{1}{2}\|y - Xw\|^2 + \tfrac{\lambda}{2}\|w\|^2,$$ $$\hat{w} = (X^\top X + \lambda I)^{-1} X^\top y.$$

$\lambda$ 项正则化逆矩阵,即使 $X^\top X$ 秩亏也保持数值稳定。

这个闭式解就是大家把岭回归当回归万金油基线的原因:没有优化循环、除了 $\lambda$ 之外没其他超参、可微、良态。从贝叶斯视角看,它还是高斯先验 $w \sim \mathcal{N}(0, (1/\lambda) I)$ 加高斯似然下的 MAP 估计——这层等价让岭回归同时是频率派的"惩罚最小二乘"和贝叶斯派的"高斯先验下的回归",后面要讲它跟 GP 的等价时正是这层贝叶斯解读在起作用。

从信息论视角看还有第三条解读:$\lambda \|w\|^2$ 项等价于在解空间上加最小描述长度(MDL)惩罚,鼓励模型用尽量少的"比特"描述自己。三种解读在数学上彼此完全等价但语言全不同——频率派说"惩罚",贝叶斯说"先验",信息论说"压缩"——这种"同一公式三套语言"的现象在 ML 里反复出现,理解任一一种解读都足以做对题,但同时持有三种解读会让你在跟不同背景的合作者讨论时方向感更稳。

这条等价对调试也有用:如果你的核岭模型预测崩盘,分三个角度自查——频率派问"$\lambda$ 是不是太小让模型过拟合?",贝叶斯派问"先验是不是跟数据规模不匹配,方差设小了?",信息论派问"模型描述长度有没有炸?"。三个角度问的是同一件事但触发的修法直觉不同,多一个角度多一份成功概率。

$$\hat{f}(x) = \langle w, \phi(x)\rangle = \sum_i \alpha_i \langle \phi(x_i), \phi(x)\rangle = \sum_i \alpha_i K(x_i, x).$$ $$\min_\alpha\ \tfrac{1}{2}\|y - K\alpha\|^2 + \tfrac{\lambda}{2} \alpha^\top K \alpha.$$ $$\alpha = (K + \lambda I)^{-1} y.$$

整个推导能写在一张明信片上。

把这条推导拆成"三步配方":先调 representer theorem 把 $w$ 写成训练点的线性组合,再把这个表达式回代到损失函数得到一个只关于 $\alpha$ 的凸二次目标,最后对 $\alpha$ 求梯度置零拿到闭式解。这三步在 SVM、核 PCA 上完全平行,只是损失换了;后面任何"核 X"算法都可以照搬这三步。

$$\hat{f}(x) = \mathbf{k}(x)^\top \alpha = \mathbf{k}(x)^\top (K + \lambda I)^{-1} y,$$

其中 $\mathbf{k}(x) \in \mathbb{R}^n$ 的分量是 $\mathbf{k}(x)_i = K(x_i, x)$

对比线性岭公式 $\hat{f}(x) = x^\top (X^\top X + \lambda I)^{-1} X^\top y$ ;结构完全相同$K$$X^\top X$$\mathbf{k}(x)$$X^\top x$ 。这是核技巧最纯粹的展现——把每个矩阵换成它的核化对应物,算法就直接通过了,不需要任何额外修改。

一个简单的数值核对:$n = 5$ 的 toy 例子,手算 $K = X X^\top$ (即线性核 $K(x, y) = \langle x, y\rangle$ ),核化解 $(K + \lambda I)^{-1} y$ 跟原始岭解 $(X^\top X + \lambda I)^{-1} X^\top y$ 在预测上完全相同——内积视角和坐标视角是同一个矩阵分解的两种写法,对线性核而言这种等价性甚至是逐元素精确的,差别只在数值精度。

没有迭代。 不像 SVM,没有 QP 要解。整个训练就是一次线性求解。$n$ 个训练点、$\mathcal{O}(d)$ 评估代价的核,总复杂度是 $\mathcal{O}(n^2 d)$ 构造 Gram 矩阵加 $\mathcal{O}(n^3)$ 求逆。预测每次 $\mathcal{O}(n d)$ ,是评估核与每个训练点的代价。

没有稀疏性——每个 $\alpha_i$ 一般都非零。这就是闭式解的代价:你用 SVM 那种稀疏支持向量结构换了"不用解 QP"。

从工程视角看,“没有迭代"也意味着没有早停、没有学习率调度、没有收敛诊断——失败模式更狭窄、调参表面更平坦,这恰恰是为什么核岭常常作为"快速基线"在跨问题的论文里频繁出现:你几乎不会因为优化器问题而错怪算法。

不过"没稀疏性"在实际部署里是个真问题。一个 $n = 10{,}000$ 训完的核岭模型预测一次要算 1 万次核求值,而同样数据训出的 RBF SVM 可能只有几百个 SV,预测代价小两个数量级。当部署延迟要求严格(比如在线推理 < 10 ms)时,核岭往往输给 SVM;当训练后预测频次少(离线分析)或预测延迟不敏感(批量打分)时,核岭的训练简洁性反过来占优。这条 trade-off 在论文里很少提,但在工程上反复出现。

$\lambda$ 的角色。 除了核自己的超参之外,$\lambda$ 是唯一旋钮。$\lambda$ 小意味着模型在训练数据上插值——$\lambda = 0$ 时任何训练点 $x_i$ 上的预测精确等于 $y_i$ ,这在训练标签干净时很棒,标签有噪声时就糟。

$\lambda$ 大则所有 $\alpha_i$ 被压向零,预测向均值回归,模型欠拟合。用交叉验证;对数网格 $\lambda \in \{10^{-6}, \ldots, 10^{2}\}$ 选留出 MSE 最小的。

一个反直觉的失败模式:$\lambda$ 选得"刚刚好"通过 5-fold CV 测试,但放到实际生产数据上残差骤增——往往是 train 和 test 的特征分布有 shift,CV 信号代表"对训练分布最优”,对 shifted 分布反而过拟合。这种情形下要么把 $\lambda$ 调大一档(牺牲 CV 精度换对分布漂移的鲁棒性),要么换用更稳健的损失(比如 Huber)。核岭的平方损失对异常值和分布漂移都敏感,是它众所周知的弱点之一。

核岭回归的留一交叉验证特别便宜,因为它能从单次拟合用闭式技巧算出来(LOO 残差通过 hat matrix $H = K(K + \lambda I)^{-1}$ 的对角分量分解出来)。

具体地,LOO 残差 $e_i^{\text{LOO}} = (y_i - \hat{y}_i) / (1 - H_{ii})$ ——单次拟合,对角元 $H_{ii}$ 复用,就拿到全部 $n$ 个 LOO 残差,不用真做 $n$ 次重新拟合。这条捷径让 $\lambda$ 选择几乎免费,是核岭相对 SVM 在调参体验上的一个隐藏优势。

值得一提的一个数值实践:当 $K + \lambda I$ 已经用 Cholesky 分解 $L L^\top$ 算过一次以后,对任意新 $\lambda'$ 重算的代价并不是从头 $\mathcal{O}(n^3)$ ,而是 $\mathcal{O}(n^3)$ 的常数压低了一截——因为 $K$ 的特征分解只需做一次,之后对每个 $\lambda$ 只是 $K + \lambda I$ 的对角加法和回代。KernelRidge 没有显式暴露这一加速接口,但你自己拼 eigh(K) 加循环很容易实现,超参网格扫描快 $5\times$$10\times$

更彻底的做法:核岭的 LOO-CV 残差 $e_i^{\text{LOO}} = (y_i - \hat{y}_i)/(1 - H_{ii})$$\lambda$ 是闭式可微的函数,可以直接用梯度优化器(L-BFGS)在 $\log \lambda$ 上最小化 LOO-MSE。这把整个超参选择降级成连续优化问题,不需要离散网格,调参体验直追 GP 的边际似然。GPML 工具箱(Rasmussen & Nickisch)里这套做法叫 “generalized cross-validation”,跟 LOO 在数值上几乎重合而更稳。

1
2
3
4
5
6
7
8
9
from sklearn.kernel_ridge import KernelRidge
import numpy as np

X = np.linspace(-3, 3, 80).reshape(-1, 1)
y = np.sin(X).ravel() + 0.1 * np.random.randn(80)

krr = KernelRidge(alpha=0.1, kernel="rbf", gamma=0.5)
krr.fit(X, y)
y_pred = krr.predict(np.linspace(-3, 3, 200).reshape(-1, 1))

注意 sklearn 把正则化参数叫 alpha(与标准岭回归对齐),不叫 $\lambda$ ,但它们是同一个东西。kernelgammaSVC 里行为完全一样。核岭回归没有 $C$ 参数,因为它没有 hinge 损失——整个损失全是平方误差,$\lambda$ 一人独控正则化。

这个 API 一致性背后是一段历史小八卦:scikit-learn 早期为 Ridge 选了 alpha,后来 KernelRidge 上线时为了一致性沿用了同一个名字,结果数学社区里大家都习惯叫 $\lambda$ ,所以新手第一次读源码总要愣一下。

核岭回归拟合带噪声的正弦波

关于条件数的实用注记。 $K + \lambda I$$\lambda$ 很小核很尖($\gamma$ 大)你有近重复训练点时会数值奇异。症状是 LinAlgError 或预测狂震荡。

修法:加大 $\lambda$ 、标准化特征、去重训练点、或换数值稳定求解器($K + \lambda I$ 的 Cholesky 分解,sklearn 内部就是这么做的)。Cholesky 之所以行得通,是因为 $K$ 半正定且 $\lambda > 0$$K + \lambda I$ 一定正定;如果哪一次它正定性失败,那是你的核实现有 bug。

一个具体诊断流程:先看 np.linalg.cond(K + lambda*np.eye(n)),超过 $10^{12}$ 说明已经病态;再看 Gram 矩阵的对角元方差,若 $K_{ii}$ 之间差异巨大(如某些点是 0 某些点是 1),说明特征没标准化;最后看是否有 $K_{ij} \approx K_{ii}$ 的近重复行——这是去重最直接的信号。

值得提一句"jitter"小技巧:GP 实现里常见的做法是给 $K$ 主对角线加一个极小常数 $\epsilon \sim 10^{-6}$ ,等价于一个额外的微小 $\lambda$ ,用来稳住 Cholesky。这条技巧从 GP 偷过来用在核岭上也完全合法,比改算法参数更轻量。如果你看到论文里写 “we added jitter of $10^{-6}$ to the diagonal”,作者多半是在跟这条数值不稳定较劲。

核岭回归 vs 高斯过程#

$$\hat{f}_{\text{KRR}}(x) = \mathbf{k}(x)^\top (K + \lambda I)^{-1} y = \mathbb{E}\bigl[f(x) \mid \mathcal{D}\bigr]_{\text{GP}}.$$

这不是比喻,也不是"差不多"——它们就是同一个公式。那么为什么被当成两个不同的算法?

差别在概率解释。 GP 回归不止给你点预测,还给你每个测试点上的完整后验分布——附带方差。核岭回归只给你点估计。那个额外的方差正是 GP 在贝叶斯优化、主动学习、不确定性量化里流行的原因——你知道在每个查询点自己有多不知道,方差在远离训练数据的输入区域会变大。核岭回归没有这一切。

这一点不可低估:在主动学习里,下一个标注样本的选择正是基于"哪个点的后验方差最大";在贝叶斯优化里,acquisition function(EI、UCB)的核心成分就是后验方差。把核岭升级成 GP 几乎是零代价(同一个矩阵分解),换来的是一整套决策理论。

后验方差的几何也值得讲一下:$\sigma_*^2(x) = K(x, x) - \mathbf{k}(x)^\top (K + \lambda I)^{-1} \mathbf{k}(x)$ 。第一项是这个点处的先验方差(用 RBF 核就是 $1$ ),第二项是训练数据带来的"信息减量"。当 $x$ 离所有训练点都远时 $\mathbf{k}(x) \approx 0$ ,方差回到先验值;当 $x$ 落在某个训练点附近时方差被压到 $\lambda$ 左右——也就是噪声水平。这条公式把"远离数据 → 不确定性大"翻译成精确的矩阵代数,不需要任何假设或近似。

代价一样。 两个算法都需要同一个 $\mathcal{O}(n^3)$ 的逆,所以没有计算上的理由偏好哪个。只需要点预测时用核岭回归;需要校准的不确定性时用 GP。第 6 篇 会详细展开这一对偶,包括 GP 框架如何让你学习核超参(最大化边际似然)——这是核岭回归没有的奢侈品。

具体而言,给定数据 $(X, y)$ ,GP 的边际似然 $p(y \mid X, \theta)$ 是关于核超参 $\theta$ (如 RBF 的 $\gamma$ )和噪声方差 $\sigma_n^2$ 的可微函数,可以用 L-BFGS 直接最大化。结果是一组数据驱动的最优超参,不需要任何 train/val split。核岭则没有这个机制——它没有似然,只有平方损失,所以没办法对超参做极大似然估计。如果你要把核岭当成"统计模型"用,要么手动包一层 CV,要么直接换成 GP。

边际似然还有一个非平凡的性质叫"Occam 剃刀效应":过复杂的核(比如长度尺度过短)虽然能在训练数据上拟合得很好,但边际似然会因为"先验质量被分散到太多无关函数上"而下降。这是贝叶斯框架自带的正则化,不需要额外加。频率派要做模型选择必须搬出 AIC/BIC/CV,贝叶斯派一个边际似然全干完——这条优势在小数据 regime 下特别明显,对应核岭加 CV 的体验差距能拉到一两个数量级。

一个微妙的对应。 核岭超参 $\lambda$ 对应 GP 的噪声方差 $\sigma_n^2$ 。核的带宽 $\gamma$ 对应 GP 的长度尺度。GP 框架给你一条原则上的路从数据学这些参数(最大化边际似然),而不用交叉验证——这是贝叶斯框架的实操优势之一。

核岭交叉验证需要选 CV 方案、度量、网格;GP 边际似然这些选择都不用做。代价是低数据量时边际似然可能过拟合,留出 CV 不会。Rasmussen & Williams 2006 的第 5 章专门讨论了边际似然 vs 留出 CV 的偏差—方差权衡:经验上 $n \gtrsim 200$ 时边际似然几乎总赢,$n < 50$ 时反过来更不稳。

统一视角:representer theorem 三连发#

退后看三个推导的形状。SVM 里 $w = \sum_i \alpha_i y_i \phi(x_i)$ 。核 PCA 里主方向 $v_k = \sum_i \alpha_i^{(k)} \phi(x_i)$ 。核岭里 $w = \sum_i \alpha_i \phi(x_i)$ 。每个算法的最优解都是特征空间里训练点的线性组合,由 $n$ 个系数加权。无穷维优化坍塌成 $n$ 维优化,从头到尾只有 Gram 矩阵 $K$ 这一个对象出场。

这种"无穷维问题变有限维"的现象在数学里被称作塌缩(collapse),是 RKHS 理论给应用数学最实在的礼物。物理学家会把它当成"自由度的有效约简"——理论上无穷自由度的系统在合适的约束下表现得只像有限自由度的系统;计算机科学家会把它当成"参数化的隐式 trick"——用有限的训练点编码了一个无穷维的假设类。两种视角都对,都指向同一个数学事实。

这不是巧合,是 representer theorem——第 3 篇 里证过——它说:对任何只通过训练点处的取值 $\{f(x_i)\}_{i=1}^n$ 依赖 $f$ 的损失,加上 $\|f\|_{\mathcal{H}_K}$ 的单调递增函数,整个 RKHS 上的最优 $f^*$ 一定住在 $\{K(x_i, \cdot)\}_{i=1}^n$ 张成的有限维子空间里。

SVM、PCA、岭回归都符合这个模板,logistic 回归、Fisher 判别、分位数回归还有一大堆经典算法也都符合。一旦你看过一次核化,等于看过了所有。

ESL 第 5.8 节和 Schölkopf & Smola 2002 的第 4 章都把这条定理的若干变体证得很干净;推广版本(如 Schölkopf, Herbrich & Smola 2001 的"广义 representer theorem")放松了正则项为 $\|f\|$ 单调函数的要求,覆盖更多正则项形状,但日常使用里前面的版本够了。

复杂度速览:

算法训练代价预测代价稀疏性输出
核 SVM$\mathcal{O}(n^2)$$\mathcal{O}(n^3)$$\mathcal{O}(n_{\text{SV}} d)$是——仅 SV类别标签
核 PCA$\mathcal{O}(n^3)$ 特征分解$\mathcal{O}(n d)$ 每分量$k$ 维编码
核岭$\mathcal{O}(n^3)$ 线性求解$\mathcal{O}(n d)$实值预测

三个都被 $\mathcal{O}(n^3)$ 矩阵操作主导——这就是核方法在没有第 7 篇 那些近似时无法 scale 到 web 数据规模的结构性原因。差别在哪种矩阵操作(SVM 的 QP,PCA 的特征分解,岭的线性求解),以及输出是否稀疏——SVM 的 $\alpha$ 因 KKT 互补松弛而稀疏,PCA 和岭一般不稀疏。

三者的内存代价都是 Gram 矩阵的 $\mathcal{O}(n^2)$ ,在 16GB 机器上用 float64 大约 $n = 30{,}000$ 就成约束。

把这三行表读成一个共同模式:所有核方法在工程上都被"$n^2$ 内存 + $n^3$ 计算"两堵墙挡住,差别只在墙后头你拿走什么。SVM 给你最稀疏的输出和最快的预测;核 PCA 给你一个降维表示;核岭给你最简洁的训练循环和最丰富的概率推广(接 GP)。三个算法都不可能"通过更聪明地用 RAM" 突破 $\mathcal{O}(n^2)$ ——突破必须来自结构性近似,那是第 7 篇 的主题。

值得在表外补一句:表里的 $n^3$ 都是渐近常数,实际 wall-clock 时间还受 BLAS 实现、缓存命中、并行度等系统因素影响。同样的 $n = 10{,}000$ 在装了 Intel MKL 的机器上可能比 OpenBLAS 快 2–3 倍,比 reference BLAS 快 10 倍。所以"什么时候应该上 Nyström" 的临界 $n$ 不是固定数字,要结合你的 BLAS 实测——很多人在不该近似的规模上提早上了近似,损失了精度却没拿到速度收益。

三个算法在同一份数据上对比

一个元观察。 在野外遇到任何线性算法——Fisher LDA、典型相关分析、偏最小二乘、核 logistic 回归——你心里冒出"要是它能非线性就好了",先看看损失是不是只通过内积依赖数据。如果是,representer theorem 适用,核化是机械的,一个下午能搞定。如果不是,得换个招(往往是神经网络风格的显式特征学习——第 8 篇 会对比)。

这条判据在实践中的命中率惊人地高:2000–2010 年那波"核 X"论文海啸(核 ICA、核 CCA、核 FDA、核 PLS……)基本上都遵循同一个三步配方——读原算法的损失函数、找出内积、换成 $K$ 。能写成一篇论文的工作量,本质上是确认 PSD 性质和给出实验。

这个"核 X"模式到 2010 年代中后期才开始式微,原因不是 representer theorem 失灵,而是数据规模冲破了 $\mathcal{O}(n^3)$ 的天花板,深度学习用 SGD + 显式特征学习把同一片应用空间收割了。但今天回头看,那批论文留下的最大遗产不是任何单个 “核 X” 算法本身——而是"任何线性算法都能机械核化"这条元认知,它至今仍是把新出现的损失函数搬上 RKHS 的标准入口。

第二个元观察。 核不是给线性算法加非线性的唯一办法。其他路径有:(i) 显式基扩展(多项式特征、B 样条、傅里叶特征),本质是核技巧的显式版本,极限下能恢复它;(ii) 在输入空间分区上集成线性模型(决策树、随机森林、梯度提升);(iii) 深度学习——把仿射层和逐元素非线性叠起来,从数据学习特征映射 $\phi$ 而不是预先固定它。

每条路径都有自己的优势 regime。核方法在低数据、平滑函数、需要校准不确定性的场景下赢。树模型在表格数据、类别特征、不规则交互下赢。深度学习在感知数据(视觉、音频、语言)下赢——那里特征层级要从几百万样本里学。第 8 篇 会做正面对比。

这套"非线性化的四条路"是机器学习四十年发展史的一个截面:从 1990 年代的核到 2000 年代的集成树到 2010 年代的深度学习,每一波都在原有基础上拓宽适用 regime,而不是替代上一波——2026 年的工程师工具箱里这四样都得有。

一个常见的初学者错觉是"既然深度学习这么强,其它三条路是不是该淘汰"。事实正好相反:深度学习赢的是有大量数据 + 复杂感知模式的窄场景,剩下的世界——表格预测、地统计、生物医学小样本、贝叶斯优化、需要不确定性的工业控制——核方法和树模型仍然是首选。Kaggle 表格比赛的金牌方案到 2026 年仍以 LightGBM/XGBoost 为主,深度学习方案的占比变化缓慢;学术 ML 期刊里 GP 论文数量逐年上升,因为不确定性量化是大模型时代越来越紧的需求。“哪条路赢"取决于数据特性,不是发表年份。

接下来#

第 6 篇 会接住核岭与 GP 的对偶继续展开。我们正经搭高斯过程:函数上的先验、给定数据的后验、均值函数的选择、用最大边际似然学超参、后验方差到底告诉你什么。第 6 篇 看完,你会把核岭看作一个更丰富概率框架的特例,并准备好做贝叶斯优化、主动学习、带不确定性的回归。

之后第 7 篇 处理我们这一篇反复提到的 $\mathcal{O}(n^3)$ 天花板——Nyström、随机傅里叶特征、inducing points 三套主流近似,每套各有 trade-off;第 8 篇 收尾,把核方法跟深度学习摆在同一张桌子上对比,包括 NTK、深度核学习、神经切线核流形这些把"老核"和"新深度"嫁接起来的工作。读完整个系列,你不仅会用核方法,还会清楚知道什么时候不该用它、什么时候它跟其他范式之间的桥可以走通。

如果你只读这一篇就停下,带走一句话也够:核 SVM 是稀疏的、核 PCA 是无监督的、核岭回归是闭式的;它们的解都长 $\sum_i \alpha_i \phi(x_i)$ ,因为 representer theorem 这条结构性事实把无穷维优化压成了 $n$ 维优化。 后面三篇是把这条事实的能量榨干。


本文是 核方法 系列的第 5 篇,共 8 篇。 上一篇: 第 4 篇 — 常见核函数族 · 下一篇: 第 6 篇 — 高斯过程

本系列

核方法 8 篇

  1. 01 核方法(一):为什么需要它——从线性算法的天花板说起
  2. 02 核方法(二):数学基础——正定核与 Mercer 定理
  3. 03 核方法(三):RKHS——核方法的理论灵魂
  4. 04 核方法(四):常见核函数族——RBF、Matern、多项式、周期与更多
  5. 05 核方法(五):核 SVM、核 PCA 与核岭回归 当前
  6. 06 核方法(六):高斯过程——当核方法遇到贝叶斯推断
  7. 07 核方法(七):大规模核方法——Nystrom 近似与随机傅里叶特征
  8. 08 核方法(八):深度核学习 vs 深度学习——选择指南与故障排查

读有所得?

GitHub 关注我 → 新文周更

GitHub