Merge branch 'devel' of https://github.com/SheffieldML/GPy into devel

This commit is contained in:
Neil Lawrence 2014-05-13 05:23:43 +01:00
commit c138ee868f
10 changed files with 114 additions and 45 deletions

View file

@ -59,6 +59,7 @@ class ObservablesList(object):
return self._poc.__repr__() return self._poc.__repr__()
def add(self, priority, observable, callble): def add(self, priority, observable, callble):
if observable is not None:
ins = 0 ins = 0
for pr, _, _ in self: for pr, _, _ in self:
if priority > pr: if priority > pr:
@ -96,8 +97,10 @@ class ObservablesList(object):
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
self.flush() self.flush()
s = ObservablesList() s = ObservablesList()
for p,o,c in self._poc:
import copy import copy
s._poc = copy.deepcopy(self._poc, memo) s.add(p, copy.deepcopy(o(), memo), copy.deepcopy(c, memo))
s.flush()
return s return s
def __getstate__(self): def __getstate__(self):

View file

@ -1,7 +1,7 @@
# Copyright (c) 2012, GPy authors (see AUTHORS.txt). # Copyright (c) 2012, GPy authors (see AUTHORS.txt).
# Licensed under the BSD 3-clause license (see LICENSE.txt) # Licensed under the BSD 3-clause license (see LICENSE.txt)
__updated__ = '2014-04-15' __updated__ = '2014-05-12'
import numpy as np import numpy as np
from parameter_core import Observable, Pickleable from parameter_core import Observable, Pickleable
@ -15,10 +15,10 @@ class ObsAr(np.ndarray, Pickleable, Observable):
""" """
__array_priority__ = -1 # Never give back ObsAr __array_priority__ = -1 # Never give back ObsAr
def __new__(cls, input_array, *a, **kw): 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): 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 else: obj = input_array
#cls.__name__ = "ObsAr" # because of fixed printing of `array` in np printing
super(ObsAr, obj).__init__(*a, **kw) super(ObsAr, obj).__init__(*a, **kw)
return obj return obj

View file

@ -45,7 +45,6 @@ class Param(OptimizationHandlable, ObsAr):
_parameters_ = [] _parameters_ = []
def __new__(cls, name, input_array, default_constraint=None): def __new__(cls, name, input_array, default_constraint=None):
obj = numpy.atleast_1d(super(Param, cls).__new__(cls, input_array=input_array)) obj = numpy.atleast_1d(super(Param, cls).__new__(cls, input_array=input_array))
cls.__name__ = "Param"
obj._current_slice_ = (slice(obj.shape[0]),) obj._current_slice_ = (slice(obj.shape[0]),)
obj._realshape_ = obj.shape obj._realshape_ = obj.shape
obj._realsize_ = obj.size obj._realsize_ = obj.size
@ -112,8 +111,8 @@ class Param(OptimizationHandlable, ObsAr):
def __getitem__(self, s, *args, **kwargs): def __getitem__(self, s, *args, **kwargs):
if not isinstance(s, tuple): if not isinstance(s, tuple):
s = (s,) s = (s,)
if not reduce(lambda a, b: a or numpy.any(b is Ellipsis), s, False) and len(s) <= self.ndim: #if not reduce(lambda a, b: a or numpy.any(b is Ellipsis), s, False) and len(s) <= self.ndim:
s += (Ellipsis,) # s += (Ellipsis,)
new_arr = super(Param, self).__getitem__(s, *args, **kwargs) new_arr = super(Param, self).__getitem__(s, *args, **kwargs)
try: new_arr._current_slice_ = s; new_arr._original_ = self.base is new_arr.base 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 except AttributeError: pass # returning 0d array or float, double etc
@ -156,6 +155,13 @@ class Param(OptimizationHandlable, ObsAr):
def _ensure_fixes(self): def _ensure_fixes(self):
if not self._has_fixes(): self._fixes_ = numpy.ones(self._realsize_, dtype=bool) 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 # Convenience
#=========================================================================== #===========================================================================

View file

