查看全课大纲(第 74 / 82 节)
  1. 1.函数与数据泛化
  2. 2.向量:从几何直觉到高维空间
  3. 3.矩阵与张量
  4. 4.特征值与特征向量:矩阵变换的不动方向
  5. 5.凸函数:从向量求导的矩阵记号到好优化的函数形状
  6. 6.概率与统计:机器学习的数学基础
  7. 7.独立性与随机变量:贝叶斯公式与二项分布
  8. 8.期望、方差与协方差:随机变量的数字画像
  9. 9.联合概率:当一条轴不够用的时候
  10. 10.概率分布(一):从伯努利到伽马函数
  11. 11.概率分布(二):贝塔、泊松、正态与两个贝叶斯故事
  12. 12.机器学习的模型:找输入与输出的关系
  13. 13.机器学习的应用
  14. 14.过拟合
  15. 15.机器学习的分类
  16. 16.有监督学习:从房价预测说起
  17. 17.损失函数
  18. 18.梯度下降(上):更新规则与学习速率
  19. 19.梯度下降(2)
  20. 20.牛顿方法
  21. 21.KNN简介
  22. 22.距离测算
  23. 23.朴素贝叶斯
  24. 24.朴素贝叶斯的实际应用
  25. 25.信息熵:决策树构建的度量基础
  26. 26.信息增益与决策树的构建
  27. 27.ID3算法
  28. 28.决策树节点的划分
  29. 29.CART树
  30. 30.Bagging
  31. 31.Boosting:自适应提升算法
  32. 32.Gradient Boosting
  33. 33.线性模型:回归与分类的同一副骨架
  34. 34.最小二乘:把最优参数直接解出来
  35. 35.最小二乘法的几何与概率视角
  36. 36.极大似然:给最小二乘一个概率出身
  37. 37.逻辑回归(1):把线性模型接到分类上
  38. 38.逻辑回归(2):损失函数与多分类
  39. 39.---- 手造数据: 5 个样本, 2 个特征; x2 几乎 = 2*x1 (偏差手工指定, 无随机) ----
  40. 40.讲师例: 向量 "23014" -- 三把范数尺子量同一个向量
  41. 41.优化方法(1):坐标下降与前向选择
  42. 42.优化方法(2):前向策略与最小角回归
  43. 43.拉格朗日乘子法(1):从无约束到等式约束
  44. 44.拉格朗日乘子法(2):等式约束下的平行条件与拉格朗日函数
  45. 45.拉格朗日乘子法(3):不等式约束与 KKT 条件
  46. 46.最大间隔:把分类问题变成优化问题
  47. 47.拉格朗日对偶问题:把 w 和 b 全部换成 α
  48. 48.支持向量:边界上的少数派
  49. 49.SVM 计算过程:一笔到底算完,再走进核方法
  50. 50.贝叶斯公式:概率即信念
  51. 51.隐含变量和概率模型:给看不见的原因建模
  52. 52.EM 算法:期望与最大化的迭代
  53. 53.琴生不等式:EM 的数学钥匙
  54. 54.三个硬币问题:EM 的复盘与衔接
  55. 55.高斯混合模型:用隐变量解释双峰数据
  56. 56.隐马尔可夫模型
  57. 57.隐马尔可夫模型(2):前向算法与动态混合模型
  58. 58.隐马尔可夫模型在 NLP 中的运用
  59. 59.EM 算法:把「为什么收敛」推到底
  60. 60.HMM 在 NLP 中的运用:从分词到机器翻译
  61. 61.HMM 参数估计:Baum-Welch 的三块拉格朗日
  62. 62.高维下的高斯模型
  63. 63.主题模型:从词袋到隐含主题
  64. 64.Dirichlet 分布(1)
  65. 65.Dirichlet 分布(2)
  66. 66.统计学习内容回顾
  67. 67.K-means 算法
  68. 68.PCA 降维
  69. 69.SVD 降维
  70. 70.从聚类到流形
  71. 71.局部线性嵌入
  72. 72.随机邻域嵌入:SNE 与 t-SNE
  73. 73.无参模型:让数据自己说话
  74. 74.高斯过程:函数空间里的正态分布
  75. 75.高斯过程(2):噪声、正则化与核的线性组合
  76. 76.神经网络简介:从感知器到自编码器
  77. 77.反向传播:把误差一层层传回去
  78. 78.卷积神经网络(CNN):让特征自己学出来
  79. 79.循环神经网络(RNN):给网络装上记忆
  80. 80.深度学习回顾:静态一类,动态一类
  81. 81.增强学习(1):蒙特卡洛、树搜索与 Q-learning
  82. 82.强化学习(2):从乌鸦吃核桃到井字棋的 value 回传

