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

This commit is contained in:
Alan Saul 2014-03-14 13:19:50 +00:00
commit a56928e11a
30 changed files with 361 additions and 310 deletions

View file

@ -10,7 +10,7 @@ from model import Model
from parameterization import ObservableArray from parameterization import ObservableArray
from .. import likelihoods from .. import likelihoods
from ..likelihoods.gaussian import Gaussian from ..likelihoods.gaussian import Gaussian
from ..inference.latent_function_inference import exact_gaussian_inference from ..inference.latent_function_inference import exact_gaussian_inference, expectation_propagation
from parameterization.variational import VariationalPosterior from parameterization.variational import VariationalPosterior
class GP(Model): class GP(Model):
@ -56,7 +56,7 @@ class GP(Model):
if isinstance(likelihood, likelihoods.Gaussian) or isinstance(likelihood, likelihoods.MixedNoise): if isinstance(likelihood, likelihoods.Gaussian) or isinstance(likelihood, likelihoods.MixedNoise):
inference_method = exact_gaussian_inference.ExactGaussianInference() inference_method = exact_gaussian_inference.ExactGaussianInference()
else: else:
inference_method = expectation_propagation inference_method = expectation_propagation.EP()
print "defaulting to ", inference_method, "for latent function inference" print "defaulting to ", inference_method, "for latent function inference"
self.inference_method = inference_method self.inference_method = inference_method
@ -94,6 +94,9 @@ class GP(Model):
#var = Kxx - np.sum(LiKx*LiKx, 0) #var = Kxx - np.sum(LiKx*LiKx, 0)
var = Kxx - np.sum(WiKx*Kx, 0) var = Kxx - np.sum(WiKx*Kx, 0)
var = var.reshape(-1, 1) var = var.reshape(-1, 1)
#force mu to be a column vector
if len(mu.shape)==1: mu = mu[:,None]
return mu, var return mu, var
def predict(self, Xnew, full_cov=False, Y_metadata=None): def predict(self, Xnew, full_cov=False, Y_metadata=None):

View file

@ -301,8 +301,7 @@ class Model(Parameterized):
denominator = (2 * np.dot(dx, gradient)) denominator = (2 * np.dot(dx, gradient))
global_ratio = (f1 - f2) / np.where(denominator==0., 1e-32, denominator) global_ratio = (f1 - f2) / np.where(denominator==0., 1e-32, denominator)
return np.abs(1. - global_ratio) < tolerance or np.abs(f1-f2).sum() + np.abs((2 * np.dot(dx, gradient))).sum() < tolerance
return np.abs(1. - global_ratio) < tolerance
else: else:
# check the gradient of each parameter individually, and do some pretty printing # check the gradient of each parameter individually, and do some pretty printing
try: try:

View file

@ -25,11 +25,10 @@ class ParameterIndexOperations(object):
self.add(t, i) self.add(t, i)
def __getstate__(self): def __getstate__(self):
return self._properties#, self._reverse return self._properties
def __setstate__(self, state): def __setstate__(self, state):
self._properties = state[0] self._properties = state
# self._reverse = state[1]
def iteritems(self): def iteritems(self):
return self._properties.iteritems() return self._properties.iteritems()
@ -76,10 +75,7 @@ class ParameterIndexOperations(object):
return vectorize(lambda i: [prop for prop in self.iterproperties() if i in self[prop]], otypes=[list])(index) return vectorize(lambda i: [prop for prop in self.iterproperties() if i in self[prop]], otypes=[list])(index)
def add(self, prop, indices): def add(self, prop, indices):
try:
self._properties[prop] = combine_indices(self._properties[prop], indices) self._properties[prop] = combine_indices(self._properties[prop], indices)
except KeyError:
self._properties[prop] = indices
def remove(self, prop, indices): def remove(self, prop, indices):
if prop in self._properties: if prop in self._properties:
@ -125,13 +121,11 @@ class ParameterIndexOperationsView(object):
def __getstate__(self): def __getstate__(self):
return [self._param_index_ops, self._offset, self._size] return [self._param_index_ops, self._offset, self._size]
def __setstate__(self, state): def __setstate__(self, state):
self._param_index_ops = state[0] self._param_index_ops = state[0]
self._offset = state[1] self._offset = state[1]
self._size = state[2] self._size = state[2]
def _filter_index(self, ind): def _filter_index(self, ind):
return ind[(ind >= self._offset) * (ind < (self._offset + self._size))] - self._offset return ind[(ind >= self._offset) * (ind < (self._offset + self._size))] - self._offset

View file

@ -5,21 +5,17 @@ Created on 27 Feb 2014
''' '''
from collections import defaultdict from collections import defaultdict
class DefaultArrayDict(defaultdict):
def __init__(self): def intarray_default_factory():
import numpy as np
return np.int_([])
class IntArrayDict(defaultdict):
def __init__(self, default_factory=None):
""" """
Default will be self._default, if not set otherwise Default will be self._default, if not set otherwise
""" """
defaultdict.__init__(self, self.default_factory) defaultdict.__init__(self, intarray_default_factory)
class SetDict(DefaultArrayDict):
def default_factory(self):
return set()
class IntArrayDict(DefaultArrayDict):
def default_factory(self):
import numpy as np
return np.int_([])
class ArrayList(list): class ArrayList(list):
""" """

View file

