From 27724fd456297888ba0d190c3fd1b9798d367b13 Mon Sep 17 00:00:00 2001 From: Max Zwiessele Date: Tue, 22 Oct 2013 16:16:54 +0100 Subject: [PATCH] GPRegression working, gradients still todo --- GPy/core/model.py | 4 ++-- GPy/core/parameter.py | 18 +++++++++--------- GPy/core/parameterized.py | 32 ++++++++++++++++++++++---------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/GPy/core/model.py b/GPy/core/model.py index 060fc56e..3a26fba5 100644 --- a/GPy/core/model.py +++ b/GPy/core/model.py @@ -311,7 +311,7 @@ class Model(Parameterized): the objective cannot be computed. :param x: the parameters of the model. - :parameter type: np.array + :type x: np.array """ try: self._set_params_transformed(x) @@ -329,7 +329,7 @@ class Model(Parameterized): Compute the objective function of the model and the gradient of the model at the point given by x. :param x: the point at which gradients are to be computed. - :type np.array: + :type x: np.array """ try: diff --git a/GPy/core/parameter.py b/GPy/core/parameter.py index 85ec15c8..0144733a 100644 --- a/GPy/core/parameter.py +++ b/GPy/core/parameter.py @@ -45,7 +45,7 @@ class Param(numpy.ndarray): obj._name_ = name obj._parent_ = None obj._parent_index_ = None - obj._updates_parent_ = None + obj._gradient_parent_ = None obj._gradient_ = gradient obj._current_slice_ = (slice(obj.shape[0]),) obj._realshape_ = obj.shape @@ -72,7 +72,7 @@ class Param(numpy.ndarray): self._realndim_ = getattr(obj, '_realndim_', None) self._updated_ = getattr(obj, '_updated_', None) self._original_ = getattr(obj, '_original_', None) - self._updates_parent_ = getattr(obj, '_updates_parent_', None) + self._gradient_parent_ = getattr(obj, '_gradient_parent_', None) def __array_wrap__(self, out_arr, context=None): return out_arr.view(numpy.ndarray) @@ -85,7 +85,7 @@ class Param(numpy.ndarray): (self._name_, self._parent_, self._parent_index_, - self._updates_parent_, + self._gradient_parent_, self._gradient_, self._current_slice_, self._realshape_, @@ -107,7 +107,7 @@ class Param(numpy.ndarray): self._realshape_ = state.pop() self._current_slice_ = state.pop() self._gradient_ = state.pop() - self._updates_parent_ = state.pop() + self._gradient_parent_ = state.pop() self._parent_index_ = state.pop() self._parent_ = state.pop() self._name_ = state.pop() @@ -174,7 +174,7 @@ class Param(numpy.ndarray): self._parent_._get_original(self).__setitem__(self._current_slice_, transform.initialize(self), update=False) self._parent_._add_constrain(self, transform, warning) if update: - self._updates_parent_.parameters_changed() + self._parent_.parameters_changed() def constrain_positive(self, warning=True): """ :param warning: print a warning if re-constraining parameters. @@ -321,7 +321,7 @@ class Param(numpy.ndarray): numpy.ndarray.__setitem__(self, s, val) self._fire_changed() if update: - self._updates_parent_.parameters_changed() + self._parent_.parameters_changed() #=========================================================================== # Index Operations: #=========================================================================== @@ -467,7 +467,7 @@ class ParamConcatenation(object): [numpy.place(p, ind[ps], vals[ps]) and p._fire_changed() for p, ps in zip(self.params, self._param_slices_)] if update: - self.params[0]._updates_parent_.parameters_changed() + self.params[0]._parent_.parameters_changed() def _vals(self): return numpy.hstack([p._get_params() for p in self.params]) #=========================================================================== @@ -489,8 +489,8 @@ class ParamConcatenation(object): def constrain_bounded(self, lower, upper, warning=True): [param.constrain_bounded(lower, upper, warning) for param in self.params] constrain_bounded.__doc__ = Param.constrain_bounded.__doc__ - def unconstrain(self, constraints=None): - [param.unconstrain(constraints) for param in self.params] + def unconstrain(self, *constraints): + [param.unconstrain(*constraints) for param in self.params] unconstrain.__doc__ = Param.unconstrain.__doc__ def unconstrain_negative(self): [param.unconstrain_negative() for param in self.params] diff --git a/GPy/core/parameterized.py b/GPy/core/parameterized.py index 3ad8be0c..0b3e8f22 100644 --- a/GPy/core/parameterized.py +++ b/GPy/core/parameterized.py @@ -12,6 +12,7 @@ import transformations import itertools from re import compile, _pattern_type import re +from GPy.util.misc import fast_array_equal #=============================================================================== # Printing: @@ -81,7 +82,7 @@ class Parameterized(object): #=========================================================================== # Parameter connection for model creation: #=========================================================================== - def set_as_parameter(self, name, array, gradient, index=None, highest_parent=None): + def set_as_parameter(self, name, array, gradient, index=None, gradient_parent=None): """ :param name: name of the parameter (in print and plots), can be callable without parameters :type name: str, callable @@ -91,7 +92,7 @@ class Parameterized(object): :type gradient: callable :param index: (optional) index of the parameter when printing - (:param highest_parent: connect these parameters to this class, but tell + (:param gradient_parent: connect these parameters to this class, but tell updates to highest_parent, this is needed when parameterized classes contain parameterized classes, but want to access the parameters of their children) @@ -107,7 +108,7 @@ class Parameterized(object): self._parameters_.append(Param(name, array, gradient)) else: self._parameters_.insert(index, Param(name, array, gradient)) - self._connect_parameters(highest_parent=highest_parent) + self._connect_parameters(gradient_parent=gradient_parent) def set_as_parameters(self, *parameters, **kwargs): """ :param parameters: the parameters to add @@ -115,13 +116,13 @@ class Parameterized(object): Add all parameters to this parameter class, you can insert parameters - at any given point using the :py:func:`list.insert` syntax + at any given index using the :py:func:`list.insert` syntax """ if kwargs.get('index',None) is None: self._parameters_.extend(parameters) else: self._parameters_.insert(kwargs['index'], parameters) - self._connect_parameters(highest_parent=kwargs.get('highest_parent', self)) + self._connect_parameters(gradient_parent=kwargs.get('gradient_parent', self)) # def remove_parameter(self, *names_params_indices): # """ # :param names_params_indices: mix of parameter_names, parameter objects, or indices @@ -137,7 +138,7 @@ class Parameterized(object): def parameters_changed(self): # will be called as soon as paramters have changed pass - def _connect_parameters(self, highest_parent=None): + def _connect_parameters(self, gradient_parent=None): # connect parameterlist to this parameterized object # This just sets up the right connection for the params objects # to be used as parameters @@ -147,11 +148,20 @@ class Parameterized(object): sizes = numpy.cumsum([0] + self._parameter_sizes_) self._parameter_size_ = sizes[-1] self._param_slices_ = [slice(start, stop) for start,stop in zip(sizes, sizes[1:])] - for i, p in enumerate(self._parameters_): + i = 0 + for p in self._parameters_: + #if p._parent_ is None: p._parent_ = self p._parent_index_ = i - p._updates_parent_ = highest_parent or self + i += 1 + p._gradient_parent_ = gradient_parent or p._gradient_parent_ or self not_unique = [] +# for k,v in self.__dict__.iteritems(): +# try: +# if fast_array_equal(v,p): +# self.__dict__[k] = p +# except: # parameter comparison, just for convenience +# pass if p.name in self.__dict__: if p.base is self.__dict__[p.name] or p is self.__dict__[p.name]: self.__dict__[p.name] = p @@ -218,7 +228,6 @@ class Parameterized(object): #=========================================================================== def _get_param_names_transformed(self): return numpy.array([p.name+str(i) for p in self._parameters_ for i in p._indices()])[self._fixes_][0] - def _get_params(self): # don't overwrite this anymore! return numpy.hstack([x._get_params() for x in self._parameters_])#numpy.fromiter(itertools.chain(*itertools.imap(lambda x: x._get_params(), self._parameters_)), dtype=numpy.float64, count=sum(self._parameter_sizes_)) @@ -233,6 +242,7 @@ class Parameterized(object): return p[self._fixes_] return p def _set_params_transformed(self, p): + p = p.copy() if self._fixes_ is not None: tmp = self._get_params(); tmp[self._fixes_] = p; p = tmp; del tmp [numpy.put(p, ind, c.f(p[ind])) for c,ind in self._constraints_.iteritems() if c != __fixed__] self._set_params(p) @@ -338,13 +348,15 @@ class Parameterized(object): print "Warning: re-constraining parameters:\n{}".format(param._short()) return rav_i def _remove_constrain(self, param, *transforms, **kwargs): - if transforms is (): + if not transforms: transforms = self._constraints_.properties() removed_indices = numpy.array([]).astype(int) if "index" in kwargs: index = kwargs['index'] else: index = self._raveled_index_for(param) for constr in transforms: removed = self._constraints_.remove(constr, index) + if constr is __fixed__: + self._set_unfixed(removed) removed_indices = numpy.union1d(removed_indices, removed) return removed_indices # convienience for iterating over items