高斯过程:函数空间里的正态分布

约 23 分钟

📺 正在播放小象官方高清录播(支持倍速与清晰度调节)

小象实战讲义 · 机器学习算法精讲

上一节我们讲了无参模型的开场:KNN 推广到核加权、KDE 用小高斯叠加出密度。这一节进入一个特别重要的非参数模型——高斯过程(Gaussian process,GP)。讲师说,讲这个过程时想换一种讲法、看能不能让大家理解得更好一点——这也正是把 GP 和 KDE 放在一起讲的原因:我们研究的问题是类似的,都是给定数据之后的估计问题。但 GP 会给出一个比 KDE 更进一步的答案:它假设函数值本身服从高维正态分布,于是对任何新点的估计,给出的不是一个点,而是一个完整的分布。

💡 核心导读

  • process = 随机过程:Gaussian process(高斯过程)是随机过程(stochastic process)的一个特例——与高斯相关、定义在函数空间里。
  • 核心假设:给定 x1,x2,x3x_1, x_2, x_3,它们对应的函数值 (f1,f2,f3)(f_1, f_2, f_3) 这个三维向量,服从三维空间里的正态分布——均值向量 + 协方差矩阵。
  • 核函数填协方差:Kij=exp⁡(−λ(xi−xj)2)K_{ij} = \exp(-\lambda (x_i - x_j)^2)——自己跟自己对角线为 1,距离无穷大时趋 0;λ(兰姆达)是可调的宽窄旋钮。
  • 加一维就能预测:把 f∗f_* 加进联合分布变四维正态,用边缘概率取出 f∗∼N(μ∗,σ∗2)f_* \sim N(\mu_*, \sigma_*^2)——给的不是点的估计,是一个分布。
  • 扫出一条带带子的线:x∗x^* 从 min⁡\min 移到 max⁡\max,学出中心线;有数据的点方差小,没有数据的地方方差大。

从三点数据到一个假设

还是上一节类似的场景,给定三个数据:x1x_1、x2x_2、x3x_3。注意一个记号细节——它们对应的值,我们不用 yy 表示,用 f1,f2,f3f_1, f_2, f_3(讲师原话「一会告诉大家为什么我管它叫 f」):因为接下来要建模的对象,正是 xx 所对应的函数关系 ff 本身。现在来了新的问题:还有一个新的 x∗x^*,想估计它所对应的 f(x∗)f(x^*) 应该等于多少——这就是我们想估计的问题。

既然要做高斯过程,就需要一个假设。这个假设是:xx 所对应的函数关系 ff——xx 映射到 ff 这个函数上——在高维空间里服从一个正态分布。也就是说,给定的 f1,f2,f3f_1, f_2, f_3 是一个三维的向量,它服从三维空间上的高斯分布。

维度升级时,正态分布的「装备」也要升级:一维空间的正态分布是均值 μ\mu 和方差 σ2\sigma^2;到了不同维度,就是均值向量和协方差矩阵——所以这里的 σ\sigma 变成了一个协方差矩阵,比如三维的情形:

K=[K11K12K13K21K22K23K31K32K33]\mathbf{K} = \begin{bmatrix} K_{11} & K_{12} & K_{13} \\ K_{21} & K_{22} & K_{23} \\ K_{31} & K_{32} & K_{33} \end{bmatrix}

所以「给定 x1,x2,x3x_1, x_2, x_3,它们对应的函数值在高维空间服从正态分布」——这就是对高斯过程的假设。(当然也可以假设成其他的分布,那就是不同的 process;我们先考虑高斯这一种。)

协方差矩阵 K:kernel 的用武之地

假设有了,默认均值 μ=0\mu = 0,现在的问题是:协方差矩阵 K 应该怎么求?跟什么相关?

协方差代表的是这三个维度之间的关联和关系。每一个 xx 都是一个随机变量——K11K_{11} 代表 x1x_1 跟 x1x_1 之间的关系:自己跟自己,相关性完全百分之百,所以 K11K_{11} 应该等于 1(K22K_{22}、K33K_{33} 同理)。

