1.7. 高斯过程#
高斯过程 (GP) 是一种非参数监督学习方法,用于解决回归和概率分类问题。
高斯过程的优点包括
预测对观测值进行插值(至少对于正则核而言)。
预测是概率性的(高斯分布),因此可以计算经验置信区间,并根据这些区间决定是否应该在某些感兴趣区域重新拟合(在线拟合、自适应拟合)预测。
通用性:可以指定不同的核函数。提供了常见的核函数,但也可以指定自定义核函数。
高斯过程的缺点包括
我们的实现不是稀疏的,也就是说,它们使用所有样本/特征信息来执行预测。
它们在高维空间中效率低下 - 也就是说,当特征数量超过几十个时。
1.7.1. 高斯过程回归 (GPR)#
GaussianProcessRegressor
实现用于回归目的的高斯过程 (GP)。为此,需要指定 GP 的先验。GP 将结合该先验和基于训练样本的似然函数。它允许通过在预测时输出均值和标准差来提供预测的概率方法。
先验均值假设为常数且为零(对于 normalize_y=False
)或训练数据的均值(对于 normalize_y=True
)。先验的协方差由传递一个 核 对象来指定。当拟合 GaussianProcessRegressor
时,通过基于传递的 optimizer
最大化对数边际似然 (LML) 来优化核的超参数。由于 LML 可能具有多个局部最优,因此可以通过指定 n_restarts_optimizer
来重复启动优化器。第一次运行总是从核的初始超参数值开始;后续运行从随机选择的允许值范围内的超参数值开始。如果应保持初始超参数固定,则可以将 None
传递为优化器。
目标中的噪声水平可以通过参数 alpha
传递来指定,可以全局地作为标量传递,也可以针对每个数据点传递。请注意,适度的噪声水平也有助于解决拟合过程中的数值不稳定性,因为它实际上是作为 Tikhonov 正则化实现的,即通过将其添加到核矩阵的对角线上。显式指定噪声水平的另一种方法是将一个 WhiteKernel
组件包含到核中,该组件可以从数据中估计全局噪声水平(参见下面的示例)。下图显示了通过设置参数 alpha
来处理噪声目标的效果。
该实现基于 [RW2006] 中的算法 2.1。除了标准 scikit-learn 估计器的 API 之外,GaussianProcessRegressor
允许在没有先验拟合的情况下进行预测(基于 GP 先验)
提供一个额外的
sample_y(X)
方法,该方法评估从 GPR(先验或后验)中抽取的样本在给定输入处的取值公开一个
log_marginal_likelihood(theta)
方法,该方法可用于外部以其他方式选择超参数,例如通过马尔可夫链蒙特卡罗。
示例
1.7.2. 高斯过程分类 (GPC)#
该 GaussianProcessClassifier
实现用于分类目的的高斯过程 (GP),更具体地说,用于概率分类,其中测试预测采用类概率的形式。GaussianProcessClassifier 在一个潜在函数 \(f\) 上放置一个 GP 先验,然后将其通过一个链接函数压缩以获得概率分类。潜在函数 \(f\) 是一个所谓的干扰函数,其值未被观察到,本身也不相关。它的目的是允许模型的方便公式化,并且 \(f\) 在预测过程中被移除(积分出去)。GaussianProcessClassifier 实现逻辑链接函数,对于该函数,积分无法通过解析计算,但在二元情况下很容易近似。
与回归设置相反,即使对于 GP 先验,潜在函数 \(f\) 的后验也不是高斯分布,因为高斯似然不适合离散类标签。相反,使用与逻辑链接函数(logit)相对应的非高斯似然。GaussianProcessClassifier 使用基于拉普拉斯近似的 Gaussian 来近似非高斯后验。更多详细信息可以在 [RW2006] 的第 3 章中找到。
假设 GP 先验均值为零。先验的协方差由传递一个 核 对象来指定。在拟合 GaussianProcessRegressor 期间,通过基于传递的 optimizer
最大化对数边际似然 (LML) 来优化核的超参数。由于 LML 可能具有多个局部最优,因此可以通过指定 n_restarts_optimizer
来重复启动优化器。第一次运行总是从核的初始超参数值开始;后续运行从随机选择的允许值范围内的超参数值开始。如果应保持初始超参数固定,则可以将 None
传递为优化器。
该 GaussianProcessClassifier
通过执行基于一对多或一对一的训练和预测来支持多类分类。在一对多中,为每个类拟合一个二元高斯过程分类器,该分类器被训练以将该类与其余类分开。在“一对一”中,为每对类拟合一个二元高斯过程分类器,该分类器被训练以将这两类分开。这些二元预测器的预测被组合成多类预测。有关更多详细信息,请参见关于 多类分类 的部分。
在高斯过程分类的情况下,“一对一”在计算上可能更便宜,因为它必须解决许多仅涉及整个训练集子集的问题,而不是更少的问题,这些问题涉及整个数据集。由于高斯过程分类的缩放比例与数据集的大小成三次方,因此这可能快得多。但是,请注意,“一对一”不支持预测概率估计,而只支持普通预测。此外,请注意,该 GaussianProcessClassifier
尚未在内部实现真正的多类拉普拉斯近似,但如上所述,它基于在内部解决多个二元分类任务,这些任务使用一对多或一对一进行组合。
1.7.3. GPC 示例#
1.7.3.1. 使用 GPC 进行概率预测#
此示例说明了 GPC 对于具有不同超参数选择的 RBF 核的预测概率。第一张图显示了 GPC 在任意选择的超参数和对应于最大对数边际似然 (LML) 的超参数下的预测概率。
虽然通过优化 LML 选择的超参数具有明显更大的 LML,但根据测试数据的对数损失,它们的性能略差。该图显示,这是因为它们在类边界处表现出类概率的急剧变化(这很好),但在远离类边界的地方,预测概率接近 0.5(这不好)。这种不良影响是由 GPC 内部使用的拉普拉斯近似引起的。
第二张图显示了不同核超参数选择的对数边际似然,通过黑点突出显示了第一张图中使用的两种超参数选择。
1.7.3.2. 在 XOR 数据集上说明 GPC#
此示例说明了 GPC 在 XOR 数据上的应用。比较了固定各向同性核 (RBF
) 和非固定核 (DotProduct
)。在这个特定的数据集上,该 DotProduct
核获得了明显更好的结果,因为类边界是线性的,并且与坐标轴重合。然而,在实践中,固定核(例如 RBF
)通常会获得更好的结果。
1.7.3.3. 在鸢尾花数据集上进行高斯过程分类 (GPC)#
此示例说明了 GPC 对于鸢尾花数据集二维版本的各向同性和各向异性 RBF 核的预测概率。这说明了 GPC 对非二元分类的适用性。各向异性 RBF 核通过为两个特征维度分配不同的长度尺度来获得略高的对数边际似然。
1.7.4. 高斯过程的核#
核(在 GP 的上下文中也称为“协方差函数”)是 GP 的一个关键组成部分,它决定了 GP 的先验和后验的形状。它们通过定义两个数据点的“相似性”来对正在学习的函数的假设进行编码,并结合了类似数据点应该具有类似目标值的假设。可以区分两类核:固定核仅取决于两个数据点的距离,而不取决于它们的绝对值 \(k(x_i, x_j)= k(d(x_i, x_j))\),因此对输入空间中的平移是不变的,而非固定核还取决于数据点的具体值。固定核可以进一步细分为各向同性和各向异性核,其中各向同性核对输入空间中的旋转也是不变的。有关更多详细信息,请参见 [RW2006] 的第 4 章。有关如何最好地组合不同核的指南,请参见 [Duv2014]。
高斯过程核 API#
该 Kernel
的主要用途是计算 GP 在数据点之间的协方差。为此,可以调用核的 __call__
方法。该方法可以用于计算 2d 数组 X 中所有数据点对的“自协方差”,也可以计算 2d 数组 X 中的数据点与 2d 数组 Y 中的数据点的所有组合的“互协方差”。以下恒等式对所有核 k(除了 WhiteKernel
)成立:k(X) == K(X, Y=X)
如果只使用自协方差的对角线,则可以调用内核的 diag()
方法,这比等效的 __call__
调用在计算上更有效:np.diag(k(X, X)) == k.diag(X)
内核由超参数向量 \(\theta\) 参数化。这些超参数可以例如控制内核的长度尺度或周期性(见下文)。所有内核都支持计算内核自协方差相对于 \(log(\theta)\) 的解析梯度,方法是在 __call__
方法中设置 eval_gradient=True
。也就是说,返回一个 (len(X), len(X), len(theta))
数组,其中条目 [i, j, l]
包含 \(\frac{\partial k_\theta(x_i, x_j)}{\partial log(\theta_l)}\)。高斯过程(回归器和分类器)在计算对数边际似然的梯度时使用此梯度,而对数边际似然又用于通过梯度上升确定 \(\theta\) 的值,该值使对数边际似然最大化。对于每个超参数,在创建内核实例时需要指定初始值和边界。可以通过内核对象的 theta
属性获取和设置 \(\theta\) 的当前值。此外,可以通过内核的 bounds
属性访问超参数的边界。请注意,这两个属性(theta 和 bounds)都返回内部使用值的 log 变换值,因为这些值通常更适合基于梯度的优化。每个超参数的规范以 Hyperparameter
实例的形式存储在相应的内核中。请注意,使用名为“x”的超参数的内核必须具有属性 self.x 和 self.x_bounds。
所有内核的抽象基类是 Kernel
。Kernel 实现与 BaseEstimator
相似的接口,提供 get_params()
、set_params()
和 clone()
方法。这允许通过元估计器(如 Pipeline
或 GridSearchCV
)来设置内核值。请注意,由于内核的嵌套结构(通过应用内核运算符,见下文),内核参数的名称可能会变得比较复杂。一般来说,对于二元内核运算符,左操作数的参数以 k1__
为前缀,右操作数的参数以 k2__
为前缀。一个额外的便利方法是 clone_with_theta(theta)
,它返回内核的克隆版本,但超参数设置为 theta
。一个说明性的例子
>>> from sklearn.gaussian_process.kernels import ConstantKernel, RBF
>>> kernel = ConstantKernel(constant_value=1.0, constant_value_bounds=(0.0, 10.0)) * RBF(length_scale=0.5, length_scale_bounds=(0.0, 10.0)) + RBF(length_scale=2.0, length_scale_bounds=(0.0, 10.0))
>>> for hyperparameter in kernel.hyperparameters: print(hyperparameter)
Hyperparameter(name='k1__k1__constant_value', value_type='numeric', bounds=array([[ 0., 10.]]), n_elements=1, fixed=False)
Hyperparameter(name='k1__k2__length_scale', value_type='numeric', bounds=array([[ 0., 10.]]), n_elements=1, fixed=False)
Hyperparameter(name='k2__length_scale', value_type='numeric', bounds=array([[ 0., 10.]]), n_elements=1, fixed=False)
>>> params = kernel.get_params()
>>> for key in sorted(params): print("%s : %s" % (key, params[key]))
k1 : 1**2 * RBF(length_scale=0.5)
k1__k1 : 1**2
k1__k1__constant_value : 1.0
k1__k1__constant_value_bounds : (0.0, 10.0)
k1__k2 : RBF(length_scale=0.5)
k1__k2__length_scale : 0.5
k1__k2__length_scale_bounds : (0.0, 10.0)
k2 : RBF(length_scale=2)
k2__length_scale : 2.0
k2__length_scale_bounds : (0.0, 10.0)
>>> print(kernel.theta) # Note: log-transformed
[ 0. -0.69314718 0.69314718]
>>> print(kernel.bounds) # Note: log-transformed
[[ -inf 2.30258509]
[ -inf 2.30258509]
[ -inf 2.30258509]]
所有高斯过程内核都与 sklearn.metrics.pairwise
互操作,反之亦然:Kernel
子类的实例可以作为 metric
传递给 sklearn.metrics.pairwise
中的 pairwise_kernels
。此外,pairwise 中的内核函数可以通过使用包装类 PairwiseKernel
作为 GP 内核使用。唯一的警告是超参数的梯度不是解析的,而是数值的,并且所有这些内核只支持各向同性距离。参数 gamma
被认为是超参数,可以进行优化。其他内核参数在初始化时直接设置,并保持固定。
1.7.4.1. 基本内核#
ConstantKernel
内核可以用作 Product
内核的一部分,它可以缩放其他因子(内核)的大小,或者用作 Sum
内核的一部分,它可以修改高斯过程的均值。它取决于参数 \(constant\_value\)。它定义为
WhiteKernel
内核的主要用例是作为求和内核的一部分,它解释了信号的噪声成分。调整其参数 \(noise\_level\) 等同于估计噪声水平。它定义为
1.7.4.2. 内核运算符#
内核运算符接受一个或两个基本内核,并将它们组合成一个新的内核。 Sum
内核接受两个内核 \(k_1\) 和 \(k_2\),并通过 \(k_{sum}(X, Y) = k_1(X, Y) + k_2(X, Y)\) 将它们组合起来。 Product
内核接受两个内核 \(k_1\) 和 \(k_2\),并通过 \(k_{product}(X, Y) = k_1(X, Y) * k_2(X, Y)\) 将它们组合起来。 Exponentiation
内核接受一个基本内核和一个标量参数 \(p\),并通过 \(k_{exp}(X, Y) = k(X, Y)^p\) 将它们组合起来。请注意,魔术方法 __add__
、__mul___
和 __pow__
在 Kernel 对象上被重写,因此可以使用例如 RBF() + RBF()
作为 Sum(RBF(), RBF())
的快捷方式。
1.7.4.3. 径向基函数 (RBF) 内核#
RBF
内核是一个平稳内核。它也被称为“平方指数”内核。它由长度尺度参数 \(l>0\) 参数化,该参数可以是标量(内核的各向同性变体)或与输入 \(x\) 维度相同的向量(内核的各向异性变体)。内核由下式给出
其中 \(d(\cdot, \cdot)\) 是欧几里得距离。该内核是无限可微的,这意味着具有该内核作为协方差函数的 GP 具有所有阶的均方导数,因此非常平滑。下图显示了由 RBF 内核产生的 GP 的先验和后验
1.7.4.4. Matérn 内核#
Matern
内核是一个平稳内核,也是 RBF
内核的推广。它有一个额外的参数 \(\nu\),它控制着所得函数的平滑度。它由长度尺度参数 \(l>0\) 参数化,该参数可以是标量(内核的各向同性变体)或与输入 \(x\) 维度相同的向量(内核的各向异性变体)。
Matérn 内核的数学实现#
内核由下式给出
其中 \(d(\cdot,\cdot)\) 是欧几里得距离,\(K_\nu(\cdot)\) 是修正贝塞尔函数,\(\Gamma(\cdot)\) 是伽马函数。当 \(\nu\rightarrow\infty\) 时,Matérn 内核收敛到 RBF 内核。当 \(\nu = 1/2\) 时,Matérn 内核与绝对指数内核相同,即
特别是,\(\nu = 3/2\)
和 \(\nu = 5/2\)
对于学习非无限可微函数(如 RBF 核假设)但至少一阶(\(\nu = 3/2\))或二阶可微(\(\nu = 5/2\))的函数,它们是流行的选择。
通过 \(\nu\) 控制学习函数的平滑度的灵活性允许适应真实底层函数关系的属性。
以下图示了由 Matérn 核产生的 GP 的先验和后验。
有关 Matérn 核的不同变体的更多详细信息,请参见 [RW2006],第 84 页。
1.7.4.5. 有理二次核#
RationalQuadratic
核可以看作是具有不同特征长度尺度的 RBF
核的尺度混合(无限和)。它由长度尺度参数 \(l>0\) 和尺度混合参数 \(\alpha>0\) 参数化。目前仅支持 \(l\) 为标量的各向同性变体。核由下式给出
以下图示了由 RationalQuadratic
核产生的 GP 的先验和后验。
1.7.4.6. Exp-Sine-Squared 核#
ExpSineSquared
核允许对周期函数进行建模。它由长度尺度参数 \(l>0\) 和周期性参数 \(p>0\) 参数化。目前仅支持 \(l\) 为标量的各向同性变体。核由下式给出
以下图示了由 ExpSineSquared 核产生的 GP 的先验和后验。
1.7.4.7. 点积核#
DotProduct
核是非平稳的,可以从线性回归中获得,方法是在 \(x_d (d = 1, . . . , D)\) 的系数上放置 \(N(0, 1)\) 先验,并在偏差上放置 \(N(0, \sigma_0^2)\) 先验。 DotProduct
核对原点周围的坐标旋转是不变的,但对平移是不变的。它由参数 \(\sigma_0^2\) 参数化。对于 \(\sigma_0^2 = 0\),核被称为齐次线性核,否则它是非齐次的。核由下式给出
DotProduct
核通常与求幂相结合。以下图示了指数为 2 的示例。