Open an interactive version of this example on Binder: Binder badge

Derivative Approximation#

This example demonstrates the use of conditional distribution embeddings to compute an approximation of the first and second derivatives of a function,

\[f(x) = x^{3} - 4 x^{2} + 6 x - 24 + \exp(-x)\]

We use an idealized dataset, which approximates the partial derivatives well. Introducing noise to the dataset creates fluctuations that needs to be offset by a higher regularization parameter and smoother kernel.

To run the example, use the following command:

python examples/kernel/derivative_approximation.py
[1]:
import numpy as np
from functools import partial

from gym_socks.kernel.metrics import rbf_kernel
from gym_socks.kernel.metrics import rbf_kernel_derivative
from gym_socks.kernel.metrics import regularized_inverse

from time import perf_counter

import matplotlib
from matplotlib import pyplot as plt

Generate the Sample#

The following sample is idealized in order to demonstrate the technique. Additive noise causes fluctuations in the derivative approximation.

[2]:
sample_size = 200
X_train = np.linspace(-5, 5, sample_size).reshape(-1, 1)
y_train = X_train ** 3 - 4 * X_train ** 2 + 6 * X_train - 24 + np.exp(-X_train)

# Uncomment the following line to incorporate noise in the sample.
# y_train += 10 * np.random.standard_normal(size=(sample_size, 1))  # Additive noise.

X_test = np.linspace(-4, 4, 1000).reshape(-1, 1)

Kernel and Parameters#

[3]:
sigma = 0.1
kernel_fn = partial(rbf_kernel, sigma=sigma)
regularization_param = 1 / (sample_size ** 2)

Compute the Approximation#

[4]:
start = perf_counter()

G = kernel_fn(X_train)
K = kernel_fn(X_train, X_test)

W = regularized_inverse(G, regularization_param=regularization_param)

C = rbf_kernel_derivative(X_train, sigma=sigma)
D = rbf_kernel_derivative(X_train, X_test, sigma=sigma)

y_pred = y_train.T @ W @ K
y_pred_d1 = -y_train.T @ W @ (K * D)
y_pred_d2 = (y_train.T @ W @ (G * C)) @ W @ (K * D)

print(perf_counter() - start)
0.019109775999822887

Plot the Results#

We then plot the original function, the first derivative, and the second derivative against the original data.

[5]:
fig = plt.figure()
ax = plt.axes()
plt.grid()

plt.scatter(X_train, y_train, marker=".", c="grey", label="Data")
plt.plot(X_test, y_pred.T, linewidth=2, label="Function Approximation")
plt.plot(X_test, y_pred_d1.T, linewidth=2, label="First Derivative")
plt.plot(X_test, y_pred_d2.T, linewidth=2, label="Second Derivative")

plt.legend()

plt.show()
../../_images/examples_kernel_derivative_approximation_9_0.png