那 K12K_{12} 和 K13K_{13},大家觉得哪个应该更大?它们描述的是 1 和 2 之间、1 和 3 之间的关系——而 1 到 2 的距离和 1 到 3 的距离不一样:离得近的一对,对应的值应该更高(讲师板书举例:比如近的那个是 0.7,远的那个是 0.2)。(讲师口播时把这句话说反了——「距离更大的话应该是更高的值」;按核函数的性质,距离小、相关性高、K 值大,正过来讲。)

那这些具体的 0.7、0.2 该怎么算?用什么办法?——我们刚才 18.1 节学了那么久,答案呼之欲出:用 kernel function。用核函数来构造协方差矩阵:xx 与 xx 之间的相对距离,化成一个权重的关系,这个权重关系就是高维空间的协方差矩阵。定义:

Kij=k(xi,xj)=exp⁡(−λ (xi−xj)2)K_{ij} = k(x_i, x_j) = \exp\left(-\lambda\,(x_i - x_j)^2\right)

验证它符合我们对 kernel 的定义:当 i=ji = j 时,xi−xj=0x_i - x_j = 0,exp⁡(0)=1\exp(0) = 1——对角线永远是 1 ✓;当 xix_i 与 xjx_j 的距离趋于无穷大时,权重趋于 0 ✓。而 λ\lambda(兰姆达)这个系数可以不断调整,从而构造出不同宽窄的核——λ 越大核越窄、λ 越小核越宽(注意它跟上一节 δ 的旋钮方向正好相反,大致是 λ≈1/(2δ2)\lambda \approx 1/(2\delta^2) 的关系)。

加一维:四维联合分布

有了协方差矩阵,怎么用它估计 x∗x^* 的 f∗f_*?思路漂亮得出奇:如果 f1,f2,f3f_1, f_2, f_3 服从三维空间的正态分布,那我们再给它加一维——f1,f2,f3,f∗f_1, f_2, f_3, f_* 四个一起,就服从四维空间的正态分布。这就是基本假设。而且 x∗x^* 可以不断加多:原来的 3 个数据再加 4 个新点,就是 7 维空间的分布;加 10 个,就是 13 维空间的分布——加得越多,就越高维的正态分布,这就是我们构造的高斯过程。

加了 x∗x^* 之后,协方差矩阵跟着扩成 4×44 \times 4:原来的 K11⋯K33K_{11} \cdots K_{33} 全部不变,多出一列 K1∗,K2∗,K3∗K_{1*}, K_{2*}, K_{3*}(新点与三个旧点)、一行 K∗1,K∗2,K∗3K_{*1}, K_{*2}, K_{*3},以及右下角的 K∗∗K_{**}。写成分块形式:

[f1f2f3f∗]∼N(0, [Kk∗k∗⊤K∗∗])\begin{bmatrix} f_1 \\ f_2 \\ f_3 \\ f_* \end{bmatrix} \sim \mathcal{N}\left(\mathbf{0},\ \begin{bmatrix} \mathbf{K} & \mathbf{k}_* \\ \mathbf{k}_*^\top & K_{**} \end{bmatrix}\right)

其中 fˉ=[f1,f2,f3]⊤\bar{f} = [f_1, f_2, f_3]^\top 服从三维的 N(0,K)\mathcal{N}(\mathbf{0}, \mathbf{K})(以前那个空间);f∗f_* 单独属于一维。当然也可以一次加好多个数据,让 f∗∈Rmf_* \in \mathbb{R}^m 同时估计一批点——咱们先看最简单的一维情形。

那 f∗f_* 的分布怎么从四维联合分布里「取」出来?这里用到正态分布的一个好性质:高维正态在任何方向上投影,边缘概率仍然是正态分布。想象一个二维正态——一口倒扣的碗,映射下来是一圈圈 contour 等高线——无论沿着 yy 方向投影、还是沿任何斜的方向投影,得到的边缘分布仍然是正态分布。所以在四维正态里,fˉ\bar{f} 服从三维正态,而 f∗f_* 这一维可以通过求边缘概率得到——它自己服从一个一维的正态分布,均值 μ∗\mu_* 和方差 σ∗2\sigma_*^2 就是关键。

