starting to sort out likelihoods WARNING not working

This commit is contained in:
Max Zwiessele 2013-10-17 14:38:43 +01:00
parent bc765134c0
commit 055eb3b70b
10 changed files with 247 additions and 142 deletions

View file

@ -53,9 +53,14 @@ class kern(Parameterized):
assert isinstance(p, Kernpart), "bad kernel part"
self.compute_param_slices()
self._parameters_ = []
for p in self.parts:
self._parameters_.extend(p._parameters_)
Parameterized.__init__(self)
def parameters_changed(self):
[p.parameters_changed() for p in self.parts]
def getstate(self):
"""
Get the current state of the class,
@ -303,20 +308,20 @@ class kern(Parameterized):
for i, t in zip(prev_constr_ind, prev_constr):
self.constrain(np.where(index_param == i)[0], t)
def _get_params(self):
return np.hstack([p._get_params() for p in self.parts])
def _set_params(self, x):
[p._set_params(x[s]) for p, s in zip(self.parts, self.param_slices)]
def _get_param_names(self):
# this is a bit nasty: we want to distinguish between parts with the same name by appending a count
part_names = np.array([k.name for k in self.parts], dtype=np.str)
counts = [np.sum(part_names == ni) for i, ni in enumerate(part_names)]
cum_counts = [np.sum(part_names[i:] == ni) for i, ni in enumerate(part_names)]
names = [name + '_' + str(cum_count) if count > 1 else name for name, count, cum_count in zip(part_names, counts, cum_counts)]
return sum([[name + '_' + n for n in k._get_param_names()] for name, k in zip(names, self.parts)], [])
# def _get_params(self):
# return np.hstack([p._get_params() for p in self.parts])
#
# def _set_params(self, x):
# [p._set_params(x[s]) for p, s in zip(self.parts, self.param_slices)]
#
# def _get_param_names(self):
# # this is a bit nasty: we want to distinguish between parts with the same name by appending a count
# part_names = np.array([k.name for k in self.parts], dtype=np.str)
# counts = [np.sum(part_names == ni) for i, ni in enumerate(part_names)]
# cum_counts = [np.sum(part_names[i:] == ni) for i, ni in enumerate(part_names)]
# names = [name + '_' + str(cum_count) if count > 1 else name for name, count, cum_count in zip(part_names, counts, cum_counts)]
#
# return sum([[name + '_' + n for n in k._get_param_names()] for name, k in zip(names, self.parts)], [])
def K(self, X, X2=None, which_parts='all'):
"""
@ -606,14 +611,14 @@ class Kern_check_model(Model):
else:
return True
def _get_params(self):
return self.kernel._get_params()
def _get_param_names(self):
return self.kernel._get_param_names()
def _set_params(self, x):
self.kernel._set_params(x)
# def _get_params(self):
# return self.kernel._get_params()
#
# def _get_param_names(self):
# return self.kernel._get_param_names()
#
# def _set_params(self, x):
# self.kernel._set_params(x)
def log_likelihood(self):
return (self.dL_dK*self.kernel.K(self.X, self.X2)).sum()

View file