@ -17,7 +17,7 @@ from transformations import Logexp, NegativeLogexp, Logistic, __fixed__, FIXED,
import numpy as np import numpy as np
import re import re
__updated__ = '2014-04-16' __updated__ = '2014-05-12'
class HierarchyError(Exception): class HierarchyError(Exception):
""" """
@ -124,7 +124,7 @@ class Parentable(object):
""" """
Disconnect this object from its parent Disconnect this object from its parent
""" """
raise NotImplementedError, "Abstaract superclass" raise NotImplementedError, "Abstract superclass"
@property @property
def _highest_parent_(self): def _highest_parent_(self):
@ -162,7 +162,6 @@ class Pickleable(object):
:param protocol: pickling protocol to use, python-pickle for details. :param protocol: pickling protocol to use, python-pickle for details.
""" """
import cPickle as pickle import cPickle as pickle
import pickle #TODO: cPickle
if isinstance(f, str): if isinstance(f, str):
with open(f, 'w') as f: with open(f, 'w') as f:
pickle.dump(self, f, protocol) pickle.dump(self, f, protocol)
@ -177,7 +176,12 @@ class Pickleable(object):
#raise NotImplementedError, "Copy is not yet implemented, TODO: Observable hierarchy" #raise NotImplementedError, "Copy is not yet implemented, TODO: Observable hierarchy"
import copy import copy
memo = {} 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.gradient)] = None
memo[id(self.param_array)] = None memo[id(self.param_array)] = None
memo[id(self._fixes_)] = None memo[id(self._fixes_)] = None
@ -202,9 +206,6 @@ class Pickleable(object):
dc = dict() dc = dict()
for k,v in self.__dict__.iteritems(): for k,v in self.__dict__.iteritems():
if k not in ignore_list: if k not in ignore_list:
#if hasattr(v, "__getstate__"):
#dc[k] = v.__getstate__()
#else:
dc[k] = v dc[k] = v
return dc return dc
@ -212,12 +213,6 @@ class Pickleable(object):
self.__dict__.update(state) self.__dict__.update(state)
return self 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): class Gradcheckable(Pickleable, Parentable):
""" """
Adds the functionality for an object to be gradcheckable. 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_] else: names = [adjust(x.name) for x in self._parameters_]
if add_self: names = map(lambda x: adjust(self.name) + "." + x, names) if add_self: names = map(lambda x: adjust(self.name) + "." + x, names)
return names return names
def _get_param_names(self): def _get_param_names(self):
n = np.array([p.hierarchy_name() + '[' + str(i) + ']' for p in self.flattened_parameters for i in p._indices()]) n = np.array([p.hierarchy_name() + '[' + str(i) + ']' for p in self.flattened_parameters for i in p._indices()])
return n return n
@ -710,12 +706,14 @@ class Parameterizable(OptimizationHandlable):
super(Parameterizable, self).__init__(*args, **kwargs) super(Parameterizable, self).__init__(*args, **kwargs)
from GPy.core.parameterization.lists_and_dicts import ArrayList from GPy.core.parameterization.lists_and_dicts import ArrayList
self._parameters_ = ArrayList() self._parameters_ = ArrayList()
self._param_array_ = None
self.size = 0 self.size = 0
self._added_names_ = set() self._added_names_ = set()
self.__visited = False # for traversing in reverse order we need to know if we were here already
@property @property
def param_array(self): 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) self._param_array_ = np.empty(self.size, dtype=np.float64)
return self._param_array_ return self._param_array_
@ -723,6 +721,42 @@ class Parameterizable(OptimizationHandlable):
def param_array(self, arr): def param_array(self, arr):
self._param_array_ = 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 # Gradient handling
#========================================================================= #=========================================================================

View file