(讲师在这里明确说:「我就不给大家具体去演算里边的最终每一步怎么算出来的」——因为到今天来讲,Gaussian process 有很多完整的代码,我们需要讲清楚的是背后的道理。下面直接给直观结果。)

μ* 与 σ*:给的不是点,是一个分布

通过贝叶斯公式,最终求出的结果是:

μ∗=k∗⊤K−1fˉ,σ∗2=K∗∗−k∗⊤K−1k∗\mu_* = \mathbf{k}_*^\top \mathbf{K}^{-1} \bar{f}, \qquad \sigma_*^2 = K_{**} - \mathbf{k}_*^\top \mathbf{K}^{-1} \mathbf{k}_*

先做一遍维度走查:k∗⊤\mathbf{k}_*^\top 是 1×31 \times 3(那个三维向量的转置),乘上 K−1\mathbf{K}^{-1} 是 3×33 \times 3,再乘 fˉ\bar{f} 是 3×13 \times 1——1×3×3×3×11 \times 3 \times 3 \times 3 \times 1,最后得到的是一个标量,一个数,这个数就是 μ∗\mu_*;σ∗2\sigma_*^2 算出来也是一个数(因为 f∗f_* 是一维空间里的分布,就像它的均值和方差)。而 K∗∗K_{**}——x∗x_* 自己跟自己——对角线永远是 1。

于是 μ∗\mu_*(均值)和 σ∗2\sigma_*^2(方差)就构成了对 x∗x^* 的最好估计。注意最关键的一点:我们给出的估计,并不是一个点的估计,仍然是一个分布——f∗f_* 以 μ∗\mu_* 为中心、以 σ∗2\sigma_*^2 为方差。这跟刚才的 kernel density estimation 是类似的情况:给定 xx 的时候,不是只给这个点的最好估计,实际上给的是这个点和它所对应的方差——给了一个区域。

用代码把这套公式跑起来(三个观测点是讲义设定,核取 λ=0.5\lambda = 0.5):

import math

def kern(a, b, lam):
    """GP 核: k(x, x') = exp(-lam * (x - x')^2)"""
    return math.exp(-lam * (a - b) ** 2)

def inv3(m):
    """3x3 矩阵求逆(伴随矩阵法)"""
    a, b, c = m[0]
    d, e, f = m[1]
    g, h, i = m[2]
    det = a*(e*i - f*h) - b*(d*i - f*g) + c*(d*h - e*g)
    r = 1.0 / det
    return [[(e*i - f*h)*r, (c*h - b*i)*r, (b*f - c*e)*r],
            [(f*g - d*i)*r, (a*i - c*g)*r, (c*d - a*f)*r],
            [(d*h - e*g)*r, (b*g - a*h)*r, (a*e - b*d)*r]]

def gp_predict(X, f, xq, lam):
    """GP 单点预测: 返回 K、k*、mu*、sigma*^2"""
    n = len(X)
    K = [[kern(X[i], X[j], lam) for j in range(n)] for i in range(n)]
    Ki = inv3(K)
    ks = [kern(x, xq, lam) for x in X]
    Ki_f = [sum(Ki[i][j] * f[j] for j in range(n)) for i in range(n)]
    mu = sum(ks[i] * Ki_f[i] for i in range(n))
    Ki_ks = [sum(Ki[i][j] * ks[j] for j in range(n)) for i in range(n)]
    s2 = kern(xq, xq, lam) - sum(ks[i] * Ki_ks[i] for i in range(n))
    return K, ks, mu, s2

X = [1.0, 2.0, 4.0]          # 三个观测点(讲义设定)
f = [1.2, 1.8, 2.1]
lam = 0.5
xq = 3.0

K, ks, mu, s2 = gp_predict(X, f, xq, lam)
print("协方差矩阵 K (lambda=0.5):")
for row in K:
    print("  [" + "  ".join(f"{v:.4f}" for v in row) + "]")