@ -49,9 +49,6 @@ class Param(OptimizationHandlable, ObservableArray):
obj._realshape_ = obj.shape obj._realshape_ = obj.shape
obj._realsize_ = obj.size obj._realsize_ = obj.size
obj._realndim_ = obj.ndim obj._realndim_ = obj.ndim
from lists_and_dicts import SetDict
obj._tied_to_me_ = SetDict()
obj._tied_to_ = []
obj._original_ = True obj._original_ = True
obj._gradient_array_ = numpy.zeros(obj.shape, dtype=numpy.float64) obj._gradient_array_ = numpy.zeros(obj.shape, dtype=numpy.float64)
return obj return obj
@ -80,13 +77,11 @@ class Param(OptimizationHandlable, ObservableArray):
self._parent_index_ = getattr(obj, '_parent_index_', None) self._parent_index_ = getattr(obj, '_parent_index_', None)
self._default_constraint_ = getattr(obj, '_default_constraint_', None) self._default_constraint_ = getattr(obj, '_default_constraint_', None)
self._current_slice_ = getattr(obj, '_current_slice_', None) self._current_slice_ = getattr(obj, '_current_slice_', None)
self._tied_to_me_ = getattr(obj, '_tied_to_me_', None)
self._tied_to_ = getattr(obj, '_tied_to_', None)
self._realshape_ = getattr(obj, '_realshape_', None) self._realshape_ = getattr(obj, '_realshape_', None)
self._realsize_ = getattr(obj, '_realsize_', None) self._realsize_ = getattr(obj, '_realsize_', None)
self._realndim_ = getattr(obj, '_realndim_', None) self._realndim_ = getattr(obj, '_realndim_', None)
self._original_ = getattr(obj, '_original_', None) self._original_ = getattr(obj, '_original_', None)
self._name = getattr(obj, 'name', None) self._name = getattr(obj, '_name', None)
self._gradient_array_ = getattr(obj, '_gradient_array_', None) self._gradient_array_ = getattr(obj, '_gradient_array_', None)
self.constraints = getattr(obj, 'constraints', None) self.constraints = getattr(obj, 'constraints', None)
self.priors = getattr(obj, 'priors', None) self.priors = getattr(obj, 'priors', None)
@ -106,10 +101,10 @@ class Param(OptimizationHandlable, ObservableArray):
#=========================================================================== #===========================================================================
# Pickling operations # Pickling operations
#=========================================================================== #===========================================================================
def __reduce_ex__(self): def __reduce__(self):
func, args, state = super(Param, self).__reduce__() func, args, state = super(Param, self).__reduce__()
return func, args, (state, return func, args, (state,
(self.name, (self._name,
self._parent_, self._parent_,
self._parent_index_, self._parent_index_,
self._default_constraint_, self._default_constraint_,
@ -117,16 +112,16 @@ class Param(OptimizationHandlable, ObservableArray):
self._realshape_, self._realshape_,
self._realsize_, self._realsize_,
self._realndim_, self._realndim_,
self._tied_to_me_, self.constraints,
self._tied_to_, self.priors
) )
) )
def __setstate__(self, state): def __setstate__(self, state):
super(Param, self).__setstate__(state[0]) super(Param, self).__setstate__(state[0])
state = list(state[1]) state = list(state[1])
self._tied_to_ = state.pop() self.priors = state.pop()
self._tied_to_me_ = state.pop() self.constraints = state.pop()
self._realndim_ = state.pop() self._realndim_ = state.pop()
self._realsize_ = state.pop() self._realsize_ = state.pop()
self._realshape_ = state.pop() self._realshape_ = state.pop()
@ -134,7 +129,7 @@ class Param(OptimizationHandlable, ObservableArray):
self._default_constraint_ = state.pop() self._default_constraint_ = 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()
def copy(self, *args): def copy(self, *args):
constr = self.constraints.copy() constr = self.constraints.copy()
@ -180,21 +175,21 @@ class Param(OptimizationHandlable, ObservableArray):
#=========================================================================== #===========================================================================
# Index Operations: # Index Operations:
#=========================================================================== #===========================================================================
def _internal_offset(self): #def _internal_offset(self):
internal_offset = 0 # internal_offset = 0
extended_realshape = numpy.cumprod((1,) + self._realshape_[:0:-1])[::-1] # extended_realshape = numpy.cumprod((1,) + self._realshape_[:0:-1])[::-1]
for i, si in enumerate(self._current_slice_[:self._realndim_]): # for i, si in enumerate(self._current_slice_[:self._realndim_]):
if numpy.all(si == Ellipsis): # if numpy.all(si == Ellipsis):
continue # continue
if isinstance(si, slice): # if isinstance(si, slice):
a = si.indices(self._realshape_[i])[0] # a = si.indices(self._realshape_[i])[0]
elif isinstance(si, (list,numpy.ndarray,tuple)): # elif isinstance(si, (list,numpy.ndarray,tuple)):
a = si[0] # a = si[0]
else: a = si # else: a = si
if a < 0: # if a < 0:
a = self._realshape_[i] + a # a = self._realshape_[i] + a
internal_offset += a * extended_realshape[i] # internal_offset += a * extended_realshape[i]
return internal_offset # return internal_offset
def _raveled_index(self, slice_index=None): def _raveled_index(self, slice_index=None):
# return an index array on the raveled array, which is formed by the current_slice # return an index array on the raveled array, which is formed by the current_slice
@ -204,6 +199,9 @@ class Param(OptimizationHandlable, ObservableArray):
if ind.ndim < 2: ind = ind[:, None] if ind.ndim < 2: ind = ind[:, None]
return numpy.asarray(numpy.apply_along_axis(lambda x: numpy.sum(extended_realshape * x), 1, ind), dtype=int) return numpy.asarray(numpy.apply_along_axis(lambda x: numpy.sum(extended_realshape * x), 1, ind), dtype=int)
def _raveled_index_for(self, obj):
return self._raveled_index()
def _expand_index(self, slice_index=None): def _expand_index(self, slice_index=None):
# this calculates the full indexing arrays from the slicing objects given by get_item for _real..._ attributes # this calculates the full indexing arrays from the slicing objects given by get_item for _real..._ attributes
# it basically translates slices to their respective index arrays and turns negative indices around # it basically translates slices to their respective index arrays and turns negative indices around
@ -224,6 +222,11 @@ class Param(OptimizationHandlable, ObservableArray):
return numpy.r_[a] return numpy.r_[a]
return numpy.r_[:b] return numpy.r_[:b]
return itertools.imap(f, itertools.izip_longest(slice_index[:self._realndim_], self._realshape_, fillvalue=slice(self.size))) return itertools.imap(f, itertools.izip_longest(slice_index[:self._realndim_], self._realshape_, fillvalue=slice(self.size)))
#===========================================================================
# Constrainable
#===========================================================================
def _ensure_fixes(self):
self._fixes_ = numpy.ones(self._realsize_, dtype=bool)
#=========================================================================== #===========================================================================
# Convenience # Convenience
@ -239,7 +242,6 @@ class Param(OptimizationHandlable, ObservableArray):
#round.__doc__ = numpy.round.__doc__ #round.__doc__ = numpy.round.__doc__
def _get_original(self, param): def _get_original(self, param):
return self return self
#=========================================================================== #===========================================================================
# Printing -> done # Printing -> done
#=========================================================================== #===========================================================================
@ -266,23 +268,11 @@ class Param(OptimizationHandlable, ObservableArray):
return [' '.join(map(lambda c: str(c[0]) if c[1].size == self._realsize_ else "{" + str(c[0]) + "}", self.priors.iteritems()))] return [' '.join(map(lambda c: str(c[0]) if c[1].size == self._realsize_ else "{" + str(c[0]) + "}", self.priors.iteritems()))]
@property @property
def _ties_str(self): def _ties_str(self):
return [t._short() for t in self._tied_to_] or [''] return ['']
def __repr__(self, *args, **kwargs): def __repr__(self, *args, **kwargs):
name = "\033[1m{x:s}\033[0;0m:\n".format( name = "\033[1m{x:s}\033[0;0m:\n".format(
x=self.hierarchy_name()) x=self.hierarchy_name())
return name + super(Param, self).__repr__(*args, **kwargs) return name + super(Param, self).__repr__(*args, **kwargs)
def _ties_for(self, rav_index):
# size = sum(p.size for p in self._tied_to_)
ties = numpy.empty(shape=(len(self._tied_to_), numpy.size(rav_index)), dtype=Param)
for i, tied_to in enumerate(self._tied_to_):
for t, ind in tied_to._tied_to_me_.iteritems():
if t._parent_index_ == self._parent_index_:
matches = numpy.where(rav_index[:, None] == t._raveled_index()[None, :])
tt_rav_index = tied_to._raveled_index()
ind_rav_matches = numpy.where(tt_rav_index == numpy.array(list(ind)))[0]
if len(ind) != 1: ties[i, matches[0][ind_rav_matches]] = numpy.take(tt_rav_index, matches[1], mode='wrap')[ind_rav_matches]
else: ties[i, matches[0]] = numpy.take(tt_rav_index, matches[1], mode='wrap')
return map(lambda a: sum(a, []), zip(*[[[tie.flatten()] if tx != None else [] for tx in t] for t, tie in zip(ties, self._tied_to_)]))
def _indices(self, slice_index=None): def _indices(self, slice_index=None):
# get a int-array containing all indices in the first axis. # get a int-array containing all indices in the first axis.
if slice_index is None: if slice_index is None:
@ -322,8 +312,8 @@ class Param(OptimizationHandlable, ObservableArray):
ravi = self._raveled_index(filter_) ravi = self._raveled_index(filter_)
if constr_matrix is None: constr_matrix = self.constraints.properties_for(ravi) if constr_matrix is None: constr_matrix = self.constraints.properties_for(ravi)
if prirs is None: prirs = self.priors.properties_for(ravi) if prirs is None: prirs = self.priors.properties_for(ravi)
if ties is None: ties = self._ties_for(ravi) if ties is None: ties = [['N/A']]*self.size
ties = [' '.join(map(lambda x: x._short(), t)) for t in ties] ties = [' '.join(map(lambda x: x, t)) for t in ties]
if lc is None: lc = self._max_len_names(constr_matrix, __constraints_name__) if lc is None: lc = self._max_len_names(constr_matrix, __constraints_name__)
if lx is None: lx = self._max_len_values() if lx is None: lx = self._max_len_values()
if li is None: li = self._max_len_index(indices) if li is None: li = self._max_len_index(indices)

View file

