核函数基础:从线性不可分到高维映射
说实话,我刚接触机器学习那会儿,对核函数也是一头雾水。当时我在做一个文本分类项目,数据在二维空间里根本分不开,就像一团乱麻。后来导师跟我说:「试试核函数吧。」我试了,效果出奇的好。今天我就把这块硬骨头给你啃下来。
什么是核函数?
核函数,说白了就是一个特殊的函数。它接收两个样本点作为输入,输出一个实数。这个实数代表了这两个样本在某个高维空间中的相似度。
你可能会问:「这不就是计算相似度吗?有什么特别的?」
嗯,特别之处在于——它不需要你显式地把数据映射到高维空间。直接算就行。我习惯把核函数比作「隐形传送门」:你输入低维数据,它直接给你高维空间的内积结果,中间过程完全黑盒。
核函数的数学定义:
设 χ 是输入空间(通常是低维欧氏空间),存在一个映射 φ: χ → H,其中 H 是希尔伯特空间(高维特征空间)。核函数 K 满足:
K(x, z) = ⟨φ(x), φ(z)⟩
其中 ⟨·,·⟩ 表示 H 中的内积。
核函数在机器学习中的角色
核函数在机器学习里扮演的角色,我总结为三个关键词:升维、内积、隐式计算。
- 解决线性不可分问题:原始空间里分不开的数据,映射到高维后往往就线性可分了。我在做手写数字识别时遇到过这种情况,原始像素特征根本分不清 0 和 6,用了 RBF 核之后,准确率直接提升了 15%。
- 降低计算复杂度:直接做高维映射,计算量是灾难性的。核函数让你在低维空间里完成高维计算,复杂度从 O(d²) 降到 O(d),d 是原始维度。
- 构建非线性模型:在 SVM、PCA、线性回归等算法中嵌入核函数,就能把它们变成非线性版本。这就是所谓的「核化」。
| 算法 | 无核函数 | 有核函数 |
|---|---|---|
| SVM | 线性分类器 | 非线性分类器 |
| PCA | 线性降维 | 非线性降维(KPCA) |
| 线性回归 | 线性拟合 | 非线性拟合(KRR) |
核技巧的本质
核技巧,英文叫 Kernel Trick。它的本质就一句话:用低维空间的内积计算,替代高维空间的内积计算。
举个例子。假设有两个二维样本 x = (x₁, x₂),z = (z₁, z₂)。我想把它们映射到三维空间:
φ(x) = (x₁², x₂², √2·x₁·x₂)
直接计算高维内积:
⟨φ(x), φ(z)⟩ = x₁²·z₁² + x₂²·z₂² + 2·x₁·x₂·z₁·z₂
这个计算量还行。但如果映射到 1000 维呢?直接算就炸了。
现在用核技巧。我定义一个核函数:
K(x, z) = (⟨x, z⟩)²
展开看看:
K(x, z) = (x₁·z₁ + x₂·z₂)²
= x₁²·z₁² + x₂²·z₂² + 2·x₁·x₂·z₁·z₂
发现没?结果和 ⟨φ(x), φ(z)⟩ 一模一样!但计算量从 O(d²) 降到了 O(d)。
我的经验之谈: 核技巧最妙的地方在于,你甚至不需要知道 φ 的具体形式。只要核函数满足 Mercer 条件(对称且半正定),它就对应某个特征空间中的内积。我曾经踩过一个坑:自己随便定义了一个核函数,结果训练出来的模型完全不收敛。后来一查,那个核函数不满足 Mercer 条件。所以记住:不是所有函数都能当核函数用。
常见核函数一览
实际项目中,我常用的核函数就这几种:
- 线性核:K(x, z) = ⟨x, z⟩。说白了就是不做映射,适合数据本来就线性可分的情况。
- 多项式核:K(x, z) = (⟨x, z⟩ + c)ᵈ。d 控制复杂度,c 控制偏移。我一般 d 不超过 3,否则容易过拟合。
- RBF 核(高斯核):K(x, z) = exp(-γ||x - z||²)。最常用的核函数,没有之一。γ 参数很敏感,我习惯用网格搜索调参。
- Sigmoid 核:K(x, z) = tanh(α⟨x, z⟩ + c)。某些情况下等价于两层神经网络。
避坑指南: 我曾经在图像分类任务中直接用了 RBF 核,结果训练时间长得离谱。后来发现图像特征维度太高(几千维),RBF 核的 Gram 矩阵计算量是 O(n²·d),n 是样本数。对于高维稀疏数据,线性核往往更高效。记住:核函数不是越复杂越好,适合数据特点才是王道。
核函数的知识体系
下面这张图是我自己梳理的核函数知识结构,帮你快速建立全局认知:
这张图把核函数的核心脉络理清楚了。从上到下依次是:数学基础 → 核心技巧 → 具体实现 → 实际应用。你想想看,掌握了这个框架,以后遇到任何核函数相关的问题,都能快速定位到对应环节。
核函数与核矩阵
实际编程中,我们很少直接操作核函数。我们操作的是核矩阵(Gram 矩阵)。
给定 n 个样本,核矩阵 K 是一个 n×n 的矩阵,其中 Kᵢⱼ = K(xᵢ, xⱼ)。
核矩阵有两个重要性质:
- 对称性:Kᵢⱼ = Kⱼᵢ
- 半正定性:对任意向量 v,有 vᵀKv ≥ 0
这两个性质保证了核函数对应的特征空间是合法的。我在项目中调试核函数时,第一件事就是检查核矩阵是否半正定。如果发现特征值出现负数(由于浮点误差可能极小负数),我会加一个小量 ε 到对角线上做正则化。
# 核矩阵计算示例(Python伪代码)
def compute_kernel_matrix(X, kernel_func):
n = X.shape[0]
K = np.zeros((n, n))
for i in range(n):
for j in range(n):
K[i, j] = kernel_func(X[i], X[j])
# 检查半正定性
eigenvalues = np.linalg.eigvalsh(K)
if np.min(eigenvalues) < -1e-10:
print("警告:核矩阵不是半正定的!")
return K
小技巧: 实际工程中,我很少自己写核矩阵计算。Scikit-learn 提供了现成的 pairwise_kernels 函数,支持多种核函数,而且底层用 C 加速,比 Python 循环快两个数量级。你想想看,10000 个样本的核矩阵,自己写循环可能要跑几分钟,用现成函数几秒钟就搞定了。
好了,核函数的基础就讲到这里。记住三个核心点:核函数是隐式高维映射的桥梁,核技巧是低维计算高维内积的魔法,核矩阵是实际编程中的操作对象。把这些吃透了,后面学核 SVM、核 PCA 就会轻松很多。
想要更多资料,联系可可