print(f"查询点 x* = {xq}")
print(f"k* = [{', '.join(f'{v:.4f}' for v in ks)}]")
print(f"mu* = {mu:.4f}, sigma*^2 = {s2:.4f}, sigma* = {math.sqrt(s2):.4f}")
print(f"90% 区间: [{mu - 1.645 * math.sqrt(s2):.4f}, {mu + 1.645 * math.sqrt(s2):.4f}]")
_, _, mu2, s22 = gp_predict(X, f, xq, 1.5)
print(f"核调窄 lambda=1.5: mu* = {mu2:.4f}, sigma*^2 = {s22:.4f}")
_, _, mu3, s23 = gp_predict(X, f, 10.0, 0.5)
print(f"x* = 10 (远离所有数据): mu* = {mu3:.4f}, sigma*^2 = {s23:.4f}")
协方差矩阵 K (lambda=0.5):
  [1.0000  0.6065  0.0111]
  [0.6065  1.0000  0.1353]
  [0.0111  0.1353  1.0000]
查询点 x* = 3.0
k* = [0.1353, 0.6065, 0.6065]
mu* = 2.0082, sigma*^2 = 0.2915, sigma* = 0.5399
90% 区间: [1.1200, 2.8964]
核调窄 lambda=1.5: mu* = 0.8284, sigma*^2 = 0.8983
x* = 10 (远离所有数据): mu* = 0.0000, sigma*^2 = 1.0000

读这组输出:K 矩阵对角线全是 1、近的点对(x1,x2x_1,x_2 距离 1)协方差 0.6065、远的点对(x1,x3x_1,x_3 距离 3)掉到 0.0111——「距离近值高」的规则逐格兑现。x∗=3x^*=3 夹在 x2=2x_2=2 和 x3=4x_3=4 中间,μ∗=2.0082\mu_* = 2.0082,恰好落在两个观测值 1.8 和 2.1 之间——核加权插值;同时给出 σ∗=0.5399\sigma_* = 0.5399、90% 区间 [1.12,2.90][1.12, 2.90]——估计自带「打包票的幅度」。两个对照也很说明问题:把核调窄(λ=1.5\lambda=1.5),x∗=3x^*=3 与数据的关联被掐细,方差反而涨到 0.8983、均值被拉向先验 0;把 x∗x^* 挪到 10——远离所有数据——k∗\mathbf{k}_* 全部归零,μ∗=0\mu_* = 0、σ∗2=1\sigma_*^2 = 1:完全回到先验(均值 0、方差 1 的正态),模型诚实地承认「这里我一无所知」。

扫出一条线,带一条带子

把上一节 KDE 的收尾动作照搬过来:把 x∗x^* 沿着最小值和最大值不断地移动,每移到一个位置就算一组 μ∗,σ∗\mu_*, \sigma_*——我们仍然可以学出一条线。而这条线自带一条「带子」:在已经有值的点上,方差小;在其他地方,方差大。给定三个点,中心线是得到的最好值的连线,外围的区域里有很大的概率(比如 90% 的概率都在这个区域里),三个观测点之间 variance 比较小。对任何给定的 x∗x^*,都可以估计它落在这个区域里的概率有多大。

import math

# 数据与核同上一块(讲义设定), 此块自包含重写
def kern(a, b, lam):
    return math.exp(-lam * (a - b) ** 2)

def inv3(m):
    a, b, c = m[0]
    d, e, f = m[1]
    g, h, i = m[2]
    det = a*(e*i - f*h) - b*(d*i - f*g) + c*(d*h - e*g)
    r = 1.0 / det
    return [[(e*i - f*h)*r, (c*h - b*i)*r, (b*f - c*e)*r],
            [(f*g - d*i)*r, (a*i - c*g)*r, (c*d - a*f)*r],
            [(d*h - e*g)*r, (b*g - a*h)*r, (a*e - b*d)*r]]

X = [1.0, 2.0, 4.0]
f = [1.2, 1.8, 2.1]
lam = 0.5

def gp_mu_sigma(xq):
    n = len(X)
    K = [[kern(X[i], X[j], lam) for j in range(n)] for i in range(n)]
    Ki = inv3(K)
    ks = [kern(x, xq, lam) for x in X]
    Ki_f = [sum(Ki[i][j] * f[j] for j in range(n)) for i in range(n)]
    mu = sum(ks[i] * Ki_f[i] for i in range(n))
    Ki_ks = [sum(Ki[i][j] * ks[j] for j in range(n)) for i in range(n)]
    s2 = kern(xq, xq, lam) - sum(ks[i] * Ki_ks[i] for i in range(n))
    return mu, math.sqrt(max(s2, 0.0))

print("x* 扫描 (lambda=0.5):")
for i in range(11):
    xq = i * 0.5
    mu, sg = gp_mu_sigma(xq)
    print(f"x*={xq:4.1f}  mu*={mu:8.4f}  sigma*={sg:8.4f}")