@ -16,7 +16,7 @@ Observable Pattern for patameterization
from transformations import Transformation, Logexp, NegativeLogexp, Logistic, __fixed__, FIXED, UNFIXED from transformations import Transformation, Logexp, NegativeLogexp, Logistic, __fixed__, FIXED, UNFIXED
import numpy as np import numpy as np
__updated__ = '2014-03-13' __updated__ = '2014-03-14'
class HierarchyError(Exception): class HierarchyError(Exception):
""" """
@ -31,7 +31,71 @@ def adjust_name_for_printing(name):
return name.replace(" ", "_").replace(".", "_").replace("-", "_m_").replace("+", "_p_").replace("!", "_I_").replace("**", "_xx_").replace("*", "_x_").replace("/", "_l_").replace("@",'_at_') return name.replace(" ", "_").replace(".", "_").replace("-", "_m_").replace("+", "_p_").replace("!", "_I_").replace("**", "_xx_").replace("*", "_x_").replace("/", "_l_").replace("@",'_at_')
return '' return ''
class Observable(object): class InterfacePickleFunctions(object):
def __init__(self, *a, **kw):
super(InterfacePickleFunctions, self).__init__()
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 = <classname>.__new__(*args,**kw)._setstate(<to_be_copied>._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 Pickleable(object):
"""
Make an object pickleable (See python doc 'pickling').
This class allows for pickling support by Memento pattern.
_getstate returns a memento of the class, which gets pickled.
_setstate(<memento>) (re-)sets the state of the class to the memento
"""
def __init__(self, *a, **kw):
super(Pickleable, self).__init__()
#===========================================================================
# Pickling operations
#===========================================================================
def pickle(self, f, protocol=-1):
"""
:param f: either filename or open file object to write to.
if it is an open buffer, you have to make sure to close
it properly.
:param protocol: pickling protocol to use, python-pickle for details.
"""
import cPickle
if isinstance(f, str):
with open(f, 'w') as f:
cPickle.dump(self, f, protocol)
else:
cPickle.dump(self, f, protocol)
def __getstate__(self):
if self._has_get_set_state():
return self._getstate()
return self.__dict__
def __setstate__(self, state):
if self._has_get_set_state():
self._setstate(state)
# TODO: maybe parameters_changed() here?
return
self.__dict__ = state
def _has_get_set_state(self):
return '_getstate' in vars(self.__class__) and '_setstate' in vars(self.__class__)
class Observable(InterfacePickleFunctions):
""" """
Observable pattern for parameterization. Observable pattern for parameterization.
@ -41,7 +105,7 @@ class Observable(object):
""" """
_updated = True _updated = True
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Observable, self).__init__() super(Observable, self).__init__(*args, **kwargs)
self._observer_callables_ = [] self._observer_callables_ = []
def add_observer(self, observer, callble, priority=0): def add_observer(self, observer, callble, priority=0):
@ -89,68 +153,16 @@ class Observable(object):
ins += 1 ins += 1
self._observer_callables_.insert(ins, (p, o, c)) self._observer_callables_.insert(ins, (p, o, c))
class Pickleable(object):
"""
Make an object pickleable (See python doc 'pickling').
This class allows for pickling support by Memento pattern.
_getstate returns a memento of the class, which gets pickled.
_setstate(<memento>) (re-)sets the state of the class to the memento
"""
#===========================================================================
# Pickling operations
#===========================================================================
def pickle(self, f, protocol=-1):
"""
:param f: either filename or open file object to write to.
if it is an open buffer, you have to make sure to close
it properly.
:param protocol: pickling protocol to use, python-pickle for details.
"""
import cPickle
if isinstance(f, str):
with open(f, 'w') as f:
cPickle.dump(self, f, protocol)
else:
cPickle.dump(self, f, protocol)
def __getstate__(self):
if self._has_get_set_state():
return self._getstate()
return self.__dict__
def __setstate__(self, state):
if self._has_get_set_state():
self._setstate(state)
# TODO: maybe parameters_changed() here?
return
self.__dict__ = state
def _has_get_set_state(self):
return '_getstate' in vars(self.__class__) and '_setstate' in vars(self.__class__)
def _getstate(self): def _getstate(self):
""" return [self._observer_callables_]
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): def _setstate(self, state):
""" self._observer_callables_ = state.pop()
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 = <classname>.__new__(*args,**kw)._setstate(<to_be_copied>._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: # Foundation framework for parameterized and param objects:
#=============================================================================== #===============================================================================
class Parentable(object): class Parentable(Observable):
""" """
Enable an Object to have a parent. Enable an Object to have a parent.
@ -160,7 +172,7 @@ class Parentable(object):
_parent_ = None _parent_ = None
_parent_index_ = None _parent_index_ = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Parentable, self).__init__() super(Parentable, self).__init__(*args, **kwargs)
def has_parent(self): def has_parent(self):
""" """
@ -284,13 +296,6 @@ class Indexable(object):
""" """
raise NotImplementedError, "Need to be able to get the raveled Index" raise NotImplementedError, "Need to be able to get the raveled Index"
def _internal_offset(self):
"""
The offset for this parameter inside its parent.
This has to account for shaped parameters!
"""
return 0
def _offset_for(self, param): def _offset_for(self, param):
""" """
Return the offset of the param inside this parameterized object. Return the offset of the param inside this parameterized object.
@ -308,7 +313,7 @@ class Indexable(object):
raise NotImplementedError, "shouldnt happen, raveld index transformation required from non parameterization object?" raise NotImplementedError, "shouldnt happen, raveld index transformation required from non parameterization object?"
class Constrainable(Nameable, Indexable, Observable): class Constrainable(Nameable, Indexable):
""" """
Make an object constrainable with Priors and Transformations. Make an object constrainable with Priors and Transformations.
TODO: Mappings!! TODO: Mappings!!
@ -367,21 +372,26 @@ class Constrainable(Nameable, Indexable, Observable):
self._highest_parent_._set_unfixed(unconstrained) self._highest_parent_._set_unfixed(unconstrained)
unfix = unconstrain_fixed unfix = unconstrain_fixed
def _ensure_fixes(self):
# Ensure that the fixes array is set:
# Parameterized: ones(self.size)
# Param: ones(self._realsize_
self._fixes_ = np.ones(self.size, dtype=bool)
def _set_fixed(self, index): def _set_fixed(self, index):
if not self._has_fixes(): self._fixes_ = np.ones(self.size, dtype=bool) self._ensure_fixes()
self._fixes_[index] = FIXED self._fixes_[index] = FIXED
if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED
def _set_unfixed(self, index): def _set_unfixed(self, index):
if not self._has_fixes(): self._fixes_ = np.ones(self.size, dtype=bool) self._ensure_fixes()
# rav_i = self._raveled_index_for(param)[index]
self._fixes_[index] = UNFIXED self._fixes_[index] = UNFIXED
if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED
def _connect_fixes(self): def _connect_fixes(self):
fixed_indices = self.constraints[__fixed__] fixed_indices = self.constraints[__fixed__]
if fixed_indices.size > 0: if fixed_indices.size > 0:
self._fixes_ = np.ones(self.size, dtype=bool) * UNFIXED self._ensure_fixes()
self._fixes_[fixed_indices] = FIXED self._fixes_[fixed_indices] = FIXED
else: else:
self._fixes_ = None self._fixes_ = None
@ -401,6 +411,15 @@ class Constrainable(Nameable, Indexable, Observable):
repriorized = self.unset_priors() repriorized = self.unset_priors()
self._add_to_index_operations(self.priors, repriorized, prior, warning) self._add_to_index_operations(self.priors, repriorized, prior, warning)
from domains import _REAL, _POSITIVE, _NEGATIVE
if prior.domain is _POSITIVE:
self.constrain_positive(warning)
elif prior.domain is _NEGATIVE:
self.constrain_negative(warning)
elif prior.domain is _REAL:
rav_i = self._raveled_index()
assert all(all(c.domain is _REAL for c in con) for con in self.constraints.properties_for(rav_i))
def unset_priors(self, *priors): def unset_priors(self, *priors):
""" """
Un-set all priors given from this parameter handle. Un-set all priors given from this parameter handle.
@ -411,14 +430,14 @@ class Constrainable(Nameable, Indexable, Observable):
def log_prior(self): def log_prior(self):
"""evaluate the prior""" """evaluate the prior"""
if self.priors.size > 0: if self.priors.size > 0:
x = self._get_params() x = self._param_array_
return reduce(lambda a, b: a + b, [p.lnpdf(x[ind]).sum() for p, ind in self.priors.iteritems()], 0) return reduce(lambda a, b: a + b, (p.lnpdf(x[ind]).sum() for p, ind in self.priors.iteritems()), 0)
return 0. return 0.
def _log_prior_gradients(self): def _log_prior_gradients(self):
"""evaluate the gradients of the priors""" """evaluate the gradients of the priors"""
if self.priors.size > 0: if self.priors.size > 0:
x = self._get_params() x = self._param_array_
ret = np.zeros(x.size) ret = np.zeros(x.size)
[np.put(ret, ind, p.lnpdf_grad(x[ind])) for p, ind in self.priors.iteritems()] [np.put(ret, ind, p.lnpdf_grad(x[ind])) for p, ind in self.priors.iteritems()]
return ret return ret

View file

@ -89,7 +89,7 @@ def toy_linear_1d_classification_laplace(seed=default_seed, optimize=True, plot=
likelihood = GPy.likelihoods.Bernoulli() likelihood = GPy.likelihoods.Bernoulli()
laplace_inf = GPy.inference.latent_function_inference.Laplace() laplace_inf = GPy.inference.latent_function_inference.Laplace()
kernel = GPy.kern.rbf(1) kernel = GPy.kern.RBF(1)
# Model definition # Model definition
m = GPy.core.GP(data['X'], Y, kernel=kernel, likelihood=likelihood, inference_method=laplace_inf) m = GPy.core.GP(data['X'], Y, kernel=kernel, likelihood=likelihood, inference_method=laplace_inf)

View file

@ -318,7 +318,7 @@ def toy_ARD(max_iters=1000, kernel_type='linear', num_samples=300, D=4, optimize
Y /= Y.std() Y /= Y.std()
if kernel_type == 'linear': if kernel_type == 'linear':
kernel = GPy.kern.linear(X.shape[1], ARD=1) kernel = GPy.kern.Linear(X.shape[1], ARD=1)
elif kernel_type == 'rbf_inv': elif kernel_type == 'rbf_inv':
kernel = GPy.kern.RBF_inv(X.shape[1], ARD=1) kernel = GPy.kern.RBF_inv(X.shape[1], ARD=1)
else: else:
@ -357,7 +357,7 @@ def toy_ARD_sparse(max_iters=1000, kernel_type='linear', num_samples=300, D=4, o
Y /= Y.std() Y /= Y.std()
if kernel_type == 'linear': if kernel_type == 'linear':
kernel = GPy.kern.linear(X.shape[1], ARD=1) kernel = GPy.kern.Linear(X.shape[1], ARD=1)
elif kernel_type == 'rbf_inv': elif kernel_type == 'rbf_inv':
kernel = GPy.kern.RBF_inv(X.shape[1], ARD=1) kernel = GPy.kern.RBF_inv(X.shape[1], ARD=1)
else: else:

View file

@ -27,8 +27,8 @@ etc.
from exact_gaussian_inference import ExactGaussianInference from exact_gaussian_inference import ExactGaussianInference
from laplace import Laplace from laplace import Laplace
expectation_propagation = 'foo' # TODO
from GPy.inference.latent_function_inference.var_dtc import VarDTC from GPy.inference.latent_function_inference.var_dtc import VarDTC
from expectation_propagation import EP
from dtc import DTC from dtc import DTC
from fitc import FITC from fitc import FITC

View file

@ -1,7 +1,7 @@
import numpy as np import numpy as np
from scipy import stats from ...util.linalg import pdinv,jitchol,DSYR,tdot,dtrtrs, dpotrs
from ..util.linalg import pdinv,mdot,jitchol,chol_inv,DSYR,tdot,dtrtrs from posterior import Posterior
from likelihood import likelihood log_2_pi = np.log(2*np.pi)
class EP(object): class EP(object):
def __init__(self, epsilon=1e-6, eta=1., delta=1.): def __init__(self, epsilon=1e-6, eta=1., delta=1.):
@ -28,30 +28,30 @@ class EP(object):
K = kern.K(X) K = kern.K(X)
mu_tilde, tau_tilde = self.expectation_propagation() mu, Sigma, mu_tilde, tau_tilde, Z_hat = self.expectation_propagation(K, Y, likelihood, Y_metadata)
Wi, LW, LWi, W_logdet = pdinv(K + np.diag(1./tau_tilde) Wi, LW, LWi, W_logdet = pdinv(K + np.diag(1./tau_tilde))
alpha, _ = dpotrs(LW, mu_tilde, lower=1) alpha, _ = dpotrs(LW, mu_tilde, lower=1)
log_marginal = 0.5*(-num_data * log_2_pi - W_logdet - np.sum(alpha * mu_tilde)) log_marginal = 0.5*(-num_data * log_2_pi - W_logdet - np.sum(alpha * mu_tilde)) # TODO: add log Z_hat??
dL_dK = 0.5 * (tdot(alpha[:,None]) - Wi) dL_dK = 0.5 * (tdot(alpha[:,None]) - Wi)
#TODO: what abot derivatives of the likelihood parameters? dL_dthetaL = np.zeros(likelihood.size)#TODO: derivatives of the likelihood parameters
return Posterior(woodbury_inv=Wi, woodbury_vector=alpha, K=K), log_marginal, {'dL_dK':dL_dK} return Posterior(woodbury_inv=Wi, woodbury_vector=alpha, K=K), log_marginal, {'dL_dK':dL_dK, 'dL_dthetaL':dL_dthetaL}
def expectation_propagation(self, K, Y, Y_metadata, likelihood) def expectation_propagation(self, K, Y, likelihood, Y_metadata):
num_data, data_dim = Y.shape num_data, data_dim = Y.shape
assert data_dim == 1, "This EP methods only works for 1D outputs" assert data_dim == 1, "This EP methods only works for 1D outputs"
#Initial values - Posterior distribution parameters: q(f|X,Y) = N(f|mu,Sigma) #Initial values - Posterior distribution parameters: q(f|X,Y) = N(f|mu,Sigma)
mu = np.zeros(self.num_data) mu = np.zeros(num_data)
Sigma = K.copy() Sigma = K.copy()
#Initial values - Marginal moments #Initial values - Marginal moments
@ -61,33 +61,32 @@ class EP(object):
#initial values - Gaussian factors #initial values - Gaussian factors
if self.old_mutilde is None: if self.old_mutilde is None:
tau_tilde, mu_tilde, v_tilde = np.zeros((3, num_data, num_data)) tau_tilde, mu_tilde, v_tilde = np.zeros((3, num_data))
else: else:
assert old_mutilde.size == num_data, "data size mis-match: did you change the data? try resetting!" assert old_mutilde.size == num_data, "data size mis-match: did you change the data? try resetting!"
mu_tilde, v_tilde = self.old_mutilde, self.old_vtilde mu_tilde, v_tilde = self.old_mutilde, self.old_vtilde
tau_tilde = v_tilde/mu_tilde tau_tilde = v_tilde/mu_tilde
#Approximation #Approximation
epsilon_np1 = self.epsilon + 1. tau_diff = self.epsilon + 1.
epsilon_np2 = self.epsilon + 1. v_diff = self.epsilon + 1.
iterations = 0 iterations = 0
while (epsilon_np1 > self.epsilon) or (epsilon_np2 > self.epsilon): while (tau_diff > self.epsilon) or (v_diff > self.epsilon):
update_order = np.random.permutation(num_data) update_order = np.random.permutation(num_data)
for i in update_order: for i in update_order:
#Cavity distribution parameters #Cavity distribution parameters
tau_cav = 1./Sigma[i,i] - self.eta*tau_tilde[i] tau_cav = 1./Sigma[i,i] - self.eta*tau_tilde[i]
v_cav = mu[i]/Sigma[i,i] - self.eta*v_tilde[i] v_cav = mu[i]/Sigma[i,i] - self.eta*v_tilde[i]
#Marginal moments #Marginal moments
Z_hat[i], mu_hat[i], sigma2_hat[i] = likelihood.moments_match(Y[i], tau_cav, v_cav, Y_metadata=(None if Y_metadata is None else Y_metadata[i])) Z_hat[i], mu_hat[i], sigma2_hat[i] = likelihood.moments_match_ep(Y[i], tau_cav, v_cav)#, Y_metadata=None)#=(None if Y_metadata is None else Y_metadata[i]))
#Site parameters update #Site parameters update
delta_tau = self.delta/self.eta*(1./sigma2_hat[i] - 1./Sigma[i,i]) delta_tau = self.delta/self.eta*(1./sigma2_hat[i] - 1./Sigma[i,i])
delta_v = self.delta/self.eta*(mu_hat[i]/sigma2_hat[i] - mu[i]/Sigma[i,i]) delta_v = self.delta/self.eta*(mu_hat[i]/sigma2_hat[i] - mu[i]/Sigma[i,i])
tau_tilde[i] += delta_tau tau_tilde[i] += delta_tau
v_tilde[i] += delta_v v_tilde[i] += delta_v
#Posterior distribution parameters update #Posterior distribution parameters update
DSYR(Sigma, Sigma[:,i].copy(), -Delta_tau/(1.+ Delta_tau*Sigma[i,i])) DSYR(Sigma, Sigma[:,i].copy(), -delta_tau/(1.+ delta_tau*Sigma[i,i]))
mu = np.dot(Sigma, v_tilde) mu = np.dot(Sigma, v_tilde)
iterations += 1
#(re) compute Sigma and mu using full Cholesky decompy #(re) compute Sigma and mu using full Cholesky decompy
tau_tilde_root = np.sqrt(tau_tilde) tau_tilde_root = np.sqrt(tau_tilde)
@ -99,10 +98,14 @@ class EP(object):
mu = np.dot(Sigma,v_tilde) mu = np.dot(Sigma,v_tilde)
#monitor convergence #monitor convergence
epsilon_np1 = np.mean(np.square(tau_tilde-tau_tilde_old)) if iterations>0:
epsilon_np2 = np.mean(np.square(v_tilde-v_tilde_old)) tau_diff = np.mean(np.square(tau_tilde-tau_tilde_old))
v_diff = np.mean(np.square(v_tilde-v_tilde_old))
tau_tilde_old = tau_tilde.copy() tau_tilde_old = tau_tilde.copy()
v_tilde_old = v_tilde.copy() v_tilde_old = v_tilde.copy()
return mu, Sigma, mu_tilde, tau_tilde iterations += 1
mu_tilde = v_tilde/tau_tilde
return mu, Sigma, mu_tilde, tau_tilde, Z_hat

View file

@ -9,7 +9,9 @@ from kern import CombinationKernel
class Add(CombinationKernel): class Add(CombinationKernel):
""" """
Add given list of kernels together. Add given list of kernels together.
propagates gradients thorugh. propagates gradients through.
This kernel will take over the active dims of it's subkernels passed in.
""" """
def __init__(self, subkerns, name='add'): def __init__(self, subkerns, name='add'):
super(Add, self).__init__(subkerns, name) super(Add, self).__init__(subkerns, name)

View file

@ -17,9 +17,9 @@ class Brownian(Kern):
:param variance: :param variance:
:type variance: float :type variance: float
""" """
def __init__(self, input_dim=1, variance=1., name='Brownian'): def __init__(self, input_dim=1, variance=1., active_dims=None, name='Brownian'):
assert input_dim==1, "Brownian motion in 1D only" assert input_dim==1, "Brownian motion in 1D only"
super(Brownian, self).__init__(input_dim, name) super(Brownian, self).__init__(input_dim, active_dims, name)
self.variance = Param('variance', variance, Logexp()) self.variance = Param('variance', variance, Logexp())
self.add_parameters(self.variance) self.add_parameters(self.variance)

View file

@ -34,8 +34,8 @@ class Coregionalize(Kern):
.. note: see coregionalization examples in GPy.examples.regression for some usage. .. note: see coregionalization examples in GPy.examples.regression for some usage.
""" """
def __init__(self, input_dim, output_dim, rank=1, W=None, kappa=None, name='coregion'): def __init__(self, input_dim, output_dim, rank=1, W=None, kappa=None, active_dims=None, name='coregion'):
super(Coregionalize, self).__init__(input_dim, name=name) super(Coregionalize, self).__init__(input_dim, active_dims, name=name)
self.output_dim = output_dim self.output_dim = output_dim
self.rank = rank self.rank = rank
if self.rank>output_dim: if self.rank>output_dim:

View file

@ -2,7 +2,7 @@
# Licensed under the BSD 3-clause license (see LICENSE.txt) # Licensed under the BSD 3-clause license (see LICENSE.txt)
from kern import Kern from kern import Kern, CombinationKernel
import numpy as np import numpy as np
import itertools import itertools
@ -32,7 +32,7 @@ def index_to_slices(index):
[ret[ind_i].append(slice(*indexes_i)) for ind_i,indexes_i in zip(ind[switchpoints[:-1]],zip(switchpoints,switchpoints[1:]))] [ret[ind_i].append(slice(*indexes_i)) for ind_i,indexes_i in zip(ind[switchpoints[:-1]],zip(switchpoints,switchpoints[1:]))]
return ret return ret
class IndependentOutputs(Kern): class IndependentOutputs(CombinationKernel):
""" """
A kernel which can represent several independent functions. A kernel which can represent several independent functions.
this kernel 'switches off' parts of the matrix where the output indexes are different. this kernel 'switches off' parts of the matrix where the output indexes are different.
@ -41,12 +41,12 @@ class IndependentOutputs(Kern):
the rest of the columns of X are passed to the underlying kernel for computation (in blocks). the rest of the columns of X are passed to the underlying kernel for computation (in blocks).
""" """
def __init__(self, index_dim, kern, name='independ'): def __init__(self, kern, index_dim=-1, name='independ'):
assert isinstance(index_dim, int), "IndependentOutputs kernel is only defined with one input dimension being the indeces" assert isinstance(index_dim, int), "IndependentOutputs kernel is only defined with one input dimension being the indeces"
super(IndependentOutputs, self).__init__(np.r_[0:max(max(kern.active_dims)+1, index_dim+1)], name) super(IndependentOutputs, self).__init__(kernels=[kern], extra_dims=[index_dim], name=name)
self.index_dim = index_dim self.index_dim = index_dim
self.kern = kern self.kern = kern
self.add_parameters(self.kern) #self.add_parameters(self.kern)
def K(self,X ,X2=None): def K(self,X ,X2=None):
slices = index_to_slices(X[:,self.index_dim]) slices = index_to_slices(X[:,self.index_dim])
@ -80,19 +80,19 @@ class IndependentOutputs(Kern):
self.kern.gradient = target self.kern.gradient = target
def gradients_X(self,dL_dK, X, X2=None): def gradients_X(self,dL_dK, X, X2=None):
target = np.zeros_like(X) target = np.zeros(X.shape)
slices = index_to_slices(X[:,self.index_dim]) slices = index_to_slices(X[:,self.index_dim])
if X2 is None: if X2 is None:
[[np.copyto(target[s,self.kern.active_dims], self.kern.gradients_X(dL_dK[s,ss],X[s],X[ss])) for s, ss in itertools.product(slices_i, slices_i)] for slices_i in slices] [[np.copyto(target[s,self.kern.active_dims], self.kern.gradients_X(dL_dK[s,ss],X[s],X[ss])) for s, ss in itertools.product(slices_i, slices_i)] for slices_i in slices]
else: else:
X2,slices2 = X2[:,:self.index_dim],index_to_slices(X2[:,-1]) slices2 = index_to_slices(X2[:,self.index_dim])
[[[np.copyto(target[s,:self.index_dim], self.kern.gradients_X(dL_dK[s,s2], X[s], X2[s2])) for s in slices_i] for s2 in slices_j] for slices_i,slices_j in zip(slices,slices2)] [[[np.copyto(target[s,self.kern.active_dims], self.kern.gradients_X(dL_dK[s,s2], X[s], X2[s2])) for s in slices_i] for s2 in slices_j] for slices_i,slices_j in zip(slices,slices2)]
return target return target
def gradients_X_diag(self, dL_dKdiag, X): def gradients_X_diag(self, dL_dKdiag, X):
slices = index_to_slices(X[:,self.index_dim]) slices = index_to_slices(X[:,self.index_dim])
target = np.zeros(X.shape) target = np.zeros(X.shape)
[[np.copyto(target[s,:-1], self.kern.gradients_X_diag(dL_dKdiag[s],X[s])) for s in slices_i] for slices_i in slices] [[np.copyto(target[s,self.kern.active_dims], self.kern.gradients_X_diag(dL_dKdiag[s],X[s])) for s in slices_i] for slices_i in slices]
return target return target
def update_gradients_diag(self, dL_dKdiag, X): def update_gradients_diag(self, dL_dKdiag, X):

View file

@ -16,26 +16,32 @@ class Kern(Parameterized):
__metaclass__ = KernCallsViaSlicerMeta __metaclass__ = KernCallsViaSlicerMeta
#=========================================================================== #===========================================================================
_debug=False _debug=False
def __init__(self, input_dim, name, *a, **kw): def __init__(self, input_dim, active_dims, name, *a, **kw):
""" """
The base class for a kernel: a positive definite function The base class for a kernel: a positive definite function
which forms of a covariance function (kernel). which forms of a covariance function (kernel).
:param input_dim: the number of input dimensions to the function :param int input_dim: the number of input dimensions to the function
:type input_dim: int :param array-like|slice active_dims: list of indices on which dimensions this kernel works on
Do not instantiate. Do not instantiate.
""" """
super(Kern, self).__init__(name=name, *a, **kw) super(Kern, self).__init__(name=name, *a, **kw)
if isinstance(input_dim, int): self.active_dims = active_dims if active_dims is not None else slice(0, input_dim)
self.active_dims = np.r_[0:input_dim]
self.input_dim = input_dim self.input_dim = input_dim
assert isinstance(self.active_dims, (slice, list, tuple, np.ndarray)), 'active_dims needs to be an array-like or slice object over dimensions, {} given'.format(self.active_dims.__class__)
if isinstance(self.active_dims, slice):
self.active_dims = slice(self.active_dims.start or 0, self.active_dims.stop or self.input_dim, self.active_dims.step or 1)
active_dim_size = int(np.round((self.active_dims.stop-self.active_dims.start)/self.active_dims.step))
elif isinstance(self.active_dims, np.ndarray):
assert self.active_dims.ndim == 1, 'only flat indices allowed, given active_dims.shape={}, provide only indexes to the dimensions of the input'.format(self.active_dims.shape)
active_dim_size = self.active_dims.size
else: else:
self.active_dims = np.r_[input_dim] active_dim_size = len(self.active_dims)
self.input_dim = len(self.active_dims) assert active_dim_size == self.input_dim, "input_dim={} does not match len(active_dim)={}, active_dims={}".format(self.input_dim, active_dim_size, self.active_dims)
self._sliced_X = 0 self._sliced_X = 0
@Cache_this(limit=10)#, ignore_args = (0,)) @Cache_this(limit=10)
def _slice_X(self, X): def _slice_X(self, X):
return X[:, self.active_dims] return X[:, self.active_dims]
@ -69,9 +75,7 @@ class Kern(Parameterized):
def update_gradients_full(self, dL_dK, X, X2): def update_gradients_full(self, dL_dK, X, X2):
"""Set the gradients of all parameters when doing full (N) inference.""" """Set the gradients of all parameters when doing full (N) inference."""
raise NotImplementedError raise NotImplementedError
def update_gradients_diag(self, dL_dKdiag, X):
"""Set the gradients for all parameters for the derivative of the diagonal of the covariance w.r.t the kernel parameters."""
raise NotImplementedError
def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior):
""" """
Set the gradients of all parameters when doing inference with Set the gradients of all parameters when doing inference with
@ -193,13 +197,28 @@ class Kern(Parameterized):
super(Kern, self)._setstate(state) super(Kern, self)._setstate(state)
class CombinationKernel(Kern): class CombinationKernel(Kern):
def __init__(self, kernels, name): """
Abstract super class for combination kernels.
A combination kernel combines (a list of) kernels and works on those.
Examples are the HierarchicalKernel or Add and Prod kernels.
"""
def __init__(self, kernels, name, extra_dims=[]):
"""
Abstract super class for combination kernels.
A combination kernel combines (a list of) kernels and works on those.
Examples are the HierarchicalKernel or Add and Prod kernels.
:param list kernels: List of kernels to combine (can be only one element)
:param str name: name of the combination kernel
:param array-like|slice extra_dims: if needed extra dimensions for the combination kernel to work on
"""
assert all([isinstance(k, Kern) for k in kernels]) assert all([isinstance(k, Kern) for k in kernels])
# make sure the active dimensions of all underlying kernels are covered: active_dims = reduce(np.union1d, (np.r_[x.active_dims] for x in kernels), np.array([], dtype=int))
ma = reduce(lambda a,b: max(a, max(b)), (x.active_dims for x in kernels), 0) input_dim = active_dims.max()+1 + len(extra_dims)
input_dim = np.r_[0:ma+1] active_dims = slice(active_dims.max()+1+len(extra_dims))
# initialize the kernel with the full input_dim # initialize the kernel with the full input_dim
super(CombinationKernel, self).__init__(input_dim, name) super(CombinationKernel, self).__init__(input_dim, active_dims, name)
self.extra_dims = extra_dims
self.add_parameters(*kernels) self.add_parameters(*kernels)
@property @property

View file

@ -34,8 +34,8 @@ class Linear(Kern):
""" """
def __init__(self, input_dim, variances=None, ARD=False, name='linear'): def __init__(self, input_dim, variances=None, ARD=False, active_dims=None, name='linear'):
super(Linear, self).__init__(input_dim, name) super(Linear, self).__init__(input_dim, active_dims, name)
self.ARD = ARD self.ARD = ARD
if not ARD: if not ARD:
if variances is not None: if variances is not None:

View file

@ -31,8 +31,8 @@ class MLP(Kern):
""" """
def __init__(self, input_dim, variance=1., weight_variance=1., bias_variance=100., name='mlp'): def __init__(self, input_dim, variance=1., weight_variance=1., bias_variance=100., active_dims=None, name='mlp'):
super(MLP, self).__init__(input_dim, name) super(MLP, self).__init__(input_dim, active_dims, name)
self.variance = Param('variance', variance, Logexp()) self.variance = Param('variance', variance, Logexp())
self.weight_variance = Param('weight_variance', weight_variance, Logexp()) self.weight_variance = Param('weight_variance', weight_variance, Logexp())
self.bias_variance = Param('bias_variance', bias_variance, Logexp()) self.bias_variance = Param('bias_variance', bias_variance, Logexp())

View file

@ -10,7 +10,7 @@ from ...core.parameterization.param import Param
from ...core.parameterization.transformations import Logexp from ...core.parameterization.transformations import Logexp
class Periodic(Kern): class Periodic(Kern):
def __init__(self, input_dim, variance, lengthscale, period, n_freq, lower, upper, name): def __init__(self, input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name):
""" """
:type input_dim: int :type input_dim: int
:param variance: the variance of the Matern kernel :param variance: the variance of the Matern kernel
@ -25,7 +25,7 @@ class Periodic(Kern):
""" """
assert input_dim==1, "Periodic kernels are only defined for input_dim=1" assert input_dim==1, "Periodic kernels are only defined for input_dim=1"
super(Periodic, self).__init__(input_dim, name) super(Periodic, self).__init__(input_dim, active_dims, name)
self.input_dim = input_dim self.input_dim = input_dim
self.lower,self.upper = lower, upper self.lower,self.upper = lower, upper
self.n_freq = n_freq self.n_freq = n_freq
@ -77,8 +77,8 @@ class PeriodicExponential(Periodic):
Only defined for input_dim=1. Only defined for input_dim=1.
""" """
def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, name='periodic_exponential'): def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, active_dims=None, name='periodic_exponential'):
super(PeriodicExponential, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, name) super(PeriodicExponential, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name)
def parameters_changed(self): def parameters_changed(self):
self.a = [1./self.lengthscale, 1.] self.a = [1./self.lengthscale, 1.]
@ -187,8 +187,8 @@ class PeriodicMatern32(Periodic):
""" """
def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, name='periodic_Matern32'): def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, active_dims=None, name='periodic_Matern32'):
super(PeriodicMatern32, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, name) super(PeriodicMatern32, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name)
def parameters_changed(self): def parameters_changed(self):
self.a = [3./self.lengthscale**2, 2*np.sqrt(3)/self.lengthscale, 1.] self.a = [3./self.lengthscale**2, 2*np.sqrt(3)/self.lengthscale, 1.]
self.b = [1,self.lengthscale**2/3] self.b = [1,self.lengthscale**2/3]
@ -300,8 +300,8 @@ class PeriodicMatern52(Periodic):
""" """
def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, name='periodic_Matern52'): def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, active_dims=None, name='periodic_Matern52'):
super(PeriodicMatern52, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, name) super(PeriodicMatern52, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name)
def parameters_changed(self): def parameters_changed(self):
self.a = [5*np.sqrt(5)/self.lengthscale**3, 15./self.lengthscale**2,3*np.sqrt(5)/self.lengthscale, 1.] self.a = [5*np.sqrt(5)/self.lengthscale**3, 15./self.lengthscale**2,3*np.sqrt(5)/self.lengthscale, 1.]

