lastsys
  • Om
  • Alla artiklar
  • RSS

Estimating Derivatives for Gaussian Processes - 2012-07-15

Building the basics for solving differential equations.

In a previous post I wrote about basic Gaussian Processes. Sometimes it is of interest to also estimate the gradient and maybe have a confidence interval for that as well. For a given covariance function $$k(x_i,x_j)$$ and an estimated function $$f(x)$$ the following relations should hold:

$$\begin{array}{rcl} \text{cov} \left( f_i, \frac{\partial f_j}{\partial x_j} \right) & = & \frac{\partial k(x_i, x_j)}{\partial x_j} \ \text{cov} \left( \frac{\partial f_i}{\partial x_i}, f_j \right) & = & \frac{\partial k(x_i, x_j)}{\partial x_i} \ \text{cov} \left( \frac{\partial f_i}{\partial x_i}, \frac{\partial f_j}{\partial x_j} \right) & = & \frac{\partial^2 k(x_i, x_j)}{\partial x_i \partial x_j} \end{array}$$

The joint distribution for two variables with normal distribution where $$f$$ represents the measured values and $$f_*$$ contains the values we want to estimate:

$$\left( \begin{array}{c} f \ f_* \end{array} \right) \sim N \left( \left( \begin{array}{c} 0 \ 0 \end{array} \right), \left( \begin{array}{cc} K(X,X) + \sigma^2_n I & K(X,X_) \ K(X_,X) & K(X_,X_) \end{array} \right) \right)$$

This means that we have:

$$\left( \begin{array}{c} f \ \frac{\partial f_}{\partial x_} \end{array} \right) \sim N \left( \left( \begin{array}{c} 0 \ \vdots \ 0 \ \hline 0 \ \vdots \ 0 \end{array} \right), \left( \begin{array}{cccc|cccc} k(x_1,x_1) + \sigma^2_n & k(x_1,x_2) & \cdots & k(x_1,x_n) & \frac{\partial k(x_1,x^_1)}{\partial x^_1} & \frac{\partial k(x_1,x^_2)}{\partial x^_2} & \cdots & \frac{\partial k(x_1,x^_n)}{\partial x^_n} \ \vdots & \vdots & & \vdots & \vdots & \vdots & & \vdots \ k(x_n,x_1) & k(x_n,x_2) & \cdots & k(x_n,x_n) + \sigma^2_n & \frac{\partial k(x_n,x^_1)}{\partial x^_1} & \frac{\partial k(x_n,x^_2)}{\partial x^_2} & \cdots & \frac{\partial k(x_n,x^_n)}{\partial x^_n} \ \hline \frac{\partial k(x^_1,x_1)}{\partial x^_1} & \frac{\partial k(x^_1,x_2)}{\partial x^_1} & \cdots & \frac{\partial k(x^_1,x_n)}{\partial x^_1} & \frac{\partial^2 k(x^_1,x^_1)}{\partial {x^_1}^2} & \frac{\partial^2 k(x^_1,x^_2)}{\partial x^_1 \partial x^_2} & \cdots & \frac{\partial^2 k(x^_1,x^_n)}{\partial x^_1 \partial x^_n} \ \vdots & \vdots & & \vdots & \vdots & \vdots & & \vdots \ \frac{\partial k(x^_n,x_1)}{\partial x^_n} & \frac{\partial k(x^_n,x_2)}{\partial x^_n} & \cdots & \frac{\partial k(x^_n,x_n)}{\partial x^_n} & \frac{\partial^2 k(x^_n,x^_1)}{\partial x^_n \partial x^_1} & \frac{\partial^2 k(x^_n,x^_2)}{\partial x^_n \partial x^_2} & \cdots & \frac{\partial^2 k(x^_n,x^_n)}{\partial {x^_n}^2} \end{array} \right) \right) $$

These expressions are used in the same way when calculating the conditional outcome:

$$\left. \frac{\partial f_}{\partial X_} \right| X_, f, X \sim N \left( \underbrace{ \frac{\partial K(X_,X)}{\partial X_} \left( K(X,X) + \sigma^2_n I \right)^{-1}}{\text{Expected derivative}}, \underbrace{ \frac{\partial^2 K(X,X_)}{\partial X^2_} - \frac{\partial K(X_,X)}{\partial X_} \left( K(X,X) + \sigma^2_n I \right)^{-1} \frac{\partial K(X,X_)}{\partial X_} }_{\text{Variance of derivative}} \right)$$

So, to make this work we need to calculate the explicit expressions for the covariance function. Using a quadratic exponential covariance function:

$$k(x_i,x_j) = \exp \left( -\frac{1}{2} \frac{||x_i-x_j||^2_2}{\ell^2} \right) $$

The derivatives with respect to $$x_i$$ and $$x_j$$ are:

$$\frac{\partial k(x_i,x_j)}{\partial x_i} = - \frac{x_i - x_j}{\ell^2} \left( -\frac{1}{2} \frac{||x_i-x_j||^2_2}{\ell^2} \right) $$

$$ \frac{\partial k(x_i,x_j)}{\partial x_j} = \frac{x_i - x_j}{\ell^2} \left( -\frac{1}{2} \frac{||x_i-x_j||^2_2}{\ell^2} \right) $$

and the second order derivatives

$$ \frac{\partial^2 k(x_i, x_j)}{\partial x^2_i} = \frac{1}{\ell^2} \left( \frac{(x_i-x_j)^2}{\ell^2} - 1 \right) \left( -\frac{1}{2} \frac{||x_i-x_j||^2_2}{\ell^2} \right) $$

