GP-basics
In [1]:
import sys

import matplotlib.pyplot as pl
%matplotlib inline

import numpy as np
np.warnings.simplefilter('ignore')
import scipy.optimize as op

from scipy.linalg import cho_factor, cho_solve
In [2]:
def lnlike_gp(r, K):
    """
    The multivariate Gaussian ln-likelihood (up to a constant) for the
    vector ``r`` given a covariance matrix ``K``.
    
    :param r: ``(N,)``   The residual vector with ``N`` points.
    :param K: ``(N, N)`` The square (``N x N``) covariance matrix.
    
    :returns lnlike: ``float`` The Gaussian ln-likelihood. 
    
    """
    alpha = np.linalg.solve(K, r)
    s, d = np.linalg.slogdet(K)
    return -0.5 * (np.dot(r, alpha) + d)


def lnlike_gp_faster(r, K):
    """
    The multivariate Gaussian ln-likelihood (up to a constant) for the
    vector ``r`` given a covariance matrix ``K``.
    
    :param r: ``(N,)``   The residual vector with ``N`` points.
    :param K: ``(N, N)`` The square (``N x N``) covariance matrix.
    
    :returns lnlike: ``float`` The Gaussian ln-likelihood. 
    
    """
    L, lower = cho_factor(K)
    Lt_alpha = cho_solve((L,lower), r)
    ln_det = 2 * sum(np.log(np.diag(L)))
    return -0.5 * (np.dot(r, Lt_alpha) + ln_det)
In [3]:
def expsq_kernel(theta, dx):
    """
    The exponential-squared kernel function. The difference matrix
    can be an arbitrarily shaped numpy array so make sure that you
    use functions like ``numpy.exp`` for exponentiation.
    
    :param theta: ``(2,)`` The parameter vector ``(amp, ell)``.
    :param dx: ``numpy.array`` The difference matrix. This can be
        a numpy array with arbitrary shape.
    
    :returns K: The kernel matrix (should be the same shape as the
        input ``dx``).
        
    """
    amp, tau = theta
    return amp ** 2 * np.exp( -1 * dx**2 / (2 * tau ** 2) )

def dx(x):
    return x[None, :] - x[:, None]

fig, axs = pl.subplots(2, 3, figsize=(11,7), sharex=True, sharey=True)
x = np.linspace(-10, 10, 500)
thetas = [1,1], [1,-1], [1,2], [2,1], [2,-1], [2,2]
for i, theta in enumerate(thetas):
    K = expsq_kernel(np.exp(theta), dx(x))
    y = np.random.multivariate_normal(np.zeros_like(x), K)
    axs.flat[i].plot(x, y.T, lw=1.5)
    axs.flat[i].set_title(r"$\alpha = {},\ \tau = {}$".format(*theta), fontsize=20)

fig.tight_layout()
In [4]:
def expsinesq_kernel(theta, dx):
    """
    The exponential-sine-squared kernel function. The difference matrix
    can be an arbitrarily shaped numpy array so make sure that you
    use functions like ``numpy.exp`` for exponentiation.
    
    :param theta: ``(2,)`` The parameter vector ``(amp, ell)``.
    :param dx: ``numpy.array`` The difference matrix. This can be
        a numpy array with arbitrary shape.
    
    :returns K: The kernel matrix (should be the same shape as the
        input ``dx``).
        
    """    
    gamma, period = theta
    return np.exp(-gamma * np.sin(np.pi * dx / period) ** 2)


fig, axs = pl.subplots(2, 3, figsize=(11,7), sharex=True, sharey=True)
x = np.linspace(-10, 10, 500)
thetas = [1,1], [1,-1], [1,2], [2,1], [2,-1], [2,2]
for i, theta in enumerate(thetas):
    K = expsinesq_kernel(np.exp(theta), dx(x))
    y = np.random.multivariate_normal(np.zeros_like(x), K)
    axs.flat[i].plot(x, y.T, lw=1.5)
    axs.flat[i].set_title(r"$\Gamma = {},\ P = {}$".format(*theta), fontsize=20)

fig.tight_layout()
In [5]:
def least_squares(x, y, yerr):

    A = np.vander(x, 2)
    AT = A.T

    cov = np.linalg.inv(np.dot(AT, A / yerr[:, None] ** 2))
    mu = np.dot(cov, np.dot(AT, y / yerr ** 2))

    return mu, cov


