From 23af82f8519077a3cd3706153271f06cc9247194 Mon Sep 17 00:00:00 2001 From: Zhenwen Dai Date: Fri, 4 Sep 2015 18:26:07 +0100 Subject: [PATCH] unify the interface of psicomp, but the psi2n of linear kernel and gaussian qradrature still needs to be done. --- GPy/kern/_src/linear.py | 14 ++++---- GPy/kern/_src/psi_comp/__init__.py | 51 ++++++++++++++++++----------- GPy/kern/_src/psi_comp/gaussherm.py | 6 ++-- GPy/kern/_src/rbf.py | 14 ++++---- 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/GPy/kern/_src/linear.py b/GPy/kern/_src/linear.py index 788fe14d..1a9793b1 100644 --- a/GPy/kern/_src/linear.py +++ b/GPy/kern/_src/linear.py @@ -117,29 +117,29 @@ class Linear(Kern): #---------------------------------------# def psi0(self, Z, variational_posterior): - return self.psicomp.psicomputations(self.variances, Z, variational_posterior)[0] + return self.psicomp.psicomputations(self, Z, variational_posterior)[0] def psi1(self, Z, variational_posterior): - return self.psicomp.psicomputations(self.variances, Z, variational_posterior)[1] + return self.psicomp.psicomputations(self, Z, variational_posterior)[1] def psi2(self, Z, variational_posterior): - return self.psicomp.psicomputations(self.variances, Z, variational_posterior)[2] + return self.psicomp.psicomputations(self, Z, variational_posterior)[2] def psi2n(self, Z, variational_posterior): - return self.psicomp.psicomputations(self.variances, Z, variational_posterior, return_psi2_n=True)[2] + return self.psicomp.psicomputations(self, Z, variational_posterior, return_psi2_n=True)[2] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): - dL_dvar = self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variances, Z, variational_posterior)[0] + dL_dvar = self.psicomp.psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[0] if self.ARD: self.variances.gradient = dL_dvar else: self.variances.gradient = dL_dvar.sum() def gradients_Z_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): - return self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variances, Z, variational_posterior)[1] + 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): - return self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variances, Z, variational_posterior)[2:] + return self.psicomp.psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[2:] class LinearFull(Kern): def __init__(self, input_dim, rank, W=None, kappa=None, active_dims=None, name='linear_full'): diff --git a/GPy/kern/_src/psi_comp/__init__.py b/GPy/kern/_src/psi_comp/__init__.py index 82126261..1e0a9b72 100644 --- a/GPy/kern/_src/psi_comp/__init__.py +++ b/GPy/kern/_src/psi_comp/__init__.py @@ -8,11 +8,25 @@ from . import rbf_psi_comp from . import ssrbf_psi_comp from . import sslinear_psi_comp from . import linear_psi_comp + + +class PSICOMP(Pickleable): + + def psicomputations(self, kern, Z, qX, return_psi2_n=False): + raise NotImplementedError("Abstract method!") + + def psiDerivativecomputations(self, kern, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, qX): + raise NotImplementedError("Abstract method!") + + def _setup_observers(self): + pass + from .gaussherm import PSICOMP_GH -class PSICOMP_RBF(Pickleable): - @Cache_this(limit=2, ignore_args=(0,)) - def psicomputations(self, variance, lengthscale, Z, variational_posterior, return_psi2_n=False): +class PSICOMP_RBF(PSICOMP): + @Cache_this(limit=5, ignore_args=(0,)) + def psicomputations(self, kern, Z, variational_posterior, return_psi2_n=False): + variance, lengthscale = kern.variance, kern.lengthscale if isinstance(variational_posterior, variational.NormalPosterior): return rbf_psi_comp.psicomputations(variance, lengthscale, Z, variational_posterior, return_psi2_n=return_psi2_n) elif isinstance(variational_posterior, variational.SpikeAndSlabPosterior): @@ -20,8 +34,9 @@ class PSICOMP_RBF(Pickleable): else: raise ValueError("unknown distriubtion received for psi-statistics") - @Cache_this(limit=2, ignore_args=(0,1,2,3)) - def psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior): + @Cache_this(limit=5, ignore_args=(0,2,3,4)) + def psiDerivativecomputations(self, kern, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + variance, lengthscale = kern.variance, kern.lengthscale if isinstance(variational_posterior, variational.NormalPosterior): return rbf_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior) elif isinstance(variational_posterior, variational.SpikeAndSlabPosterior): @@ -29,28 +44,26 @@ class PSICOMP_RBF(Pickleable): else: raise ValueError("unknown distriubtion received for psi-statistics") - def _setup_observers(self): - pass +class PSICOMP_Linear(PSICOMP): -class PSICOMP_Linear(Pickleable): - - @Cache_this(limit=2, ignore_args=(0,)) - def psicomputations(self, variance, Z, variational_posterior, return_psi2_n=False): + @Cache_this(limit=5, ignore_args=(0,)) + def psicomputations(self, kern, Z, variational_posterior, return_psi2_n=False): + variances = kern.variances if isinstance(variational_posterior, variational.NormalPosterior): - return linear_psi_comp.psicomputations(variance, Z, variational_posterior, return_psi2_n=return_psi2_n) + return linear_psi_comp.psicomputations(variances, Z, variational_posterior, return_psi2_n=return_psi2_n) elif isinstance(variational_posterior, variational.SpikeAndSlabPosterior): - return sslinear_psi_comp.psicomputations(variance, Z, variational_posterior) + return sslinear_psi_comp.psicomputations(variances, Z, variational_posterior) else: raise ValueError("unknown distriubtion received for psi-statistics") - @Cache_this(limit=2, ignore_args=(0,1,2,3)) - def psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior): + @Cache_this(limit=2, ignore_args=(0,2,3,4)) + def psiDerivativecomputations(self, kern, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + variances = kern.variances if isinstance(variational_posterior, variational.NormalPosterior): - return linear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior) + return linear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variances, Z, variational_posterior) elif isinstance(variational_posterior, variational.SpikeAndSlabPosterior): - return sslinear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior) + return sslinear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variances, Z, variational_posterior) else: raise ValueError("unknown distriubtion received for psi-statistics") - def _setup_observers(self): - pass \ No newline at end of file + diff --git a/GPy/kern/_src/psi_comp/gaussherm.py b/GPy/kern/_src/psi_comp/gaussherm.py index cb0585a5..afbca545 100644 --- a/GPy/kern/_src/psi_comp/gaussherm.py +++ b/GPy/kern/_src/psi_comp/gaussherm.py @@ -9,9 +9,9 @@ import numpy as np from GPy.util.caching import Cache_this from ....util.linalg import tdot -from ....core.parameterization.parameter_core import Pickleable +from . import PSICOMP -class PSICOMP_GH(Pickleable): +class PSICOMP_GH(PSICOMP): def __init__(self, degree=5, cache_K=True): self.degree = degree @@ -36,7 +36,7 @@ class PSICOMP_GH(Pickleable): return self.Xs @Cache_this(limit=10, ignore_args=(0,)) - def psicomputations(self, kern, Z, qX): + def psicomputations(self, kern, Z, qX, return_psi2_n=False): mu, S = qX.mean.values, qX.variance.values N,M,Q = mu.shape[0],Z.shape[0],mu.shape[1] if self.cache_K: Xs = self.comp_K(Z, qX) diff --git a/GPy/kern/_src/rbf.py b/GPy/kern/_src/rbf.py index c422ead7..cb34738a 100644 --- a/GPy/kern/_src/rbf.py +++ b/GPy/kern/_src/rbf.py @@ -53,25 +53,25 @@ class RBF(Stationary): #---------------------------------------# def psi0(self, Z, variational_posterior): - return self.psicomp.psicomputations(self.variance, self.lengthscale, Z, variational_posterior)[0] + return self.psicomp.psicomputations(self, Z, variational_posterior)[0] def psi1(self, Z, variational_posterior): - return self.psicomp.psicomputations(self.variance, self.lengthscale, Z, variational_posterior)[1] + return self.psicomp.psicomputations(self, Z, variational_posterior)[1] def psi2(self, Z, variational_posterior): - return self.psicomp.psicomputations(self.variance, self.lengthscale, Z, variational_posterior, return_psi2_n=False)[2] + return self.psicomp.psicomputations(self, Z, variational_posterior, return_psi2_n=False)[2] def psi2n(self, Z, variational_posterior): - return self.psicomp.psicomputations(self.variance, self.lengthscale, Z, variational_posterior, return_psi2_n=True)[2] + return self.psicomp.psicomputations(self, Z, variational_posterior, return_psi2_n=True)[2] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): - dL_dvar, dL_dlengscale = self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variance, self.lengthscale, Z, variational_posterior)[:2] + dL_dvar, dL_dlengscale = self.psicomp.psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[:2] self.variance.gradient = dL_dvar self.lengthscale.gradient = dL_dlengscale def gradients_Z_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): - return self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variance, self.lengthscale, Z, variational_posterior)[2] + return self.psicomp.psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[2] def gradients_qX_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): - return self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variance, self.lengthscale, Z, variational_posterior)[3:] + return self.psicomp.psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[3:]