From 1d2b771e09bdbd5125c3403972db89a17889478a Mon Sep 17 00:00:00 2001 From: Zhenwen Dai Date: Thu, 20 Aug 2015 17:33:49 +0100 Subject: [PATCH] psi-statistics for any kernels via Gaussian quadrature --- GPy/kern/_src/kern.py | 16 ++++++++++------ GPy/kern/_src/psi_comp/__init__.py | 9 +++++---- GPy/kern/_src/stationary.py | 6 +++--- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/GPy/kern/_src/kern.py b/GPy/kern/_src/kern.py index e63ddad4..5af3fb1c 100644 --- a/GPy/kern/_src/kern.py +++ b/GPy/kern/_src/kern.py @@ -59,6 +59,9 @@ class Kern(Parameterized): self._sliced_X = 0 self.useGPU = self._support_GPU and useGPU self._return_psi2_n_flag = ObsAr(np.zeros(1)).astype(bool) + + from .psi_comp import PSICOMP_GH + self.psicomp = PSICOMP_GH() @property def return_psi2_n(self): @@ -90,11 +93,11 @@ class Kern(Parameterized): def Kdiag(self, X): raise NotImplementedError def psi0(self, Z, variational_posterior): - raise NotImplementedError + return self.psicomp.psicomputations(self, Z, variational_posterior)[0] def psi1(self, Z, variational_posterior): - raise NotImplementedError + return self.psicomp.psicomputations(self, Z, variational_posterior)[1] def psi2(self, Z, variational_posterior): - raise NotImplementedError + return self.psicomp.psicomputations(self, Z, variational_posterior)[2] def gradients_X(self, dL_dK, X, X2): raise NotImplementedError def gradients_X_diag(self, dL_dKdiag, X): @@ -119,21 +122,22 @@ class Kern(Parameterized): dL_dpsi1 * dpsi1_d{theta_i} + dL_dpsi2 * dpsi2_d{theta_i} """ - raise NotImplementedError + dtheta = self.psicomp.psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[0] + self.gradient[:] = dtheta def gradients_Z_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): """ Returns the derivative of the objective wrt Z, using the chain rule through the expectation variables. """ - raise NotImplementedError + return self.psicomp.psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[1] def gradients_qX_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): """ Compute the gradients wrt the parameters of the variational distruibution q(X), chain-ruling via the expectations of the kernel """ - raise NotImplementedError + return self.psicomp.psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[2:] def plot(self, x=None, fignum=None, ax=None, title=None, plot_limits=None, resolution=None, **mpl_kwargs): """ diff --git a/GPy/kern/_src/psi_comp/__init__.py b/GPy/kern/_src/psi_comp/__init__.py index 5041da50..6d7222be 100644 --- a/GPy/kern/_src/psi_comp/__init__.py +++ b/GPy/kern/_src/psi_comp/__init__.py @@ -8,9 +8,10 @@ from . import rbf_psi_comp from . import ssrbf_psi_comp from . import sslinear_psi_comp from . import linear_psi_comp +from .gaussherm import PSICOMP_GH class PSICOMP_RBF(Pickleable): - @Cache_this(limit=2, ignore_args=(0,)) + @Cache_this(limit=10, ignore_args=(0,)) def psicomputations(self, variance, lengthscale, Z, variational_posterior): if isinstance(variational_posterior, variational.NormalPosterior): return rbf_psi_comp.psicomputations(variance, lengthscale, Z, variational_posterior) @@ -19,7 +20,7 @@ class PSICOMP_RBF(Pickleable): else: raise ValueError("unknown distriubtion received for psi-statistics") - @Cache_this(limit=2, ignore_args=(0,1,2,3)) + @Cache_this(limit=10, ignore_args=(0,1,2,3)) def psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior): if isinstance(variational_posterior, variational.NormalPosterior): return rbf_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior) @@ -33,7 +34,7 @@ class PSICOMP_RBF(Pickleable): class PSICOMP_Linear(Pickleable): - @Cache_this(limit=2, ignore_args=(0,)) + @Cache_this(limit=10, ignore_args=(0,)) def psicomputations(self, variance, Z, variational_posterior): if isinstance(variational_posterior, variational.NormalPosterior): return linear_psi_comp.psicomputations(variance, Z, variational_posterior) @@ -42,7 +43,7 @@ class PSICOMP_Linear(Pickleable): else: raise ValueError("unknown distriubtion received for psi-statistics") - @Cache_this(limit=2, ignore_args=(0,1,2,3)) + @Cache_this(limit=10, ignore_args=(0,1,2,3)) def psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior): if isinstance(variational_posterior, variational.NormalPosterior): return linear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior) diff --git a/GPy/kern/_src/stationary.py b/GPy/kern/_src/stationary.py index e69e316b..9c4f1436 100644 --- a/GPy/kern/_src/stationary.py +++ b/GPy/kern/_src/stationary.py @@ -77,7 +77,7 @@ class Stationary(Kern): def dK_dr(self, r): raise NotImplementedError("implement derivative of the covariance function wrt r to use this class") - @Cache_this(limit=5, ignore_args=()) + @Cache_this(limit=20, ignore_args=()) def K(self, X, X2=None): """ Kernel function applied on inputs X and X2. @@ -89,7 +89,7 @@ class Stationary(Kern): r = self._scaled_dist(X, X2) return self.K_of_r(r) - @Cache_this(limit=3, ignore_args=()) + @Cache_this(limit=20, ignore_args=()) def dK_dr_via_X(self, X, X2): #a convenience function, so we can cache dK_dr return self.dK_dr(self._scaled_dist(X, X2)) @@ -114,7 +114,7 @@ class Stationary(Kern): r2 = np.clip(r2, 0, np.inf) return np.sqrt(r2) - @Cache_this(limit=5, ignore_args=()) + @Cache_this(limit=20, ignore_args=()) def _scaled_dist(self, X, X2=None): """ Efficiently compute the scaled distance, r.