如何在 scikit-learn 中为高斯过程回归器创建自定义内核?

问题描述 投票:0回答:1

我正在考虑在一个相当特殊的环境中使用 GPR,我需要编写自己的内核。但是我发现没有关于如何执行此操作的文档。尝试简单地继承

Kernel
并实现方法
__call__
get_params
diag
is_stationary
足以让拟合过程正常工作,但当我尝试预测 y 值和标准时就会崩溃偏差。构建一个最小但功能齐全的类,该类继承自
Kernel
,同时使用自己的函数,需要哪些必要步骤?谢谢!

scikit-learn
1个回答
11
投票

根据您的内核的异国情调,您问题的答案可能会有所不同。

我发现 RBF 内核的实现 非常自我记录,所以我用它作为参考。要点如下:

class RBF(StationaryKernelMixin, NormalizedKernelMixin, Kernel):
    def __init__(self, length_scale=1.0, length_scale_bounds=(1e-5, 1e5)):
        self.length_scale = length_scale
        self.length_scale_bounds = length_scale_bounds

    @property
    def hyperparameter_length_scale(self):
        if self.anisotropic:
            return Hyperparameter("length_scale", "numeric",
                                  self.length_scale_bounds,
                                  len(self.length_scale))
        return Hyperparameter(
            "length_scale", "numeric", self.length_scale_bounds)

    def __call__(self, X, Y=None, eval_gradient=False):
        # ...

正如您所提到的,您的内核应该继承自Kernel,这需要您实现

__call__
diag
is_stationary
。请注意,
sklearn.gaussian_process.kernels
提供了
StationaryKernelMixin
NormalizedKernelMixin
,它们为您实现了
diag
is_stationary
(参见代码中的RBF类定义)。

您不应该覆盖

get_params
!这是由 Kernel 类为您完成的,它期望 scikit-learn 内核遵循约定,您的内核也应该遵循约定:将构造函数签名中的参数指定为关键字参数(请参阅上一个示例中的
length_scale
) RBF 核)。这确保了您的内核可以被复制,这是由
GaussianProcessRegressor.fit(...)
完成的(这可能是您无法预测标准偏差的原因)。

此时,您可能会注意到另一个参数

length_scale_bounds
。这只是对实际超参数
length_scale
的约束(参见约束优化)。这让我们认识到一个事实,即您还需要声明您想要优化的超级参数,并且需要在您的
__call__
实现中计算梯度。您可以通过定义一个以
hyperparameter_
为前缀的类属性来实现这一点(参见代码中的
hyperparameter_length_scale
)。每个不固定的超参数(固定 =
hyperparameter.fixed == True
)由
Kernel.theta
返回,GP 在
fit()
上使用它并计算边际对数似然。因此,如果您想使参数适合您的数据,这是必不可少的

关于

Kernel.theta
的最后一个细节,实施状态:

返回(展平、对数转换)非固定超参数。

因此,您应该小心超参数中的 0 值,因为它们最终可能会成为 np.nan 并破坏内容。

我希望这会有所帮助,尽管这个问题已经有点老了。实际上,我自己从未实现过内核,但很想浏览一下 sklearn 代码库。不幸的是,没有这方面的官方教程,但是代码库非常干净并带有注释。

© www.soinside.com 2019 - 2024. All rights reserved.