我正在考虑使用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__,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在代码中为cf )的属性。每个未固定的超级参数(fixed = hyperparameter.fixed == True)都会由返回Kernel.theta,GP会使用它fit()来计算边际对数似然。因此,如果要使参数适合数据,这是必不可少的。
关于的最后一个细节Kernel.theta表示:
返回(展平,对数转换的)非固定超参数。
因此,您应谨慎使用超级参数中的0值,因为它们最终可能会变成np.nan并破坏东西。
我希望这会有所帮助,即使这个问题已经有点老了。我实际上从未亲自实现过内核,但渴望浏览sklearn代码库。不幸的是,没有关于它的官方教程,但是代码库很干净,也很注释。
| 归档时间: |
|
| 查看次数: |
1437 次 |
| 最近记录: |