def compute(theta, kernel, x, y, yerr, xs):

    rxx = x[:, None] - x[None, :]
    rss = xs[:, None] - xs[None, :]
    rxs = x[None, :] - xs[:, None]
    ye2 = yerr ** 2
    
    # Compute the covariance matrices.
    Kxx = kernel(theta, rxx)
    Kxx[np.diag_indices_from(Kxx)] += ye2
    Kss = kernel(theta, rss)
    Kxs = kernel(theta, rxs)

    # Compute the residuals.
    mu, _ = least_squares(x, y, yerr)
    m, b = mu
    resid = y - (m*x+b)
    model = m*xs+b
    a = np.linalg.solve(Kxx, resid)

    # Compute the predictive mean.
    mu = np.dot(Kxs, a) + model

    # Compute the predictive covariance.
    cov = Kss - np.dot(Kxs, np.linalg.solve(Kxx, Kxs.T))

    return mu, cov


def sample_conditional(theta, kernel, x, y, yerr, xs, n):
    
    mu, cov = compute(theta, kernel, x, y, yerr, xs)
    
    ys = np.random.multivariate_normal(mu, cov, n)

    return ys
In [6]:
n = 10
t = np.sort(20*np.random.rand(n)-10)
sig = 1
y = np.random.randn(n) * sig
yerr = np.ones_like(y) * sig

t_pred = np.linspace(-10, 10, 500)

theta = 1, 1

fig, axs = pl.subplots(1, 3, figsize=(15,3), sharex=True, sharey=True)

amp, tau = np.exp(theta)
mu = np.zeros_like(t_pred)
K = expsq_kernel(np.exp(theta), dx(t_pred))    
for ys in np.random.multivariate_normal(mu, K, 10):
    axs[0].plot(t_pred, ys, color='C9', lw=1.5, alpha=0.5)
axs[0].set_title('GP samples from prior')

theta = amp, tau
kernel = expsq_kernel
mu, cov = compute(theta, kernel, t, y, yerr, t_pred)
for ys in np.random.multivariate_normal(mu, cov, 20):
    axs[1].plot(t_pred, ys, color='C9', lw=1.5, alpha=0.5, zorder=0)
axs[1].errorbar(t, y, yerr, marker='o', color='C0', linestyle='none', zorder=1)
axs[1].set_title('GP conditional samples')

pred_mean = mu
pred_std = np.sqrt(cov.diagonal())
axs[2].plot(t_pred, pred_mean, color='C9', zorder=0)
axs[2].fill_between(t_pred, pred_mean+pred_std, pred_mean-pred_std, color='C9', alpha=0.5, edgecolor="none", zorder=0)
axs[2].errorbar(t, y, yerr, marker='o', color='C0', linestyle='none', zorder=1)
axs[2].set_title('GP conditional mean and sigma')

fig.tight_layout()
In [13]:
n = 10
t = np.sort(20*np.random.rand(n)-10)
sig = 1
y = np.random.randn(n) * sig
yerr = np.ones_like(y) * sig

t_pred = np.linspace(-10, 10, 100)

fig, axs = pl.subplots(2, 3, figsize=(15,8), sharex=False, sharey=False)

thetas = list(zip([1,5,10],[-1,2,5]))
for i, theta in enumerate(thetas):

    mu = np.zeros_like(t_pred)
    K = expsq_kernel(np.exp(theta), dx(t_pred))    

    axs[0,i].imshow(K, interpolation='none', cmap=pl.cm.gray)
    axs[0,i].xaxis.set_visible(False)
    axs[0,i].yaxis.set_visible(False)
    
    kernel = expsq_kernel
    mu, cov = compute(theta, kernel, t, y, yerr, t_pred)

    pred_mean = mu
    pred_std = np.sqrt(cov.diagonal())

    axs[1,i].plot(t_pred, pred_mean, color='C9', zorder=0)
    axs[1,i].fill_between(t_pred, pred_mean+pred_std, pred_mean-pred_std, color='C9', alpha=0.5, edgecolor="none", zorder=0)
    axs[1,i].errorbar(t, y, yerr, marker='o', color='C0', linestyle='none', zorder=1)
    axs[1,i].set_title(r"$\alpha = {},\ \tau = {}$".format(*theta), fontsize=20)

fig.tight_layout()
In [ ]: