diff --git a/GPy/core/parameterization/lists_and_dicts.py b/GPy/core/parameterization/lists_and_dicts.py index 604d0a01..13547c94 100644 --- a/GPy/core/parameterization/lists_and_dicts.py +++ b/GPy/core/parameterization/lists_and_dicts.py @@ -59,13 +59,14 @@ class ObservablesList(object): return self._poc.__repr__() def add(self, priority, observable, callble): - ins = 0 - for pr, _, _ in self: - if priority > pr: - break - ins += 1 - self._poc.insert(ins, (priority, weakref.ref(observable), callble)) - + if observable is not None: + ins = 0 + for pr, _, _ in self: + if priority > pr: + break + ins += 1 + self._poc.insert(ins, (priority, weakref.ref(observable), callble)) + def __str__(self): ret = [] curr_p = None @@ -96,8 +97,10 @@ class ObservablesList(object): def __deepcopy__(self, memo): self.flush() s = ObservablesList() - import copy - s._poc = copy.deepcopy(self._poc, memo) + for p,o,c in self._poc: + import copy + s.add(p, copy.deepcopy(o(), memo), copy.deepcopy(c, memo)) + s.flush() return s def __getstate__(self): diff --git a/GPy/core/parameterization/observable_array.py b/GPy/core/parameterization/observable_array.py index a280d74f..5b8aa1cd 100644 --- a/GPy/core/parameterization/observable_array.py +++ b/GPy/core/parameterization/observable_array.py @@ -1,7 +1,7 @@ # Copyright (c) 2012, GPy authors (see AUTHORS.txt). # Licensed under the BSD 3-clause license (see LICENSE.txt) -__updated__ = '2014-04-15' +__updated__ = '2014-05-12' import numpy as np from parameter_core import Observable, Pickleable @@ -15,10 +15,10 @@ class ObsAr(np.ndarray, Pickleable, Observable): """ __array_priority__ = -1 # Never give back ObsAr def __new__(cls, input_array, *a, **kw): + # allways make a copy of input paramters, as we need it to be in C order: if not isinstance(input_array, ObsAr): - obj = np.atleast_1d(np.require(input_array, dtype=np.float64, requirements=['W', 'C'])).view(cls) + obj = np.atleast_1d(np.require(np.copy(input_array), dtype=np.float64, requirements=['W', 'C'])).view(cls) else: obj = input_array - #cls.__name__ = "ObsAr" # because of fixed printing of `array` in np printing super(ObsAr, obj).__init__(*a, **kw) return obj diff --git a/GPy/core/parameterization/param.py b/GPy/core/parameterization/param.py index 7055838a..3ccbd169 100644 --- a/GPy/core/parameterization/param.py +++ b/GPy/core/parameterization/param.py @@ -45,7 +45,6 @@ class Param(OptimizationHandlable, ObsAr): _parameters_ = [] def __new__(cls, name, input_array, default_constraint=None): obj = numpy.atleast_1d(super(Param, cls).__new__(cls, input_array=input_array)) - cls.__name__ = "Param" obj._current_slice_ = (slice(obj.shape[0]),) obj._realshape_ = obj.shape obj._realsize_ = obj.size @@ -112,8 +111,8 @@ class Param(OptimizationHandlable, ObsAr): def __getitem__(self, s, *args, **kwargs): if not isinstance(s, tuple): s = (s,) - if not reduce(lambda a, b: a or numpy.any(b is Ellipsis), s, False) and len(s) <= self.ndim: - s += (Ellipsis,) + #if not reduce(lambda a, b: a or numpy.any(b is Ellipsis), s, False) and len(s) <= self.ndim: + # s += (Ellipsis,) new_arr = super(Param, self).__getitem__(s, *args, **kwargs) try: new_arr._current_slice_ = s; new_arr._original_ = self.base is new_arr.base except AttributeError: pass # returning 0d array or float, double etc @@ -156,6 +155,13 @@ class Param(OptimizationHandlable, ObsAr): def _ensure_fixes(self): if not self._has_fixes(): self._fixes_ = numpy.ones(self._realsize_, dtype=bool) + #=========================================================================== + # parameterizable + #=========================================================================== + def traverse(self, visit, *args, **kwargs): + visit(self, *args, **kwargs) + + #=========================================================================== # Convenience #=========================================================================== diff --git a/GPy/core/parameterization/parameter_core.py b/GPy/core/parameterization/parameter_core.py index 68140763..93924678 100644 --- a/GPy/core/parameterization/parameter_core.py +++ b/GPy/core/parameterization/parameter_core.py @@ -17,7 +17,7 @@ from transformations import Logexp, NegativeLogexp, Logistic, __fixed__, FIXED, import numpy as np import re -__updated__ = '2014-04-16' +__updated__ = '2014-05-12' class HierarchyError(Exception): """ @@ -124,7 +124,7 @@ class Parentable(object): """ Disconnect this object from its parent """ - raise NotImplementedError, "Abstaract superclass" + raise NotImplementedError, "Abstract superclass" @property def _highest_parent_(self): @@ -162,14 +162,13 @@ class Pickleable(object): :param protocol: pickling protocol to use, python-pickle for details. """ import cPickle as pickle - import pickle #TODO: cPickle if isinstance(f, str): with open(f, 'w') as f: pickle.dump(self, f, protocol) else: pickle.dump(self, f, protocol) - #=========================================================================== + #=========================================================================== # copy and pickling #=========================================================================== def copy(self): @@ -177,7 +176,12 @@ class Pickleable(object): #raise NotImplementedError, "Copy is not yet implemented, TODO: Observable hierarchy" import copy memo = {} - memo[id(self._parent_)] = None + parents = [] + self.traverse_parents(parents.append) + # remove self, which is the first arguments + parents = [p for p in parents if p is not self] + for p in parents: + memo[id(p)] = None memo[id(self.gradient)] = None memo[id(self.param_array)] = None memo[id(self._fixes_)] = None @@ -202,9 +206,6 @@ class Pickleable(object): dc = dict() for k,v in self.__dict__.iteritems(): if k not in ignore_list: - #if hasattr(v, "__getstate__"): - #dc[k] = v.__getstate__() - #else: dc[k] = v return dc @@ -212,12 +213,6 @@ class Pickleable(object): self.__dict__.update(state) return self - #def __getstate__(self, memo): - # raise NotImplementedError, "get state must be implemented to be able to pickle objects" - - #def __setstate__(self, memo): - # raise NotImplementedError, "set state must be implemented to be able to pickle objects" - class Gradcheckable(Pickleable, Parentable): """ Adds the functionality for an object to be gradcheckable. @@ -644,6 +639,7 @@ class OptimizationHandlable(Constrainable): else: names = [adjust(x.name) for x in self._parameters_] if add_self: names = map(lambda x: adjust(self.name) + "." + x, names) return names + def _get_param_names(self): n = np.array([p.hierarchy_name() + '[' + str(i) + ']' for p in self.flattened_parameters for i in p._indices()]) return n @@ -710,12 +706,14 @@ class Parameterizable(OptimizationHandlable): super(Parameterizable, self).__init__(*args, **kwargs) from GPy.core.parameterization.lists_and_dicts import ArrayList self._parameters_ = ArrayList() + self._param_array_ = None self.size = 0 self._added_names_ = set() + self.__visited = False # for traversing in reverse order we need to know if we were here already @property def param_array(self): - if not hasattr(self, '_param_array_'): + if self._param_array_ is None: self._param_array_ = np.empty(self.size, dtype=np.float64) return self._param_array_ @@ -723,6 +721,42 @@ class Parameterizable(OptimizationHandlable): def param_array(self, arr): self._param_array_ = arr + def traverse(self, visit, *args, **kwargs): + """ + Traverse the hierarchy performing visit(self, *args, **kwargs) at every node passed by. + See "visitor pattern" in literature. This is implemented in pre-order fashion. + + Example: + Collect all children: + + children = [] + self.traverse(children.append) + print children + """ + if not self.__visited: + visit(self, *args, **kwargs) + self.__visited = True + for c in self._parameters_: + c.traverse(visit, *args, **kwargs) + + def traverse_parents(self, visit, *args, **kwargs): + """ + Traverse the hierarchy upwards, visiting all parents and their children. + See "visitor pattern" in literature. This is implemented in pre-order fashion. + + Example: + + parents = [] + self.traverse_parents(parents.append) + print parents + """ + if not self.__visited: + visit(self, *args, **kwargs) + self.__visited = True + if self.has_parent(): + self._parent_.traverse_parents(visit, *args, **kwargs) + self._parent_.traverse(visit, *args, **kwargs) + self.__visited = False #========================================================================= # Gradient handling #========================================================================= diff --git a/GPy/examples/dimensionality_reduction.py b/GPy/examples/dimensionality_reduction.py index 8a31968e..43ba5937 100644 --- a/GPy/examples/dimensionality_reduction.py +++ b/GPy/examples/dimensionality_reduction.py @@ -161,6 +161,7 @@ def bgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, import GPy from matplotlib import pyplot as plt from ..util.misc import param_to_array + import numpy as np _np.random.seed(0) data = GPy.util.datasets.oil() @@ -174,11 +175,10 @@ def bgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, m.optimize('scg', messages=verbose, max_iters=max_iters, gtol=.05) if plot: - y = m.Y fig, (latent_axes, sense_axes) = plt.subplots(1, 2) m.plot_latent(ax=latent_axes, labels=m.data_labels) - data_show = GPy.plotting.matplot_dep.visualize.vector_show(y) - lvm_visualizer = GPy.plotting.matplot_dep.visualize.lvm_dimselect(param_to_array(m.X.mean), # @UnusedVariable + data_show = GPy.plotting.matplot_dep.visualize.vector_show((m.Y[0,:])) + lvm_visualizer = GPy.plotting.matplot_dep.visualize.lvm_dimselect(param_to_array(m.X.mean)[0:1,:], # @UnusedVariable m, data_show, latent_axes=latent_axes, sense_axes=sense_axes) raw_input('Press enter to finish') plt.close(fig) @@ -186,7 +186,7 @@ def bgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, def _simulate_sincos(D1, D2, D3, N, num_inducing, Q, plot_sim=False): _np.random.seed(1234) - + x = _np.linspace(0, 4 * _np.pi, N)[:, None] s1 = _np.vectorize(lambda x: _np.sin(x)) s2 = _np.vectorize(lambda x: _np.cos(x)**2) diff --git a/GPy/kern/__init__.py b/GPy/kern/__init__.py index 1ed5e805..ab8fb523 100644 --- a/GPy/kern/__init__.py +++ b/GPy/kern/__init__.py @@ -3,7 +3,7 @@ from _src.rbf import RBF from _src.linear import Linear, LinearFull from _src.static import Bias, White from _src.brownian import Brownian -from _src.stationary import Exponential, Matern32, Matern52, ExpQuad, RatQuad, Cosine +from _src.stationary import Exponential, OU, Matern32, Matern52, ExpQuad, RatQuad, Cosine from _src.mlp import MLP from _src.periodic import PeriodicExponential, PeriodicMatern32, PeriodicMatern52 from _src.independent_outputs import IndependentOutputs, Hierarchical diff --git a/GPy/kern/_src/kern.py b/GPy/kern/_src/kern.py index 368a9c87..8982c87f 100644 --- a/GPy/kern/_src/kern.py +++ b/GPy/kern/_src/kern.py @@ -164,8 +164,8 @@ class Kern(Parameterized): """ Shortcut for tensor `prod`. """ - assert self.active_dims == range(self.input_dim), "Can only use kernels, which have their input_dims defined from 0" - assert other.active_dims == range(other.input_dim), "Can only use kernels, which have their input_dims defined from 0" + assert np.all(self.active_dims == range(self.input_dim)), "Can only use kernels, which have their input_dims defined from 0" + assert np.all(other.active_dims == range(other.input_dim)), "Can only use kernels, which have their input_dims defined from 0" other.active_dims += self.input_dim return self.prod(other) diff --git a/GPy/kern/_src/stationary.py b/GPy/kern/_src/stationary.py index a560f8ad..f561baa4 100644 --- a/GPy/kern/_src/stationary.py +++ b/GPy/kern/_src/stationary.py @@ -192,6 +192,27 @@ class Exponential(Stationary): def dK_dr(self, r): return -0.5*self.K_of_r(r) + +class OU(Stationary): + """ + OU kernel: + + .. math:: + + k(r) = \\sigma^2 \exp(- r) \\ \\ \\ \\ \\text{ where } r = \sqrt{\sum_{i=1}^input_dim \\frac{(x_i-y_i)^2}{\ell_i^2} } + + """ + + def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='OU'): + super(OU, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) + + def K_of_r(self, r): + return self.variance * np.exp(-r) + + def dK_dr(self,r): + return -1.*self.variance*np.exp(-r) + + class Matern32(Stationary): """ Matern 3/2 kernel: diff --git a/GPy/plotting/matplot_dep/visualize.py b/GPy/plotting/matplot_dep/visualize.py index fae05ff3..fb443de1 100644 --- a/GPy/plotting/matplot_dep/visualize.py +++ b/GPy/plotting/matplot_dep/visualize.py @@ -74,13 +74,16 @@ class vector_show(matplotlib_show): """ def __init__(self, vals, axes=None): matplotlib_show.__init__(self, vals, axes) - self.handle = self.axes.plot(np.arange(0, len(vals))[:, None], self.vals) + #assert vals.ndim == 2, "Please give a vector in [n x 1] to plot" + #assert vals.shape[1] == 1, "only showing a vector in one dimension" + self.size = vals.size + self.handle = self.axes.plot(np.arange(0, vals.size)[:, None], vals)[0] def modify(self, vals): self.vals = vals.copy() - for handle, vals in zip(self.handle, self.vals.T): - xdata, ydata = handle.get_data() - handle.set_data(xdata, vals) + xdata, ydata = self.handle.get_data() + assert vals.size == self.size, "values passed into modify changed size! vals.size:{} != in.size:{}".format(vals.size, self.size) + self.handle.set_data(xdata, self.vals) self.axes.figure.canvas.draw() @@ -94,12 +97,12 @@ class lvm(matplotlib_show): :type data_visualize: visualize.data_show type. :param latent_axes: the axes where the latent visualization should be plotted. """ - if vals == None: + if vals is None: if isinstance(model.X, VariationalPosterior): vals = param_to_array(model.X.mean) else: vals = param_to_array(model.X) - + vals = param_to_array(vals) matplotlib_show.__init__(self, vals, axes=latent_axes) diff --git a/GPy/testing/parameterized_tests.py b/GPy/testing/parameterized_tests.py index fbdedc61..bc989637 100644 --- a/GPy/testing/parameterized_tests.py +++ b/GPy/testing/parameterized_tests.py @@ -27,11 +27,11 @@ class ArrayCoreTest(unittest.TestCase): class ParameterizedTest(unittest.TestCase): def setUp(self): - self.rbf = GPy.kern.RBF(1) + self.rbf = GPy.kern.RBF(20) self.white = GPy.kern.White(1) from GPy.core.parameterization import Param from GPy.core.parameterization.transformations import Logistic - self.param = Param('param', np.random.rand(25,2), Logistic(0, 1)) + self.param = Param('param', np.random.uniform(0,1,(25,2)), Logistic(0, 1)) self.test1 = GPy.core.Parameterized("test model") self.test1.param = self.param @@ -142,6 +142,8 @@ class ParameterizedTest(unittest.TestCase): self.testmodel.randomize() self.assertEqual(val, self.testmodel.kern.lengthscale) + + def test_regular_expression_misc(self): self.testmodel.kern.lengthscale.fix() val = float(self.testmodel.kern.lengthscale)