【发布时间】:2021-08-04 00:15:14
【问题描述】:
我有一个关于 gpflow 2 中的多输出内核的问题。对于我正在处理的应用程序,我想创建一个独立的多输出内核,它在 一些 输出维度上共享内核,但不是全部。 GPflow 中的两个相关类是SharedIndependent 和SeparateIndependent 多输出内核类。然而,它们要么对所有 P 个输出维度使用一个共享内核,要么对 P 个输出维度使用 P 个单独的内核。
下面附加的代码是对多输出内核笔记本 (https://gpflow.readthedocs.io/en/master/notebooks/advanced/multioutput.html) 的小改编。 4 个输出维度可分为 2 组(每组 2 个输出维度):一组灵活性高,另一组灵活性低。我想为这个任务使用 2 个内核,以便为 Squared Exponential 内核检测 2 个不同的长度尺度参数。为了完整起见,我从示例笔记本中添加了 SharedIndependent 类和 SeparateIndependent 类的实现。
我目前尝试将这些组合如下:SeparateIndependent([SharedIndependent(SquaredExponential()+Linear(), output_dim=2) for _ in range(2)])。这会导致以下错误:(15是诱导点数)
ValueError: 维度必须相等,但对于 '{{node 来说是 2 和 15 add_8}} = AddV2[T=DT_DOUBLE](stack, mul_13)' 输入形状: [2,15,2,15,2],[1,15,15]。
为此,我还尝试创建一个新的多输出内核类,它在很大程度上模仿了SeparateIndependent 类,并对K(X, X2) 和K_diag(X) 函数中的循环列表理解进行了一些更改。这并没有成功,因为不知道如何为多输出内核类注册正确的Kuu()、Kuf() 和conditional() 函数。尝试创建与 SeparateIndependent 类相同但名称不同的类也失败了。
我很高兴知道是否可以组合 SharedIndependent 和 SeparateIndependent 类,或者构造一个新的 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)
【问题讨论】: