From 83510e75151e80bc0f74aead9458cacd4e46dab0 Mon Sep 17 00:00:00 2001 From: James Hensman Date: Tue, 30 Apr 2013 11:25:57 +0100 Subject: [PATCH] first attemot at the new constraint framework --- GPy/core/model.py | 19 +-- GPy/core/parameterised.py | 261 ++++++++++++++------------------------ GPy/kern/kern.py | 52 +++----- GPy/kern/rbf.py | 4 +- GPy/models/GP.py | 11 +- 5 files changed, 129 insertions(+), 218 deletions(-) diff --git a/GPy/core/model.py b/GPy/core/model.py index f3542ce8..f0e50782 100644 --- a/GPy/core/model.py +++ b/GPy/core/model.py @@ -8,7 +8,7 @@ import sys, pdb import multiprocessing as mp from GPy.util.misc import opt_wrapper #import numdifftools as ndt -from parameterised import parameterised, truncate_pad +from parameterised import parameterised import priors from ..util.linalg import jitchol from ..inference import optimization @@ -108,22 +108,15 @@ class model(parameterised): return ret def _transform_gradients(self, g): - """ - Takes a list of gradients and return an array of transformed gradients (positive/negative/tied/and so on) - """ - x = self._get_params() - g[self.constrained_positive_indices] = g[self.constrained_positive_indices]*x[self.constrained_positive_indices] - g[self.constrained_negative_indices] = g[self.constrained_negative_indices]*x[self.constrained_negative_indices] - [np.put(g,i,g[i]*(x[i]-l)*(h-x[i])/(h-l)) for i,l,h in zip(self.constrained_bounded_indices, self.constrained_bounded_lowers, self.constrained_bounded_uppers)] - [np.put(g,i,v) for i,v in [(t[0],np.sum(g[t])) for t in self.tied_indices]] - if len(self.tied_indices) or len(self.constrained_fixed_indices): - to_remove = np.hstack((self.constrained_fixed_indices+[t[1:] for t in self.tied_indices])) + for index,constraint in zip(self.constrained_indices, self.constraints): + g[index] = g[index] * constraint.gradfactor(x[index]) + if len(self.tied_indices) or len(self.fixed_indices): + to_remove = np.hstack((self.fixed_indices+[t[1:] for t in self.tied_indices])) return np.delete(g,to_remove) else: return g - def randomize(self): """ Randomize the model. @@ -207,7 +200,7 @@ class model(parameterised): """ Ensure that any variables which should clearly be positive have been constrained somehow. """ - positive_strings = ['variance','lengthscale', 'precision'] + positive_strings = ['variance','lengthscale', 'precision', 'kappa'] param_names = self._get_param_names() currently_constrained = self.all_constrained_indices() to_make_positive = [] diff --git a/GPy/core/parameterised.py b/GPy/core/parameterised.py index 4d1d6992..9a1828a3 100644 --- a/GPy/core/parameterised.py +++ b/GPy/core/parameterised.py @@ -9,26 +9,7 @@ import cPickle import os from ..util.squashers import sigmoid import warnings - -def truncate_pad(string, width, align='m'): - """ - A helper function to make aligned strings for parameterised.__str__ - """ - width = max(width, 4) - if len(string) > width: - return string[:width - 3] + '...' - elif len(string) == width: - return string - elif len(string) < width: - diff = width - len(string) - if align == 'm': - return ' ' * np.floor(diff / 2.) + string + ' ' * np.ceil(diff / 2.) - elif align == 'l': - return string + ' ' * diff - elif align == 'r': - return ' ' * diff + string - else: - raise ValueError +import transformations class parameterised(object): def __init__(self): @@ -36,13 +17,10 @@ class parameterised(object): This is the base class for model and kernel. Mostly just handles tieing and constraining of parameters """ self.tied_indices = [] - self.constrained_fixed_indices = [] - self.constrained_fixed_values = [] - self.constrained_positive_indices = np.empty(shape=(0,), dtype=np.int64) - self.constrained_negative_indices = np.empty(shape=(0,), dtype=np.int64) - self.constrained_bounded_indices = [] - self.constrained_bounded_uppers = [] - self.constrained_bounded_lowers = [] + self.fixed_indices = [] + self.fixed_values = [] + self.constrained_indices = [] + self.constraints = [] def pickle(self, filename, protocol= -1): f = file(filename, 'w') @@ -50,20 +28,18 @@ class parameterised(object): f.close() def copy(self): - """ - Returns a (deep) copy of the current model - """ - + """Returns a (deep) copy of the current model """ return copy.deepcopy(self) @property def params(self): """ Returns a **copy** of parameters in non transformed space - - :see_also: :py:func:`GPy.core.parameterised.params_transformed` + + :see_also: :py:func:`GPy.core.parameterised.params_transformed` """ return self._get_params() + @params.setter def params(self, params): self._set_params(params) @@ -72,10 +48,11 @@ class parameterised(object): def params_transformed(self): """ Returns a **copy** of parameters in transformed space - - :see_also: :py:func:`GPy.core.parameterised.params` + + :see_also: :py:func:`GPy.core.parameterised.params` """ return self._get_params_transformed() + @params_transformed.setter def params_transformed(self, params): self._set_params_transformed(params) @@ -85,7 +62,7 @@ class parameterised(object): Assume m is a model class: print m['var'] # > prints all parameters matching 'var' m['var'] = 2. # > sets all parameters matching 'var' to 2. - m['var'] = # > sets parameters matching 'var' to + m['var'] = # > sets parameters matching 'var' to """ def get(self, name): warnings.warn(self._get_set_deprecation, FutureWarning, stacklevel=2) @@ -97,7 +74,9 @@ class parameterised(object): def __getitem__(self, name, return_names=False): """ - Get a model parameter by name. The name is applied as a regular expression and all parameters that match that regular expression are returned. + Get a model parameter by name. The name is applied as a regular + expression and all parameters that match that regular expression are + returned. """ matches = self.grep_param_names(name) if len(matches): @@ -110,7 +89,9 @@ class parameterised(object): def __setitem__(self, name, val): """ - Set model parameter(s) by name. The name is provided as a regular expression. All parameters matching that regular expression are set to ghe given value. + Set model parameter(s) by name. The name is provided as a regular + expression. All parameters matching that regular expression are set to + the given value. """ matches = self.grep_param_names(name) if len(matches): @@ -119,8 +100,6 @@ class parameterised(object): x = self.params x[matches] = val self.params = x -# import ipdb;ipdb.set_trace() -# self.params[matches] = val else: raise AttributeError, "no parameter matches %s" % name @@ -140,13 +119,6 @@ class parameterised(object): """Unties all parameters by setting tied_indices to an empty list.""" self.tied_indices = [] - def all_constrained_indices(self): - """Return a np array of all the constrained indices""" - ret = [np.hstack(i) for i in [self.constrained_bounded_indices, self.constrained_positive_indices, self.constrained_negative_indices, self.constrained_fixed_indices] if len(i)] - if len(ret): - return np.hstack(ret) - else: - return [] def grep_param_names(self, expr): """ Arguments @@ -159,7 +131,7 @@ class parameterised(object): Notes ----- - Other objects are passed through - i.e. integers which were'nt meant for grepping + Other objects are passed through - i.e. integers which weren't meant for grepping """ if type(expr) in [str, np.string_, np.str]: @@ -171,100 +143,76 @@ class parameterised(object): return expr def Nparam_transformed(self): - ties = 0 - for ar in self.tied_indices: - ties += ar.size - 1 - return self.Nparam - len(self.constrained_fixed_indices) - ties + removed = 0 + for tie in self.tied_indices: + removed += tie.size - 1 - def constrain_positive(self, which): - """ - Set positive constraints. - - Arguments - --------- - which -- np.array(dtype=int), or regular expression object or string - """ - matches = self.grep_param_names(which) - assert not np.any(matches[:, None] == self.all_constrained_indices()), "Some indices are already constrained" - self.constrained_positive_indices = np.hstack((self.constrained_positive_indices, matches)) - # check to ensure constraint is in place - x = self._get_params() - for i, xx in enumerate(x): - if (xx < 0) & (i in matches): - x[i] = -xx - self._set_params(x) + for fix in self.fixed_indices: + removed += fix.size + return len(self._get_params()) - removed def unconstrain(self, which): """Unconstrain matching parameters. does not untie parameters""" matches = self.grep_param_names(which) - # positive/negative - self.constrained_positive_indices = np.delete(self.constrained_positive_indices, np.nonzero(np.sum(self.constrained_positive_indices[:, None] == matches[None, :], 1))[0]) - self.constrained_negative_indices = np.delete(self.constrained_negative_indices, np.nonzero(np.sum(self.constrained_negative_indices[:, None] == matches[None, :], 1))[0]) - # bounded - if len(self.constrained_bounded_indices): - self.constrained_bounded_indices = [np.delete(a, np.nonzero(np.sum(a[:, None] == matches[None, :], 1))[0]) for a in self.constrained_bounded_indices] - if np.hstack(self.constrained_bounded_indices).size: - self.constrained_bounded_uppers, self.constrained_bounded_lowers, self.constrained_bounded_indices = zip(*[(u, l, i) for u, l, i in zip(self.constrained_bounded_uppers, self.constrained_bounded_lowers, self.constrained_bounded_indices) if i.size]) - self.constrained_bounded_uppers, self.constrained_bounded_lowers, self.constrained_bounded_indices = list(self.constrained_bounded_uppers), list(self.constrained_bounded_lowers), list(self.constrained_bounded_indices) - else: - self.constrained_bounded_uppers, self.constrained_bounded_lowers, self.constrained_bounded_indices = [], [], [] - # fixed: - for i, indices in enumerate(self.constrained_fixed_indices): - self.constrained_fixed_indices[i] = np.delete(indices, np.nonzero(np.sum(indices[:, None] == matches[None, :], 1))[0]) - # remove empty elements - tmp = [(i, v) for i, v in zip(self.constrained_fixed_indices, self.constrained_fixed_values) if len(i)] + + #tranformed contraints: + for match in matches: + self.constrained_indices = [i[i<>match] for i in self.constrained_indices] + + #remove empty constraints + tmp = zip(*[(i,t) for i,t in zip(self.constrained_indices,self.constraints) if len(i)]) if tmp: - self.constrained_fixed_indices, self.constrained_fixed_values = zip(*tmp) - self.constrained_fixed_indices, self.constrained_fixed_values = list(self.constrained_fixed_indices), list(self.constrained_fixed_values) + self.constrained_indices, self.constraints = zip(*[(i,t) for i,t in zip(self.constrained_indices,self.constraints) if len(i)]) + self.constrained_indices, self.constraints = list(self.constrained_indices), list(self.constraints) + + # fixed: + for i, indices in enumerate(self.fixed_indices): + self.fixed_indices[i] = np.delete(indices, np.nonzero(np.sum(indices[:, None] == matches[None, :], 1))[0]) + # remove empty elements + tmp = [(i, v) for i, v in zip(self.fixed_indices, self.fixed_values) if len(i)] + if tmp: + self.fixed_indices, self.fixed_values = zip(*tmp) + self.fixed_indices, self.fixed_values = list(self.fixed_indices), list(self.fixed_values) else: - self.constrained_fixed_indices, self.constrained_fixed_values = [], [] - - + self.fixed_indices, self.fixed_values = [], [] def constrain_negative(self, which): - """ - Set negative constraints. + """ Set negative constraints. """ + self.constrain(which, transformations.negative_exponent()) - :param which: which variables to constrain - :type which: regular expression string + def constrain_positive(self, which): + """ Set positive constraints. """ + self.constrain(which, transformations.logexp()) + + def constrain_bounded(self, which,lower, upper): + """ Set bounded constraints. """ + self.constrain(which, transformations.logistic(lower, upper)) + + def all_constrained_indices(self): + if len(self.constrained_indices): + return np.hstack(self.constrained_indices) + else: + return np.empty(shape=(0,)) + + def constrain(self,which,transform): + assert isinstance(transform,transformations.transformation) - """ matches = self.grep_param_names(which) - assert not np.any(matches[:, None] == self.all_constrained_indices()), "Some indices are already constrained" - self.constrained_negative_indices = np.hstack((self.constrained_negative_indices, matches)) - # check to ensure constraint is in place + overlap = set(matches).intersection(set(self.all_constrained_indices())) + if overlap: + self.unconstrain(np.asarray(list(overlap))) + print 'Warning: re-constraining these parameters' + pn = self._get_param_names() + for i in overlap: + print pn[i] + + self.constrained_indices.append(matches) + self.constraints.append(transform) x = self._get_params() - for i, xx in enumerate(x): - if (xx > 0.) and (i in matches): - x[i] = -xx + x[matches] = transform.initialize(x[matches]) self._set_params(x) - - - def constrain_bounded(self, which, lower, upper): - """Set bounded constraints. - - Arguments - --------- - which -- np.array(dtype=int), or regular expression object or string - upper -- (float) the upper bound on the constraint - lower -- (float) the lower bound on the constraint - """ - matches = self.grep_param_names(which) - assert not np.any(matches[:, None] == self.all_constrained_indices()), "Some indices are already constrained" - assert lower < upper, "lower bound must be smaller than upper bound!" - self.constrained_bounded_indices.append(matches) - self.constrained_bounded_uppers.append(upper) - self.constrained_bounded_lowers.append(lower) - # check to ensure constraint is in place - x = self._get_params() - for i, xx in enumerate(x): - if ((xx <= lower) | (xx >= upper)) & (i in matches): - x[i] = sigmoid(xx) * (upper - lower) + lower - self._set_params(x) - - def constrain_fixed(self, which, value=None): """ Arguments @@ -280,42 +228,36 @@ class parameterised(object): """ matches = self.grep_param_names(which) assert not np.any(matches[:, None] == self.all_constrained_indices()), "Some indices are already constrained" - self.constrained_fixed_indices.append(matches) + self.fixed_indices.append(matches) if value != None: - self.constrained_fixed_values.append(value) + self.fixed_values.append(value) else: - self.constrained_fixed_values.append(self._get_params()[self.constrained_fixed_indices[-1]]) + self.fixed_values.append(self._get_params()[self.fixed_indices[-1]]) - # self.constrained_fixed_values.append(value) + # self.fixed_values.append(value) self._set_params_transformed(self._get_params_transformed()) def _get_params_transformed(self): """use self._get_params to get the 'true' parameters of the model, which are then tied, constrained and fixed""" x = self._get_params() - x[self.constrained_positive_indices] = np.log(x[self.constrained_positive_indices]) - x[self.constrained_negative_indices] = np.log(-x[self.constrained_negative_indices]) - [np.put(x, i, np.log(np.clip(x[i] - l, 1e-10, np.inf) / np.clip(h - x[i], 1e-10, np.inf))) for i, l, h in zip(self.constrained_bounded_indices, self.constrained_bounded_lowers, self.constrained_bounded_uppers)] + [np.put(x,i,t.finv(x[i])) for i,t in zip(self.constrained_indices,self.constraints)] - to_remove = self.constrained_fixed_indices + [t[1:] for t in self.tied_indices] + to_remove = self.fixed_indices + [t[1:] for t in self.tied_indices] if len(to_remove): return np.delete(x, np.hstack(to_remove)) else: return x - def _set_params_transformed(self, x): """ takes the vector x, which is then modified (by untying, reparameterising or inserting fixed values), and then call self._set_params""" # work out how many places are fixed, and where they are. tricky logic! - Nfix_places = 0. - if len(self.tied_indices): - Nfix_places += np.hstack(self.tied_indices).size - len(self.tied_indices) - if len(self.constrained_fixed_indices): - Nfix_places += np.hstack(self.constrained_fixed_indices).size - if Nfix_places: - fix_places = np.hstack(self.constrained_fixed_indices + [t[1:] for t in self.tied_indices]) + fix_places = self.fixed_indices + [t[1:] for t in self.tied_indices] + if len(fix_places): + fix_places = np.hstack(fix_places) + Nfix_places = fix_places.size else: - fix_places = [] + Nfix_places = 0 free_places = np.setdiff1d(np.arange(Nfix_places + x.size, dtype=np.int), fix_places) @@ -323,11 +265,12 @@ class parameterised(object): xx = np.zeros(Nfix_places + free_places.size, dtype=np.float64) xx[free_places] = x - [np.put(xx, i, v) for i, v in zip(self.constrained_fixed_indices, self.constrained_fixed_values)] + [np.put(xx, i, v) for i, v in zip(self.fixed_indices, self.fixed_values)] [np.put(xx, i, v) for i, v in [(t[1:], xx[t[0]]) for t in self.tied_indices] ] - xx[self.constrained_positive_indices] = np.exp(xx[self.constrained_positive_indices]) - xx[self.constrained_negative_indices] = -np.exp(xx[self.constrained_negative_indices]) - [np.put(xx, i, low + sigmoid(xx[i]) * (high - low)) for i, low, high in zip(self.constrained_bounded_indices, self.constrained_bounded_lowers, self.constrained_bounded_uppers)] + + [np.put(xx,i,t.f(xx[i])) for i,t in zip(self.constrained_indices, self.constraints)] + if hasattr(self,'debug'): + stop self._set_params(xx) def _get_param_names_transformed(self): @@ -346,17 +289,13 @@ class parameterised(object): remove = np.empty(shape=(0,), dtype=np.int) # also remove the fixed params - if len(self.constrained_fixed_indices): - remove = np.hstack((remove, np.hstack(self.constrained_fixed_indices))) + if len(self.fixed_indices): + remove = np.hstack((remove, np.hstack(self.fixed_indices))) # add markers to show that some variables are constrained - for i in self.constrained_positive_indices: - n[i] = n[i] + '(+ve)' - for i in self.constrained_negative_indices: - n[i] = n[i] + '(-ve)' - for i, l, h in zip(self.constrained_bounded_indices, self.constrained_bounded_lowers, self.constrained_bounded_uppers): + for i,t in zip(self.constrained_indices,self.constraints): for ii in i: - n[ii] = n[ii] + '(bounded)' + n[ii] = n[ii] + t.__str__() n = [nn for i, nn in enumerate(n) if not i in remove] return n @@ -374,16 +313,12 @@ class parameterised(object): values = self._get_params() # map(str,self._get_params()) # sort out the constraints constraints = [''] * len(names) - for i in self.constrained_positive_indices: - constraints[i] = '(+ve)' - for i in self.constrained_negative_indices: - constraints[i] = '(-ve)' - for i in self.constrained_fixed_indices: + for i,t in zip(self.constrained_indices,self.constraints): + for ii in i: + constraints[ii] = t.__str__() + for i in self.fixed_indices: for ii in i: constraints[ii] = 'Fixed' - for i, u, l in zip(self.constrained_bounded_indices, self.constrained_bounded_uppers, self.constrained_bounded_lowers): - for ii in i: - constraints[ii] = '(' + str(l) + ', ' + str(u) + ')' # sort out the ties ties = [''] * len(names) for i, tie in enumerate(self.tied_indices): diff --git a/GPy/kern/kern.py b/GPy/kern/kern.py index 67333765..fd135bcb 100644 --- a/GPy/kern/kern.py +++ b/GPy/kern/kern.py @@ -71,12 +71,10 @@ class kern(parameterised): def _transform_gradients(self, g): x = self._get_params() - g[self.constrained_positive_indices] = g[self.constrained_positive_indices] * x[self.constrained_positive_indices] - g[self.constrained_negative_indices] = g[self.constrained_negative_indices] * x[self.constrained_negative_indices] - [np.put(g, i, g[i] * (x[i] - l) * (h - x[i]) / (h - l)) for i, l, h in zip(self.constrained_bounded_indices, self.constrained_bounded_lowers, self.constrained_bounded_uppers)] + [np.put(x,i,x*t.gradfactor(x[i])) for i,t in zip(self.constrained_indices, self.constraints)] [np.put(g, i, v) for i, v in [(t[0], np.sum(g[t])) for t in self.tied_indices]] - if len(self.tied_indices) or len(self.constrained_fixed_indices): - to_remove = np.hstack((self.constrained_fixed_indices + [t[1:] for t in self.tied_indices])) + if len(self.tied_indices) or len(self.fixed_indices): + to_remove = np.hstack((self.fixed_indices + [t[1:] for t in self.tied_indices])) return np.delete(g, to_remove) else: return g @@ -93,13 +91,10 @@ class kern(parameterised): assert self.D == other.D newkern = kern(self.D, self.parts + other.parts, self.input_slices + other.input_slices) # transfer constraints: - newkern.constrained_positive_indices = np.hstack((self.constrained_positive_indices, self.Nparam + other.constrained_positive_indices)) - newkern.constrained_negative_indices = np.hstack((self.constrained_negative_indices, self.Nparam + other.constrained_negative_indices)) - newkern.constrained_bounded_indices = self.constrained_bounded_indices + [self.Nparam + x for x in other.constrained_bounded_indices] - newkern.constrained_bounded_lowers = self.constrained_bounded_lowers + other.constrained_bounded_lowers - newkern.constrained_bounded_uppers = self.constrained_bounded_uppers + other.constrained_bounded_uppers - newkern.constrained_fixed_indices = self.constrained_fixed_indices + [self.Nparam + x for x in other.constrained_fixed_indices] - newkern.constrained_fixed_values = self.constrained_fixed_values + other.constrained_fixed_values + newkern.constrained_indices = self.constrained_indices + [i+self.Nparam for i in other.constrained_indices] + newkern.constraints = self.constraints + other.constraints + newkern.fixed_indices = self.fixed_indices + [self.Nparam + x for x in other.fixed_indices] + newkern.fixed_values = self.fixed_values + other.fixed_values newkern.tied_indices = self.tied_indices + [self.Nparam + x for x in other.tied_indices] return newkern @@ -126,13 +121,12 @@ class kern(parameterised): newkern = kern(D, self.parts + other.parts, self_input_slices + other_input_slices) # transfer constraints: - newkern.constrained_positive_indices = np.hstack((self.constrained_positive_indices, self.Nparam + other.constrained_positive_indices)) - newkern.constrained_negative_indices = np.hstack((self.constrained_negative_indices, self.Nparam + other.constrained_negative_indices)) - newkern.constrained_bounded_indices = self.constrained_bounded_indices + [self.Nparam + x for x in other.constrained_bounded_indices] - newkern.constrained_bounded_lowers = self.constrained_bounded_lowers + other.constrained_bounded_lowers + newkern.constrained_indices = self.constrained_indices + [x+self.Nparam for x in other.constrained_indices] + newkern.constraints = self.constraints + other.constraints + newkern.fixed_indices = self.fixed_indices + [self.Nparam + x for x in other.fixed_indices] + newkern.fixed_values = self.fixed_values + other.fixed_values + newkern.constraints = self.constraints + other.constraints newkern.constrained_bounded_uppers = self.constrained_bounded_uppers + other.constrained_bounded_uppers - newkern.constrained_fixed_indices = self.constrained_fixed_indices + [self.Nparam + x for x in other.constrained_fixed_indices] - newkern.constrained_fixed_values = self.constrained_fixed_values + other.constrained_fixed_values newkern.tied_indices = self.tied_indices + [self.Nparam + x for x in other.tied_indices] return newkern @@ -208,15 +202,11 @@ class kern(parameterised): # Get the ties and constrains of the kernels before the multiplication prev_ties = K1.tied_indices + [arr + K1.Nparam for arr in K2.tied_indices] - prev_constr_pos = np.append(K1.constrained_positive_indices, K1.Nparam + K2.constrained_positive_indices) - prev_constr_neg = np.append(K1.constrained_negative_indices, K1.Nparam + K2.constrained_negative_indices) + prev_constr_ind = [K1.constrained_indices] + [K1.Nparam + i for i in K2.constrained_indices] + prev_constr = K1.constraints + K2.constraints - prev_constr_fix = K1.constrained_fixed_indices + [arr + K1.Nparam for arr in K2.constrained_fixed_indices] - prev_constr_fix_values = K1.constrained_fixed_values + K2.constrained_fixed_values - - prev_constr_bou = K1.constrained_bounded_indices + [arr + K1.Nparam for arr in K2.constrained_bounded_indices] - prev_constr_bou_low = K1.constrained_bounded_lowers + K2.constrained_bounded_lowers - prev_constr_bou_upp = K1.constrained_bounded_uppers + K2.constrained_bounded_uppers + prev_constr_fix = K1.fixed_indices + [arr + K1.Nparam for arr in K2.fixed_indices] + prev_constr_fix_values = K1.fixed_values + K2.fixed_values # follow the previous ties for arr in prev_ties: @@ -228,14 +218,8 @@ class kern(parameterised): index = np.where(index_param == i)[0] if index.size > 1: self.tie_params(index) - for i in prev_constr_pos: - self.constrain_positive(np.where(index_param == i)[0]) - for i in prev_constr_neg: - self.constrain_neg(np.where(index_param == i)[0]) - for j, i in enumerate(prev_constr_fix): - self.constrain_fixed(np.where(index_param == i)[0], prev_constr_fix_values[j]) - for j, i in enumerate(prev_constr_bou): - self.constrain_bounded(np.where(index_param == i)[0], prev_constr_bou_low[j], prev_constr_bou_upp[j]) + for i,t in zip(prev_constr_ind,prev_constr): + self.constrain(np.where(index_param == i)[0],t) def _get_params(self): return np.hstack([p._get_params() for p in self.parts]) diff --git a/GPy/kern/rbf.py b/GPy/kern/rbf.py index 027e5e9e..c413b469 100644 --- a/GPy/kern/rbf.py +++ b/GPy/kern/rbf.py @@ -188,12 +188,12 @@ class rbf(kernpart): self._X2 = None X = X/self.lengthscale Xsquare = np.sum(np.square(X),1) - self._K_dist2 = (-2.*tdot(X) + Xsquare[:,None] + Xsquare[None,:]) + self._K_dist2 = -2.*tdot(X) + (Xsquare[:,None] + Xsquare[None,:]) else: self._X2 = X2.copy() X = X/self.lengthscale X2 = X2/self.lengthscale - self._K_dist2 = (-2.*np.dot(X, X2.T) + np.sum(np.square(X),1)[:,None] + np.sum(np.square(X2),1)[None,:]) + self._K_dist2 = -2.*np.dot(X, X2.T) + (np.sum(np.square(X),1)[:,None] + np.sum(np.square(X2),1)[None,:]) self._K_dvar = np.exp(-0.5*self._K_dist2) def _psi_computations(self,Z,mu,S): diff --git a/GPy/models/GP.py b/GPy/models/GP.py index 45ed61ca..ced8311b 100644 --- a/GPy/models/GP.py +++ b/GPy/models/GP.py @@ -35,6 +35,9 @@ class GP(model): self.N, self.Q = self.X.shape assert isinstance(kernel, kern.kern) self.kern = kernel + self.likelihood = likelihood + assert self.X.shape[0] == self.likelihood.data.shape[0] + self.N, self.D = self.likelihood.data.shape # here's some simple normalization for the inputs if normalize_X: @@ -47,12 +50,8 @@ class GP(model): self._Xmean = np.zeros((1, self.X.shape[1])) self._Xstd = np.ones((1, self.X.shape[1])) - self.likelihood = likelihood - # assert self.X.shape[0] == self.likelihood.Y.shape[0] - # self.N, self.D = self.likelihood.Y.shape - assert self.X.shape[0] == self.likelihood.data.shape[0] - self.N, self.D = self.likelihood.data.shape + self.has_uncertain_inputs = False model.__init__(self) def dL_dZ(self): @@ -232,7 +231,7 @@ class GP(model): else: raise NotImplementedError, "Cannot define a frame with more than two input dimensions" - def plot(self, samples=0, plot_limits=None, which_data='all', which_functions='all', resolution=None, levels=20): + def plot(self, samples=0, plot_limits=None, which_data='all', which_parts='all', resolution=None, levels=20): """ TODO: Docstrings! :param levels: for 2D plotting, the number of contour levels to use