x* 扫描 (lambda=0.5):
x*= 0.0  mu*=  0.4119  sigma*=  0.7381
x*= 0.5  mu*=  0.7694  sigma*=  0.3870
x*= 1.0  mu*=  1.2000  sigma*=  0.0000
x*= 1.5  mu*=  1.5779  sigma*=  0.1706
x*= 2.0  mu*=  1.8000  sigma*=  0.0000
x*= 2.5  mu*=  1.9009  sigma*=  0.3423
x*= 3.0  mu*=  2.0082  sigma*=  0.5399
x*= 3.5  mu*=  2.1344  sigma*=  0.4058
x*= 4.0  mu*=  2.1000  sigma*=  0.0000
x*= 4.5  mu*=  1.7517  sigma*=  0.4615
x*= 5.0  mu*=  1.1786  sigma*=  0.7904

这张表就是那条「线 + 带子」的数值形态。看 σ∗\sigma_* 那一列的节律:恰好落在观测点上(x∗=1,2,4x^*=1, 2, 4)时 σ∗=0.0000\sigma_* = 0.0000——有数据的地方,模型分毫不让(这是无噪声 GP 的精确插值性质);离开观测点半步(x∗=1.5x^*=1.5 只有 0.17)方差开始抬头;两点之间的空档(x∗=3.0x^*=3.0 夹在 2 与 4 之间较远的距离)涨到 0.54;两端越出数据范围(x∗=0x^*=0 和 x∗=5x^*=5)方差冲到 0.74~0.79,直奔先验的 1。而 μ∗\mu_* 那一列穿过三个观测值,在数据覆盖的区间里平滑爬升,出了区间就被拉回先验均值 0 的方向——中心线由数据说话,带子的宽窄由「离数据多远」说话。

GP 与 KDE:区别与相似

最后把两节课放在一起对齐。大家可以看到,GP 跟刚才描述的 KDE 有区别,但关键的部分有相似:μ∗\mu_* 和 σ∗\sigma_* 的构造,都是关于 K\mathbf{K} 和 k∗\mathbf{k}_* 的——而所有的 K 都是可求的:K\mathbf{K} 根据 x1,x2,x3x_1, x_2, x_3 彼此之间的距离,带入 kernel 算出值的大小;k∗\mathbf{k}_* 也一样可算:给定了新的 x∗x^*,算它对 x1,x2,x3x_1, x_2, x_3 各种不同的距离,带入 kernel 就求出了 k∗\mathbf{k}_*。

所以关键的问题还是看:给定一个对 x∗x^* 的估计,就看 x∗x^* 相对于每一个 xx 之间的距离,和它们 xx 之间互相的距离,决定出 kernel 构成的协方差矩阵,最后决定估计。这跟 KDE 只是形式不同——不同的地方在最开始的假设:GP 认为得到的函数所对应的函数关系,在函数空间、在高维空间里,服从一个高维的正态分布——这是高斯过程跟别的模型很不同的部分。

📝 动手练一练

  1. 概念辨析:GP 和 KDE 都用核函数、都从数据出发,它们研究的分别是什么问题?GP 对新点 x∗x^* 给出的「估计」和 KDE 给出的有什么本质区别?
👉 点击查看参考答案

相似:都是非参数方法;核心都靠 kernel 把「距离」化成「权重/相关性」——KDE 里核是密度的小山峰,GP 里核是协方差矩阵的元素。

区别:KDE 研究的是数据本身的分布——给定 xx,估计密度 p^(x)\hat{p}(x),回答「数据在这里出现的可能性多大」;GP 研究的是函数关系——假设函数值 (f1,…,fn)(f_1, \dots, f_n) 的联合分布是高维正态,给定 x∗x^* 回答「f(x∗)f(x^*) 最可能是什么、我有多确信」。GP 给出的估计不是一个点,而是一个分布 f∗∼N(μ∗,σ∗2)f_* \sim N(\mu_*, \sigma_*^2)——均值给预测、方差给置信。

  1. 单点 GP 手算:只有一个观测点 (x1,f1)=(0,1)(x_1, f_1) = (0, 1),核 k(x,x′)=exp⁡(−0.5(x−x′)2)k(x, x') = \exp(-0.5(x - x')^2)。预测点 x∗=1x^* = 1:手算 K\mathbf{K}、k∗\mathbf{k}_*、μ∗\mu_* 和 σ∗2\sigma_*^2。