View file

@ -19,8 +19,8 @@ class RBF(Stationary):
k(r) = \sigma^2 \exp \\bigg(- \\frac{1}{2} r^2 \\bigg) k(r) = \sigma^2 \exp \\bigg(- \\frac{1}{2} r^2 \\bigg)
""" """
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, name='rbf'): def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='rbf'):
super(RBF, self).__init__(input_dim, variance, lengthscale, ARD, name) super(RBF, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
self.weave_options = {} self.weave_options = {}
def K_of_r(self, r): def K_of_r(self, r):

View file

@ -33,9 +33,9 @@ class SSRBF(Stationary):
.. Note: this object implements both the ARD and 'spherical' version of the function .. Note: this object implements both the ARD and 'spherical' version of the function
""" """
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=True, name='SSRBF'): def __init__(self, input_dim, variance=1., lengthscale=None, ARD=True, active_dims=None, name='SSRBF'):
assert ARD==True, "Not Implemented!" assert ARD==True, "Not Implemented!"
super(SSRBF, self).__init__(input_dim, variance, lengthscale, ARD, name) super(SSRBF, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
def K_of_r(self, r): def K_of_r(self, r):
return self.variance * np.exp(-0.5 * r**2) return self.variance * np.exp(-0.5 * r**2)

View file

@ -9,8 +9,8 @@ from ...core.parameterization.transformations import Logexp
import numpy as np import numpy as np
class Static(Kern): class Static(Kern):
def __init__(self, input_dim, variance, name): def __init__(self, input_dim, variance, active_dims, name):
super(Static, self).__init__(input_dim, name) super(Static, self).__init__(input_dim, active_dims, name)
self.variance = Param('variance', variance, Logexp()) self.variance = Param('variance', variance, Logexp())
self.add_parameters(self.variance) self.add_parameters(self.variance)
@ -43,8 +43,8 @@ class Static(Kern):
class White(Static): class White(Static):
def __init__(self, input_dim, variance=1., name='white'): def __init__(self, input_dim, variance=1., active_dims=None, name='white'):
super(White, self).__init__(input_dim, variance, name) super(White, self).__init__(input_dim, variance, active_dims, name)
def K(self, X, X2=None): def K(self, X, X2=None):
if X2 is None: if X2 is None:
@ -66,8 +66,8 @@ class White(Static):
class Bias(Static): class Bias(Static):
def __init__(self, input_dim, variance=1., name='bias'): def __init__(self, input_dim, variance=1., active_dims=None, name='bias'):
super(Bias, self).__init__(input_dim, variance, name) super(Bias, self).__init__(input_dim, variance, active_dims, name)
def K(self, X, X2=None): def K(self, X, X2=None):
shape = (X.shape[0], X.shape[0] if X2 is None else X2.shape[0]) shape = (X.shape[0], X.shape[0] if X2 is None else X2.shape[0])
@ -90,14 +90,14 @@ class Bias(Static):
self.variance.gradient = dL_dpsi0.sum() + dL_dpsi1.sum() + 2.*self.variance*dL_dpsi2.sum() self.variance.gradient = dL_dpsi0.sum() + dL_dpsi1.sum() + 2.*self.variance*dL_dpsi2.sum()
class Fixed(Static): class Fixed(Static):
def __init__(self, input_dim, covariance_matrix, variance=1., name='fixed'): def __init__(self, input_dim, covariance_matrix, variance=1., active_dims=None, name='fixed'):
""" """
:param input_dim: the number of input dimensions :param input_dim: the number of input dimensions
:type input_dim: int :type input_dim: int
:param variance: the variance of the kernel :param variance: the variance of the kernel
:type variance: float :type variance: float
""" """
super(Bias, self).__init__(input_dim, variance, name) super(Bias, self).__init__(input_dim, variance, active_dims, name)
self.fixed_K = covariance_matrix self.fixed_K = covariance_matrix
def K(self, X, X2): def K(self, X, X2):
return self.variance * self.fixed_K return self.variance * self.fixed_K

View file

@ -41,8 +41,8 @@ class Stationary(Kern):
""" """
def __init__(self, input_dim, variance, lengthscale, ARD, name): def __init__(self, input_dim, variance, lengthscale, ARD, active_dims, name):
super(Stationary, self).__init__(input_dim, name) super(Stationary, self).__init__(input_dim, active_dims, name)
self.ARD = ARD self.ARD = ARD
if not ARD: if not ARD:
if lengthscale is None: if lengthscale is None:
@ -186,8 +186,8 @@ class Stationary(Kern):
return np.ones(self.input_dim)/self.lengthscale return np.ones(self.input_dim)/self.lengthscale
class Exponential(Stationary): class Exponential(Stationary):
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, name='Exponential'): def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Exponential'):
super(Exponential, self).__init__(input_dim, variance, lengthscale, ARD, name) super(Exponential, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
def K_of_r(self, r): def K_of_r(self, r):
return self.variance * np.exp(-0.5 * r) return self.variance * np.exp(-0.5 * r)
@ -205,8 +205,8 @@ class Matern32(Stationary):
""" """
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, name='Mat32'): def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Mat32'):
super(Matern32, self).__init__(input_dim, variance, lengthscale, ARD, name) super(Matern32, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
def K_of_r(self, r): def K_of_r(self, r):
return self.variance * (1. + np.sqrt(3.) * r) * np.exp(-np.sqrt(3.) * r) return self.variance * (1. + np.sqrt(3.) * r) * np.exp(-np.sqrt(3.) * r)
@ -249,8 +249,8 @@ class Matern52(Stationary):
k(r) = \sigma^2 (1 + \sqrt{5} r + \\frac53 r^2) \exp(- \sqrt{5} r) k(r) = \sigma^2 (1 + \sqrt{5} r + \\frac53 r^2) \exp(- \sqrt{5} r)
""" """
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, name='Mat52'): def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Mat52'):
super(Matern52, self).__init__(input_dim, variance, lengthscale, ARD, name) super(Matern52, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
def K_of_r(self, r): def K_of_r(self, r):
return self.variance*(1+np.sqrt(5.)*r+5./3*r**2)*np.exp(-np.sqrt(5.)*r) return self.variance*(1+np.sqrt(5.)*r+5./3*r**2)*np.exp(-np.sqrt(5.)*r)
@ -291,8 +291,8 @@ class Matern52(Stationary):
class ExpQuad(Stationary): class ExpQuad(Stationary):
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, name='ExpQuad'): def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='ExpQuad'):
super(ExpQuad, self).__init__(input_dim, variance, lengthscale, ARD, name) super(ExpQuad, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
def K_of_r(self, r): def K_of_r(self, r):
return self.variance * np.exp(-0.5 * r**2) return self.variance * np.exp(-0.5 * r**2)
@ -301,8 +301,8 @@ class ExpQuad(Stationary):
return -r*self.K_of_r(r) return -r*self.K_of_r(r)
class Cosine(Stationary): class Cosine(Stationary):
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, name='Cosine'): def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Cosine'):
super(Cosine, self).__init__(input_dim, variance, lengthscale, ARD, name) super(Cosine, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
def K_of_r(self, r): def K_of_r(self, r):
return self.variance * np.cos(r) return self.variance * np.cos(r)
@ -322,8 +322,8 @@ class RatQuad(Stationary):
""" """
def __init__(self, input_dim, variance=1., lengthscale=None, power=2., ARD=False, name='ExpQuad'): def __init__(self, input_dim, variance=1., lengthscale=None, power=2., ARD=False, active_dims=None, name='ExpQuad'):
super(RatQuad, self).__init__(input_dim, variance, lengthscale, ARD, name) super(RatQuad, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name)
self.power = Param('power', power, Logexp()) self.power = Param('power', power, Logexp())
self.add_parameters(self.power) self.add_parameters(self.power)

View file

@ -26,13 +26,13 @@ class Sympykern(Kern):
- to handle multiple inputs, call them x_1, z_1, etc - to handle multiple inputs, call them x_1, z_1, etc
- to handle multpile correlated outputs, you'll need to add parameters with an index, such as lengthscale_i and lengthscale_j. - to handle multpile correlated outputs, you'll need to add parameters with an index, such as lengthscale_i and lengthscale_j.
""" """
def __init__(self, input_dim, k=None, output_dim=1, name=None, param=None): def __init__(self, input_dim, k=None, output_dim=1, name=None, param=None, active_dims=None):
if name is None: if name is None:
name='sympykern' name='sympykern'
if k is None: if k is None:
raise ValueError, "You must provide an argument for the covariance function." raise ValueError, "You must provide an argument for the covariance function."
super(Sympykern, self).__init__(input_dim, name) super(Sympykern, self).__init__(input_dim, active_dims, name)
self._sp_k = k self._sp_k = k

View file

@ -5,6 +5,7 @@ import numpy as np
from ..util.univariate_Gaussian import std_norm_pdf, std_norm_cdf from ..util.univariate_Gaussian import std_norm_pdf, std_norm_cdf
import link_functions import link_functions
from likelihood import Likelihood from likelihood import Likelihood
from scipy import stats
class Bernoulli(Likelihood): class Bernoulli(Likelihood):
""" """
@ -43,7 +44,7 @@ class Bernoulli(Likelihood):
Y_prep[Y.flatten() == 0] = -1 Y_prep[Y.flatten() == 0] = -1
return Y_prep return Y_prep
def moments_match_ep(self, data_i, tau_i, v_i): def moments_match_ep(self, Y_i, tau_i, v_i):
""" """
Moments match of the marginal approximation in EP algorithm Moments match of the marginal approximation in EP algorithm
@ -51,9 +52,9 @@ class Bernoulli(Likelihood):
:param tau_i: precision of the cavity distribution (float) :param tau_i: precision of the cavity distribution (float)
:param v_i: mean/variance of the cavity distribution (float) :param v_i: mean/variance of the cavity distribution (float)
""" """
if data_i == 1: if Y_i == 1:
sign = 1. sign = 1.
elif data_i == 0: elif Y_i == 0:
sign = -1 sign = -1
else: else:
raise ValueError("bad value for Bernouilli observation (0, 1)") raise ValueError("bad value for Bernouilli observation (0, 1)")
@ -76,7 +77,7 @@ class Bernoulli(Likelihood):
return Z_hat, mu_hat, sigma2_hat return Z_hat, mu_hat, sigma2_hat
def predictive_mean(self, mu, variance): def predictive_mean(self, mu, variance, Y_metadata=None):
if isinstance(self.gp_link, link_functions.Probit): if isinstance(self.gp_link, link_functions.Probit):
return stats.norm.cdf(mu/np.sqrt(1+variance)) return stats.norm.cdf(mu/np.sqrt(1+variance))
@ -87,7 +88,7 @@ class Bernoulli(Likelihood):
else: else:
raise NotImplementedError raise NotImplementedError
def predictive_variance(self, mu, variance, pred_mean): def predictive_variance(self, mu, variance, pred_mean, Y_metadata=None):
if isinstance(self.gp_link, link_functions.Heaviside): if isinstance(self.gp_link, link_functions.Heaviside):
return 0. return 0.
@ -211,7 +212,7 @@ class Bernoulli(Likelihood):
np.seterr(**state) np.seterr(**state)
return d3logpdf_dlink3 return d3logpdf_dlink3
def samples(self, gp): def samples(self, gp, Y_metadata=None):
""" """
Returns a set of samples of observations based on a given value of the latent variable. Returns a set of samples of observations based on a given value of the latent variable.

View file

@ -23,7 +23,7 @@ class GPClassification(GP):
def __init__(self, X, Y, kernel=None): def __init__(self, X, Y, kernel=None):
if kernel is None: if kernel is None:
kernel = kern.rbf(X.shape[1]) kernel = kern.RBF(X.shape[1])
likelihood = likelihoods.Bernoulli() likelihood = likelihoods.Bernoulli()

View file

@ -118,7 +118,7 @@ class MRD(Model):
self._log_marginal_likelihood += lml self._log_marginal_likelihood += lml
# likelihood gradients # likelihood gradients
l.update_gradients(grad_dict.pop('partial_for_likelihood')) l.update_gradients(grad_dict.pop('dL_dthetaL'))
#gradients wrt kernel #gradients wrt kernel
dL_dKmm = grad_dict.pop('dL_dKmm') dL_dKmm = grad_dict.pop('dL_dKmm')

View file

@ -17,21 +17,30 @@ class Test(unittest.TestCase):
self.param_index.add(one, [3]) self.param_index.add(one, [3])
self.param_index.add(two, [0,5]) self.param_index.add(two, [0,5])
self.param_index.add(three, [2,4,7]) self.param_index.add(three, [2,4,7])
self.view = ParameterIndexOperationsView(self.param_index, 2, 6)
def test_clear(self):
self.param_index.clear()
self.assertDictEqual(self.param_index._properties, {})
def test_remove(self): def test_remove(self):
self.param_index.remove(three, np.r_[3:10]) self.param_index.remove(three, np.r_[3:10])
self.assertListEqual(self.param_index[three].tolist(), [2]) self.assertListEqual(self.param_index[three].tolist(), [2])
self.param_index.remove(one, [1]) self.param_index.remove(one, [1])
self.assertListEqual(self.param_index[one].tolist(), [3]) self.assertListEqual(self.param_index[one].tolist(), [3])
self.assertListEqual(self.param_index.remove('not in there', []).tolist(), [])
self.param_index.remove(one, [9])
self.assertListEqual(self.param_index[one].tolist(), [3])
self.assertListEqual(self.param_index.remove('not in there', [2,3,4]).tolist(), [])
def test_shift_left(self): def test_shift_left(self):
self.param_index.shift_left(1, 2) self.view.shift_left(0, 2)
self.assertListEqual(self.param_index[three].tolist(), [2,5]) self.assertListEqual(self.param_index[three].tolist(), [2,5])
self.assertListEqual(self.param_index[two].tolist(), [0,3]) self.assertListEqual(self.param_index[two].tolist(), [0,3])
self.assertListEqual(self.param_index[one].tolist(), [1]) self.assertListEqual(self.param_index[one].tolist(), [])
def test_shift_right(self): def test_shift_right(self):
self.param_index.shift_right(5, 2) self.view.shift_right(3, 2)
self.assertListEqual(self.param_index[three].tolist(), [2,4,9]) self.assertListEqual(self.param_index[three].tolist(), [2,4,9])
self.assertListEqual(self.param_index[two].tolist(), [0,7]) self.assertListEqual(self.param_index[two].tolist(), [0,7])
self.assertListEqual(self.param_index[one].tolist(), [3]) self.assertListEqual(self.param_index[one].tolist(), [3])
@ -44,17 +53,17 @@ class Test(unittest.TestCase):
# three three three # three three three
# view: [0 1 2 3 4 5 ] # view: [0 1 2 3 4 5 ]
#======================================================================= #=======================================================================
view = ParameterIndexOperationsView(self.param_index, 2, 6) self.view = ParameterIndexOperationsView(self.param_index, 2, 6)
self.assertSetEqual(set(view.properties()), set([one, two, three])) self.assertSetEqual(set(self.view.properties()), set([one, two, three]))
for v,p in zip(view.properties_for(np.r_[:6]), self.param_index.properties_for(np.r_[2:2+6])): for v,p in zip(self.view.properties_for(np.r_[:6]), self.param_index.properties_for(np.r_[2:2+6])):
self.assertEqual(v, p) self.assertEqual(v, p)
self.assertSetEqual(set(view[two]), set([3])) self.assertSetEqual(set(self.view[two]), set([3]))
self.assertSetEqual(set(self.param_index[two]), set([0, 5])) self.assertSetEqual(set(self.param_index[two]), set([0, 5]))
view.add(two, np.array([0])) self.view.add(two, np.array([0]))
self.assertSetEqual(set(view[two]), set([0,3])) self.assertSetEqual(set(self.view[two]), set([0,3]))
self.assertSetEqual(set(self.param_index[two]), set([0, 2, 5])) self.assertSetEqual(set(self.param_index[two]), set([0, 2, 5]))
view.clear() self.view.clear()
for v,p in zip(view.properties_for(np.r_[:6]), self.param_index.properties_for(np.r_[2:2+6])): for v,p in zip(self.view.properties_for(np.r_[:6]), self.param_index.properties_for(np.r_[2:2+6])):
self.assertEqual(v, p) self.assertEqual(v, p)
self.assertEqual(v, []) self.assertEqual(v, [])
param_index = ParameterIndexOperations() param_index = ParameterIndexOperations()
@ -62,11 +71,17 @@ class Test(unittest.TestCase):
param_index.add(two, [0,5]) param_index.add(two, [0,5])
param_index.add(three, [2,4,7]) param_index.add(three, [2,4,7])
view2 = ParameterIndexOperationsView(param_index, 2, 6) view2 = ParameterIndexOperationsView(param_index, 2, 6)
view.update(view2) self.view.update(view2)
for [i,v],[i2,v2] in zip(sorted(param_index.items()), sorted(self.param_index.items())): for [i,v],[i2,v2] in zip(sorted(param_index.items()), sorted(self.param_index.items())):
self.assertEqual(i, i2) self.assertEqual(i, i2)
self.assertTrue(np.all(v == v2)) self.assertTrue(np.all(v == v2))
def test_misc(self):
for k,v in self.param_index.copy()._properties.iteritems():
self.assertListEqual(self.param_index[k].tolist(), v.tolist())
self.assertEqual(self.param_index.size, 6)
self.assertEqual(self.view.size, 5)
if __name__ == "__main__": if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.test_index_view'] #import sys;sys.argv = ['', 'Test.test_index_view']
unittest.main() unittest.main()

View file

@ -228,12 +228,12 @@ class KernelGradientTestsContinuous(unittest.TestCase):
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
def test_Prod(self): def test_Prod(self):
k = GPy.kern.Matern32([2,3]) * GPy.kern.RBF([0,4]) + GPy.kern.Linear(self.D) k = GPy.kern.Matern32(2, active_dims=[2,3]) * GPy.kern.RBF(2, active_dims=[0,4]) + GPy.kern.Linear(self.D)
k.randomize() k.randomize()
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
def test_Add(self): def test_Add(self):
k = GPy.kern.Matern32([2,3]) + GPy.kern.RBF([0,4]) + GPy.kern.Linear(self.D) k = GPy.kern.Matern32(2, active_dims=[2,3]) + GPy.kern.RBF(2, active_dims=[0,4]) + GPy.kern.Linear(self.D)
k.randomize() k.randomize()
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
@ -282,15 +282,16 @@ class KernelTestsMiscellaneous(unittest.TestCase):
def setUp(self): def setUp(self):
N, D = 100, 10 N, D = 100, 10
self.X = np.linspace(-np.pi, +np.pi, N)[:,None] * np.ones(D) self.X = np.linspace(-np.pi, +np.pi, N)[:,None] * np.ones(D)
self.rbf = GPy.kern.RBF(range(2)) self.rbf = GPy.kern.RBF(2, active_dims=slice(0,4,2))
self.linear = GPy.kern.Linear((3,6)) self.linear = GPy.kern.Linear(2, active_dims=(3,9))
self.matern = GPy.kern.Matern32(np.array([2,4,7])) self.matern = GPy.kern.Matern32(3, active_dims=np.array([2,4,9]))
self.sumkern = self.rbf + self.linear self.sumkern = self.rbf + self.linear
self.sumkern += self.matern self.sumkern += self.matern
self.sumkern.randomize() self.sumkern.randomize()
def test_active_dims(self): def test_active_dims(self):
self.assertListEqual(self.sumkern.active_dims.tolist(), range(8)) self.assertEqual(self.sumkern.input_dim, 10)
self.assertEqual(self.sumkern.active_dims, slice(0, 10, 1))
def test_which_parts(self): def test_which_parts(self):
self.assertTrue(np.allclose(self.sumkern.K(self.X, which_parts=[self.linear, self.matern]), self.linear.K(self.X)+self.matern.K(self.X))) self.assertTrue(np.allclose(self.sumkern.K(self.X, which_parts=[self.linear, self.matern]), self.linear.K(self.X)+self.matern.K(self.X)))
@ -310,11 +311,12 @@ class KernelTestsNonContinuous(unittest.TestCase):
self.X_block[N:N+N1, D:D+D] = self.X2 self.X_block[N:N+N1, D:D+D] = self.X2
self.X_block[0:N, -1] = 1 self.X_block[0:N, -1] = 1
self.X_block[N:N+1, -1] = 2 self.X_block[N:N+1, -1] = 2
self.X_block = self.X_block[self.X_block.argsort(0)[:, -1], :]
def test_IndependantOutputs(self): def test_IndependentOutputs(self):
k = GPy.kern.RBF(self.D) k = GPy.kern.RBF(self.D)
kern = GPy.kern.IndependentOutputs(self.D+self.D,k) kern = GPy.kern.IndependentOutputs(k, -1)
self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose)) self.assertTrue(check_kernel_gradient_functions(kern, X=self.X_block, X2=self.X_block, verbose=verbose))
if __name__ == "__main__": if __name__ == "__main__":
print "Running unit tests, please be (very) patient..." print "Running unit tests, please be (very) patient..."

