python 几何各向异性高斯过程回归

q8l4jmvw  于 2022-12-21  发布在  Python
关注(0)|答案(1)|浏览(142)
    • bounty将于明天到期**。回答此问题可获得+100的声望奖励。Rutger Kassies希望吸引更多人关注此问题。

是否可以为使用"几何各向异性"的GaussianProcessRegressor定义一个内核?
我知道可以用一些现有的核来定义各向异性,但它似乎只允许各向异性平行于维度。考虑相关维度的情况(例如空间x/y坐标),我希望各向异性能够考虑旋转由两个长度尺度(它们将成为长轴和短轴)定义的"椭圆"的Angular 。
这对我来说并不明显,这是否已经可以在Scikit-Learn中使用当前的内核,或者我是否应该通过子类化现有的内核来创建自己的内核。
请看下面的例子:

import numpy as np
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import Matern, ConstantKernel

# training data
ygrid, xgrid = np.mgrid[-2:3:1, -2:3:1]
X_train = np.stack([ygrid.flat, xgrid.flat], axis=1)
y_train = np.eye(*ygrid.shape).ravel()

# define the kernel
c = ConstantKernel(constant_value=y_train.mean(), constant_value_bounds='fixed')
m = Matern(length_scale=[0.5, 0.5], nu=0.5)

kernel = c * m

# fit
gp = GaussianProcessRegressor(kernel=kernel)
gp.fit(X_train, y_train)

拟合后的内核参数为:

print(gp.kernel_.get_params())
{'k1': 0.447**2,
 'k2': Matern(length_scale=[0.444, 0.444], nu=0.5),
 'k1__constant_value': 0.2,
 'k1__constant_value_bounds': 'fixed',
 'k2__length_scale': array([0.4443361, 0.4443361]),
 'k2__length_scale_bounds': (1e-05, 100000.0),
 'k2__nu': 0.5}

详细预测:

ygrid, xgrid = np.mgrid[-3:4:0.05, -3:4:0.05]
X_predict = np.stack([ygrid.flat, xgrid.flat], axis=1)

y_predict = gp.predict(X_predict)
y_predict = y_predict.reshape(xgrid.shape)

左轴显示训练数据(25个样本),右轴显示在更细网格上的预测:

从拟合结果中可以明显看出,各向异性在这种情况下不会增加任何内容,因为数据沿对角线相关,而Matern内核的各向异性无法捕捉到这一点。该图显示,如果我能够在某个地方指定此参数,沿对角线的预测可能会平滑得多。
对于我的用例,Angular 可以是任何值(0 - 360度),而且我事先不知道它,因此无法转换输入坐标。
对于现有的内核,是否有解决方法?或者我如何通过创建一个新的内核(最好是基于母体的)来添加此行为?

dced5bon

dced5bon1#

是的,对现有内核之一进行子类化并定义自己的内核函数是最好的选择。

import numpy as np
from sklearn.gaussian_process.kernels import Kernel

class GeometricAnisotropicKernel(Kernel):
    def __init__(self, length_scale, angle, nu=0.5):
        self.length_scale = length_scale
        self.angle = angle
        self.nu = nu
        
    def __call__(self, X, Y=None, eval_gradient=False):
        # Convert the angle to radians
        angle_rad = np.deg2rad(self.angle)
        
        # Rotate the coordinates by the angle
        X_rot = np.dot(X, [[np.cos(angle_rad), -np.sin(angle_rad)],
                           [np.sin(angle_rad), np.cos(angle_rad)]])
        if Y is not None:
            Y_rot = np.dot(Y, [[np.cos(angle_rad), -np.sin(angle_rad)],
                               [np.sin(angle_rad), np.cos(angle_rad)]])
        
        # Compute the kernel function using the rotated coordinates
        k = Matern(length_scale=self.length_scale, nu=self.nu)(X_rot, Y_rot, eval_gradient)
        
        return k

然后,您可以在GaussianProcessRegressor中使用此自定义内核,如下所示:

# training data
ygrid, xgrid = np.mgrid[-2:3:1, -2:3:1]
X_train = np.stack([ygrid.flat, xgrid.flat], axis=1)
y_train = np.eye(*ygrid.shape).ravel()

# define the kernel
c = ConstantKernel(constant_value=y_train.mean(), constant_value_bounds='fixed')
m = GeometricAnisotropicKernel(length_scale=[0.5, 0.5], angle=45)

kernel = c * m

# fit
gp = GaussianProcessRegressor(kernel=kernel)
gp.fit(X_train, y_train)

相关问题