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

Oka*_*rin 6 scikit-learn

我正在考虑使用GPR作为一个相当特殊的上下文,我需要编写自己的内核.但是我发现没有关于如何做到这一点的文档.试图简单地从继承Kernel和实施方法__call__,get_params,diag并且is_stationary是足以让安装过程顺利进行,但随后打破了,当我试图预测y值和标准差.构建一个Kernel在使用自己的函数时继承的最小但功能类的必要步骤是什么?谢谢!

小智 6

取决于您的内核的奇特程度,对您问题的答案可能有所不同。

我发现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):
        # ...
Run Code Online (Sandbox Code Playgroud)

至于你提到的内核应该继承内核,这就需要你来实现__call__diagis_stationary。请注意,这sklearn.gaussian_process.kernels提供了StationaryKernelMixinNormalizedKernelMixin,其实现diagis_stationary你(代码参见RBF类定义)。

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

此时,您可能会注意到另一个参数length_scale_bounds。那只是对实际超参数的length_scale约束(请参阅约束优化)。这使我们意识到,您还需要声明您的超级参数,您需要对其进行优化,并需要在__call__实现中计算梯度。为此,您可以定义类的前缀为hyperparameter_hyperparameter_length_scale在代码中为cf )的属性。每个未固定的超级参数(fixed = hyperparameter.fixed == True)都会由返回Kernel.theta,GP会使用它fit()来计算边际对数似然。因此,如果要使参数适合数据,这是必不可少的

关于的最后一个细节Kernel.theta表示:

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

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

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