View file

@ -7,8 +7,24 @@ import unittest
import GPy import GPy
import numpy as np import numpy as np
from GPy.core.parameterization.parameter_core import HierarchyError from GPy.core.parameterization.parameter_core import HierarchyError
from GPy.core.parameterization.array_core import ObservableArray
class Test(unittest.TestCase): class ArrayCoreTest(unittest.TestCase):
def setUp(self):
self.X = np.random.normal(1,1, size=(100,10))
self.obsX = ObservableArray(self.X)
def test_init(self):
X = ObservableArray(self.X)
X2 = ObservableArray(X)
self.assertIs(X, X2, "no new Observable array, when Observable is given")
def test_slice(self):
t1 = self.X[2:78]
t2 = self.obsX[2:78]
self.assertListEqual(t1.tolist(), t2.tolist(), "Slicing should be the exact same, as in ndarray")
class ParameterizedTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.rbf = GPy.kern.RBF(1) self.rbf = GPy.kern.RBF(1)
@ -35,7 +51,6 @@ class Test(unittest.TestCase):
self.white.fix(warning=False) self.white.fix(warning=False)
self.test1.remove_parameter(self.test1.param) self.test1.remove_parameter(self.test1.param)
self.assertTrue(self.test1._has_fixes()) self.assertTrue(self.test1._has_fixes())
from GPy.core.parameterization.transformations import FIXED, UNFIXED from GPy.core.parameterization.transformations import FIXED, UNFIXED
self.assertListEqual(self.test1._fixes_.tolist(),[UNFIXED,UNFIXED,FIXED]) self.assertListEqual(self.test1._fixes_.tolist(),[UNFIXED,UNFIXED,FIXED])