$$ \frac{\partial^2 k(x_i, x_j)}{\partial x^2_j} = \frac{1}{\ell^2} \left( \frac{(x_i-x_j)^2}{\ell^2} - 1 \right) \left( -\frac{1}{2} \frac{||x_i-x_j||^2_2}{\ell^2} \right) $$

$$ \frac{\partial^2 k(x_i, x_j)}{\partial x_i \partial x_j} = \frac{1}{\ell^2} \left( 1 - \frac{(x_i-x_j)^2}{\ell^2} \right) \left( -\frac{1}{2} \frac{||x_i-x_j||^2_2}{\ell^2} \right) $$

Combining all of this gives a result shown in the following figure:

Derivatives.

The blue line is the expected function value, the dashed blue line is the 95%-confidence interval. The thick red lines are expected derivatives and the dashed red lines are 95%-confidence intervals for the derivatives. A strange result is that the derivative is very uncertain close to an observation while it is more certain in-between. The uncertainty of the derivatives is highly dependent on the length scale (a longer length scale reduces the uncertainty) and many points in a tight interval also helps.

Python code for creating the plot is given below:

#!/usr/bin/env python2.7
import numpy as np
import matplotlib.pyplot as plt

def covfun(x1, x2, ell):
    k = np.exp(-0.5 * ((x1 - x2) / ell) ** 2.0)
    return k

def dx1_covfun(x1, x2, ell):
    ell2 = ell ** 2.0
    k = (x2 - x1) / ell2 * covfun(x1, x2, ell)
    return k

def dx2_covfun(x1, x2, ell):
    ell2 = ell ** 2.0
    k = (x1 - x2) / ell2 * covfun(x1, x2, ell)
    return k

def ddx1x2_covfun(x1, x2, ell):
    ell2 = ell ** 2.0
    ell4 = ell ** 4.0
    k = ((ell2 - (x1 - x2) ** 2.0) / ell4 * covfun(x1, x2, ell))
    return k

# Characteristic length.
l = np.sqrt(0.025)

# Noise variance.
s = 0.01

# Measured points.
x = np.array([0.1, 0.15, 0.18, 0.2, 0.4, 0.6, 0.8, 0.9])
y = np.array([0.2, 0.3, 0.4, 0.5, 0.7, 0.4, 0.3, 0.2])

# Grid to predict values for.
xg = np.linspace(0.0, 1.0, 61)

# Initialization of covariance matrix.
K11 = np.zeros((len(x), len(x)))
K12 = np.zeros((len(x), len(xg)))
K21 = np.zeros((len(xg), len(x)))
K22 = np.zeros((len(xg), len(xg)))

D11 = K11
D12 = np.zeros((len(x), len(xg)))
D21 = np.zeros((len(xg), len(x)))
D22 = np.zeros((len(xg), len(xg)))

# Fill covariance matrix with values.
for row in xrange(len(x)):
    for col in xrange(len(x)):
        K11[row, col] = covfun(x[row], x[col], l)

# Do the same for the parts where the grid is involved.
for row in xrange(len(x)):
    for col in xrange(len(xg)):
        K12[row, col] = covfun(x[row], xg[col], l)
        K21[col, row] = covfun(xg[col], x[row], l)
        D12[row, col] = dx2_covfun(x[row], xg[col], l)
        D21[col, row] = dx1_covfun(xg[col], x[row], l)

# And the grid itself.
for row in xrange(len(xg)):
    for col in xrange(len(xg)):
        K22[row, col] = covfun(xg[row], xg[col], l)
        D22[row, col] = ddx1x2_covfun(xg[row], xg[col], l)

# Expected values for grid.
Kinv = np.linalg.pinv(K11 + s * np.eye(len(x)))
yg = np.dot(np.dot(K21, Kinv), y)
covyg = np.diag(K22 - np.dot(np.dot(K21, Kinv), K12))

dyg = np.dot(np.dot(D21, Kinv), y)
dcovyg = (D22 - np.dot(np.dot(D21, Kinv), D12))
dcovyg = np.diag(dcovyg)

plt.plot(xg, yg, 'b', linewidth=2)
plt.hold(True)
plt.plot(xg, yg + covyg * 1.96, 'b--')
plt.plot(xg, yg - covyg * 1.96, 'b--')
L = 0.025
for k in xrange(5, len(xg), 5):
    plt.plot(np.array([xg[k] - L, xg[k] + L]),
             np.array([yg[k] - dyg[k] * L,
                      yg[k] + dyg[k] * L]), 'r', linewidth=3)

    plt.plot(np.array([xg[k] - L, xg[k] + L]),
             np.array([yg[k] - (dyg[k] + 1.96 * dcovyg[k]) * L,
                      yg[k] + (dyg[k] + 1.96 * dcovyg[k]) * L]), 'r--')

    plt.plot(np.array([xg[k] - L, xg[k] + L]),
             np.array([yg[k] - (dyg[k] - 1.96 * dcovyg[k]) * L,
                      yg[k] + (dyg[k] - 1.96 * dcovyg[k]) * L]), 'r--')
plt.plot(x, y, 'ok')

plt.axis([0.0, 1.0, 0.0, 1.0])
plt.xlabel('$x$')
plt.ylabel('$f(x)$')
plt.show()


© Stefan Larsson 2012-2025

Linkedin GitHub GitLab