👉 点击查看参考答案

单点情形:K=[k(0,0)]=[e0]=[1]\mathbf{K} = [k(0,0)] = [e^0] = [1],所以 K−1=[1]\mathbf{K}^{-1} = [1];k∗=[k(0,1)]=[e−0.5]≈[0.6065]\mathbf{k}_* = [k(0,1)] = [e^{-0.5}] \approx [0.6065];K∗∗=k(1,1)=1K_{**} = k(1,1) = 1。

μ∗=k∗⊤K−1fˉ=0.6065×1×1=0.6065\mu_* = \mathbf{k}_*^\top \mathbf{K}^{-1} \bar{f} = 0.6065 \times 1 \times 1 = 0.6065

σ∗2=K∗∗−k∗⊤K−1k∗=1−0.60652=1−0.3679=0.6321\sigma_*^2 = K_{**} - \mathbf{k}_*^\top \mathbf{K}^{-1} \mathbf{k}_* = 1 - 0.6065^2 = 1 - 0.3679 = 0.6321

预测 f∗∼N(0.6065,0.6321)f_* \sim N(0.6065, 0.6321):只有一个观测点、距离又是 1,所以不确定性相当大。若把 x∗x^* 挪远,k∗\mathbf{k}_* 变小,μ∗\mu_* 趋向先验均值 0、σ∗2\sigma_*^2 趋向先验方差 1——跟正文中 x∗=10x^* = 10 的机器验证一致。

本章小结

这一节从「估计问题」出发构造了高斯过程。第一,核心假设:xx 对应的函数关系 ff,其函数值 (f1,f2,f3)(f_1, f_2, f_3) 作为三维向量服从三维正态——均值向量(默认 0)+ 协方差矩阵;也可以假设别的分布,那就是别的 process。第二,协方差矩阵由核函数填:Kij=exp⁡(−λ(xi−xj)2)K_{ij} = \exp(-\lambda(x_i - x_j)^2)——对角线恒 1、无穷远趋 0、λ 调宽窄。第三,预测 = 加一维:(f1,f2,f3,f∗)(f_1, f_2, f_3, f_*) 服从四维正态(加 4 个点就是 7 维、加 10 个就是 13 维),分块成 [K,k∗;k∗⊤,K∗∗][\mathbf{K}, \mathbf{k}_*; \mathbf{k}_*^\top, K_{**}];利用「高维正态任何方向的边缘仍是正态」的性质,取出 f∗∼N(μ∗,σ∗2)f_* \sim N(\mu_*, \sigma_*^2),其中 μ∗=k∗⊤K−1fˉ\mu_* = \mathbf{k}_*^\top \mathbf{K}^{-1} \bar{f}、σ∗2=K∗∗−k∗⊤K−1k∗\sigma_*^2 = K_{**} - \mathbf{k}_*^\top \mathbf{K}^{-1} \mathbf{k}_*。第四,给的不是点的估计而是分布——x∗x^* 沿 min 到 max 扫描,学出中心线加置信带:观测点上方差为 0、点间渐宽、数据之外回到先验。第五,与 KDE 的对照:一切都绕着 K\mathbf{K} 和 k∗\mathbf{k}_* 转,而它们全部由距离经 kernel 可求——GP 独特之处在于「函数值在高维空间服从正态分布」这个假设。下一节把 GP 重新正式定义、泛化到一般形式(均值函数 m(x)m(x) 与协方差核 k(x,x′)k(x, x'))。

📋 行动清单

  • 口述假设:不借助资料,说清「为什么用 ff 不用 yy」和高斯过程的核心假设(函数值联合正态)。
  • 手算走查:独立完成练一练第 2 题的单点 GP,再用正文代码的思路验证。
  • 跑改代码:把扫描块的观测点改成 [1,3,3.5][1, 3, 3.5]、函数值改成自己编的三个数,观察 σ∗=0\sigma_* = 0 的行怎么移动。
  • 对照两节课:各用一句话说清 KDE 与 GP 里 kernel 的角色(密度的小山峰 vs 协方差的元素),以及两者「给估计」的方式差在哪。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第18章笔记:核方法(Kernel)
    下载