@ -22,15 +22,17 @@ class Exponential(Kernpart):
:type lengthscale: array or list of the appropriate size (or float if there is only one lengthscale parameter)
:param ARD: Auto Relevance Determination. If equal to "False", the kernel is isotropic (ie. one single lengthscale parameter \ell), otherwise there is one lengthscale parameter per dimension.
:type ARD: Boolean
:param name: the name of the kernel
:rtype: kernel object
"""
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False):
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, name='exp'):
self.input_dim = input_dim
self.ARD = ARD
self.variance = variance
self.name = name
if ARD == False:
self.num_params = 2
self.name = 'exp'
if lengthscale is not None:
lengthscale = np.asarray(lengthscale)
assert lengthscale.size == 1, "Only one lengthscale needed for non-ARD kernel"
@ -38,30 +40,30 @@ class Exponential(Kernpart):
lengthscale = np.ones(1)
else:
self.num_params = self.input_dim + 1
self.name = 'exp'
if lengthscale is not None:
lengthscale = np.asarray(lengthscale)
assert lengthscale.size == self.input_dim, "bad number of lengthscales"
else:
lengthscale = np.ones(self.input_dim)
self._set_params(np.hstack((variance, lengthscale.flatten())))
#self._set_params(np.hstack((variance, lengthscale.flatten())))
self.set_as_parameter('variance', 'lengthscale')
def _get_params(self):
"""return the value of the parameters."""
return np.hstack((self.variance, self.lengthscale))
def _set_params(self, x):
"""set the value of the parameters."""
assert x.size == self.num_params
self.variance = x[0]
self.lengthscale = x[1:]
def _get_param_names(self):
"""return parameter names."""
if self.num_params == 2:
return ['variance', 'lengthscale']
else:
return ['variance'] + ['lengthscale_%i' % i for i in range(self.lengthscale.size)]
# def _get_params(self):
# """return the value of the parameters."""
# return np.hstack((self.variance, self.lengthscale))
#
# def _set_params(self, x):
# """set the value of the parameters."""
# assert x.size == self.num_params
# self.variance = x[0]
# self.lengthscale = x[1:]
#
# def _get_param_names(self):
# """return parameter names."""
# if self.num_params == 2:
# return ['variance', 'lengthscale']
# else:
# return ['variance'] + ['lengthscale_%i' % i for i in range(self.lengthscale.size)]
def K(self, X, X2, target):
"""Compute the covariance matrix between X and X2."""

View file

@ -1,11 +1,13 @@
# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
# Licensed under the BSD 3-clause license (see LICENSE.txt)
from ...core.parameter import Param
#from ...core.parameterized.Parameterized import set_as_parameter
class Kernpart(object):
def __init__(self,input_dim):
"""
The base class for a kernpart: a positive definite function which forms part of a covariance function (kernel).
The base class for a kernpart: a positive definite function
which forms part of a covariance function (kernel).
:param input_dim: the number of input dimensions to the function
:type input_dim: int
@ -18,13 +20,42 @@ class Kernpart(object):
self.num_params = 1
# the name of the covariance function.
self.name = 'unnamed'
def _get_params(self):
raise NotImplementedError
def _set_params(self,x):
raise NotImplementedError
def _get_param_names(self):
raise NotImplementedError
# link to parameterized objects
self._parameters_ = []
def set_as_parameter_named(self, name, gradient, index=None, *args, **kwargs):
"""
:param names: name of parameter to set as parameter
:param gradient: gradient method to get the gradient of this parameter
:param index: index of where to place parameter in printing
:param args, kwargs: additional arguments to gradient
Convenience method to connect Kernpart parameters:
parameter with name (attribute of this Kernpart) will be set as parameter with following name:
kernel_name + _ + parameter_name
To add the kernels name to the parameter name use this method to
add parameters.
"""
self.set_as_parameter(name, getattr(self, name), gradient, index, *args, **kwargs)
def set_as_parameter(self, name, array, gradient, index=None, *args, **kwargs):
"""
See :py:func:`GPy.core.parameterized.Parameterized.set_as_parameter`
Note: this method adds the kernels name in front of the parameter.
"""
p = Param(self.name+"_"+name, array, gradient, *args, **kwargs)
if index is None:
self._parameters_.append(p)
else:
self._parameters_.insert(index, p)
#set_as_parameter.__doc__ += set_as_parameter.__doc__ # @UndefinedVariable
# def _get_params(self):
# raise NotImplementedError
# def _set_params(self,x):
# raise NotImplementedError
# def _get_param_names(self):
# raise NotImplementedError
def K(self,X,X2,target):
raise NotImplementedError
def Kdiag(self,X,target):
@ -87,13 +118,13 @@ class Kernpart_stationary(Kernpart):
# initialize cache
self._Z, self._mu, self._S = np.empty(shape=(3, 1))
self._X, self._X2, self._params = np.empty(shape=(3, 1))
self._X, self._X2, self._parameters_ = np.empty(shape=(3, 1))
def _set_params(self, x):
self.lengthscale = x
self.lengthscale2 = np.square(self.lengthscale)
# reset cached results
self._X, self._X2, self._params = np.empty(shape=(3, 1))
self._X, self._X2, self._parameters_ = np.empty(shape=(3, 1))
self._Z, self._mu, self._S = np.empty(shape=(3, 1)) # cached versions of Z,mu,S
@ -120,4 +151,4 @@ class Kernpart_inner(Kernpart):
# initialize cache
self._Z, self._mu, self._S = np.empty(shape=(3, 1))
self._X, self._X2, self._params = np.empty(shape=(3, 1))
self._X, self._X2, self._parameters_ = np.empty(shape=(3, 1))

