Radial Basis Functions revisted!

Radial Basis Functions revisted!#

The modern implementation of RBFs accoutns for the global trend of the data through a polynomial least squares fit alongside normal RBFs for local features.

\[ \begin{align} y(x) &= \sum_i^N \omega_i \varphi_i(\|x-x_i\|) + \sum_i^N P_i(x_i) b_i \end{align} \]

Where \(P_i\) is an order \(n\lt m\) polynomial. The Numpy RBFInterpolator object fits this equation to:

\[\begin{split} \begin{align} [\Phi(x_i, x_j) -\lambda I]\omega +P(x_i) b &= y_i \\ P(x_i)^T \omega &=0 \end{align} \end{split}\]

where \(\lambda = 0\) recovers an exact fit and \(\lambda \gt 0\) effecitvely shifts the fitting of the \(x_i=x_j\) terms to the bestfit polynomial.

Example: Toy gaussian over a quadratic#

#Sampled gaussian

import numpy as np
import matplotlib.pyplot as plt

# Define the function
def f(x):
  return np.exp(-(x/2)**2)+.1*x**2

# Create x values for plotting
x_toy = np.linspace(-6, 6, 100)
y_toy = f(x_toy)

# Sample 11 times at 1-interval intervals
x_d = np.arange(-5, 6, 1)
y_d = f(x_d)
# prompt: Use a numpy scipy.interpolate.RBFInterpolator over x_d and y_d and plot the result against the true function

import matplotlib.pyplot as plt
from scipy.interpolate import RBFInterpolator

# Create an RBFInterpolator object
print(len(np.array([y_d]).T))
rbf = RBFInterpolator(np.array([x_d]).T, y_d.T, kernel='gaussian', epsilon=1, degree=2)

# Interpolate at the x_toy values
y_rbf = rbf(np.array([x_toy]).T)

# Plot the results
plt.plot(x_toy, y_toy, label='True Function')
plt.plot(x_d, y_d, 'o', label='Data Points')
plt.plot(x_toy, y_rbf, label='RBF Interpolation')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.title('RBF Interpolation')
plt.show()
11
../../../_images/95fe0e4a35f2c616c0ed44ee76ba60d2767cb3dd3a1ce7314ac4260e3224541b.png
import numpy as np
import plotly.graph_objects as go
from scipy.interpolate import RBFInterpolator

# Define the target function
def f(x, y):
    return np.exp(-.5*x**2 - .2*y**2) * np.sin(x) * np.cos(.5*y)

x_grid_vals = np.linspace(-3, 3, 100)
y_grid_vals = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x_grid_vals, y_grid_vals)
Z_true = f(X, Y)

num_samples = 100
x_samples = np.random.uniform(-3, 3, num_samples)
y_samples = np.random.uniform(-3, 3, num_samples)
z_samples = f(x_samples, y_samples)

# Prepare sample points for RBFInterpolator
sample_points = np.column_stack((x_samples, y_samples))

dist_matrix = np.sqrt((x_samples[:, np.newaxis] - x_samples)**2 + (y_samples[:, np.newaxis] - y_samples)**2)
average_distance = np.mean(dist_matrix)
eps = 1 / average_distance

# Fit RBF interpolator (using Gaussian kernel, can adjust epsilon and degree as needed)
rbf = RBFInterpolator(sample_points, z_samples, kernel='gaussian', epsilon=1, degree=1)

# Evaluate on grid
grid_points = np.column_stack((X.ravel(), Y.ravel()))
Z_fit = rbf(grid_points).reshape(X.shape)

surface_true = go.Surface(x=X, y=Y, z=Z_true, colorscale='Blues', showscale=False, name='Original')
surface_fit = go.Surface(x=X, y=Y, z=Z_fit, colorscale='Viridis', showscale=False, name='RBF Fit')
scatter_samples = go.Scatter3d(
    x=x_samples, y=y_samples, z=z_samples,
    mode='markers', marker=dict(color='red', size=3), name='Samples'
 )

# Plot 1: Original Function
fig_original = go.Figure(data=[surface_true, scatter_samples])
fig_original.update_layout(
    title='Original Function and Data Samples',
    scene=dict(
        xaxis_title='x', yaxis_title='y', zaxis_title='z',
        zaxis=dict(range=[-.7, .7]),
        aspectratio=dict(x=1, y=1, z=0.5)
    )
)
print("Displaying the original function...")
fig_original.show()

# Plot 2: RBF Interpolation
fig_fit = go.Figure(data=[surface_fit, scatter_samples])
fig_fit.update_layout(
    title='RBF Interpolated Fit and Data Samples',
    scene=dict(
        xaxis_title='x', yaxis_title='y', zaxis_title='z',
        zaxis=dict(range=[-.7, .7]),
        aspectmode='manual',
        aspectratio=dict(x=1, y=1, z=0.5)
    )
)
print("Displaying the RBF fitted function...")
fig_fit.show()
Displaying the original function...
Displaying the RBF fitted function...