从欧式空间到希尔伯特空间:机器学习中的数学基础入门指南
从欧式空间到希尔伯特空间:机器学习中的数学基础入门指南
很多机器学习实践者在阅读论文或高级教程时,都会遇到“希尔伯特空间”这个听起来颇为高深的概念。对于没有数学背景的开发者来说,它常常被描述为“完备的内积空间”或“欧式空间的推广”,这些定义本身就像一堵墙,将直观理解挡在外面。我们习惯于将向量视为一组有序的数字,例如 [1.2, -0.5, 3.1],并在其中进行点积、计算距离。但当支持向量机的核方法、函数逼近甚至深度学习的某些理论开始频繁提及“函数空间”和“再生核”时,那种熟悉的几何直观似乎消失了。这篇文章的目的,就是为你重新搭建这座桥梁。我们将从你最熟悉的欧式空间操作出发,一步步走向希尔伯特空间的抽象世界,并最终让你看到,这个抽象的数学框架如何具体地支撑起像支持向量机这样的强大工具。整个过程,我们会用代码和几何类比来替代纯粹的公式推导,让你亲手“触摸”这些概念。
1. 重温基石:从向量、空间到内积
在深入未知领域前,让我们先巩固一下大本营。我们熟悉的欧式空间,比如三维空间 ℝ³,其元素是向量 v = (x, y, z)。这个空间之所以强大,是因为我们为其装备了两件核心武器:线性结构和度量结构。
线性结构意味着我们可以对向量进行加法和数乘,并且这些运算满足一系列直观的规则(封闭性、结合律、分配律等)。这允许我们将空间中的点进行组合与缩放。而度量结构,则源于我们定义的内积(点积)。对于两个向量 u = (u1, u2, u3) 和 v = (v1, v2, v3),其内积定义为:
<u, v> = u1*v1 + u2*v2 + u3*v3
这个简单的运算蕴含着丰富的几何意义:
- 长度(范数):向量
v的长度||v||就是其与自身内积的平方根,即sqrt(<v, v>)。 - 夹角:两个向量的夹角 θ 可以通过
cosθ = <u, v> / (||u|| * ||v||)计算。内积为零意味着垂直(正交)。 - 投影:一个向量在另一个向量方向上的“影子”长度,可以通过内积计算。
关键的思想跃迁在于:向量不一定非得是 (x, y, z) 这种形式。任何满足线性空间那八条公理的对象的集合,都可以构成一个向量空间。那么,函数呢?考虑所有定义在区间 [0, 1] 上的连续函数 f(x) 的集合。我们可以定义函数的加法和数乘:
(f+g)(x) = f(x) + g(x)(c*f)(x) = c * f(x)
这个集合也满足线性空间的所有要求。因此,函数也可以被视为向量,只不过它们是“无限维”的向量——每个 x 的取值对应一个“维度”。那么,我们能否为这些“函数向量”也定义一个类似点积的运算,从而引入几何概念呢?答案是肯定的,这就是函数内积。
对于两个函数 f 和 g,一个常见的内积定义是它们的积分:
<f, g> = ∫ f(x) * g(x) dx (在某个区间上,比如 [0, 1])
这个定义同样满足内积所需的对称性、线性和正定性。现在,函数 f 的“长度”就是 sqrt(∫ f(x)² dx),两个函数的“夹角”和“正交性”也有了定义。装备了这样一个内积的函数空间,我们就得到了一个内积空间。它已经具备了欧式空间的许多几何特性。
注意:这里我们略过了严格的数学细节,例如函数需要属于
L²空间(平方可积)以保证内积有限。对于应用理解,我们可以先接受在“表现良好”的函数集合上,这个定义是成立的。
2. 完备性:从内积空间到希尔伯特空间
拥有了内积,我们得到了一个可以谈论角度和距离的空间。但还有一个关键性质将普通的内积空间与希尔伯特空间区分开来:完备性。
什么是完备性?直观上,你可以把它理解为“空间没有漏洞”。考虑有理数集合,它在通常的距离定义下是不完备的,因为像 √2 这样的极限点(一个有理数序列的极限)本身不是有理数。在函数空间中,完备性意味着:如果一个函数序列(可以想象为一串越来越接近某个形状的函数)在由内积导出的距离意义下彼此越来越接近(柯西序列),那么它的极限一定也在这个空间里。
让我们用 Python 来感受一下“收敛”和“极限不在空间中”的概念。考虑在区间 [0, 1] 上,用多项式去逼近一个在 x=0.5 处有跳跃的函数。
import numpy as np
import matplotlib.pyplot as plt
# 定义目标函数:一个在0.5处跳跃的阶梯函数
def target_func(x):
return np.where(x < 0.5, 0, 1)
# 定义一组逼近多项式(伯恩斯坦多项式形式)
def bernstein_poly(n, k, x):
from math import comb
return comb(n, k) * (x**k) * ((1-x)**(n-k))
def approx_func(n, x):
"""用n次伯恩斯坦多项式逼近阶梯函数"""
total = 0.0
for k in range(n+1):
total += target_func(k/n) * bernstein_poly(n, k, x)
return total
# 可视化
x = np.linspace(0, 1, 400)
y_target = target_func(x)
plt.figure(figsize=(12, 8))
for i, n in enumerate([2, 5, 10, 20, 50]):
y_approx = approx_func(n, x)
# 计算L2距离(内积导出的距离的平方)
l2_dist = np.sqrt(np.trapz((y_target - y_approx)**2, x))
plt.subplot(2, 3, i+1)
plt.plot(x, y_target, 'k-', linewidth=2, label='Target (Step)')
plt.plot(x, y_approx, 'r--', linewidth=1.5, label=f'n={n}')
plt.title(f'n={n}, L2 Dist ≈ {l2_dist:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
运行这段代码,你会看到随着多项式次数 n 增加,逼近曲线越来越接近阶梯函数。在 L² 距离(由函数内积 ∫ (f-g)² dx 的平方根定义)下,这个多项式序列是一个柯西序列。然而,它的极限——那个阶梯函数——本身并不是一个连续函数(在 x=0.5 处不连续)。如果我们只考虑所有连续函数构成的内积空间,那么这个极限就不在该空间内,因此该空间是不完备的。
希尔伯特空间要求是完备的内积空间。为了得到希尔伯特空间,我们需要将空间扩展,包含所有此类极限点。对于函数空间,这就是著名的 L² 空间——所有平方可积函数的集合(严格定义涉及勒贝格积分)。L² 空间就是一个希尔伯特空间的例子。完备性保证了我们在进行极限操作、无穷级数展开(如傅里叶级数)时不会“掉出”空间之外,这在理论分析和保证算法收敛性时至关重要。
从内积空间到希尔伯特空间的关键升级路径可以总结如下:
| 空间类型 | 核心结构 | 关键性质 | 例子 |
|---|---|---|---|
| 向量空间 | 加法、数乘 | 线性组合仍在空间内 | 所有三维向量 (x,y,z);所有多项式函数 |
| 内积空间 | 向量空间 + 内积 <·, ·> | 可定义长度、角度、正交 | 欧式空间 ℝⁿ;连续函数空间 C[a,b](装备积分内积) |
| 赋范空间 | 向量空间 + 范数 ` | · | |
| 度量空间 | 集合 + 距离函数 d(·,·) | 可谈论收敛、极限 | 任何赋范空间(由范数导出距离) |
| 希尔伯特空间 | 完备的内积空间 | 柯西序列的极限仍在空间内 | 欧式空间 ℝⁿ;平方可积函数空间 L² |
3. 函数作为向量:傅里叶级数的几何解读
理解了函数可以作为无限维向量,并且它们构成希尔伯特空间后,一个绝佳的例子就是傅里叶级数。这可能是连接有限维几何直观和无限维函数空间最经典的桥梁。
在高维欧式空间中,任何向量都可以表示为一组标准正交基向量的线性组合。例如在 ℝ³ 中,向量 v = (2, 1, 3) 可以写成:
v = 2 * (1,0,0) + 1 * (0,1,0) + 3 * (0,0,1)
系数 2, 1, 3 正是 v 与各个基向量 e1, e2, e3 的内积。
在由 L² 函数构成的希尔伯特空间中,我们也可以找到一组“标准正交基函数”。对于定义在 [-π, π] 上的平方可积函数,一组著名的正交基是三角函数族:
{1/√(2π), cos(x)/√π, sin(x)/√π, cos(2x)/√π, sin(2x)/√π, ...}
这些函数两两之间的内积(积分)为0(正交),且每个函数与自身的内积为1(归一化)。那么,任何一个该空间中的函数 f(x),都可以像向量一样,表示为这组基函数的线性组合:
f(x) = a₀/√(2π) + Σ [aₙ * cos(nx)/√π + bₙ * sin(nx)/√π]
其中,系数 aₙ 和 bₙ 正是函数 f(x) 与对应基函数的内积:
aₙ = <f(x), cos(nx)/√π> = ∫ f(x) * cos(nx)/√π dxbₙ = <f(x), sin(nx)/√π> = ∫ f(x) * sin(nx)/√π dx
这就是傅里叶级数展开的几何本质:将一个函数向一组正交的基函数上投影,得到其在这个“坐标系”下的坐标。 系数的大小反映了函数中包含该频率分量的“多少”。下面我们用代码来可视化这个投影过程。
import numpy as np
import matplotlib.pyplot as plt
# 定义一个目标函数,例如一个锯齿波
def target_f(x):
# 周期为2π的锯齿波
return (x + np.pi) % (2*np.pi) - np.pi
# 计算傅里叶系数 (到第N阶)
def fourier_coeffs(f, N):
a = [0] * (N+1)
b = [0] * (N+1)
n_points = 1000
x_vals = np.linspace(-np.pi, np.pi, n_points, endpoint=False)
f_vals = f(x_vals)
dx = x_vals[1] - x_vals[0]
# a0
a[0] = np.trapz(f_vals, x_vals) / (2*np.pi)
# an, bn
for n in range(1, N+1):
a[n] = np.trapz(f_vals * np.cos(n*x_vals), x_vals) / np.pi
b[n] = np.trapz(f_vals * np.sin(n*x_vals), x_vals) / np.pi
return a, b
# 用傅里叶级数重构函数
def fourier_reconstruct(x, a, b):
result = a[0] / 2.0 # 注意a0项的形式
N = len(a) - 1
for n in range(1, N+1):
result += a[n] * np.cos(n*x) + b[n] * np.sin(n*x)
return result
# 主程序
N = 10 # 使用的最大谐波次数
a, b = fourier_coeffs(target_f, N)
x_plot = np.linspace(-3*np.pi, 3*np.pi, 1200)
y_target = target_f(x_plot)
y_approx = fourier_reconstruct(x_plot, a, b)
plt.figure(figsize=(12, 5))
plt.plot(x_plot, y_target, 'b-', linewidth=2, alpha=0.7, label='Target Function')
plt.plot(x_plot, y_approx, 'r--', linewidth=2, label=f'Fourier Series (N={N})')
plt.title('Function as Vector: Fourier Series Approximation')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 打印前几个系数,即“坐标”
print("傅里叶系数(函数在正交基上的坐标):")
for n in range(min(5, N+1)):
print(f" a[{n}] = {a[n]:.4f}, b[{n}] = {b[n]:.4f}")
运行代码,你会看到红色的傅里叶级数逼近蓝色的锯齿波函数。输出的系数 a[n] 和 b[n] 就是函数 f(x) 在 cos(nx) 和 sin(nx) 这两个“方向”上的“坐标”或“投影长度”。随着 N 增大,逼近会越来越精确。这完美诠释了希尔伯特空间中的几何:函数是点,内积定义投影,正交函数系是坐标系,级数展开就是坐标表示。
4. 核技巧与再生核希尔伯特空间
现在,我们进入机器学习的核心应用场景。支持向量机在处理线性不可分数据时,会使用一个巧妙的“核技巧”:将数据映射到一个高维(甚至无限维)的特征空间,希望在那个空间里数据变得线性可分。这个映射 Φ(x) 往往是隐式的,我们不需要知道它的具体形式,只需要知道映射后两个向量的内积 K(x, y) = <Φ(x), Φ(y)>,这个 K 就是核函数。
那么,这个高维特征空间是什么?理论上,它就是一个希尔伯特空间。更具体地说,对于给定的核函数 K,存在一个唯一的希尔伯特空间与之对应,称为再生核希尔伯特空间。RKHS 有一个非凡的性质,叫做再生性:
f(x) = <f, K(x, ·)> 对于空间中的所有函数 f 成立。
这里 K(x, ·) 是一个以 x 为参数的函数(固定核函数的一个变量)。这个性质意味着,核函数 K(x, ·) 可以看作是 RKHS 中的一组特殊基函数(称为再生核),而函数 f 在 x 点的取值,就等于 f 与这个基函数 K(x, ·) 的内积。这类似于在有限维欧式空间中,向量 v 的第 i 个分量 v_i 等于 v 与标准基向量 e_i 的内积。
让我们以最常见的高斯核为例,来直观感受一下 RKHS 的威力。高斯核定义为:
K(x, y) = exp(-γ * ||x - y||²)
它对应的映射 Φ 将数据隐式地映射到一个无限维的空间。在这个无限维的 RKHS 中,数据点 x 被表示为函数 K(x, ·)。SVM 在这个空间里寻找一个线性超平面。由于空间维度极高(无限),线性可分的可能性大大增加。而这个超平面在原输入空间中的“倒影”,就是一个复杂的非线性决策边界。
下面的代码演示了如何使用高斯核将二维平面上的“异或”问题(线性不可分)映射到高维空间后,变得近似线性可分。我们通过核主成分分析来可视化这种“拉伸”效果。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import KernelPCA
from sklearn.datasets import make_circles
# 创建一个线性不可分的经典数据集:两个同心圆
X, y = make_circles(n_samples=400, factor=0.3, noise=0.05, random_state=42)
# 使用核PCA(基于核函数)将数据映射到高维空间,再投影回2维以便可视化
# 这模拟了在高维特征空间观察数据分布
gamma = 15 # 高斯核参数
kpca = KernelPCA(n_components=2, kernel='rbf', gamma=gamma)
X_kpca = kpca.fit_transform(X)
# 可视化
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 原始空间
scatter1 = axes[0].scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', edgecolor='k', alpha=0.7)
axes[0].set_title('Original Space (Linearly Inseparable)')
axes[0].set_xlabel('Feature 1')
axes[0].set_ylabel('Feature 2')
axes[0].grid(True, alpha=0.3)
# 经过核映射后的空间(通过核PCA的2维投影)
scatter2 = axes[1].scatter(X_kpca[:, 0], X_kpca[:, 1], c=y, cmap='viridis', edgecolor='k', alpha=0.7)
axes[1].set_title(f'Feature Space via RBF Kernel (gamma={gamma})\n(Projected back to 2D for visualization)')
axes[1].set_xlabel('First Kernel Principal Component')
axes[1].set_ylabel('Second Kernel Principal Component')
axes[1].grid(True, alpha=0.3)
plt.colorbar(scatter1, ax=axes[0], label='Class')
plt.colorbar(scatter2, ax=axes[1], label='Class')
plt.tight_layout()
plt.show()
print("观察右图:经过高斯核映射后,在特征空间的投影中,两个类别的数据分布被‘拉伸’开,变得更容易用线性平面分隔。")
通过调整 gamma 参数,你可以看到映射后空间形态的变化。这个可视化虽然只是高维空间的一个二维投影,但它清晰地展示了核函数如何通过改变数据的几何结构来解决线性不可分问题。而这一切的理论基石,正是再生核希尔伯特空间——它为核函数提供了一个严格、优美且功能强大的数学家园。
从有限维的欧式几何到无限维的函数空间,希尔伯特空间的概念为我们提供了描述和分析复杂数据与模型的统一语言。理解它,不仅能让你更深刻地掌握 SVM 的核方法,也为理解更广泛的基于核的学习方法、高斯过程乃至函数数据分析打开了大门。下次当你调用 sklearn.svm.SVC(kernel=‘rbf’) 时,希望你能想起,这行简洁的代码背后,是一个关于空间、映射与内积的宏大几何故事。
更多推荐


所有评论(0)