GPflow2:具有部分共享内核的多输出内核(MOK)

2024-10-03 21:25:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个关于gpflow 2中的多输出内核的问题。对于我正在处理的应用程序,我想创建一个独立的多输出内核,它在一些输出维度(但不是全部)之间共享内核。GPflow中的两个相关类是SharedIndependentSeparateIndependent多输出内核类。然而,它们要么对所有P输出维度使用一个共享内核,要么对P输出维度使用P个单独的内核

下面附带的代码是多输出内核笔记本(https://gpflow.readthedocs.io/en/master/notebooks/advanced/multioutput.html)的一个小改编。4个输出维度可分为2组(每组2个输出维度):一组具有高灵活性,另一组具有低灵活性。我想在这个任务中使用2个内核,以便为平方指数内核检测2个不同的长度尺度参数。为了完整起见,我在示例笔记本中为SharedIndependent类和SeparateIndependent类添加了实现

目前,我已尝试将这些组合如下:SeparateIndependent([SharedIndependent(SquaredExponential()+Linear(), output_dim=2) for _ in range(2)])。这会导致以下错误:(15是诱导点的数量)

ValueError: Dimensions must be equal, but are 2 and 15 for '{{node add_8}} = AddV2[T=DT_DOUBLE](stack, mul_13)' with input shapes: [2,15,2,15,2], [1,15,15].

我还尝试为此创建一个新的多输出内核类,它在很大程度上模仿了SeparateIndependent类,并对K(X, X2)K_diag(X)函数中的循环列表理解进行了一些修改。由于不知道如何为多输出内核类注册正确的Kuu()Kuf()conditional()函数,因此这没有成功。尝试使用不同名称创建与SeparateIndependent类相同的类也失败

我很高兴知道是否有可能将SharedIndependentSeparateIndependent类结合起来,或者构建一个新的MOK类是否是解决这个问题的更好方法。如果是这样,解决注册条件表达式(Kuu()Kuf()conditional())问题的最佳方法是什么

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import gpflow
from gpflow.kernels import SquaredExponential, Linear, SharedIndependent, SeparateIndependent
from gpflow.inducing_variables import SharedIndependentInducingVariables, InducingPoints
from gpflow.utilities import print_summary
from gpflow.ci_utils import ci_niter
gpflow.config.set_default_float(np.float64)
np.random.seed(0)
MAXITER = ci_niter(2000)

N = 100  # number of points
D = 1  # number of input dimensions
M = 15  # number of inducing points
L = P = 4  # number of latent GPs, number of observations = output dimension

def generate_data(N=100):
    X = np.random.rand(N)[:, None] * 10 - 5  # Inputs = N x D
    G = np.hstack((0.5 * np.sin(X/2) + X, 3.0 * np.cos(X/2) - X,0.5 * np.sin(4 * X) + X, 3.0 * np.cos(4*X) - X))  # G = N x L
    W = np.array([[0.5, -0.3, 0, 0], [0.5, -0.3, 0, 0], [0, 0, -0.4, 0.6],[0.0, 0.0, 0.6, -0.4]])  # L x P
    F = np.matmul(G, W)  # N x P
    Y = F + np.random.randn(*F.shape) * [0.2, 0.2, 0.2, 0.2]

    return X, Y
X, Y = data = generate_data(N)
print(X.shape, Y.shape)
Zinit = np.linspace(-5, 5, M)[:, None]

def plot_model(m, name, lower=-7.0, upper=7.0):
    pX = np.linspace(lower, upper, 100)[:, None]
    pY, pYv = m.predict_y(pX)
    if pY.ndim == 3:
        pY = pY[:, 0, :]
    plt.plot(X, Y, "x")
    plt.gca().set_prop_cycle(None)
    plt.plot(pX, pY)
    for i in range(pY.shape[1]):
        top = pY[:, i] + 2.0 * pYv[:, i] ** 0.5
        bot = pY[:, i] - 2.0 * pYv[:, i] ** 0.5
        plt.fill_between(pX[:, 0], top, bot, alpha=0.3)
    plt.xlabel("X")
    plt.ylabel("f")
    plt.title(f"{name} kernel.")
    plt.show()

# initialization of inducing input locations (M random points from the training inputs)
Z = Zinit.copy()
# create multi-output inducing variables from Z
iv = SharedIndependentInducingVariables(InducingPoints(Z))

def optimize_model_with_scipy(model):
    optimizer = gpflow.optimizers.Scipy()
    optimizer.minimize(
        model.training_loss_closure(data),
        variables=model.trainable_variables,
        method="l-bfgs-b",
        options={"disp": True, "maxiter": MAXITER},
    )


# create multi-output kernel
kernels = [
        (SeparateIndependent([SquaredExponential() + Linear() for _ in range(P)]),'Seperate Independent'),
        (SharedIndependent(SquaredExponential()+Linear(), output_dim=P), 'Shared Independent'),
        (SeparateIndependent([SharedIndependent(SquaredExponential()+Linear(), output_dim=2) for _ in range(2)]), 'Partially shared independent')
       ]
for (kernel, name) in kernels:
    m = gpflow.models.SVGP(kernel, gpflow.likelihoods.Gaussian(), inducing_variable=iv, num_latent_gps=P)
    print_summary(m)
    optimize_model_with_scipy(m)
    print_summary(m)
    plot_model(m, name)

Tags: offrompyimportforoutputmodelnp