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

时间:2018-03-08 17:01:01

标签: scikit-learn

我正在研究使用GPR作为一个相当特殊的上下文,我需要编写自己的内核。但是我发现没有关于如何做到这一点的文档。尝试简单地从Kernel继承并实施方法__call__get_paramsdiagis_stationary足以使拟合过程起作用,但随后会中断当我试图预测y值和标准差时。构建一个在使用自己的函数时继承自Kernel的最小但功能类的必要步骤是什么?谢谢!

1 个答案:

答案 0 :(得分:5)

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

我发现implementation of the RBF kernel完全是自我记录的,因此我将其用作参考。要点如下:

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__diagis_stationary。请注意,sklearn.gaussian_process.kernels提供了StationaryKernelMixinNormalizedKernelMixin,它们为您实现了diagis_stationary(参见代码中的RBF类定义)。

您不应覆盖get_params!这是由Kernel类为您完成的,它期望scikit-learn内核遵循一个约定,您的内核也应遵循一个约定:在构造函数的签名中将参数指定为关键字参数(请参见{{ 1}}。这样可以确保您的内核可以通过length_scale复制(这可能是您无法预测标准偏差的原因)。

这时,您可能会注意到另一个参数GaussianProcessRegressor.fit(...)。这仅是对实际超参数length_scale_bounds的约束(请参阅约束优化)。这带给我们一个事实,即您还需要声明hyper parameters,要进行优化并且需要在length_scale实现中计算梯度。为此,您可以定义类的属性,该属性以__call__为前缀(参见代码中的hyperparameter_)。 hyperparameter_length_scale返回每个不固定(固定= hyperparameter.fixed == True)的超级参数,GP在Kernel.theta上使用它来计算边际对数似然。因此,如果要使参数适合数据,这是 essential

关于fit()的最后一个细节,该实现指出:

  

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

因此,您应该在超级参数中使用0值,因为它们最终可能会变成np.nan并破坏东西。

我希望这会有所帮助,即使这个问题已经有点老了。我实际上从未亲自实现过内核,但渴望浏览sklearn代码库。不幸的是,没有关于它的官方教程,但是代码库却很干净而且带有注释。