@ -161,6 +161,7 @@ def bgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40,
import GPy import GPy
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
from ..util.misc import param_to_array from ..util.misc import param_to_array
import numpy as np
_np.random.seed(0) _np.random.seed(0)
data = GPy.util.datasets.oil() 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) m.optimize('scg', messages=verbose, max_iters=max_iters, gtol=.05)
if plot: if plot:
y = m.Y
fig, (latent_axes, sense_axes) = plt.subplots(1, 2) fig, (latent_axes, sense_axes) = plt.subplots(1, 2)
m.plot_latent(ax=latent_axes, labels=m.data_labels) m.plot_latent(ax=latent_axes, labels=m.data_labels)
data_show = GPy.plotting.matplot_dep.visualize.vector_show(y) 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), # @UnusedVariable 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) m, data_show, latent_axes=latent_axes, sense_axes=sense_axes)
raw_input('Press enter to finish') raw_input('Press enter to finish')
plt.close(fig) plt.close(fig)

View file

@ -3,7 +3,7 @@ from _src.rbf import RBF
from _src.linear import Linear, LinearFull from _src.linear import Linear, LinearFull
from _src.static import Bias, White from _src.static import Bias, White
from _src.brownian import Brownian 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.mlp import MLP
from _src.periodic import PeriodicExponential, PeriodicMatern32, PeriodicMatern52 from _src.periodic import PeriodicExponential, PeriodicMatern32, PeriodicMatern52
from _src.independent_outputs import IndependentOutputs, Hierarchical from _src.independent_outputs import IndependentOutputs, Hierarchical

View file

@ -164,8 +164,8 @@ class Kern(Parameterized):
""" """
Shortcut for tensor `prod`. 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 np.all(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(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 other.active_dims += self.input_dim
return self.prod(other) return self.prod(other)

View file

@ -192,6 +192,27 @@ class Exponential(Stationary):
def dK_dr(self, r): def dK_dr(self, r):
return -0.5*self.K_of_r(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): class Matern32(Stationary):
""" """
Matern 3/2 kernel: Matern 3/2 kernel:

View file

@ -74,13 +74,16 @@ class vector_show(matplotlib_show):
""" """
def __init__(self, vals, axes=None): def __init__(self, vals, axes=None):
matplotlib_show.__init__(self, vals, axes) 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): def modify(self, vals):
self.vals = vals.copy() self.vals = vals.copy()
for handle, vals in zip(self.handle, self.vals.T): xdata, ydata = self.handle.get_data()
xdata, ydata = handle.get_data() assert vals.size == self.size, "values passed into modify changed size! vals.size:{} != in.size:{}".format(vals.size, self.size)
handle.set_data(xdata, vals) self.handle.set_data(xdata, self.vals)
self.axes.figure.canvas.draw() self.axes.figure.canvas.draw()
@ -94,7 +97,7 @@ class lvm(matplotlib_show):
:type data_visualize: visualize.data_show type. :type data_visualize: visualize.data_show type.
:param latent_axes: the axes where the latent visualization should be plotted. :param latent_axes: the axes where the latent visualization should be plotted.
""" """
if vals == None: if vals is None:
if isinstance(model.X, VariationalPosterior): if isinstance(model.X, VariationalPosterior):
vals = param_to_array(model.X.mean) vals = param_to_array(model.X.mean)
else: else:

View file

@ -27,11 +27,11 @@ class ArrayCoreTest(unittest.TestCase):
class ParameterizedTest(unittest.TestCase): class ParameterizedTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.rbf = GPy.kern.RBF(1) self.rbf = GPy.kern.RBF(20)
self.white = GPy.kern.White(1) self.white = GPy.kern.White(1)
from GPy.core.parameterization import Param from GPy.core.parameterization import Param
from GPy.core.parameterization.transformations import Logistic 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 = GPy.core.Parameterized("test model")
self.test1.param = self.param self.test1.param = self.param
@ -142,6 +142,8 @@ class ParameterizedTest(unittest.TestCase):
self.testmodel.randomize() self.testmodel.randomize()
self.assertEqual(val, self.testmodel.kern.lengthscale) self.assertEqual(val, self.testmodel.kern.lengthscale)
def test_regular_expression_misc(self): def test_regular_expression_misc(self):
self.testmodel.kern.lengthscale.fix() self.testmodel.kern.lengthscale.fix()
val = float(self.testmodel.kern.lengthscale) val = float(self.testmodel.kern.lengthscale)