View file

@ -7,6 +7,7 @@ import numpy as np
from scipy import weave
from ...util.linalg import tdot
from ...util.misc import fast_array_equal
from GPy.core.parameter import Param
class RBF(Kernpart):
"""
@ -31,10 +32,11 @@ class RBF(Kernpart):
.. Note: this object implements both the ARD and 'spherical' version of the function
"""
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False):
def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, name='rbf'):
self.input_dim = input_dim
self.name = 'rbf'
self.name = name
self.ARD = ARD
self.variance = variance
if not ARD:
self.num_params = 2
if lengthscale is not None:
@ -50,36 +52,43 @@ class RBF(Kernpart):
else:
lengthscale = np.ones(self.input_dim)
self._set_params(np.hstack((variance, lengthscale.flatten())))
#self._set_params(np.hstack((variance, lengthscale.flatten())))
self.set_as_parameter_named('variance', )
# initialize cache
self._Z, self._mu, self._S = np.empty(shape=(3, 1))
self._X, self._X2, self._params = np.empty(shape=(3, 1))
self._X, self._X2, self._params_save = np.empty(shape=(3, 1))
# a set of optional args to pass to weave
self.weave_options = {'headers' : ['<omp.h>'],
'extra_compile_args': ['-fopenmp -O3'], # -march=native'],
'extra_link_args' : ['-lgomp']}
def _get_params(self):
return np.hstack((self.variance, self.lengthscale))
def _set_params(self, x):
assert x.size == (self.num_params)
self.variance = x[0]
self.lengthscale = x[1:]
def parameters_changed(self):
self.lengthscale2 = np.square(self.lengthscale)
# reset cached results
self._X, self._X2, self._params = np.empty(shape=(3, 1))
self._X, self._X2, self._params_save = np.empty(shape=(3, 1))
self._Z, self._mu, self._S = np.empty(shape=(3, 1)) # cached versions of Z,mu,S
def _get_param_names(self):
if self.num_params == 2:
return ['variance', 'lengthscale']
else:
return ['variance'] + ['lengthscale_%i' % i for i in range(self.lengthscale.size)]
# def _get_params(self):
# return np.hstack((self.variance, self.lengthscale))
#
# def _set_params(self, x):
# assert x.size == (self.num_params)
# self.variance = x[0]
# self.lengthscale = x[1:]
# self.lengthscale2 = np.square(self.lengthscale)
# # reset cached results
# self._X, self._X2, self._params_save = np.empty(shape=(3, 1))
# self._Z, self._mu, self._S = np.empty(shape=(3, 1)) # cached versions of Z,mu,S
#
# def _get_param_names(self):
# if self.num_params == 2:
# return ['variance', 'lengthscale']
# else:
# return ['variance'] + ['lengthscale_%i' % i for i in range(self.lengthscale.size)]
def _dK_dvariance(self, model):
pass
def K(self, X, X2, target):
self._K_computations(X, X2)
@ -225,9 +234,9 @@ class RBF(Kernpart):
def _K_computations(self, X, X2):
params = self._get_params()
if not (fast_array_equal(X, self._X) and fast_array_equal(X2, self._X2) and fast_array_equal(self._params , params)):
if not (fast_array_equal(X, self._X) and fast_array_equal(X2, self._X2) and fast_array_equal(self._params_save , params)):
self._X = X.copy()
self._params = params.copy()
self._params_save = params.copy()
if X2 is None:
self._X2 = None
X = X / self.lengthscale