mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-05-15 06:52:39 +02:00
X caching is not yet done, parameter caching working fine. X cache must be adjusted to update at the right times
This commit is contained in:
parent
d3721b76a8
commit
d8151eee61
12 changed files with 249 additions and 109 deletions
|
|
@ -52,6 +52,9 @@ class kern(Parameterized):
|
|||
def parameters_changed(self):
|
||||
[p.parameters_changed() for p in self._parameters_]
|
||||
|
||||
def connect_input(self, Xparam):
|
||||
[p.connect_input(Xparam) for p in self._parameters_]
|
||||
|
||||
def getstate(self):
|
||||
"""
|
||||
Get the current state of the class,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class Bias(Kernpart):
|
|||
:type variance: float
|
||||
"""
|
||||
super(Bias, self).__init__(input_dim, 'bias')
|
||||
self.variance = Param("variance", variance, None)
|
||||
self.variance = Param("variance", variance)
|
||||
self.add_parameter(self.variance)
|
||||
#self._set_params(np.array([variance]).flatten())
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,22 @@ class Kernpart(Parameterized):
|
|||
# the name of the covariance function.
|
||||
# link to parameterized objects
|
||||
self._parameters_ = []
|
||||
self._X = None
|
||||
|
||||
def connect_input(self, X):
|
||||
X.add_observer(self, self.on_input_change)
|
||||
self._X = X
|
||||
|
||||
def on_input_change(self, X):
|
||||
"""
|
||||
During optimization this function will be called when
|
||||
the inputs X changed. Use this to update caches dependent
|
||||
on the inputs X.
|
||||
"""
|
||||
# overwrite this to update kernel when inputs X change
|
||||
pass
|
||||
|
||||
|
||||
# def set_as_parameter_named(self, name, gradient, index=None, *args, **kwargs):
|
||||
# """
|
||||
# :param names: name of parameter to set as parameter
|
||||
|
|
|
|||
|
|
@ -39,16 +39,23 @@ class Linear(Kernpart):
|
|||
else:
|
||||
if variances is not None:
|
||||
variances = np.asarray(variances)
|
||||
assert variances.size == self.input_dim, "bad number of lengthscales"
|
||||
assert variances.size == self.input_dim, "bad number of variances, need one ARD variance per input_dim"
|
||||
else:
|
||||
variances = np.ones(self.input_dim)
|
||||
|
||||
self.variances = Param('variances', variances)
|
||||
self.add_parameters(self.variances)
|
||||
self.variances.add_observer(self, self.update_variance)
|
||||
|
||||
# initialize cache
|
||||
self._Z, self._mu, self._S = np.empty(shape=(3, 1))
|
||||
self._X, self._X2 = np.empty(shape=(2, 1))
|
||||
|
||||
def update_variance(self, v):
|
||||
self.variances2 = np.square(self.variances)
|
||||
|
||||
def on_input_change(self, X):
|
||||
self._K_computations(X, None)
|
||||
|
||||
# def _get_params(self):
|
||||
# return self.variances
|
||||
|
|
@ -56,8 +63,8 @@ class Linear(Kernpart):
|
|||
# def _set_params(self, x):
|
||||
# assert x.size == (self.num_params)
|
||||
# self.variances = x
|
||||
def parameters_changed(self):
|
||||
self.variances2 = np.square(self.variances)
|
||||
#def parameters_changed(self):
|
||||
# self.variances2 = np.square(self.variances)
|
||||
#
|
||||
# def _get_param_names(self):
|
||||
# if self.num_params == 1:
|
||||
|
|
@ -74,7 +81,8 @@ class Linear(Kernpart):
|
|||
XX2 = X2 * np.sqrt(self.variances)
|
||||
target += np.dot(XX, XX2.T)
|
||||
else:
|
||||
self._K_computations(X, X2)
|
||||
if X is not self._X or X2 is not None:
|
||||
self._K_computations(X, X2)
|
||||
target += self.variances * self._dot_product
|
||||
|
||||
def Kdiag(self, X, target):
|
||||
|
|
@ -88,7 +96,8 @@ class Linear(Kernpart):
|
|||
product = X[:, None, :] * X2[None, :, :]
|
||||
target += (dL_dK[:, :, None] * product).sum(0).sum(0)
|
||||
else:
|
||||
self._K_computations(X, X2)
|
||||
if X is not self._X or X2 is not None:
|
||||
self._K_computations(X, X2)
|
||||
target += np.sum(self._dot_product * dL_dK)
|
||||
|
||||
def dKdiag_dtheta(self, dL_dKdiag, X, target):
|
||||
|
|
|
|||
|
|
@ -50,32 +50,34 @@ class RBF(Kernpart):
|
|||
else:
|
||||
lengthscale = np.ones(self.input_dim)
|
||||
|
||||
#self._set_params(np.hstack((variance, lengthscale.flatten())))
|
||||
self.variance = Param('variance', variance, None)
|
||||
self.lengthscale = Param('lengthscale', lengthscale, None)
|
||||
|
||||
self.variance = Param('variance', variance)
|
||||
self.lengthscale = Param('lengthscale', lengthscale)
|
||||
self.lengthscale.add_observer(self, self.update_lengthscale)
|
||||
self.add_parameters(self.variance, self.lengthscale)
|
||||
# self.set_as_parameter('variance', self.variance, None)
|
||||
# self.set_as_parameter('lengthscale', self.lengthscale, None)
|
||||
|
||||
# initialize cache
|
||||
self._Z, self._mu, self._S = np.empty(shape=(3, 1))
|
||||
self._X, self._X2, self._params_save = np.empty(shape=(3, 1))
|
||||
#self._Z, self._mu, self._S = np.empty(shape=(3, 1))
|
||||
#self._X, self._X2, self._params_save = np.empty(shape=(3, 1))
|
||||
|
||||
# a set of optional args to pass to weave
|
||||
self.weave_options = {'headers' : ['<omp.h>'],
|
||||
'extra_compile_args': ['-fopenmp -O3'], # -march=native'],
|
||||
'extra_link_args' : ['-lgomp']}
|
||||
|
||||
def on_input_change(self, X):
|
||||
import pdb;pdb.set_trace()
|
||||
self._K_computations(X, None)
|
||||
|
||||
def update_lengthscale(self, l):
|
||||
self.lengthscale2 = np.square(self.lengthscale)
|
||||
|
||||
def parameters_changed(self):
|
||||
self.lengthscale2 = np.square(self.lengthscale)
|
||||
# reset cached results
|
||||
#self._X, self._X2, self._params_save = np.empty(shape=(3, 1))
|
||||
#self._Z, self._mu, self._S = np.empty(shape=(3, 1)) # cached versions of Z,mu,S
|
||||
self._X, self._X2 = np.empty(shape=(2, 1))
|
||||
self._Z, self._mu, self._S = np.empty(shape=(3, 1)) # cached versions of Z,mu,S
|
||||
|
||||
#self._X, self._X2 = np.empty(shape=(2, 1))
|
||||
#self._Z, self._mu, self._S = np.empty(shape=(3, 1)) # cached versions of Z,mu,S
|
||||
pass
|
||||
# def _get_params(self):
|
||||
# return np.hstack((self.variance, self.lengthscale))
|
||||
# #
|
||||
|
|
@ -97,14 +99,17 @@ class RBF(Kernpart):
|
|||
# return ['variance'] + ['lengthscale_%i' % i for i in range(self.lengthscale.size)]
|
||||
|
||||
def K(self, X, X2, target):
|
||||
self._K_computations(X, X2)
|
||||
if self._X is None or X.base is not self._X.base or X2 is not None:
|
||||
import pdb;pdb.set_trace()
|
||||
self._K_computations(X, X2)
|
||||
target += self.variance * self._K_dvar
|
||||
|
||||
def Kdiag(self, X, target):
|
||||
np.add(target, self.variance, target)
|
||||
|
||||
def dK_dtheta(self, dL_dK, X, X2, target):
|
||||
self._K_computations(X, X2)
|
||||
if self._X is None or X.base is not self._X.base or X2 is not None:
|
||||
self._K_computations(X, X2)
|
||||
target[0] += np.sum(self._K_dvar * dL_dK)
|
||||
if self.ARD:
|
||||
dvardLdK = self._K_dvar * dL_dK
|
||||
|
|
@ -152,7 +157,8 @@ class RBF(Kernpart):
|
|||
target[0] += np.sum(dL_dKdiag)
|
||||
|
||||
def dK_dX(self, dL_dK, X, X2, target):
|
||||
self._K_computations(X, X2)
|
||||
if self._X is None or X.base is not self._X.base or X2 is not None:
|
||||
self._K_computations(X, X2)
|
||||
if X2 is None:
|
||||
_K_dist = 2*(X[:, None, :] - X[None, :, :])
|
||||
else:
|
||||
|
|
@ -241,7 +247,7 @@ class RBF(Kernpart):
|
|||
def _K_computations(self, X, X2):
|
||||
#params = self._get_params()
|
||||
if not (fast_array_equal(X, self._X) and fast_array_equal(X2, self._X2)):# and fast_array_equal(self._params_save , params)):
|
||||
self._X = X.copy()
|
||||
#self._X = X.copy()
|
||||
#self._params_save = params.copy()
|
||||
if X2 is None:
|
||||
self._X2 = None
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class White(Kernpart):
|
|||
def __init__(self,input_dim,variance=1.):
|
||||
super(White, self).__init__(input_dim, 'white')
|
||||
self.input_dim = input_dim
|
||||
self.variance = Param('variance', variance, None)
|
||||
self.variance = Param('variance', variance)
|
||||
self.add_parameters(self.variance)
|
||||
# self._set_params(np.array([variance]).flatten())
|
||||
self._psi1 = 0 # TODO: more elegance here
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue