Fix description of exponentiated quadratic covariance function and add kernels. (#872)

* Fix description of ExpQuad covariance.

* Add sinc kernel.

* Add ExpQuadCosine covariance
This commit is contained in:
Neil Lawrence 2021-05-13 18:50:32 +01:00 committed by GitHub
parent e272c666c1
commit 46ce7c1680
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 7 deletions

View file

@ -38,7 +38,7 @@ from .src.rbf import RBF
from .src.linear import Linear, LinearFull from .src.linear import Linear, LinearFull
from .src.static import Bias, White, Fixed, WhiteHeteroscedastic, Precomputed from .src.static import Bias, White, Fixed, WhiteHeteroscedastic, Precomputed
from .src.brownian import Brownian from .src.brownian import Brownian
from .src.stationary import Exponential, OU, Matern32, Matern52, ExpQuad, RatQuad, Cosine from .src.stationary import Exponential, OU, Matern32, Matern52, ExpQuad, RatQuad, Cosine, Sinc, ExpQuadCosine
from .src.mlp import MLP from .src.mlp import MLP
from .src.periodic import PeriodicExponential, PeriodicMatern32, PeriodicMatern52 from .src.periodic import PeriodicExponential, PeriodicMatern32, PeriodicMatern52
from .src.standard_periodic import StdPeriodic from .src.standard_periodic import StdPeriodic

View file

@ -621,10 +621,10 @@ class ExpQuad(Stationary):
.. math:: .. math::
k(r) = \sigma^2 (1 + \sqrt{5} r + \\frac53 r^2) \exp(- \sqrt{5} r) k(r) = \sigma^2 \exp(- 0.5 r^2)
notes:: notes::
- Yes, this is exactly the same as the RBF covariance function, but the - This is exactly the same as the RBF covariance function, but the
RBF implementation also has some features for doing variational kernels RBF implementation also has some features for doing variational kernels
(the psi-statistics). (the psi-statistics).
@ -657,6 +657,14 @@ class ExpQuad(Stationary):
return -r*self.K_of_r(r) return -r*self.K_of_r(r)
class Cosine(Stationary): class Cosine(Stationary):
"""
Cosine Covariance function
.. math::
k(r) = \sigma^2 \cos(r)
"""
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Cosine'): def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Cosine'):
super(Cosine, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) super(Cosine, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
@ -666,6 +674,62 @@ class Cosine(Stationary):
def dK_dr(self, r): def dK_dr(self, r):
return -self.variance * np.sin(r) return -self.variance * np.sin(r)
class ExpQuadCosine(Stationary):
"""
Exponentiated quadratic multiplied by cosine covariance function (spectral mixture kernel).
.. math::
k(r) = \sigma^2 \exp(-2\pi^2r^2)\cos(2\pi r/T)
"""
def __init__(self, input_dim, variance=1., lengthscale=None, period=1., ARD=False, active_dims=None, name='ExpQuadCosine'):
super(ExpQuadCosine, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
self.period = Param('period', period, Logexp())
self.link_parameters(self.period)
def K_of_r(self, r):
return self.variance * np.exp(-2*np.pi**2*r**2)*np.cos(2*np.pi*r/self.period)
def dK_dr(self, r):
return -4*np.pi**2*r*self.K_of_r(r) - self.variance * 2*np.pi/self.period*np.exp(-2*np.pi**2*r**2)*np.sin(2*np.pi*r/self.period)
def update_gradients_full(self, dL_dK, X, X2=None):
super(ExpQuadCosine, self).update_gradients_full(dL_dK, X, X2)
r = self._scaled_dist(X, X2)
r2 = np.square(r)
dK_dperiod = self.variance * 2*np.pi*r/self.period**2*np.exp(-2*np.pi**2*r**2)*np.sin(2*np.pi*r/self.period)
grad = np.sum(dL_dK*dK_dperiod)
self.period.gradient = grad
def update_gradients_diag(self, dL_dKdiag, X):
super(ExpQuadCosine, self).update_gradients_diag(dL_dKdiag, X)
self.period.gradient = 0.
class Sinc(Stationary):
"""
Sinc Covariance function
.. math::
k(r) = \sigma^2 \sinc(\pi r)
"""
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Sinc'):
super(Sinc, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
def K_of_r(self, r):
return self.variance * np.sinc(2*r)
def dK_dr(self, r):
# small angle approximation to avoid divide by zero errors.
return np.where(r<1e-5, -self.variance*4/3*np.pi*np.pi*r, self.variance/r * (np.cos(2*np.pi*r)-np.sinc(2*r)))
class RatQuad(Stationary): class RatQuad(Stationary):
""" """
@ -677,7 +741,6 @@ class RatQuad(Stationary):
""" """
def __init__(self, input_dim, variance=1., lengthscale=None, power=2., ARD=False, active_dims=None, name='RatQuad'): def __init__(self, input_dim, variance=1., lengthscale=None, power=2., ARD=False, active_dims=None, name='RatQuad'):
super(RatQuad, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) super(RatQuad, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
self.power = Param('power', power, Logexp()) self.power = Param('power', power, Logexp())

View file

@ -426,6 +426,22 @@ class KernelGradientTestsContinuous(unittest.TestCase):
k.randomize() k.randomize()
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
def test_Cosine(self):
# Don't test Cosine directly as it fails positive definite test.
k = GPy.kern.RBF(self.D-1, ARD=False)*GPy.kern.Cosine(self.D-1, ARD=True)
k.randomize()
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
def test_ExpQuadCosine(self):
k = GPy.kern.ExpQuadCosine(self.D-1, ARD=True)
k.randomize()
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
def test_Sinc(self):
k = GPy.kern.Sinc(self.D-1, ARD=True)
k.randomize()
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
def test_RatQuad(self): def test_RatQuad(self):
k = GPy.kern.RatQuad(self.D-1, ARD=True) k = GPy.kern.RatQuad(self.D-1, ARD=True)
k.randomize() k.randomize()

View file

@ -722,9 +722,9 @@ class StateSpaceKernelsTests(np.testing.TestCase):
# plotting <- # plotting <-
# 2D measurement, 3 ts_no <- # 2D measurement, 3 ts_no <-
def test_continuos_ss(self,plot=False): def test_continuous_ss(self,plot=False):
""" """
This function tests the continuos state-space model. This function tests the continuous state-space model.
""" """
# 1D measurements, 1 ts_no -> # 1D measurements, 1 ts_no ->