From f35578804a2dcbc9066d48a103bcaf4ed1d0fd5d Mon Sep 17 00:00:00 2001 From: James Hensman Date: Tue, 23 Apr 2013 10:56:10 +0100 Subject: [PATCH] prod_orthogonal now caches the K matrices --- GPy/kern/coregionalise.py | 13 ++++++--- GPy/kern/prod_orthogonal.py | 53 ++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/GPy/kern/coregionalise.py b/GPy/kern/coregionalise.py index a76bb31e..b1b69325 100644 --- a/GPy/kern/coregionalise.py +++ b/GPy/kern/coregionalise.py @@ -62,11 +62,16 @@ class coregionalise(kernpart): ii,jj = np.meshgrid(index,index2) ii,jj = ii.T, jj.T + #dL_dK_small = np.zeros_like(self.B) + #for i in range(self.Nout): + #for j in range(self.Nout): + #tmp = np.sum(dL_dK[(ii==i)*(jj==j)]) + #dL_dK_small[i,j] = tmp + #as above, but slightly faster dL_dK_small = np.zeros_like(self.B) - for i in range(self.Nout): - for j in range(self.Nout): - tmp = np.sum(dL_dK[(ii==i)*(jj==j)]) - dL_dK_small[i,j] = tmp + where_i = [ii==i for i in xrange(self.Nout)] + where_j = [jj==j for j in xrange(self.Nout)] + [[np.put(dL_dK_small,i+self.Nout*j,np.sum(dL_dK[np.logical_and(wi,wj)])) for i,wi in enumerate(where_i)] for j,wj in enumerate(where_j)] dkappa = np.diag(dL_dK_small) dL_dK_small += dL_dK_small.T diff --git a/GPy/kern/prod_orthogonal.py b/GPy/kern/prod_orthogonal.py index fc349da8..2afafe25 100644 --- a/GPy/kern/prod_orthogonal.py +++ b/GPy/kern/prod_orthogonal.py @@ -22,6 +22,7 @@ class prod_orthogonal(kernpart): self.k1 = k1 self.k2 = k2 self._set_params(np.hstack((k1._get_params(),k2._get_params()))) + self._X, self._X2, self._params = np.empty(shape=(3,1)) # initialize cache def _get_params(self): """return the value of the parameters.""" @@ -39,23 +40,38 @@ class prod_orthogonal(kernpart): def K(self,X,X2,target): """Compute the covariance matrix between X and X2.""" - if X2 is None: X2 = X - target1 = np.zeros_like(target) - target2 = np.zeros_like(target) - self.k1.K(X[:,:self.k1.D],X2[:,:self.k1.D],target1) - self.k2.K(X[:,self.k1.D:],X2[:,self.k1.D:],target2) - target += target1 * target2 + self._K_computations(X,X2) + target += self._K1*self._K2 + + def _K_computations(self,X,X2): + """ + Compute the two kernel matrices. + The computation is only done if needed: many times it will be the same as the previous call + """ + if not (np.all(X==self._X) and np.all(X2==self._X2) and np.all(self._params == self._get_params())): + #store new values in cache + self._X = X.copy() + self._X2 = X2.copy() + self._params = self._get_params().copy() + + #update self._K1, self._K2 + if X2 is None: X2 = X + self._K1 = np.zeros((X.shape[0],X2.shape[0])) + self._K2 = np.zeros((X.shape[0],X2.shape[0])) + self.k1.K(X[:,:self.k1.D],X2[:,:self.k1.D],self._K1) + self.k2.K(X[:,self.k1.D:],X2[:,self.k1.D:],self._K2) def dK_dtheta(self,dL_dK,X,X2,target): """derivative of the covariance matrix with respect to the parameters.""" - if X2 is None: X2 = X - K1 = np.zeros((X.shape[0],X2.shape[0])) - K2 = np.zeros((X.shape[0],X2.shape[0])) - self.k1.K(X[:,:self.k1.D],X2[:,:self.k1.D],K1) - self.k2.K(X[:,self.k1.D:],X2[:,self.k1.D:],K2) + self._K_computations(X,X2) + self.k1.dK_dtheta(dL_dK*self._K2, X[:,:self.k1.D], X2[:,:self.k1.D], target[:self.k1.Nparam]) + self.k2.dK_dtheta(dL_dK*self._K1, X[:,self.k1.D:], X2[:,self.k1.D:], target[self.k1.Nparam:]) - self.k1.dK_dtheta(dL_dK*K2, X[:,:self.k1.D], X2[:,:self.k1.D], target[:self.k1.Nparam]) - self.k2.dK_dtheta(dL_dK*K1, X[:,self.k1.D:], X2[:,self.k1.D:], target[self.k1.Nparam:]) + def dK_dX(self,dL_dK,X,X2,target): + """derivative of the covariance matrix with respect to X.""" + self._K_computations(X,X2) + self.k1.dK_dX(dL_dK*self._K2, X[:,:self.k1.D], X2[:,:self.k1.D], target) + self.k2.dK_dX(dL_dK*self._K1, X[:,self.k1.D:], X2[:,self.k1.D:], target) def Kdiag(self,X,target): """Compute the diagonal of the covariance matrix associated to X.""" @@ -73,17 +89,6 @@ class prod_orthogonal(kernpart): self.k1.dKdiag_dtheta(dL_dKdiag*K2,X[:,:self.k1.D],target[:self.k1.Nparam]) self.k2.dKdiag_dtheta(dL_dKdiag*K1,X[:,self.k1.D:],target[self.k1.Nparam:]) - def dK_dX(self,dL_dK,X,X2,target): - """derivative of the covariance matrix with respect to X.""" - if X2 is None: X2 = X - K1 = np.zeros((X.shape[0],X2.shape[0])) - K2 = np.zeros((X.shape[0],X2.shape[0])) - self.k1.K(X[:,0:self.k1.D],X2[:,0:self.k1.D],K1) - self.k2.K(X[:,self.k1.D:],X2[:,self.k1.D:],K2) - - self.k1.dK_dX(dL_dK*K2, X[:,:self.k1.D], X2[:,:self.k1.D], target) - self.k2.dK_dX(dL_dK*K1, X[:,self.k1.D:], X2[:,self.k1.D:], target) - def dKdiag_dX(self, dL_dKdiag, X, target): K1 = np.zeros(X.shape[0]) K2 = np.zeros(X.shape[0])