GPRegression working, gradients still todo

This commit is contained in:
Max Zwiessele 2013-10-22 16:16:54 +01:00
parent 9a70f27010
commit 27724fd456
3 changed files with 33 additions and 21 deletions

View file

@ -311,7 +311,7 @@ class Model(Parameterized):
the objective cannot be computed. the objective cannot be computed.
:param x: the parameters of the model. :param x: the parameters of the model.
:parameter type: np.array :type x: np.array
""" """
try: try:
self._set_params_transformed(x) 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. 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. :param x: the point at which gradients are to be computed.
:type np.array: :type x: np.array
""" """
try: try:

View file

@ -45,7 +45,7 @@ class Param(numpy.ndarray):
obj._name_ = name obj._name_ = name
obj._parent_ = None obj._parent_ = None
obj._parent_index_ = None obj._parent_index_ = None
obj._updates_parent_ = None obj._gradient_parent_ = None
obj._gradient_ = gradient obj._gradient_ = gradient
obj._current_slice_ = (slice(obj.shape[0]),) obj._current_slice_ = (slice(obj.shape[0]),)
obj._realshape_ = obj.shape obj._realshape_ = obj.shape
@ -72,7 +72,7 @@ class Param(numpy.ndarray):
self._realndim_ = getattr(obj, '_realndim_', None) self._realndim_ = getattr(obj, '_realndim_', None)
self._updated_ = getattr(obj, '_updated_', None) self._updated_ = getattr(obj, '_updated_', None)
self._original_ = getattr(obj, '_original_', 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): def __array_wrap__(self, out_arr, context=None):
return out_arr.view(numpy.ndarray) return out_arr.view(numpy.ndarray)
@ -85,7 +85,7 @@ class Param(numpy.ndarray):
(self._name_, (self._name_,
self._parent_, self._parent_,
self._parent_index_, self._parent_index_,
self._updates_parent_, self._gradient_parent_,
self._gradient_, self._gradient_,
self._current_slice_, self._current_slice_,
self._realshape_, self._realshape_,
@ -107,7 +107,7 @@ class Param(numpy.ndarray):
self._realshape_ = state.pop() self._realshape_ = state.pop()
self._current_slice_ = state.pop() self._current_slice_ = state.pop()
self._gradient_ = state.pop() self._gradient_ = state.pop()
self._updates_parent_ = state.pop() self._gradient_parent_ = state.pop()
self._parent_index_ = state.pop() self._parent_index_ = state.pop()
self._parent_ = state.pop() self._parent_ = state.pop()
self._name_ = 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_._get_original(self).__setitem__(self._current_slice_, transform.initialize(self), update=False)
self._parent_._add_constrain(self, transform, warning) self._parent_._add_constrain(self, transform, warning)
if update: if update:
self._updates_parent_.parameters_changed() self._parent_.parameters_changed()
def constrain_positive(self, warning=True): def constrain_positive(self, warning=True):
""" """
:param warning: print a warning if re-constraining parameters. :param warning: print a warning if re-constraining parameters.
@ -321,7 +321,7 @@ class Param(numpy.ndarray):
numpy.ndarray.__setitem__(self, s, val) numpy.ndarray.__setitem__(self, s, val)
self._fire_changed() self._fire_changed()
if update: if update:
self._updates_parent_.parameters_changed() self._parent_.parameters_changed()
#=========================================================================== #===========================================================================
# Index Operations: # Index Operations:
#=========================================================================== #===========================================================================
@ -467,7 +467,7 @@ class ParamConcatenation(object):
[numpy.place(p, ind[ps], vals[ps]) and p._fire_changed() [numpy.place(p, ind[ps], vals[ps]) and p._fire_changed()
for p, ps in zip(self.params, self._param_slices_)] for p, ps in zip(self.params, self._param_slices_)]
if update: if update:
self.params[0]._updates_parent_.parameters_changed() self.params[0]._parent_.parameters_changed()
def _vals(self): def _vals(self):
return numpy.hstack([p._get_params() for p in self.params]) 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): def constrain_bounded(self, lower, upper, warning=True):
[param.constrain_bounded(lower, upper, warning) for param in self.params] [param.constrain_bounded(lower, upper, warning) for param in self.params]
constrain_bounded.__doc__ = Param.constrain_bounded.__doc__ constrain_bounded.__doc__ = Param.constrain_bounded.__doc__
def unconstrain(self, constraints=None): def unconstrain(self, *constraints):
[param.unconstrain(constraints) for param in self.params] [param.unconstrain(*constraints) for param in self.params]
unconstrain.__doc__ = Param.unconstrain.__doc__ unconstrain.__doc__ = Param.unconstrain.__doc__
def unconstrain_negative(self): def unconstrain_negative(self):
[param.unconstrain_negative() for param in self.params] [param.unconstrain_negative() for param in self.params]

View file

@ -12,6 +12,7 @@ import transformations
import itertools import itertools
from re import compile, _pattern_type from re import compile, _pattern_type
import re import re
from GPy.util.misc import fast_array_equal
#=============================================================================== #===============================================================================
# Printing: # Printing:
@ -81,7 +82,7 @@ class Parameterized(object):
#=========================================================================== #===========================================================================
# Parameter connection for model creation: # 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 :param name: name of the parameter (in print and plots), can be callable without parameters
:type name: str, callable :type name: str, callable
@ -91,7 +92,7 @@ class Parameterized(object):
:type gradient: callable :type gradient: callable
:param index: (optional) index of the parameter when printing :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 updates to highest_parent, this is needed when parameterized classes
contain parameterized classes, but want to access the parameters contain parameterized classes, but want to access the parameters
of their children) of their children)
@ -107,7 +108,7 @@ class Parameterized(object):
self._parameters_.append(Param(name, array, gradient)) self._parameters_.append(Param(name, array, gradient))
else: else:
self._parameters_.insert(index, Param(name, array, gradient)) 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): def set_as_parameters(self, *parameters, **kwargs):
""" """
:param parameters: the parameters to add :param parameters: the parameters to add
@ -115,13 +116,13 @@ class Parameterized(object):
Add all parameters to this parameter class, you can insert parameters 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: if kwargs.get('index',None) is None:
self._parameters_.extend(parameters) self._parameters_.extend(parameters)
else: else:
self._parameters_.insert(kwargs['index'], parameters) 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): # def remove_parameter(self, *names_params_indices):
# """ # """
# :param names_params_indices: mix of parameter_names, parameter objects, or indices # :param names_params_indices: mix of parameter_names, parameter objects, or indices
@ -137,7 +138,7 @@ class Parameterized(object):
def parameters_changed(self): def parameters_changed(self):
# will be called as soon as paramters have changed # will be called as soon as paramters have changed
pass pass
def _connect_parameters(self, highest_parent=None): def _connect_parameters(self, gradient_parent=None):
# connect parameterlist to this parameterized object # connect parameterlist to this parameterized object
# This just sets up the right connection for the params objects # This just sets up the right connection for the params objects
# to be used as parameters # to be used as parameters
@ -147,11 +148,20 @@ class Parameterized(object):
sizes = numpy.cumsum([0] + self._parameter_sizes_) sizes = numpy.cumsum([0] + self._parameter_sizes_)
self._parameter_size_ = sizes[-1] self._parameter_size_ = sizes[-1]
self._param_slices_ = [slice(start, stop) for start,stop in zip(sizes, 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_ = self
p._parent_index_ = i 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 = [] 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.name in self.__dict__:
if p.base is self.__dict__[p.name] or p is self.__dict__[p.name]: if p.base is self.__dict__[p.name] or p is self.__dict__[p.name]:
self.__dict__[p.name] = p self.__dict__[p.name] = p
@ -218,7 +228,6 @@ class Parameterized(object):
#=========================================================================== #===========================================================================
def _get_param_names_transformed(self): 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] return numpy.array([p.name+str(i) for p in self._parameters_ for i in p._indices()])[self._fixes_][0]
def _get_params(self): def _get_params(self):
# don't overwrite this anymore! # 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_)) 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[self._fixes_]
return p return p
def _set_params_transformed(self, 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 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__] [numpy.put(p, ind, c.f(p[ind])) for c,ind in self._constraints_.iteritems() if c != __fixed__]
self._set_params(p) self._set_params(p)
@ -338,13 +348,15 @@ class Parameterized(object):
print "Warning: re-constraining parameters:\n{}".format(param._short()) print "Warning: re-constraining parameters:\n{}".format(param._short())
return rav_i return rav_i
def _remove_constrain(self, param, *transforms, **kwargs): def _remove_constrain(self, param, *transforms, **kwargs):
if transforms is (): if not transforms:
transforms = self._constraints_.properties() transforms = self._constraints_.properties()
removed_indices = numpy.array([]).astype(int) removed_indices = numpy.array([]).astype(int)
if "index" in kwargs: index = kwargs['index'] if "index" in kwargs: index = kwargs['index']
else: index = self._raveled_index_for(param) else: index = self._raveled_index_for(param)
for constr in transforms: for constr in transforms:
removed = self._constraints_.remove(constr, index) removed = self._constraints_.remove(constr, index)
if constr is __fixed__:
self._set_unfixed(removed)
removed_indices = numpy.union1d(removed_indices, removed) removed_indices = numpy.union1d(removed_indices, removed)
return removed_indices return removed_indices
# convienience for iterating over items # convienience for iterating over items