Multi-output Gaussian Processes in PyMC [GSoC Week 04-06]
A personal note on the progress of incoporating Multi-output Gaussian Processes (MOGPs) into PyMC. Week 04-06 focus on implementing Linear model of coregionalization (LMC).
This work is supported by GSoC, NumFOCUS, and PyMC team.
import math
import numpy as np
import pymc as pm
import arviz as az
import matplotlib.pyplot as plt
# set the seed
np.random.seed(1)
%matplotlib inline
%load_ext autoreload
%reload_ext autoreload
%autoreload 2
train_x = np.linspace(0, 1, 50)
train_y = np.stack([
np.sin(train_x * (2 * math.pi)) + np.random.randn(len(train_x)) * 0.2,
np.cos(train_x * (2 * math.pi)) + np.random.randn(len(train_x)) * 0.2,
np.cos(train_x * (1 * math.pi)) + np.random.randn(len(train_x)) * 0.1,
], -1)
train_x.shape, train_y.shape
fig, ax = plt.subplots(1,1, figsize=(12,5))
ax.scatter(train_x, train_y[:,0])
ax.scatter(train_x, train_y[:,1])
ax.scatter(train_x, train_y[:,2])
plt.legend(["sin", "cos"])
x = train_x
xx = np.concatenate((x, x, x), axis=0)[:,None]
n = len(x)
idx2 = np.ones(n) + 1
idx = np.concatenate((np.zeros(n), np.ones(n), idx2))[:,None]
X = np.concatenate((xx, idx), axis=1)
y = np.concatenate((train_y[:,0], train_y[:,1], train_y[:,2]))
x.shape, X.shape, y.shape
X.shape, y.shape
with pm.Model() as model:
ell = pm.Gamma("ell", alpha=2, beta=0.5)
eta = pm.Gamma("eta", alpha=2, beta=0.5)
cov = eta**2 * pm.gp.cov.ExpQuad(2, ls=ell, active_dims=[0])
ell2 = pm.Gamma("ell2", alpha=2, beta=0.5)
eta2 = pm.Gamma("eta2", alpha=2, beta=0.5)
cov2 = eta**2 * pm.gp.cov.Matern32(2, ls=ell, active_dims=[0])
W = pm.Normal("W", mu=0, sigma=3, shape=(3,2), initval=np.random.randn(3,2))
kappa = pm.Gamma("kappa", alpha=1.5, beta=1, shape=3)
coreg = pm.gp.cov.Coregion(input_dim=2, active_dims=[1], kappa=kappa, W=W)
W2 = pm.Normal("W2", mu=0, sigma=3, shape=(3,2), initval=np.random.randn(3,2))
kappa2 = pm.Gamma("kappa2", alpha=1.5, beta=1, shape=3)
coreg2 = pm.gp.cov.Coregion(input_dim=2, active_dims=[1], kappa=kappa2, W=W2)
cov_func1 = coreg * cov #pm.gp.cov.Prod([coreg, cov])
cov_func2 = coreg2 * cov2 #pm.gp.cov.Prod([coreg2, cov2])
cov_func = cov_func1 + cov_func2 #pm.gp.cov.Add([cov_func1, cov_func2])
sigma = pm.HalfNormal("sigma", sigma=3)
gp = pm.gp.Marginal(cov_func=cov_func)
y_ = gp.marginal_likelihood("f", X, y, noise=sigma)
%%time
with model:
gp_trace = pm.sample(500, chains=1)
x_new = np.linspace(-0.5, 1.5, 200)[:, None]
xx_new = np.concatenate((x_new, x_new, x_new), axis=0)
idx2 = np.ones(200) + 1
idx2 = np.concatenate((np.zeros(200), np.ones(200), idx2))[:, None]
X_new = np.concatenate((xx_new, idx2), axis=1)
X_new.shape
with model:
preds = gp.conditional("preds", X_new)
gp_samples = pm.sample_posterior_predictive(gp_trace, var_names=['preds'], random_seed=42)
from pymc.gp.util import plot_gp_dist
fig = plt.figure(figsize=(12,5))
ax = fig.gca()
f_pred = gp_samples.posterior_predictive["preds"].sel(chain=0)
plot_gp_dist(ax, f_pred[:,:200], X_new[:200,0], palette="Blues", fill_alpha=0.5, samples_alpha=0.1)
ax.plot(x, train_y[:,0], 'ok', ms=3, alpha=0.5, label="Data 1");
from pymc.gp.util import plot_gp_dist
fig = plt.figure(figsize=(12,5))
ax = fig.gca()
plot_gp_dist(ax, f_pred[:,200:400], X_new[200:400,0], palette="Blues", fill_alpha=0.9, samples_alpha=0.1)
ax.plot(x, train_y[:,1], 'ok', ms=3, alpha=0.5, label="Data 2");
ax.set_ylim([-4,4])
from pymc.gp.util import plot_gp_dist
fig = plt.figure(figsize=(12,5))
ax = fig.gca()
plot_gp_dist(ax, f_pred[:,400:], X_new[400:,0], palette="Blues", fill_alpha=0.9, samples_alpha=0.1)
ax.plot(x, train_y[:,2], 'ok', ms=3, alpha=0.5, label="Data 2");
ax.set_ylim([-4,4])
az.summary(gp_trace)
az.plot_trace(gp_trace);
%load_ext watermark
%watermark -n -u -v -iv -w