View file

@ -15,7 +15,7 @@ class PriorTests(unittest.TestCase):
X, y = X[:, None], y[:, None] X, y = X[:, None], y[:, None]
m = GPy.models.GPRegression(X, y) m = GPy.models.GPRegression(X, y)
lognormal = GPy.priors.LogGaussian(1, 2) lognormal = GPy.priors.LogGaussian(1, 2)
m.set_prior('rbf', lognormal) m.rbf.set_prior(lognormal)
m.randomize() m.randomize()
self.assertTrue(m.checkgrad()) self.assertTrue(m.checkgrad())
@ -28,7 +28,7 @@ class PriorTests(unittest.TestCase):
X, y = X[:, None], y[:, None] X, y = X[:, None], y[:, None]
m = GPy.models.GPRegression(X, y) m = GPy.models.GPRegression(X, y)
Gamma = GPy.priors.Gamma(1, 1) Gamma = GPy.priors.Gamma(1, 1)
m.set_prior('rbf', Gamma) m.rbf.set_prior(Gamma)
m.randomize() m.randomize()
self.assertTrue(m.checkgrad()) self.assertTrue(m.checkgrad())
@ -41,16 +41,9 @@ class PriorTests(unittest.TestCase):
X, y = X[:, None], y[:, None] X, y = X[:, None], y[:, None]
m = GPy.models.GPRegression(X, y) m = GPy.models.GPRegression(X, y)
gaussian = GPy.priors.Gaussian(1, 1) gaussian = GPy.priors.Gaussian(1, 1)
success = False
# setting a Gaussian prior on non-negative parameters # setting a Gaussian prior on non-negative parameters
# should raise an assertionerror. # should raise an assertionerror.
try: self.assertRaises(AssertionError, m.rbf.set_prior, gaussian)
m.set_prior('rbf', gaussian)
except AssertionError:
success = True
self.assertTrue(success)
if __name__ == "__main__": if __name__ == "__main__":