GPFlow多个独立实现同一个GP,不规则采样times/lengths

GPFlow multiple independent realizations of same GP, irregular sampling times/lengths

在GPflow中,我有多个时间序列,采样时间在时间​​序列之间没有对齐,时间序列可能有不同的长度(纵向数据)。我假设它们是来自同一 GP 的独立实现。使用 svgp 以及更普遍的 GPflow 处理此问题的正确方法是什么?我需要使用核心区域化吗?共区域化笔记本假定相关轨迹,而我想要共享 mean/kernel 但独立。

是的,在 GPflow 中实现的 Coregion 内核可以用来解决您的问题。

让我们根据您描述的生成模型设置一些数据,时间序列的长度不同:

import numpy as np
import gpflow
import matplotlib.pyplot as plt

Ns = [80, 90, 100]  # number of observations for three different realizations
Xs = [np.random.uniform(0, 10, size=N) for N in Ns]  # observation locations

# three different draws from the same GP:
k = gpflow.kernels.Matern52(variance=2.0, lengthscales=0.5)  # kernel

Ks = [k(X[:, None]) for X in Xs]
Ls = [np.linalg.cholesky(K) for K in Ks]
vs = [np.random.randn(N, 1) for N in Ns]
fs = [(L @ v).squeeze(axis=-1) for L, v in zip(Ls, vs)]

为 gpflow GP 模型实际设置训练数据:

# output indicator for the observations: which timeseries is this?
os = [o * np.ones(N) for o, N in enumerate(Ns)]  # [0 ... 0, 1 ... 1, 2 ... 2]

# now assemble the three timeseries in single data set:
allX = np.concatenate(Xs)
allo = np.concatenate(os)
allf = np.concatenate(fs)
X = np.c_[allX, allo]
Y = allf[:, None]
assert X.shape == (sum(Ns), 2)
assert Y.shape == (sum(Ns), 1)
# now let's set up a copy of the original kernel:
k2 = gpflow.kernels.Matern52(active_dims=[0])  # the same as k above, but with different hyperparameters

# and a Coregionalization kernel that effectively says they are all independent:
kc = gpflow.kernels.Coregion(output_dim=len(Ns), rank=1, active_dims=[1])
kc.W.assign(np.zeros(kc.W.shape))
kc.kappa.assign(np.ones(kc.kappa.shape))
gpflow.set_trainable(kc, False)  # we want W and kappa fixed

Coregion 内核定义协方差矩阵 B = W Wᵀ + diag(kappa),因此通过设置 W=0 我们规定零相关(独立实现)和 kappa=1(实际上是默认值)确保原始内核副本的方差超参数仍然可以解释。

现在构建实际模型并优化超参数:

k2c = k2 * kc

m = gpflow.models.GPR((X, Y), k2c, noise_variance=1e-5)

opt = gpflow.optimizers.Scipy()
opt.minimize(m.training_loss, m.trainable_variables, compile=False)

很好地恢复了初始方差和长度尺度超参数。

如果你想预测,你必须在 m.predict_f()Xnew 参数中提供额外的“输出”列,例如如下:

Xtest = np.linspace(0, 10, 100)
Xtest_augmented = np.c_[Xtest, np.zeros_like(Xtest)]
f_mean, f_var = m.predict_f(Xtest_augmented)

(将输出列设置为 0、1 或 2 并不重要,因为我们将它们全部设置为与我们选择的 Wkappa 相同)。

如果您的输入超过one-dimensional,您可以设置 active_dims=list(range(X.shape[1] - 1)) 表示第一个内核,active_dims=[X.shape[1]-1] 表示 Coregion 内核。