18.2. 高斯过程先验
在 Colab 中打开 Notebook
在 Colab 中打开 Notebook
在 Colab 中打开 Notebook
在 Colab 中打开 Notebook
在 SageMaker Studio Lab 中打开 Notebook

理解高斯过程(GP)对于推理模型构建和泛化,以及在主动学习、深度学习中的超参数调整等多种应用中实现最先进的性能至关重要。高斯过程无处不在,了解它们是什么以及如何使用它们对我们很有帮助。

在本节中,我们介绍函数上的高斯过程先验。在下一个笔记本中,我们将展示如何使用这些先验进行后验推断和预测。下一节可以被看作是“高斯过程简介”,快速为您提供在实践中应用高斯过程所需的内容。

import numpy as np
from scipy.spatial import distance_matrix
from d2l import torch as d2l

d2l.set_figsize()

18.2.1. 定义

高斯过程被定义为一组随机变量的集合,其中任意有限个随机变量都服从联合高斯分布。如果函数 \(f(x)\) 是一个高斯过程,其均值函数\(m(x)\)协方差函数核函数\(k(x,x')\),记作 \(f(x) \sim \mathcal{GP}(m, k)\),那么在任意一组输入点 \(x\)(时间、空间位置、图像像素等)上查询到的任意一组函数值,都服从联合多元高斯分布,其均值向量为 \(\mu\),协方差矩阵为 \(K\)\(f(x_1),\dots,f(x_n) \sim \mathcal{N}(\mu, K)\),其中 \(\mu_i = E[f(x_i)] = m(x_i)\)\(K_{ij} = \textrm{Cov}(f(x_i),f(x_j)) = k(x_i,x_j)\)

这个定义可能看起来抽象难懂,但实际上高斯过程是非常简单的对象。任何函数

(18.2.1)\[f(x) = w^{\top} \phi(x) = \langle w, \phi(x) \rangle,\]

其中 \(w\) 从高斯(正态)分布中抽取,而 \(\phi\) 是任何基函数向量,例如 \(\phi(x) = (1, x, x^2, ..., x^d)^{\top}\),就是一个高斯过程。此外,任何高斯过程 f(x) 都可以表示为方程 (18.2.1) 的形式。让我们通过几个具体的例子来开始熟悉高斯过程,之后我们就能体会到它们是多么简单和有用。

18.2.2. 一个简单的高斯过程

假设 \(f(x) = w_0 + w_1 x\),并且 \(w_0, w_1 \sim \mathcal{N}(0,1)\),其中 \(w_0, w_1, x\) 都是一维的。我们可以将这个函数等价地写成内积形式 \(f(x) = (w_0, w_1)(1, x)^{\top}\)。在上面的 (18.2.1) 中,\(w = (w_0, w_1)^{\top}\)\(\phi(x) = (1,x)^{\top}\)

对于任何 \(x\)\(f(x)\) 都是两个高斯随机变量的和。由于高斯分布在加法下是封闭的,所以对于任何 \(x\)\(f(x)\) 也是一个高斯随机变量。事实上,我们可以计算出对于任何特定的 \(x\)\(f(x)\) 服从 \(\mathcal{N}(0,1+x^2)\)。同样,对于任意一组输入 \(x_1,\dots,x_n\),任意一组函数值 \((f(x_1),\dots,f(x_n))\) 的联合分布是一个多元高斯分布。因此,\(f(x)\) 是一个高斯过程。

简而言之,\(f(x)\) 是一个随机函数,或者说是一个函数上的分布。我们可以通过重复采样 \(w_0, w_1\) 的值,并可视化相应的函数 \(f(x)\)(它们是具有不同斜率和截距的直线),来深入了解这个分布,如下所示

def lin_func(x, n_sample):
    preds = np.zeros((n_sample, x.shape[0]))
    for ii in range(n_sample):
        w = np.random.normal(0, 1, 2)
        y = w[0] + w[1] * x
        preds[ii, :] = y
    return preds

x_points = np.linspace(-5, 5, 50)
outs = lin_func(x_points, 10)
lw_bd = -2 * np.sqrt((1 + x_points ** 2))
up_bd = 2 * np.sqrt((1 + x_points ** 2))

d2l.plt.fill_between(x_points, lw_bd, up_bd, alpha=0.25)
d2l.plt.plot(x_points, np.zeros(len(x_points)), linewidth=4, color='black')
d2l.plt.plot(x_points, outs.T)
d2l.plt.xlabel("x", fontsize=20)
d2l.plt.ylabel("f(x)", fontsize=20)
d2l.plt.show()
../_images/output_gp-priors_df56c3_3_0.svg

如果 \(w_0\)\(w_1\) 改为从 \(\mathcal{N}(0,\alpha^2)\) 中抽取,您认为改变 \(\alpha\) 会如何影响函数上的分布?

18.2.3. 从权重空间到函数空间

在上面的图中,我们看到了模型中参数的分布如何引出函数上的分布。虽然我们通常对我们想要建模的函数有所了解——它们是平滑的、周期的、快速变化的等等——但要推理这些很大程度上不可解释的参数是相对繁琐的。幸运的是,高斯过程提供了一种简单的机制来直接对函数进行推理。由于高斯分布完全由其前两个矩(均值和协方差矩阵)定义,因此高斯过程也由其均值函数和协方差函数定义。

在上面的例子中,均值函数是

(18.2.2)\[m(x) = E[f(x)] = E[w_0 + w_1x] = E[w_0] + E[w_1]x = 0+0 = 0.\]

同样,协方差函数是

(18.2.3)\[k(x,x') = \textrm{Cov}(f(x),f(x')) = E[f(x)f(x')]-E[f(x)]E[f(x')] = E[w_0^2 + w_0w_1x' + w_1w_0x + w_1^2xx'] = 1 + xx'.\]

我们现在可以直接指定和采样函数上的分布,而无需从参数分布中采样。例如,要从 \(f(x)\) 中抽取样本,我们只需为任何我们想查询的 \(x\) 集合构建其关联的多元高斯分布,并直接从中采样。我们将开始看到这种表述方式是多么有利。

首先,我们注意到,对于上面简单的直线模型,基本相同的推导可以应用于任何形式为 \(f(x) = w^{\top} \phi(x)\)\(w \sim \mathcal{N}(u,S)\) 的模型,以找到其均值和协方差函数。在这种情况下,均值函数为 \(m(x) = u^{\top}\phi(x)\),协方差函数为 \(k(x,x') = \phi(x)^{\top}S\phi(x')\)。由于 \(\phi(x)\) 可以表示任何非线性基函数的向量,我们正在考虑一个非常通用的模型类别,甚至包括具有无限多个参数的模型。

18.2.4. 径向基函数(RBF)核

径向基函数 (RBF) 核是高斯过程和一般核方法中最常用的协方差函数。该核的形式为 \(k_{\textrm{RBF}}(x,x') = a^2\exp\left(-\frac{1}{2\ell^2}||x-x'||^2\right)\),其中 \(a\) 是一个振幅参数,\(\ell\) 是一个长度尺度超参数。

让我们从权重空间开始推导这个核。考虑函数

(18.2.4)\[f(x) = \sum_{i=1}^J w_i \phi_i(x), w_i \sim \mathcal{N}\left(0,\frac{\sigma^2}{J}\right), \phi_i(x) = \exp\left(-\frac{(x-c_i)^2}{2\ell^2 }\right).\]

\(f(x)\) 是径向基函数的和,宽度为 \(\ell\),中心在点 \(c_i\) 处,如下图所示。

我们可以认出 \(f(x)\) 具有 \(w^{\top} \phi(x)\) 的形式,其中 \(w = (w_1,\dots,w_J)^{\top}\)\(\phi(x)\) 是一个包含每个径向基函数的向量。这个高斯过程的协方差函数是

(18.2.5)\[k(x,x') = \frac{\sigma^2}{J} \sum_{i=1}^{J} \phi_i(x)\phi_i(x').\]

现在让我们考虑当参数(和基函数)数量趋于无穷大时会发生什么。设 \(c_J = \log J\)\(c_1 = -\log J\),且 \(c_{i+1}-c_{i} = \Delta c = 2\frac{\log J}{J}\),并让 \(J \to \infty\)。协方差函数变成了黎曼和

(18.2.6)\[k(x,x') = \lim_{J \to \infty} \frac{\sigma^2}{J} \sum_{i=1}^{J} \phi_i(x)\phi_i(x') = \int_{c_0}^{c_\infty} \phi_c(x)\phi_c(x') dc.\]

通过设置 \(c_0 = -\infty\)\(c_\infty = \infty\),我们将无限多的基函数分布在整个实数线上,每个基函数之间的距离 \(\Delta c \to 0\)

(18.2.7)\[k(x,x') = \int_{-\infty}^{\infty} \exp(-\frac{(x-c)^2}{2\ell^2}) \exp(-\frac{(x'-c)^2}{2\ell^2 }) dc = \sqrt{\pi}\ell \sigma^2 \exp(-\frac{(x-x')^2}{2(\sqrt{2} \ell)^2}) \propto k_{\textrm{RBF}}(x,x').\]

我们在这里所做的事情值得花点时间来理解。通过转换到函数空间表示,我们推导出了如何用有限的计算量来表示一个具有无限数量参数的模型。具有RBF核的高斯过程是一个通用逼近器,能够以任意精度表示任何连续函数。从上面的推导中,我们可以直观地看到原因。我们可以将每个径向基函数塌缩成一个点质量,取 \(\ell \to 0\),并给每个点质量任意我们想要的高度。

因此,具有RBF核的高斯过程是一个拥有无限参数的模型,其灵活性远超任何有限的神经网络。也许所有关于过参数化神经网络的讨论都是错位的。正如我们将看到的,具有RBF核的GP并不会过拟合,事实上在小数据集上提供了特别有说服力的泛化性能。此外,在 (Zhang et al., 2021) 中的例子,例如能够完美拟合带有随机标签的图像,但在结构化问题上仍能很好地泛化,(可以用高斯过程完美地复现)(Wilson and Izmailov, 2020)。神经网络并不像我们所认为的那样独特。

通过直接从函数分布中采样,我们可以进一步建立关于具有RBF核的高斯过程及其超参数(如长度尺度)的直觉。和之前一样,这涉及一个简单的过程

  1. 选择我们想要查询GP的输入点 \(x\)\(x_1,\dots,x_n\)

  2. 评估 \(m(x_i)\)(对于 \(i = 1,\dots,n\))和 \(k(x_i,x_j)\)(对于 \(i,j = 1,\dots,n\)),以分别构成均值向量 \(\mu\) 和协方差矩阵 \(K\),其中 \((f(x_1),\dots,f(x_n)) \sim \mathcal{N}(\mu, K)\)

  3. 从此多元高斯分布中采样,以获得样本函数值。

  4. 多次采样以可视化在这些点上查询的更多样本函数。

我们在下图中说明了这个过程。

def rbfkernel(x1, x2, ls=4.):  #@save
    dist = distance_matrix(np.expand_dims(x1, 1), np.expand_dims(x2, 1))
    return np.exp(-(1. / ls / 2) * (dist ** 2))

x_points = np.linspace(0, 5, 50)
meanvec = np.zeros(len(x_points))
covmat = rbfkernel(x_points,x_points, 1)

prior_samples= np.random.multivariate_normal(meanvec, covmat, size=5);
d2l.plt.plot(x_points, prior_samples.T, alpha=0.5)
d2l.plt.show()
../_images/output_gp-priors_df56c3_5_0.svg

18.2.5. 神经网络核

机器学习中对高斯过程的研究是由对神经网络的研究引发的。Radford Neal一直在追求越来越大的贝叶斯神经网络,最终在1994年(后来于1996年发表,因为这是NeurIPS最臭名昭著的拒稿之一)证明,具有无限隐藏单元的此类网络会变成具有特定核函数的高斯过程 (Neal, 1996)。对这一推导的兴趣重新浮现,像神经正切核这样的思想被用来研究神经网络的泛化特性 (Matthews et al., 2018) (Novak et al., 2018)。我们可以如下推导神经网络核。

考虑一个具有一个隐藏层的神经网络函数 \(f(x)\)

(18.2.8)\[f(x) = b + \sum_{i=1}^{J} v_i h(x; u_i).\]

\(b\) 是偏置,\(v_i\) 是隐藏层到输出层的权重,\(h\) 是任何有界的隐藏单元传递函数,\(u_i\) 是输入层到隐藏层的权重,\(J\) 是隐藏单元的数量。让 \(b\)\(v_i\) 独立,均值为零,方差分别为 \(\sigma_b^2\)\(\sigma_v^2/J\),并让 \(u_i\) 具有独立的相同分布。然后,我们可以使用中心极限定理来证明,任何函数值的集合 \(f(x_1),\dots,f(x_n)\) 都服从联合多元高斯分布。

相应的高斯过程的均值和协方差函数是

(18.2.9)\[m(x) = E[f(x)] = 0\]
(18.2.10)\[k(x,x') = \textrm{cov}[f(x),f(x')] = E[f(x)f(x')] = \sigma_b^2 + \frac{1}{J} \sum_{i=1}^{J} \sigma_v^2 E[h_i(x; u_i)h_i(x'; u_i)]\]

在某些情况下,我们基本上可以用封闭形式评估这个协方差函数。设 \(h(x; u) = \textrm{erf}(u_0 + \sum_{j=1}^{P} u_j x_j)\),其中 \(\textrm{erf}(z) = \frac{2}{\sqrt{\pi}} \int_{0}^{z} e^{-t^2} dt\),并且 \(u \sim \mathcal{N}(0,\Sigma)\)。那么 \(k(x,x') = \frac{2}{\pi} \textrm{sin}(\frac{2 \tilde{x}^{\top} \Sigma \tilde{x}'}{\sqrt{(1 + 2 \tilde{x}^{\top} \Sigma \tilde{x})(1 + 2 \tilde{x}'^{\top} \Sigma \tilde{x}')}})\)

RBF 核是平稳的,这意味着它是平移不变的,因此可以写成 \(\tau = x-x'\) 的函数。直观地说,平稳性意味着函数的高级属性(如变化率)在输入空间中移动时不会改变。然而,神经网络核是非平稳的。下面,我们展示了从具有此核的高斯过程中采样的函数。我们可以看到,该函数在原点附近看起来有质的不同。

18.2.6. 总结

进行贝叶斯推断的第一步是指定先验。高斯过程可以用来指定一个完整的函数先验。从传统的“权重空间”建模视角出发,我们可以通过从模型的函数形式开始,并引入其参数的分布来诱导一个函数先验。我们也可以直接在函数空间中指定先验分布,其属性由核函数控制。函数空间方法有很多优点。我们可以构建实际上对应于无限数量参数的模型,但只使用有限的计算量!此外,虽然这些模型具有很大的灵活性,但它们也对哪些类型的函数是先验可能的做出了强有力的假设,从而在小数据集上实现了相对较好的泛化。

函数空间中模型的假设由核函数直观地控制,核函数通常编码了函数的高级属性,如平滑度和周期性。许多核是平稳的,这意味着它们是平移不变的。从具有平稳核的高斯过程中抽取的函数,无论我们在输入空间的哪个位置观察,都具有大致相同的高级属性(如变化率)。

高斯过程是一个相对通用的模型类别,包含了我们已经熟悉的许多模型示例,包括多项式、傅里叶级数等,只要我们在参数上有一个高斯先验。它们还包括具有无限数量参数的神经网络,即使参数上没有高斯分布。Radford Neal发现的这种联系,促使机器学习研究人员从神经网络转向高斯过程。

18.2.7. 练习

  1. 从具有Ornstein-Uhlenbeck (OU) 核 \(k_{\textrm{OU}}(x,x') = \exp\left(-\frac{1}{2\ell}||x - x'|\right)\) 的 GP 中抽取样本先验函数。如果将长度尺度 \(\ell\) 固定为相同的值,这些函数与从具有RBF核的GP中抽取的样本函数有何不同?

  2. 改变RBF核的振幅 \(a^2\) 会如何影响函数上的分布?

  3. 假设我们构造 \(u(x) = f(x) + 2g(x)\),其中 \(f(x) \sim \mathcal{GP}(m_1,k_1)\)\(g(x) \sim \mathcal{GP}(m_2,k_2)\)。那么 \(u(x)\) 是一个高斯过程吗?如果是,它的均值和协方差函数是什么?

  4. 假设我们构造 \(g(x) = a(x)f(x)\),其中 \(f(x) \sim \mathcal{GP}(0,k)\)\(a(x) = x^2\)。那么 \(g(x)\) 是一个高斯过程吗?如果是,它的均值和协方差函数是什么?\(a(x)\) 的作用是什么?从 \(g(x)\) 中抽取的样本函数看起来像什么?

  5. 假设我们构造 \(u(x) = f(x)g(x)\),其中 \(f(x) \sim \mathcal{GP}(m_1,k_1)\)\(g(x) \sim \mathcal{GP}(m_2,k_2)\)。那么 \(u(x)\) 是一个高斯过程吗?如果是,它的均值和协方差函数是什么?

讨论