diff --git a/GPy/core/__init__.py b/GPy/core/__init__.py index 9813d5ae..37c95ee8 100644 --- a/GPy/core/__init__.py +++ b/GPy/core/__init__.py @@ -2,10 +2,10 @@ # Licensed under the BSD 3-clause license (see LICENSE.txt) from model import * -from parameterized import * -import priors +from parameterization import priors +from parameterization.parameterized import * from gp import GP from sparse_gp import SparseGP -from fitc import FITC +from ..inference.latent_function_inference.fitc import FITC from svigp import SVIGP from mapping import * diff --git a/GPy/core/gp_base.py b/GPy/core/gp_base.py index ce5cd311..445f9ea8 100644 --- a/GPy/core/gp_base.py +++ b/GPy/core/gp_base.py @@ -1,11 +1,15 @@ +# Copyright (c) 2012, GPy authors (see AUTHORS.txt). +# Licensed under the BSD 3-clause license (see LICENSE.txt) + import numpy as np import pylab as pb import warnings from .. import kern from ..util.plot import gpplot, Tango, x_frame1D, x_frame2D from model import Model -from parameter import ObservableArray +from parameterization import ObservableArray from .. import likelihoods +from GPy.likelihoods.gaussian import Gaussian class GPBase(Model): """ @@ -87,10 +91,10 @@ class GPBase(Model): :returns: Ysim: set of simulations, a Numpy array (N x samples). """ Ysim = self.posterior_samples_f(X, size, which_parts=which_parts, full_cov=full_cov) - if isinstance(self.likelihood,Gaussian): + if isinstance(self.likelihood, Gaussian): noise_std = np.sqrt(self.likelihood._get_params()) Ysim += np.random.normal(0,noise_std,Ysim.shape) - elif isinstance(self.likelihood,Gaussian_Mixed_Noise): + elif isinstance(self.likelihood, Gaussian_Mixed_Noise): assert noise_model is not None, "A noise model must be specified." noise_std = np.sqrt(self.likelihood._get_params()[noise_model]) Ysim += np.random.normal(0,noise_std,Ysim.shape) diff --git a/GPy/core/mapping.py b/GPy/core/mapping.py index 0da93c7c..82bf33ba 100644 --- a/GPy/core/mapping.py +++ b/GPy/core/mapping.py @@ -2,7 +2,7 @@ # Licensed under the BSD 3-clause license (see LICENSE.txt) from ..util.plot import Tango, x_frame1D, x_frame2D -from parameterized import Parameterized +from parameterization import Parameterized import numpy as np import pylab as pb diff --git a/GPy/core/model.py b/GPy/core/model.py index 16c4c21a..103d8ccf 100644 --- a/GPy/core/model.py +++ b/GPy/core/model.py @@ -6,14 +6,14 @@ from .. import likelihoods from ..inference import optimization from ..util.linalg import jitchol from ..util.misc import opt_wrapper -from parameterized import Parameterized, __fixed__ +from parameterization import Parameterized +from parameterization.parameterized import UNFIXED +from parameterization.domains import _POSITIVE, _REAL +from parameterization.index_operations import ParameterIndexOperations import multiprocessing as mp import numpy as np -from domains import _POSITIVE, _REAL from numpy.linalg.linalg import LinAlgError -from index_operations import ParameterIndexOperations import itertools -from GPy.core.parameterized import UNFIXED # import numdifftools as ndt class Model(Parameterized): @@ -161,21 +161,6 @@ class Model(Parameterized): [np.put(ret, i, p.lnpdf_grad(xx)) for i, (p, xx) in enumerate(zip(self.priors, x)) if not p is None] return ret - -# def _transform_gradients(self, g): -# x = self._get_params() -# for constraint, index in self.constraints.iteritems(): -# if constraint != __fixed__: -# g[index] = g[index] * constraint.gradfactor(x[index]) -# #[np.put(g, i, v) for i, v in [(t[0], np.sum(g[t])) for t in self.tied_indices]] -# [np.put(g, i, v) for i, v in [[i, t.sum()] for p in self.flattened_parameters for t,i in p._tied_to_me_.iteritems()]] -# # 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: -# if self._fixes_ is not None: return g[self._fixes_] -# return g - def randomize(self): """ Randomize the model. diff --git a/GPy/core/parameterization/__init__.py b/GPy/core/parameterization/__init__.py new file mode 100644 index 00000000..ccbac39d --- /dev/null +++ b/GPy/core/parameterization/__init__.py @@ -0,0 +1,5 @@ +# Copyright (c) 2012, GPy authors (see AUTHORS.txt). +# Licensed under the BSD 3-clause license (see LICENSE.txt) + +from param import Param, ObservableArray +from parameterized import Parameterized diff --git a/GPy/core/parameterization/array_core.py b/GPy/core/parameterization/array_core.py new file mode 100644 index 00000000..d73eed78 --- /dev/null +++ b/GPy/core/parameterization/array_core.py @@ -0,0 +1,50 @@ +# Copyright (c) 2012, GPy authors (see AUTHORS.txt). +# Licensed under the BSD 3-clause license (see LICENSE.txt) + +__updated__ = '2013-12-16' + +import numpy as np +from parameter_core import Observable + +class ListArray(np.ndarray): + """ + ndarray which can be stored in lists and checked if it is in. + WARNING: This overrides the functionality of x==y!!! + Use numpy.equal(x,y) for element-wise equality testing. + """ + def __new__(cls, input_array): + obj = np.asanyarray(input_array).view(cls) + return obj + def __eq__(self, other): + return other is self + +class ObservableArray(ListArray, Observable): + """ + An ndarray which reports changes to its observers. + The observers can add themselves with a callable, which + will be called every time this array changes. The callable + takes exactly one argument, which is this array itself. + """ + def __new__(cls, input_array): + obj = super(ObservableArray, cls).__new__(cls, input_array).view(cls) + obj._observers_ = {} + return obj + def __array_finalize__(self, obj): + # see InfoArray.__array_finalize__ for comments + if obj is None: return + self._observers_ = getattr(obj, '_observers_', None) + def __setitem__(self, s, val, update=True): + if self.ndim: + if not np.all(np.equal(self[s], val)): + super(ObservableArray, self).__setitem__(s, val) + if update: + self._notify_observers() + else: + if not np.all(np.equal(self, val)): + super(ObservableArray, self).__setitem__(Ellipsis, val) + if update: + self._notify_observers() + def __getslice__(self, start, stop): + return self.__getitem__(slice(start, stop)) + def __setslice__(self, start, stop, val): + return self.__setitem__(slice(start, stop), val) \ No newline at end of file diff --git a/GPy/core/domains.py b/GPy/core/parameterization/domains.py similarity index 100% rename from GPy/core/domains.py rename to GPy/core/parameterization/domains.py diff --git a/GPy/core/index_operations.py b/GPy/core/parameterization/index_operations.py similarity index 98% rename from GPy/core/index_operations.py rename to GPy/core/parameterization/index_operations.py index ea7dfe2d..99b5a4de 100644 --- a/GPy/core/index_operations.py +++ b/GPy/core/parameterization/index_operations.py @@ -5,7 +5,7 @@ Created on Oct 2, 2013 ''' import numpy from numpy.lib.function_base import vectorize -from parameter import Param +from param import Param from collections import defaultdict class ParamDict(defaultdict): @@ -49,13 +49,13 @@ class IntArrayDict(ParamDict): class ParameterIndexOperations(object): ''' - Index operations for storing parameter index _properties + Index operations for storing param index _properties This class enables index with slices retrieved from object.__getitem__ calls. Adding an index will add the selected indexes by the slice of an indexarray indexing a shape shaped array to the flattened index array. Remove will remove the selected slice indices from the flattened array. You can give an offset to set an offset for the given indices in the - index array, for multi-parameter handling. + index array, for multi-param handling. ''' def __init__(self): self._properties = ParamDict() diff --git a/GPy/core/parameter.py b/GPy/core/parameterization/param.py similarity index 84% rename from GPy/core/parameter.py rename to GPy/core/parameterization/param.py index ae7061e8..1942c88a 100644 --- a/GPy/core/parameter.py +++ b/GPy/core/parameterization/param.py @@ -1,13 +1,10 @@ -''' -Created on 4 Sep 2013 +# Copyright (c) 2012, GPy authors (see AUTHORS.txt). +# Licensed under the BSD 3-clause license (see LICENSE.txt) -@author: maxz -''' import itertools import numpy -from transformations import Logexp, NegativeLogexp, Logistic -from parameterized import Nameable, Pickleable, Observable, Parentable -from parameterized import _adjust_name_for_printing +from parameter_core import Constrainable, adjust_name_for_printing +from array_core import ObservableArray ###### printing __constraints_name__ = "Constraint" @@ -15,132 +12,7 @@ __index_name__ = "Index" __tie_name__ = "Tied to" __precision__ = numpy.get_printoptions()['precision'] # numpy printing precision used, sublassing numpy ndarray after all __print_threshold__ = 5 -###### - -class ListArray(numpy.ndarray): - """ - ndarray which can be stored in lists and checked if it is in. - WARNING: This overrides the functionality of x==y!!! - Use numpy.equal(x,y) for element-wise equality testing. - """ - def __new__(cls, input_array): - obj = numpy.asanyarray(input_array).view(cls) - return obj - def __eq__(self, other): - return other is self - -class ObservableArray(ListArray, Observable): - """ - An ndarray which reports changes to its observers. - The observers can add themselves with a callable, which - will be called every time this array changes. The callable - takes exactly one argument, which is this array itself. - """ - def __new__(cls, input_array): - obj = super(ObservableArray, cls).__new__(cls, input_array).view(cls) - obj._observers_ = {} - return obj - def __array_finalize__(self, obj): - # see InfoArray.__array_finalize__ for comments - if obj is None: return - self._observers_ = getattr(obj, '_observers_', None) - def __setitem__(self, s, val, update=True): - if self.ndim: - if not numpy.all(numpy.equal(self[s], val)): - super(ObservableArray, self).__setitem__(s, val) - if update: - self._notify_observers() - else: - if not numpy.all(numpy.equal(self, val)): - super(ObservableArray, self).__setitem__(Ellipsis, val) - if update: - self._notify_observers() - def __getslice__(self, start, stop): - return self.__getitem__(slice(start, stop)) - def __setslice__(self, start, stop, val): - return self.__setitem__(slice(start, stop), val) - -class Constrainable(Nameable): - def __init__(self, name): - super(Constrainable,self).__init__(name) - #=========================================================================== - # Constrain operations -> done - #=========================================================================== - def constrain(self, transform, warning=True, update=True): - """ - :param transform: the :py:class:`GPy.core.transformations.Transformation` - to constrain the this parameter to. - :param warning: print a warning if re-constraining parameters. - - Constrain the parameter to the given - :py:class:`GPy.core.transformations.Transformation`. - """ - if self.has_parent(): - self._highest_parent_._add_constrain(self, transform, warning) - if update: - self._highest_parent_.parameters_changed() - else: - for p in self._parameters_: - self._add_constrain(p, transform, warning) - if update: - self.parameters_changed() - def constrain_positive(self, warning=True): - """ - :param warning: print a warning if re-constraining parameters. - - Constrain this parameter to the default positive constraint. - """ - self.constrain(Logexp(), warning) - - def constrain_negative(self, warning=True): - """ - :param warning: print a warning if re-constraining parameters. - - Constrain this parameter to the default negative constraint. - """ - self.constrain(NegativeLogexp(), warning) - - def constrain_bounded(self, lower, upper, warning=True): - """ - :param lower, upper: the limits to bound this parameter to - :param warning: print a warning if re-constraining parameters. - - Constrain this parameter to lie within the given range. - """ - self.constrain(Logistic(lower, upper), warning) - - def unconstrain(self, *transforms): - """ - :param transforms: The transformations to unconstrain from. - - remove all :py:class:`GPy.core.transformations.Transformation` - transformats of this parameter object. - """ - if self.has_parent(): - self._highest_parent_._remove_constrain(self, *transforms) - else: - for p in self._parameters_: - self._remove_constrain(p, *transforms) - - def unconstrain_positive(self): - """ - Remove positive constraint of this parameter. - """ - self.unconstrain(Logexp()) - - def unconstrain_negative(self): - """ - Remove negative constraint of this parameter. - """ - self.unconstrain(NegativeLogexp()) - - def unconstrain_bounded(self, lower, upper): - """ - :param lower, upper: the limits to unbound this parameter from - - Remove (lower, upper) bounded constrain from this parameter/ - """ - self.unconstrain(Logistic(lower, upper)) +###### class Float(numpy.float64, Constrainable): def __init__(self, f, base): @@ -523,8 +395,8 @@ class Param(ObservableArray, Constrainable): @property def name_hirarchical(self): if self.has_parent(): - return self._direct_parent_.hirarchy_name()+_adjust_name_for_printing(self.name) - return _adjust_name_for_printing(self.name) + return self._direct_parent_.hirarchy_name()+adjust_name_for_printing(self.name) + return adjust_name_for_printing(self.name) def __repr__(self, *args, **kwargs): name = "\033[1m{x:s}\033[0;0m:\n".format( x=self.name_hirarchical) @@ -564,7 +436,7 @@ class Param(ObservableArray, Constrainable): return reduce(lambda a, b:max(a, len(str(b))), ind, len(__index_name__)) def _short(self): # short string to print - name = self._direct_parent_.hirarchy_name() + _adjust_name_for_printing(self.name) + name = self._direct_parent_.hirarchy_name() + adjust_name_for_printing(self.name) if self._realsize_ < 2: return name ind = self._indices() diff --git a/GPy/core/parameterization/parameter_core.py b/GPy/core/parameterization/parameter_core.py new file mode 100644 index 00000000..40e76818 --- /dev/null +++ b/GPy/core/parameterization/parameter_core.py @@ -0,0 +1,155 @@ +# Copyright (c) 2012, GPy authors (see AUTHORS.txt). +# Licensed under the BSD 3-clause license (see LICENSE.txt) + +from transformations import Logexp, NegativeLogexp, Logistic + +__updated__ = '2013-12-16' + +def adjust_name_for_printing(name): + if name is not None: + return name.replace(" ", "_").replace(".", "_").replace("-","").replace("+","").replace("!","").replace("*","").replace("/","") + return '' + +class Observable(object): + _observers_ = {} + def add_observer(self, observer, callble): + self._observers_[observer] = callble + callble(self) + def remove_observer(self, observer): + del self._observers_[observer] + def _notify_observers(self): + [callble(self) for callble in self._observers_.itervalues()] + +class Pickleable(object): + def getstate(self): + """ + Returns the state of this class in a memento pattern. + The state must be a list-like structure of all the fields + this class needs to run. + + See python doc "pickling" (`__getstate__` and `__setstate__`) for details. + """ + raise NotImplementedError, "To be able to use pickling you need to implement this method" + def setstate(self, state): + """ + Set the state (memento pattern) of this class to the given state. + Usually this is just the counterpart to getstate, such that + an object is a copy of another when calling + + copy = .__new__(*args,**kw).setstate(.getstate()) + + See python doc "pickling" (`__getstate__` and `__setstate__`) for details. + """ + raise NotImplementedError, "To be able to use pickling you need to implement this method" + +#=============================================================================== +# Foundation framework for parameterized and param objects: +#=============================================================================== + +class Parentable(object): + def __init__(self, direct_parent=None, highest_parent=None, parent_index=None): + super(Parentable,self).__init__() + self._direct_parent_ = direct_parent + self._parent_index_ = parent_index + self._highest_parent_ = highest_parent + + def has_parent(self): + return self._direct_parent_ is not None + +class Nameable(Parentable): + _name = None + def __init__(self, name, direct_parent=None, highest_parent=None, parent_index=None): + super(Nameable,self).__init__(direct_parent, highest_parent, parent_index) + self._name = name or self.__class__.__name__ + + @property + def name(self): + return self._name + @name.setter + def name(self, name): + from_name = self.name + self._name = name + if self.has_parent(): + self._direct_parent_._name_changed(self, from_name) + +class Constrainable(Nameable): + def __init__(self, name): + super(Constrainable,self).__init__(name) + #=========================================================================== + # Constrain operations -> done + #=========================================================================== + def constrain(self, transform, warning=True, update=True): + """ + :param transform: the :py:class:`GPy.core.transformations.Transformation` + to constrain the this parameter to. + :param warning: print a warning if re-constraining parameters. + + Constrain the parameter to the given + :py:class:`GPy.core.transformations.Transformation`. + """ + if self.has_parent(): + self._highest_parent_._add_constrain(self, transform, warning) + if update: + self._highest_parent_.parameters_changed() + else: + for p in self._parameters_: + self._add_constrain(p, transform, warning) + if update: + self.parameters_changed() + def constrain_positive(self, warning=True): + """ + :param warning: print a warning if re-constraining parameters. + + Constrain this parameter to the default positive constraint. + """ + self.constrain(Logexp(), warning) + + def constrain_negative(self, warning=True): + """ + :param warning: print a warning if re-constraining parameters. + + Constrain this parameter to the default negative constraint. + """ + self.constrain(NegativeLogexp(), warning) + + def constrain_bounded(self, lower, upper, warning=True): + """ + :param lower, upper: the limits to bound this parameter to + :param warning: print a warning if re-constraining parameters. + + Constrain this parameter to lie within the given range. + """ + self.constrain(Logistic(lower, upper), warning) + + def unconstrain(self, *transforms): + """ + :param transforms: The transformations to unconstrain from. + + remove all :py:class:`GPy.core.transformations.Transformation` + transformats of this parameter object. + """ + if self.has_parent(): + self._highest_parent_._remove_constrain(self, *transforms) + else: + for p in self._parameters_: + self._remove_constrain(p, *transforms) + + def unconstrain_positive(self): + """ + Remove positive constraint of this parameter. + """ + self.unconstrain(Logexp()) + + def unconstrain_negative(self): + """ + Remove negative constraint of this parameter. + """ + self.unconstrain(NegativeLogexp()) + + def unconstrain_bounded(self, lower, upper): + """ + :param lower, upper: the limits to unbound this parameter from + + Remove (lower, upper) bounded constrain from this parameter/ + """ + self.unconstrain(Logistic(lower, upper)) diff --git a/GPy/core/parameterized.py b/GPy/core/parameterization/parameterized.py similarity index 85% rename from GPy/core/parameterized.py rename to GPy/core/parameterization/parameterized.py index bff75fbb..f2905ba3 100644 --- a/GPy/core/parameterized.py +++ b/GPy/core/parameterization/parameterized.py @@ -5,74 +5,10 @@ import numpy; np = numpy import copy import cPickle -import transformations import itertools from re import compile, _pattern_type -import re - -class Parentable(object): - def __init__(self, direct_parent=None, highest_parent=None, parent_index=None): - super(Parentable,self).__init__() - self._direct_parent_ = direct_parent - self._parent_index_ = parent_index - self._highest_parent_ = highest_parent - - def has_parent(self): - return self._direct_parent_ is not None - -class Nameable(Parentable): - _name = None - def __init__(self, name, direct_parent=None, highest_parent=None, parent_index=None): - super(Nameable,self).__init__(direct_parent, highest_parent, parent_index) - self._name = name or self.__class__.__name__ - - @property - def name(self): - return self._name - @name.setter - def name(self, name): - from_name = self.name - self._name = name - if self.has_parent(): - self._direct_parent_._name_changed(self, from_name) - -class Pickleable(object): - def getstate(self): - """ - Returns the state of this class in a memento pattern. - The state must be a list-like structure of all the fields - this class needs to run. - - See python doc "pickling" (`__getstate__` and `__setstate__`) for details. - """ - raise NotImplementedError, "To be able to use pickling you need to implement this method" - def setstate(self, state): - """ - Set the state (memento pattern) of this class to the given state. - Usually this is just the counterpart to getstate, such that - an object is a copy of another when calling - - copy = .__new__(*args,**kw).setstate(.getstate()) - - See python doc "pickling" (`__getstate__` and `__setstate__`) for details. - """ - raise NotImplementedError, "To be able to use pickling you need to implement this method" - -class Observable(object): - _observers_ = {} - def add_observer(self, observer, callble): - self._observers_[observer] = callble - callble(self) - def remove_observer(self, observer): - del self._observers_[observer] - def _notify_observers(self): - [callble(self) for callble in self._observers_.itervalues()] - -def _adjust_name_for_printing(name): - if name is not None: - return name.replace(" ", "_").replace(".", "_").replace("-","").replace("+","").replace("!","").replace("*","").replace("/","") - return '' -from parameter import ParamConcatenation, Param, Constrainable +from param import ParamConcatenation, Param +from parameter_core import Constrainable, Pickleable, Observable, adjust_name_for_printing from index_operations import ParameterIndexOperations,\ index_empty @@ -96,35 +32,35 @@ class Parameterized(Constrainable, Pickleable, Observable): Printing parameters: - print m: prints a nice summary over all parameters - - print m.name: prints details for parameter with name 'name' + - print m.name: prints details for param with name 'name' - print m[regexp]: prints details for all the parameters which match (!) regexp - print m['']: prints details for all parameters Fields: - Name: The name of the parameter, can be renamed! + Name: The name of the param, can be renamed! Value: Shape or value, if one-valued - Constrain: constraint of the parameter, curly "{c}" brackets indicate + Constrain: constraint of the param, curly "{c}" brackets indicate some parameters are constrained by c. See detailed print to get exact constraints. Tied_to: which paramter it is tied to. Getting and setting parameters: - Set all values in parameter to one: + Set all values in param to one: - m.name.to.parameter = 1 + m.name.to.param = 1 Handling of constraining, fixing and tieing parameters: - You can constrain parameters by calling the constrain on the parameter itself, e.g: + You can constrain parameters by calling the constrain on the param itself, e.g: - m.name[:,1].constrain_positive() - m.name[0].tie_to(m.name[1]) Fixing parameters will fix them to the value they are right now. If you change - the parameters value, the parameter will be fixed to the new value! + the parameters value, the param will be fixed to the new value! If you want to operate on all parameters use m[''] to wildcard select all paramters and concatenate them. Printing m[''] will result in printing of all parameters in detail. @@ -153,13 +89,13 @@ class Parameterized(Constrainable, Pickleable, Observable): #=========================================================================== # 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 param (in print and plots), can be callable without parameters # :type name: str, callable -# :param array: array which the parameter consists of +# :param array: array which the param consists of # :type array: array-like -# :param gradient: gradient method of the parameter +# :param gradient: gradient method of the param # :type gradient: callable -# :param index: (optional) index of the parameter when printing +# :param index: (optional) index of the param when printing # # (:param gradient_parent: connect these parameters to this class, but tell # updates to highest_parent, this is needed when parameterized classes @@ -167,11 +103,11 @@ class Parameterized(Constrainable, Pickleable, Observable): # of their children) # # -# Set array (e.g. self.X) as parameter with name and gradient. +# Set array (e.g. self.X) as param with name and gradient. # I.e: self.set_as_parameter('curvature', self.lengthscale, self.dK_dlengthscale) # # Note: the order in which parameters are added can be adjusted by -# giving an index, of where to put this parameter in printing +# giving an index, of where to put this param in printing # """ # if index is None: # self._parameters_.append(Param(name, array, gradient)) @@ -182,63 +118,63 @@ class Parameterized(Constrainable, Pickleable, Observable): def _has_fixes(self): return hasattr(self, "_fixes_") and self._fixes_ is not None - def add_parameter(self, parameter, gradient=None, index=None): + def add_parameter(self, param, gradient=None, index=None): """ :param parameters: the parameters to add - :type parameters: list of or one :py:class:`GPy.core.parameter.Param` - :param [gradients]: gradients for each parameter, - one gradient per parameter + :type parameters: list of or one :py:class:`GPy.core.param.Param` + :param [gradients]: gradients for each param, + one gradient per param :param [index]: index of where to put parameters - Add all parameters to this parameter class, you can insert parameters + Add all parameters to this param class, you can insert parameters at any given index using the :func:`list.insert` syntax """ - if parameter in self._parameters_ and index is not None: + if param in self._parameters_ and index is not None: # make sure fixes and constraints are indexed right if self._has_fixes(): - param_slice = slice(self._offset_for(parameter),self._offset_for(parameter)+parameter.size) + param_slice = slice(self._offset_for(param),self._offset_for(param)+param.size) dest_index = sum((p.size for p in self._parameters_[:index])) - dest_slice = slice(dest_index,dest_index+parameter.size) + dest_slice = slice(dest_index,dest_index+param.size) fixes_param = self._fixes_[param_slice].copy() self._fixes_[param_slice] = self._fixes_[dest_slice] self._fixes_[dest_slice] = fixes_param - del self._parameters_[parameter._parent_index_] - self._parameters_.insert(index, parameter) - elif parameter not in self._parameters_: + del self._parameters_[param._parent_index_] + self._parameters_.insert(index, param) + elif param not in self._parameters_: # make sure the size is set if not hasattr(self, 'size'): self.size = sum(p.size for p in self._parameters_) if index is None: - self._parameters_.append(parameter) + self._parameters_.append(param) # make sure fixes and constraints are indexed right - if parameter._has_fixes(): fixes_param = parameter._fixes_.copy() - else: fixes_param = numpy.ones(parameter.size, dtype=bool) + if param._has_fixes(): fixes_param = param._fixes_.copy() + else: fixes_param = numpy.ones(param.size, dtype=bool) if self._has_fixes(): self._fixes_ = np.r_[self._fixes_, fixes_param] - elif parameter._has_fixes(): self._fixes_ = np.r_[np.ones(self.size, dtype=bool), fixes_param] + elif param._has_fixes(): self._fixes_ = np.r_[np.ones(self.size, dtype=bool), fixes_param] else: - self._parameters_.insert(index, parameter) + self._parameters_.insert(index, param) # make sure fixes and constraints are indexed right - if parameter._has_fixes(): fixes_param = parameter._fixes_.copy() - else: fixes_param = numpy.ones(parameter.size, dtype=bool) + if param._has_fixes(): fixes_param = param._fixes_.copy() + else: fixes_param = numpy.ones(param.size, dtype=bool) ins = sum((p.size for p in self._parameters_[:index])) if self._has_fixes(): self._fixes_ = np.r_[self._fixes_[:ins], fixes_param, self._fixes[ins:]] elif not np.all(fixes_param): - self._fixes_ = np.ones(self.size+parameter.size, dtype=bool) - self._fixes_[ins:ins+parameter.size] = fixes_param - self.size += parameter.size + self._fixes_ = np.ones(self.size+param.size, dtype=bool) + self._fixes_[ins:ins+param.size] = fixes_param + self.size += param.size if gradient: - self.gradient_mapping[parameter] = gradient + self.gradient_mapping[param] = gradient self._connect_parameters() # make sure the constraints are pulled over: - if hasattr(parameter, "_constraints_") and parameter._constraints_ is not None: - for t, ind in parameter._constraints_.iteritems(): - self.constraints.add(t, ind+self._offset_for(parameter)) - parameter._constraints_.clear() + if hasattr(param, "_constraints_") and param._constraints_ is not None: + for t, ind in param._constraints_.iteritems(): + self.constraints.add(t, ind+self._offset_for(param)) + param._constraints_.clear() if self._has_fixes() and np.all(self._fixes_): # ==UNFIXED self._fixes_= None @@ -251,8 +187,8 @@ class Parameterized(Constrainable, Pickleable, Observable): def remove_parameter(self, *names_params_indices): """ - :param names_params_indices: mix of parameter_names, parameter objects, or indices - to remove from being a parameter of this parameterized object. + :param names_params_indices: mix of parameter_names, param objects, or indices + to remove from being a param of this parameterized object. note: if it is a string object it will not (!) be regexp-matched automatically. @@ -266,9 +202,9 @@ class Parameterized(Constrainable, Pickleable, Observable): def parameters_changed(self): """ This method gets called when parameters have changed. - Another way of listening to parameter changes is to - add self as a listener to the parameter, such that - updates get passed through. See :py:function:``GPy.core.parameter.Observable.add_observer`` + Another way of listening to param changes is to + add self as a listener to the param, such that + updates get passed through. See :py:function:``GPy.core.param.Observable.add_observer`` """ # will be called as soon as paramters have changed pass @@ -292,7 +228,7 @@ class Parameterized(Constrainable, Pickleable, Observable): not_unique = [] sizes.append(p.size+sizes[-1]) self._param_slices_.append(slice(sizes[-2], sizes[-1])) - pname = _adjust_name_for_printing(p.name) + pname = adjust_name_for_printing(p.name) # and makes sure to not delete programmatically added parameters if pname in self.__dict__: if isinstance(self.__dict__[pname], (Parameterized, Param)): @@ -404,7 +340,7 @@ class Parameterized(Constrainable, Pickleable, Observable): if hasattr(self, old_name) and old_name in self._added_names_: delattr(self, old_name) self._added_names_.remove(old_name) - pname = _adjust_name_for_printing(param.name) + pname = adjust_name_for_printing(param.name) if pname not in self.__dict__: self._added_names_.add(pname) self.__dict__[pname] = param @@ -428,9 +364,9 @@ class Parameterized(Constrainable, Pickleable, Observable): def _raveled_index_for(self, param): """ - get the raveled index for a parameter + get the raveled index for a param that is an int array, containing the indexes for the flattened - parameter inside this parameterized logic. + param inside this parameterized logic. """ return param._raveled_index() + self._offset_for(param) @@ -477,10 +413,10 @@ class Parameterized(Constrainable, Pickleable, Observable): f = self._remove_constrain(param, __fixed__) self._set_unfixed(f) #=========================================================================== - # Convenience for fixed, tied checking of parameter: + # Convenience for fixed, tied checking of param: #=========================================================================== def _is_fixed(self, param): - # returns if the whole parameter is fixed + # returns if the whole param is fixed if not self._has_fixes(): return False return not self._fixes_[self._raveled_index_for(param)].any() @@ -492,12 +428,12 @@ class Parameterized(Constrainable, Pickleable, Observable): return True def _get_original(self, param): # if advanced indexing is activated it happens that the array is a copy - # you can retrieve the original parameter through this method, by passing + # you can retrieve the original param through this method, by passing # the copy here return self._parameters_[param._parent_index_] def hirarchy_name(self): if self.has_parent(): - return self._direct_parent_.hirarchy_name() + _adjust_name_for_printing(self.name) + "." + return self._direct_parent_.hirarchy_name() + adjust_name_for_printing(self.name) + "." return '' #=========================================================================== # Constraint Handling: @@ -540,7 +476,7 @@ class Parameterized(Constrainable, Pickleable, Observable): for _, ind in self._constraints_iter_items(param): yield ind def _constraint_indices(self, param, constraint): - # indices in model range for parameter and constraint + # indices in model range for param and constraint return self._backtranslate_index(param, self.constraints[constraint]) + self._offset_for(param) def _constraints_for(self, param, rav_index): # constraint for param given its internal rav_index @@ -592,7 +528,7 @@ class Parameterized(Constrainable, Pickleable, Observable): # except AttributeError: # raise AttributeError, a.message, tb def __setattr__(self, name, val): - # override the default behaviour, if setting a parameter, so broadcasting can by used + # override the default behaviour, if setting a param, so broadcasting can by used if hasattr(self, "_parameters_"): paramlist = self.grep_param_names(name) if len(paramlist) == 1: self.__setitem__(name, val, paramlist); return @@ -603,12 +539,12 @@ class Parameterized(Constrainable, Pickleable, Observable): def _short(self): # short string to print if self.has_parent(): - return self._direct_parent_.hirarchy_name() + _adjust_name_for_printing(self.name) + return self._direct_parent_.hirarchy_name() + adjust_name_for_printing(self.name) else: - return _adjust_name_for_printing(self.name) + return adjust_name_for_printing(self.name) def _parameter_names(self, add_name=False): if add_name: - return [_adjust_name_for_printing(self.name) + "." + xi for x in self._parameters_ for xi in x._parameter_names(add_name=True)] + return [adjust_name_for_printing(self.name) + "." + xi for x in self._parameters_ for xi in x._parameter_names(add_name=True)] return [xi for x in self._parameters_ for xi in x._parameter_names(add_name=True)] parameter_names = property(_parameter_names, doc="Names for all parameters handled by this parameterization object -- will add hirarchy name entries for printing") @property @@ -636,7 +572,7 @@ class Parameterized(Constrainable, Pickleable, Observable): return [','.join(x._ties_str) for x in self.flattened_parameters] def __str__(self, header=True): - name = _adjust_name_for_printing(self.name) + "." + name = adjust_name_for_printing(self.name) + "." constrs = self._constraints_str; ts = self._ties_str desc = self._description_str; names = self.parameter_names nl = max([len(str(x)) for x in names + [name]]) @@ -731,7 +667,7 @@ class Parameterized(Constrainable, Pickleable, Observable): # # def __getitem__(self, regexp, return_names=False): # """ -# Get a model parameter by name. The name is applied as a regular +# Get a model param by name. The name is applied as a regular # expression and all parameters that match that regular expression are # returned. # """ @@ -742,11 +678,11 @@ class Parameterized(Constrainable, Pickleable, Observable): # else: # return self._get_params()[matches] # else: -# raise AttributeError, "no parameter matches %s" % regexp +# raise AttributeError, "no param matches %s" % regexp # # def __setitem__(self, name, val): # """ -# Set model parameter(s) by name. The name is provided as a regular +# Set model param(s) by name. The name is provided as a regular # expression. All parameters matching that regular expression are set to # the given value. # """ @@ -758,7 +694,7 @@ class Parameterized(Constrainable, Pickleable, Observable): # x[matches] = val # self._set_params(x) # else: -# raise AttributeError, "no parameter matches %s" % name +# raise AttributeError, "no param matches %s" % name # # def tie_params(self, regexp): # """ @@ -781,7 +717,7 @@ class Parameterized(Constrainable, Pickleable, Observable): # # def grep_param_names(self, regexp, transformed=False, search=False): # """ -# :param regexp: regular expression to select parameter parameter_names +# :param regexp: regular expression to select param parameter_names # :type regexp: re | str | int # :rtype: the indices of self._get_param_names which match the regular expression. # @@ -884,14 +820,14 @@ class Parameterized(Constrainable, Pickleable, Observable): # :param regexp: which parameters need to be fixed. # :type regexp: ndarray(dtype=int) or regular expression object or string # :param value: the vlaue to fix the parameters to. If the value is not specified, -# the parameter is fixed to the current value +# the param is fixed to the current value # :type value: float # # **Notes** # -# Fixing a parameter which is tied to another, or constrained in some way will result in an error. +# Fixing a param which is tied to another, or constrained in some way will result in an error. # -# To fix multiple parameters to the same value, simply pass a regular expression which matches both parameter parameter_names, or pass both of the indexes. +# To fix multiple parameters to the same value, simply pass a regular expression which matches both param parameter_names, or pass both of the indexes. # # """ # matches = self.grep_param_names(regexp) @@ -933,7 +869,7 @@ class Parameterized(Constrainable, Pickleable, Observable): # The Transformation required for _set_params_transformed. # # This moves the vector x seen by the optimiser (unconstrained) to the -# valid parameter vector seen by the model +# valid param vector seen by the model # # Note: # - This function is separate from _set_params_transformed for downstream flexibility @@ -963,12 +899,12 @@ class Parameterized(Constrainable, Pickleable, Observable): # # def _get_param_names_transformed(self): # """ -# Returns the parameter parameter_names as propagated after constraining, +# Returns the param parameter_names as propagated after constraining, # tying or fixing, i.e. a list of the same length as _get_params_transformed() # """ # n = self._get_param_names() # -# # remove/concatenate the tied parameter parameter_names +# # remove/concatenate the tied param parameter_names # if len(self.tied_indices): # for t in self.tied_indices: # n[t[0]] = "".join([n[tt] for tt in t]) @@ -996,7 +932,7 @@ class Parameterized(Constrainable, Pickleable, Observable): # #def __str__(self, parameter_names=None, nw=30): # def __str__(self, nw=30): # """ -# Return a string describing the parameter parameter_names and their ties and constraints +# Return a string describing the param parameter_names and their ties and constraints # """ # parameter_names = self._get_param_names() # #if parameter_names is None: diff --git a/GPy/core/priors.py b/GPy/core/parameterization/priors.py similarity index 99% rename from GPy/core/priors.py rename to GPy/core/parameterization/priors.py index 864c2587..9614ca53 100644 --- a/GPy/core/priors.py +++ b/GPy/core/parameterization/priors.py @@ -5,8 +5,8 @@ import numpy as np import pylab as pb from scipy.special import gammaln, digamma -from ..util.linalg import pdinv -from GPy.core.domains import _REAL, _POSITIVE +from ...util.linalg import pdinv +from domains import _REAL, _POSITIVE import warnings import weakref diff --git a/GPy/core/transformations.py b/GPy/core/parameterization/transformations.py similarity index 99% rename from GPy/core/transformations.py rename to GPy/core/parameterization/transformations.py index 44aba9e3..fd2c3ee5 100644 --- a/GPy/core/transformations.py +++ b/GPy/core/parameterization/transformations.py @@ -3,7 +3,7 @@ import numpy as np -from GPy.core.domains import _POSITIVE,_NEGATIVE, _BOUNDED +from domains import _POSITIVE,_NEGATIVE, _BOUNDED import sys import weakref _lim_val = -np.log(sys.float_info.epsilon) diff --git a/GPy/core/variational.py b/GPy/core/parameterization/variational.py similarity index 97% rename from GPy/core/variational.py rename to GPy/core/parameterization/variational.py index 510d36da..e7119445 100644 --- a/GPy/core/variational.py +++ b/GPy/core/parameterization/variational.py @@ -5,8 +5,8 @@ Created on 6 Nov 2013 ''' import numpy as np from parameterized import Parameterized -from parameter import Param -from ..util.misc import param_to_array +from param import Param +from ...util.misc import param_to_array class Normal(Parameterized): ''' diff --git a/GPy/core/sparse_gp.py b/GPy/core/sparse_gp.py index 2d15ff0c..6c4da1af 100644 --- a/GPy/core/sparse_gp.py +++ b/GPy/core/sparse_gp.py @@ -3,10 +3,9 @@ import numpy as np import pylab as pb -from ..util.linalg import mdot, jitchol, tdot, symmetrify, backsub_both_sides, chol_inv, dtrtrs, dpotrs, dpotri -from scipy import linalg +from ..util.linalg import mdot, tdot, symmetrify, backsub_both_sides, chol_inv, dtrtrs, dpotrs, dpotri from gp_base import GPBase -from GPy.core.parameter import Param +from GPy.core import Param class SparseGP(GPBase): """ diff --git a/GPy/core/svigp.py b/GPy/core/svigp.py index 5d47611e..95c3b592 100644 --- a/GPy/core/svigp.py +++ b/GPy/core/svigp.py @@ -3,10 +3,8 @@ import numpy as np import pylab as pb -from .. import kern from ..util.linalg import pdinv, mdot, tdot, dpotrs, dtrtrs, jitchol, backsub_both_sides from gp_base import GPBase -from model import Model import time import sys @@ -502,7 +500,7 @@ class SVIGP(GPBase): ax.plot(Zu, np.zeros_like(Zu) + Z_height, 'r|', mew=1.5, markersize=12) if self.input_dim==2: - ax.scatter(self.X[:,0], self.X[:,1], 20., self.Y[:,0], linewidth=0, cmap=pb.cm.jet) + ax.scatter(self.X[:,0], self.X[:,1], 20., self.Y[:,0], linewidth=0, cmap=pb.cm.jet) # @UndefinedVariable ax.plot(Zu[:,0], Zu[:,1], 'w^') def plot_traces(self): diff --git a/GPy/inference/latent_function_inference/fitc.py b/GPy/inference/latent_function_inference/fitc.py index 0d294d07..d5aa80bc 100644 --- a/GPy/inference/latent_function_inference/fitc.py +++ b/GPy/inference/latent_function_inference/fitc.py @@ -2,12 +2,8 @@ # Licensed under the BSD 3-clause license (see LICENSE.txt) import numpy as np -import pylab as pb -from ..util.linalg import mdot, jitchol, chol_inv, tdot, symmetrify, pdinv, dtrtrs -from ..util.plot import gpplot -from .. import kern -from scipy import stats -from sparse_gp import SparseGP +from ...util.linalg import mdot, jitchol, chol_inv, tdot, dtrtrs +from ...core import SparseGP class FITC(SparseGP): """ diff --git a/GPy/kern/kern.py b/GPy/kern/kern.py index 782cfa1b..353540b0 100644 --- a/GPy/kern/kern.py +++ b/GPy/kern/kern.py @@ -4,12 +4,12 @@ import sys import numpy as np import pylab as pb -from ..core.parameterized import Parameterized -from parts.kernpart import Kernpart import itertools -from parts.prod import Prod as prod from matplotlib.transforms import offset_copy -from GPy.kern.parts.linear import Linear +from parts.prod import Prod as prod +from parts.linear import Linear +from parts.kernpart import Kernpart +from ..core.parameterization import Parameterized class kern(Parameterized): def __init__(self, input_dim, parts=[], input_slices=None): diff --git a/GPy/kern/parts/bias.py b/GPy/kern/parts/bias.py index 647744b6..cb2a385c 100644 --- a/GPy/kern/parts/bias.py +++ b/GPy/kern/parts/bias.py @@ -3,9 +3,7 @@ from kernpart import Kernpart -import numpy as np -import hashlib -from GPy.core.parameter import Param +from ...core.parameterization import Param class Bias(Kernpart): def __init__(self,input_dim,variance=1.,name=None): diff --git a/GPy/kern/parts/kernpart.py b/GPy/kern/parts/kernpart.py index 9b9726dc..8314e7a7 100644 --- a/GPy/kern/parts/kernpart.py +++ b/GPy/kern/parts/kernpart.py @@ -1,7 +1,7 @@ # Copyright (c) 2012, GPy authors (see AUTHORS.txt). # Licensed under the BSD 3-clause license (see LICENSE.txt) #from ...core.parameterized.Parameterized import set_as_parameter -from GPy.core.parameterized import Parameterized +from ...core.parameterization import Parameterized class Kernpart(Parameterized): def __init__(self,input_dim,name): diff --git a/GPy/kern/parts/linear.py b/GPy/kern/parts/linear.py index c3bbf837..62f1ac36 100644 --- a/GPy/kern/parts/linear.py +++ b/GPy/kern/parts/linear.py @@ -7,7 +7,7 @@ from scipy import weave from kernpart import Kernpart from ...util.linalg import tdot from ...util.misc import fast_array_equal, param_to_array -from ...core.parameter import Param +from ...core.parameterization import Param class Linear(Kernpart): """ diff --git a/GPy/kern/parts/rbf.py b/GPy/kern/parts/rbf.py index c6e827b0..b8152622 100644 --- a/GPy/kern/parts/rbf.py +++ b/GPy/kern/parts/rbf.py @@ -7,7 +7,7 @@ from scipy import weave from kernpart import Kernpart from ...util.linalg import tdot from ...util.misc import fast_array_equal, param_to_array -from ...core.parameter import Param +from ...core.parameterization import Param class RBF(Kernpart): """ diff --git a/GPy/kern/parts/rbf_inv.py b/GPy/kern/parts/rbf_inv.py index d3f52b0d..c4461267 100644 --- a/GPy/kern/parts/rbf_inv.py +++ b/GPy/kern/parts/rbf_inv.py @@ -4,10 +4,9 @@ from rbf import RBF import numpy as np -import hashlib from scipy import weave from ...util.linalg import tdot -from GPy.core.parameter import Param +from ...core.parameterization import Param class RBFInv(RBF): """ diff --git a/GPy/kern/parts/rbfcos.py b/GPy/kern/parts/rbfcos.py index 28630f21..b6411e0a 100644 --- a/GPy/kern/parts/rbfcos.py +++ b/GPy/kern/parts/rbfcos.py @@ -1,11 +1,10 @@ - # Copyright (c) 2012, James Hensman and Andrew Gordon Wilson # Licensed under the BSD 3-clause license (see LICENSE.txt) from kernpart import Kernpart import numpy as np -from ...core.parameter import Param +from ...core.parameterization import Param class RBFCos(Kernpart): def __init__(self,input_dim,variance=1.,frequencies=None,bandwidths=None,ARD=False): diff --git a/GPy/kern/parts/spline.py b/GPy/kern/parts/spline.py index e59642fd..c31258f3 100644 --- a/GPy/kern/parts/spline.py +++ b/GPy/kern/parts/spline.py @@ -4,8 +4,8 @@ from kernpart import Kernpart import numpy as np -import hashlib -from ...core.parameter import Param +from ...core.parameterization import Param + def theta(x): """Heaviside step function""" return np.where(x>=0.,1.,0.) diff --git a/GPy/kern/parts/white.py b/GPy/kern/parts/white.py index fbb4c72d..671e85f5 100644 --- a/GPy/kern/parts/white.py +++ b/GPy/kern/parts/white.py @@ -3,7 +3,7 @@ from kernpart import Kernpart import numpy as np -from ...core.parameter import Param +from ...core.parameterization import Param class White(Kernpart): """ diff --git a/GPy/likelihoods/gaussian.py b/GPy/likelihoods/gaussian.py index 699699ae..988301f6 100644 --- a/GPy/likelihoods/gaussian.py +++ b/GPy/likelihoods/gaussian.py @@ -17,7 +17,7 @@ from scipy import stats, special from GPy.util.univariate_Gaussian import std_norm_pdf, std_norm_cdf import link_functions from likelihood import Likelihood -from ..core.parameter import Param +from ..core.parameterization import Param class Gaussian(Likelihood): """ diff --git a/GPy/likelihoods/likelihood.py b/GPy/likelihoods/likelihood.py index c1c02f3f..8ae3174e 100644 --- a/GPy/likelihoods/likelihood.py +++ b/GPy/likelihoods/likelihood.py @@ -11,7 +11,7 @@ import link_functions from ..util.misc import chain_1, chain_2, chain_3 from scipy.integrate import quad import warnings -from ..core.parameterized import Parameterized +from ..core.parameterization import Parameterized class Likelihood(Parameterized): """ diff --git a/GPy/models/bayesian_gplvm.py b/GPy/models/bayesian_gplvm.py index 5223397f..405a0ddf 100644 --- a/GPy/models/bayesian_gplvm.py +++ b/GPy/models/bayesian_gplvm.py @@ -2,17 +2,16 @@ # Licensed under the BSD 3-clause license (see LICENSE.txt) import numpy as np +import itertools +from matplotlib import pyplot +from gplvm import GPLVM +from .. import kern from ..core import SparseGP from ..likelihoods import Gaussian -from .. import kern -import itertools -from matplotlib.colors import colorConverter -from GPy.inference.optimization import SCG -from GPy.util import plot_latent, linalg -from GPy.models.gplvm import GPLVM -from GPy.util.plot_latent import most_significant_input_dimensions -from matplotlib import pyplot -from GPy.core.variational import Normal +from ..inference.optimization import SCG +from ..util import plot_latent, linalg +from ..util.plot_latent import most_significant_input_dimensions +from ..core.parameterization.variational import Normal class BayesianGPLVM(SparseGP, GPLVM): """ diff --git a/GPy/models/gplvm.py b/GPy/models/gplvm.py index 6b5ac07f..cdbcb90e 100644 --- a/GPy/models/gplvm.py +++ b/GPy/models/gplvm.py @@ -4,16 +4,12 @@ import numpy as np import pylab as pb -import sys, pdb from .. import kern -from ..core import Model -from ..util.linalg import pdinv, PCA -from ..core.priors import Gaussian as Gaussian_prior +from ..util.linalg import PCA from ..core import GP from ..likelihoods import Gaussian from .. import util -from GPy.util import plot_latent -from GPy.core.parameter import Param +from ..core import Param class GPLVM(GP): @@ -37,7 +33,6 @@ class GPLVM(GP): GP.__init__(self, X, likelihood, kernel, normalize_X=False, name=name) self.X = Param('q_mean', self.X) self.add_parameter(self.X, gradient=self.dK_dX, index=0) - #self.set_prior('.*X', Gaussian_prior(0, 1)) self.ensure_default_constraints() def initialise_latent(self, init, input_dim, Y): @@ -86,7 +81,7 @@ class GPLVM(GP): def plot(self): assert self.likelihood.Y.shape[1] == 2 - pb.scatter(self.likelihood.Y[:, 0], self.likelihood.Y[:, 1], 40, self.X[:, 0].copy(), linewidth=0, cmap=pb.cm.jet) + pb.scatter(self.likelihood.Y[:, 0], self.likelihood.Y[:, 1], 40, self.X[:, 0].copy(), linewidth=0, cmap=pb.cm.jet) # @UndefinedVariable Xnew = np.linspace(self.X.min(), self.X.max(), 200)[:, None] mu, var, upper, lower = self.predict(Xnew) pb.plot(mu[:, 0], mu[:, 1], 'k', linewidth=1.5)