GPs on Non-Euclidean Input Spaces#

GPs on non-Euclidean input spaces have become more and more relevant in recent years. fvgp can be used for that purpose as long as a cvalid kernel is provided. Of course, if mean functions and noise functions are also provided, they have to operate on these non-Euclidean spaces.

In this example, we run a small GP on words. It’s a proof of concept, the results are not super relevant

#install the newest version of fvgp
#!pip install fvgp~=4.8.0
import numpy as np
import matplotlib.pyplot as plt
from fvgp import GP
from dask.distributed import Client
%load_ext autoreload
%autoreload 2

Single Task#

#making the x_data a set will allow us to put any objects or structures into it.
x_data = ['hello','world','this','is','fvgp']
y_data = np.array([2.,1.9,1.8,3.0,5.])


from fvgp.kernels import *
def string_distance(string1, string2):
    difference = abs(len(string1) - len(string2))
    common_length = min(len(string1),len(string2))
    string1 = string1[0:common_length]
    string2 = string2[0:common_length]
    
    for i in range(len(string1)):
        if string1[i] != string2[i]:
            difference += 1.

    return difference


def kernel(x1,x2,hps):
    d = np.zeros((len(x1),len(x2)))
    count1 = 0
    for string1 in x1:
        count2 = 0
        for string2 in x2:
            d[count1,count2] = string_distance(string1,string2)
            count2 += 1
        count1 += 1
    return hps[0] * matern_kernel_diff1(d,hps[1])
    



my_gp = GP(x_data,y_data,init_hyperparameters=np.ones((2)), kernel_function=kernel)

bounds = np.array([[0.001,100.],[0.001,100]])
my_gp.train(hyperparameter_bounds=bounds)

print("hyperparameters: ", my_gp.hyperparameters)
print("prediction : ",my_gp.posterior_mean(['full'])["m(x)"])
print("uncertainty: ",np.sqrt(my_gp.posterior_covariance(['full'])["v(x)"]))
/home/marcus/Coding/fvGP/fvgp/gp.py:329: UserWarning: No noise function or measurement noise provided. Noise variances will be set to (0.01 * mean(|y_data|))^2.
  self.likelihood = GPlikelihood(self.data,
hyperparameters:  [28.85710592 28.97643312]
prediction :  3.3575135028855434
uncertainty:  [0.5369167]

Multi-Task Capability on Non-Euclidean Spaces#

import numpy as np
import matplotlib.pyplot as plt
from fvgp import GP
import plotly.graph_objects as go
from itertools import product

%load_ext autoreload
%autoreload 2
The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload
x_data = ['frf','ferfe','ferf','febhn']
y_data = np.zeros((len(x_data),5))


y_data[:,0] = np.random.rand(len(x_data))
y_data[:,1] = np.random.rand(len(x_data))
y_data[:,2] = np.random.rand(len(x_data))
y_data[:,3] = np.random.rand(len(x_data))
y_data[:,4] = np.random.rand(len(x_data))

#it is good practice to check the format of the data
print(len(x_data))
print(y_data.shape)
4
(4, 5)
def string_distance(string1, string2):
    difference = abs(len(string1) - len(string2))
    common_length = min(len(string1),len(string2))
    string1 = string1[0:common_length]
    string2 = string2[0:common_length]
    
    for i in range(len(string1)):
        if string1[i] != string2[i]:
            difference += 1.

    return difference


from fvgp.kernels import matern_kernel_diff1
def kernel(x1,x2,hps):
    d = np.zeros((len(x1),len(x2)))
    count1 = 0
    for entry in x1:
        string1 = entry[0]
        count2 = 0
        for entry2 in x2:
            string2 = entry2[0]
            d[count1,count2] = string_distance(string1,string2)
            count2 += 1
        count1 += 1
    return hps[0] * matern_kernel_diff1(d,hps[1])
    

bounds = np.array([[0.001,100.],[0.001,100]])
from fvgp import fvGP
my_gp2 = fvGP(x_data,y_data,init_hyperparameters=np.ones((2)),
              kernel_function=kernel
             )
print("Global Training in progress")
my_gp2.train(hyperparameter_bounds=bounds, max_iter = 20)
Global Training in progress
array([1.69625485, 3.96570178])
x_pred = ["dwed","dwe"]
my_gp2.posterior_mean(x_pred, x_out = np.array([0,1,2,3]))
my_gp2.posterior_mean(x_pred)
{'x': ['dwed', 'dwe'],
 'm(x)': array([[0.49867421, 0.49867421, 0.49867421, 0.49867421, 0.49867421],
        [0.53123029, 0.53123029, 0.53123029, 0.53123029, 0.53123029]]),
 'm(x)_flat': array([0.49867421, 0.53123029, 0.49867421, 0.53123029, 0.49867421,
        0.53123029, 0.49867421, 0.53123029, 0.49867421, 0.53123029]),
 'x_pred': [['dwed', np.int64(0)],
  ['dwe', np.int64(0)],
  ['dwed', np.int64(1)],
  ['dwe', np.int64(1)],
  ['dwed', np.int64(2)],
  ['dwe', np.int64(2)],
  ['dwed', np.int64(3)],
  ['dwe', np.int64(3)],
  ['dwed', np.int64(4)],
  ['dwe', np.int64(4)]]}