Source code for fvgp.kernels

import numpy as np


[docs] def squared_exponential_kernel(distance, length): """ Function for the squared exponential kernel. kernel = np.exp(-(distance ** 2) / (2.0 * (length ** 2))) Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. length : scalar The length scale hyperparameters. Return ------ Kernel output : same as distance parameter. """ kernel = np.exp(-(distance ** 2) / (2.0 * (length ** 2))) return kernel
[docs] def squared_exponential_kernel_robust(distance, phi): """ Function for the squared exponential kernel (robust version) kernel = np.exp(-(distance ** 2) * (phi ** 2)) Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. phi : scalar The length scale hyperparameters. Return ------ Kernel output : same as distance parameter. """ kernel = np.exp(-(distance ** 2) * (phi ** 2)) return kernel
[docs] def exponential_kernel(distance, length): """ Function for the exponential kernel. kernel = np.exp(-(distance) / (length)) Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. length : scalar The length scale hyperparameters. Return ------ Kernel output : same as distance parameter. """ kernel = np.exp(-distance / length) return kernel
[docs] def exponential_kernel_robust(distance, phi): """ Function for the exponential kernel (robust version) kernel = np.exp(-(distance) * (phi**2)) Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. phi : scalar The length scale hyperparameters. Return ------ Kernel output : same as distance parameter. """ kernel = np.exp(-(distance) * (phi ** 2)) return kernel
[docs] def matern_kernel_diff1(distance, length): """ Function for the Matern kernel, order of differentiability = 1. kernel = (1.0 + ((np.sqrt(3.0) * distance) / (length))) * np.exp( -(np.sqrt(3.0) * distance) / length Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. length : scalar The length scale hyperparameters. Return ------ Kernel output : same as distance parameter. """ kernel = (1.0 + ((np.sqrt(3.0) * distance) / length)) * np.exp( -(np.sqrt(3.0) * distance) / length ) return kernel
[docs] def matern_kernel_diff1_grad(distance, dist_der): ##verified """ Function for the Matern kernel derivative, order of differentiability = 1. kernel = (1.0 + ((np.sqrt(3.0) * distance) / (length))) * np.exp( -(np.sqrt(3.0) * distance) / length Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. dist_der : scalar or np.ndarray The derivative of the distance matrix. We assume here that the distance is a function of the hyperparameters. Return ------ Kernel output : same as distance parameter. """ a = (np.sqrt(3.0) * distance) dadl = np.sqrt(3.0) * dist_der ea = np.exp(-a) kernel_der = dadl * ea - (1.+a) * dadl * ea return kernel_der
[docs] def matern_kernel_diff1_robust(distance, phi): """ Function for the Matern kernel, order of differentiability = 1, robust version. kernel = (1.0 + ((np.sqrt(3.0) * distance) * (phi**2))) * np.exp( -(np.sqrt(3.0) * distance) * (phi**2)) Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. phi : scalar The length scale hyperparameters. Return ------ Kernel output : same as distance parameter. """ ##1/l --> phi**2 kernel = (1.0 + ((np.sqrt(3.0) * distance) * (phi ** 2))) * np.exp( -(np.sqrt(3.0) * distance) * (phi ** 2)) return kernel
[docs] def matern_kernel_diff2(distance, length): """ Function for the Matern kernel, order of differentiability = 2. kernel = ( 1.0 + ((np.sqrt(5.0) * distance) / (length)) + ((5.0 * distance ** 2) / (3.0 * length ** 2)) ) * np.exp(-(np.sqrt(5.0) * distance) / length) Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. length : scalar The length scale hyperparameters. Return ------ Kernel output : same as distance parameter. """ kernel = ( 1.0 + ((np.sqrt(5.0) * distance) / (length)) + ((5.0 * distance ** 2) / (3.0 * length ** 2)) ) * np.exp(-(np.sqrt(5.0) * distance) / length) return kernel
[docs] def matern_kernel_diff2_robust(distance, phi): """ Function for the Matern kernel, order of differentiability = 2, robust version. kernel = ( 1.0 + ((np.sqrt(5.0) * distance) * (phi**2)) + ((5.0 * distance ** 2) * (3.0 * phi ** 4)) ) * np.exp(-(np.sqrt(5.0) * distance) * (phi**2)) Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. phi : scalar The length scale hyperparameters. Return ------ Kernel output : same as distance parameter. """ kernel = ( 1.0 + ((np.sqrt(5.0) * distance) * (phi ** 2)) + ((5.0 * distance ** 2) * (3.0 * phi ** 4)) ) * np.exp(-(np.sqrt(5.0) * distance) * (phi ** 2)) return kernel
[docs] def sparse_kernel(distance, radius): """ Function for a compactly supported kernel. Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. radius : scalar Radius of support. Return ------ Kernel output : same as distance parameter. """ d = np.array(distance) d[d == 0.0] = 10e-6 d[d > radius] = radius kernel = (np.sqrt(2.0) / (3.0 * np.sqrt(np.pi))) * \ ((3.0 * (d / radius) ** 2 * np.log((d / radius) / (1 + np.sqrt(1.0 - (d / radius) ** 2)))) + ((2.0 * (d / radius) ** 2 + 1.0) * np.sqrt(1.0 - (d / radius) ** 2))) return kernel
[docs] def periodic_kernel(distance, length, p): """ Function for a periodic kernel. kernel = np.exp(-(2.0/length**2)*(np.sin(np.pi*distance/p)**2)) Parameters ---------- distance : scalar or np.ndarray Distance between a set of points. length : scalar Length scale. p : scalar Period. Return ------ Kernel output : same as distance parameter. """ kernel = np.exp(-(2.0 / length ** 2) * (np.sin(np.pi * distance / p) ** 2)) return kernel
[docs] def linear_kernel(x1, x2, hp1, hp2, hp3): """ Function for a linear kernel. kernel = hp1 + (hp2*(x1-hp3)*(x2-hp3)) Parameters ---------- x1 : float Point 1. x2 : float Point 2. hp1 : float Hyperparameter. hp2 : float Hyperparameter. hp3 : float Hyperparameter. Return ------ Kernel output : same as distance parameter. """ kernel = hp1 + (hp2 * (x1 - hp3) * (x2 - hp3)) return kernel
[docs] def dot_product_kernel(x1, x2, hp, matrix): """ Function for a dot-product kernel. kernel = hp + x1.T @ matrix @ x2 Parameters ---------- x1 : np.ndarray Point 1. x2 : np.ndarray Point 2. hp : float Offset hyperparameter. matrix : np.ndarray PSD matrix defining the inner product. Return ------ Kernel output : same as distance parameter. """ kernel = hp + x1.T @ matrix @ x2 return kernel
[docs] def polynomial_kernel(x1, x2, p): """ Function for a polynomial kernel. kernel = (1.0+x1.T @ x2)**p Parameters ---------- x1 : np.ndarray Point 1. x2 : np.ndarray Point 2. p : float Power hyperparameter. Return ------ Kernel output : same as distance parameter. """ kernel = (1.0 + x1.T @ x2) ** p return p
[docs] def wendland_kernel(d): """ Function for the Wendland kernel with a given distance matrix. The Wendland kernel is compactly supported, leading to sparse covariance matrices. Parameters ---------- d : np.ndarray Distance matrix. Return ------ Covariance matrix : np.ndarray """ d[d > 1.] = 1. kernel = (1. - d) ** 8 * (35. * d ** 3 + 25. * d ** 2 + 8. * d + 1.) return kernel
[docs] def wendland_anisotropic(x1, x2, hyperparameters): """ Function for the Wendland kernel. The Wendland kernel is compactly supported, leading to sparse covariance matrices. Parameters ---------- x1 : np.ndarray Numpy array of shape (U x D). x2 : np.ndarray Numpy array of shape (V x D). hyperparameters : np.ndarray Array of hyperparameters. For this kernel we need D + 1 hyperparameters. Return ------ Covariance matrix : np.ndarray """ hps = hyperparameters distance_matrix = np.zeros((len(x1), len(x2))) for i in range(len(x1[0])): distance_matrix += abs(np.subtract.outer(x1[:, i], x2[:, i]) / hps[1 + i]) ** 2 d = np.sqrt(distance_matrix) d[d > 1.] = 1. kernel = (1. - d) ** 8 * (35. * d ** 3 + 25. * d ** 2 + 8. * d + 1.) return hps[0] * kernel
[docs] def non_stat_kernel(x1, x2, x0, w, l): """ Non-stationary kernel. kernel = g(x1) g(x2) Parameters ---------- x1 : np.ndarray Numpy array of shape (U x D). x2 : np.ndarray Numpy array of shape (V x D). x0 : np.ndarray Numpy array of the basis function locations. w : np.ndarray 1d np.ndarray of weights. len(w) = len(x0). l : float Width measure of the basis functions. Return ------ Covariance matrix : np.ndarray """ non_stat = np.outer(_g(x1, x0, w, l), _g(x2, x0, w, l)) return non_stat
[docs] def non_stat_kernel_gradient(x1, x2, x0, w, l): """ Non-stationary kernel gradient. kernel = g(x1) g(x2) Parameters ---------- x1 : np.ndarray Numpy array of shape (U x D). x2 : np.ndarray Numpy array of shape (V x D). x0 : np.ndarray Numpy array of the basis function locations. w : np.ndarray 1d np.ndarray of weights. len(w) = len(x0). l : float Width measure of the basis functions. Return ------ Covariance matrix : np.ndarray """ dkdw = (np.einsum('ij,k->ijk', _dgdw(x1, x0, w, l), _g(x2, x0, w, l)) + np.einsum('ij,k->ikj', _dgdw(x2, x0, w, l), _g(x1, x0, w, l))) dkdl = (np.outer(_dgdl(x1, x0, w, l), _g(x2, x0, w, l)) + np.outer(_dgdl(x2, x0, w, l), _g(x1, x0, w, l)).T) res = np.empty((len(w) + 1, len(x1), len(x2))) res[0:len(w)] = dkdw res[-1] = dkdl return res
[docs] def get_distance_matrix(x1, x2): """ Function to calculate the pairwise distance matrix of points in x1 and x2. Parameters ---------- x1 : np.ndarray Numpy array of shape (U x D). x2 : np.ndarray Numpy array of shape (V x D). Return ------ distance matrix : np.ndarray """ d = np.zeros((len(x1), len(x2))) for i in range(x1.shape[1]): d += (x1[:, i].reshape(-1, 1) - x2[:, i]) ** 2 return np.sqrt(d)
[docs] def get_anisotropic_distance_matrix(x1, x2, hps): """ Function to calculate the pairwise axial-anisotropic distance matrix of points in x1 and x2. Parameters ---------- x1 : np.ndarray Numpy array of shape (U x D). x2 : np.ndarray Numpy array of shape (V x D). hps : np.ndarray 1d array of values. The diagonal of the metric tensor describing the axial anisotropy. Return ------ distance matrix : np.ndarray """ d = np.zeros((len(x1), len(x2))) for i in range(len(x1[0])): d += abs(np.subtract.outer(x1[:, i], x2[:, i]) / hps[i]) ** 2 return np.sqrt(d)
def _g(x, x0, w, l): d = get_distance_matrix(x, x0) e = np.exp(-(d ** 2) / l) return np.sum(w * e, axis=1) def _dgdw(x, x0, w, l): d = get_distance_matrix(x, x0) e = np.exp(-(d ** 2) / l).T return e def _dgdl(x, x0, w, l): d = get_distance_matrix(x, x0) e = np.exp(-(d ** 2) / l) return np.sum(w * e * (d ** 2 / l ** 2), axis=1)
[docs] def wendland_anisotropic_gp2Scale_cpu(x1, x2, hps): """ Function for the anisotropic Wendland kernel computed on the CPU. The Wendland kernel is compactly supported, leading to sparse covariance matrices. Parameters ---------- x1 : np.ndarray Numpy array of shape (U x D). x2 : np.ndarray Numpy array of shape (V x D). hps : np.ndarray Array of hyperparameters. For this kernel we need D + 1 hyperparameters. Return ------ Covariance matrix : np.ndarray """ distance_matrix = np.zeros((len(x1), len(x2))) for i in range(len(x1[0])): distance_matrix += (np.subtract.outer(x1[:, i], x2[:, i]) / hps[1 + i]) ** 2 d = np.sqrt(distance_matrix) d[d > 1.] = 1. kernel = hps[0] * (1. - d) ** 8 * (35. * d ** 3 + 25. * d ** 2 + 8. * d + 1.) return kernel
def _get_distance_matrix_gpu(x1, x2, device, hps): # pragma: no cover import torch d = torch.zeros((len(x1), len(x2))).to(device, dtype=torch.float32) for i in range(x1.shape[1]): d += ((x1[:, i].reshape(-1, 1) - x2[:, i]) / hps[1 + i]) ** 2 return torch.sqrt(d)
[docs] def wendland_anisotropic_gp2Scale_gpu(x1, x2, hps): # pragma: no cover """ Function for the anisotropic Wendland kernel computed on the GPU. Needs pytorch. The Wendland kernel is compactly supported, leading to sparse covariance matrices. Parameters ---------- x1 : np.ndarray Numpy array of shape (U x D). x2 : np.ndarray Numpy array of shape (V x D). hps : np.ndarray Array of hyperparameters. For this kernel we need D + 1 hyperparameters. Return ------ Covariance matrix : np.ndarray """ import torch cuda_device = torch.device("cuda:0") x1_dev = torch.from_numpy(x1).to(cuda_device, dtype=torch.float32) x2_dev = torch.from_numpy(x2).to(cuda_device, dtype=torch.float32) hps_dev = torch.from_numpy(hps).to(cuda_device, dtype=torch.float32) d = _get_distance_matrix_gpu(x1_dev, x2_dev, cuda_device, hps_dev) d[d > 1.] = 1. kernel = hps[0] * (1. - d) ** 8 * (35. * d ** 3 + 25. * d ** 2 + 8. * d + 1.) return kernel.cpu().numpy()
[docs] def wasserstein_1d(a, b): """ The 1d Wasserstein distance. Parameters ---------- a : np.ndarray 1d Numpy array. Input distribution. b : np.ndarray 1d Numpy array. Input distribution. Return ------ Wasserstein distance : float """ a = a / np.sum(a) b = b / np.sum(b) a_sorted = np.sort(a) b_sorted = np.sort(b) return np.mean(np.abs(a_sorted - b_sorted))
def wasserstein_1d_outer_vec(a, b): a = a / a.sum(axis=1, keepdims=True) b = b / b.sum(axis=1, keepdims=True) a_sorted = np.sort(a, axis=1) b_sorted = np.sort(b, axis=1) s = a_sorted[:, None, :] - b_sorted[None, :, :] return np.mean(np.abs(s), axis=2)