domain and trtansformations namespace prettyfying

This commit is contained in:
Max Zwiessele 2013-10-11 17:26:04 +01:00
parent 780daac03e
commit 2018368d8d
5 changed files with 36 additions and 41 deletions

View file

@ -6,21 +6,21 @@ Created on 4 Jun 2013
(Hyper-)Parameter domains defined for :py:mod:`~GPy.core.priors` and :py:mod:`~GPy.kern`. (Hyper-)Parameter domains defined for :py:mod:`~GPy.core.priors` and :py:mod:`~GPy.kern`.
These domains specify the legitimate realm of the parameters to live in. These domains specify the legitimate realm of the parameters to live in.
:const:`~GPy.core.domains.REAL` : :const:`~GPy.core.domains._REAL` :
real domain, all values in the real numbers are allowed real domain, all values in the real numbers are allowed
:const:`~GPy.core.domains.POSITIVE`: :const:`~GPy.core.domains._POSITIVE`:
positive domain, only positive real values are allowed positive domain, only positive real values are allowed
:const:`~GPy.core.domains.NEGATIVE`: :const:`~GPy.core.domains._NEGATIVE`:
same as :const:`~GPy.core.domains.POSITIVE`, but only negative values are allowed same as :const:`~GPy.core.domains._POSITIVE`, but only negative values are allowed
:const:`~GPy.core.domains.BOUNDED`: :const:`~GPy.core.domains._BOUNDED`:
only values within the bounded range are allowed, only values within the bounded range are allowed,
the bounds are specified withing the object with the bounded range the bounds are specified withing the object with the bounded range
''' '''
REAL = 'real' _REAL = 'real'
POSITIVE = "positive" _POSITIVE = "positive"
NEGATIVE = 'negative' _NEGATIVE = 'negative'
BOUNDED = 'bounded' _BOUNDED = 'bounded'

View file

@ -9,7 +9,7 @@ from GPy.util.misc import opt_wrapper
from parameterized import Parameterized from parameterized import Parameterized
import multiprocessing as mp import multiprocessing as mp
import numpy as np import numpy as np
from GPy.core.domains import POSITIVE, REAL from GPy.core.domains import _POSITIVE, _REAL
from numpy.linalg.linalg import LinAlgError from numpy.linalg.linalg import LinAlgError
# import numdifftools as ndt # import numdifftools as ndt
@ -93,8 +93,8 @@ class Model(Parameterized):
# check constraints are okay # check constraints are okay
if what.domain is POSITIVE: if what.domain is _POSITIVE:
constrained_positive_indices = [i for i, t in zip(self.constrained_indices, self.constraints) if t.domain is POSITIVE] constrained_positive_indices = [i for i, t in zip(self.constrained_indices, self.constraints) if t.domain is _POSITIVE]
if len(constrained_positive_indices): if len(constrained_positive_indices):
constrained_positive_indices = np.hstack(constrained_positive_indices) constrained_positive_indices = np.hstack(constrained_positive_indices)
else: else:
@ -107,7 +107,7 @@ class Model(Parameterized):
print '\n'.join([n for i, n in enumerate(self._get_param_names()) if i in unconst]) print '\n'.join([n for i, n in enumerate(self._get_param_names()) if i in unconst])
print '\n' print '\n'
self.constrain_positive(unconst) self.constrain_positive(unconst)
elif what.domain is REAL: elif what.domain is _REAL:
assert not np.any(which[:, None] == self.all_constrained_indices()), "constraint and prior incompatible" assert not np.any(which[:, None] == self.all_constrained_indices()), "constraint and prior incompatible"
else: else:
raise ValueError, "prior not recognised" raise ValueError, "prior not recognised"

View file

@ -41,7 +41,7 @@ class Parameterized(object):
- m.name regular expression matches all parameters beginning with name - m.name regular expression matches all parameters beginning with name
- m['name'] regular expression matches all parameters with name - m['name'] regular expression matches all parameters with name
Handling of constraining, fixing and tieing parameters together: Handling of constraining, fixing and tieing parameters:
@ -74,28 +74,23 @@ class Parameterized(object):
self.__dict__[p.name] = p self.__dict__[p.name] = p
#=========================================================================== #===========================================================================
# Optimization handling: # Optimization handles:
#=========================================================================== #===========================================================================
def _get_params(self): def _get_params(self):
return numpy.hstack([x._get_params() for x in self._params])#numpy.fromiter(itertools.chain(*itertools.imap(lambda x: x._get_params(), self._params)), dtype=numpy.float64, count=sum(self.parameter_sizes)) return numpy.hstack([x._get_params() for x in self._params])#numpy.fromiter(itertools.chain(*itertools.imap(lambda x: x._get_params(), self._params)), dtype=numpy.float64, count=sum(self.parameter_sizes))
def _set_params(self, params): def _set_params(self, params):
[p._set_params(params[s]) for p,s in itertools.izip(self._params,self._param_slices)] [p._set_params(params[s]) for p,s in itertools.izip(self._params,self._param_slices)]
def _get_params_transformed(self): def _get_params_transformed(self):
p = self._get_params() p = self._get_params()
[numpy.put(p, ind, c.finv(p[ind])) for c,ind in self._constraints.iteritems() if c is not __fixed__] [numpy.put(p, ind, c.finv(p[ind])) for c,ind in self._constraints.iteritems() if c is not __fixed__]
if self._ties_fixes is not None: if self._ties_fixes is not None:
return p[self._ties_fixes] return p[self._ties_fixes]
return p return p
def _set_params_transformed(self, p): def _set_params_transformed(self, p):
if self._ties_fixes is not None: tmp = self._get_params(); tmp[self._ties_fixes] = p; p = tmp; del tmp if self._ties_fixes is not None: tmp = self._get_params(); tmp[self._ties_fixes] = p; p = tmp; del tmp
[numpy.put(p, ind, c.f(p[ind])) for c,ind in self._constraints.iteritems() if c is not __fixed__] [numpy.put(p, ind, c.f(p[ind])) for c,ind in self._constraints.iteritems() if c is not __fixed__]
[numpy.put(p, f, p[t]) for f,t in self._ties.iter_from_to_indices()] [numpy.put(p, f, p[t]) for f,t in self._ties.iter_from_to_indices()]
self._set_params(p) self._set_params(p)
def _handle_ties(self): def _handle_ties(self):
if not self._init: if not self._init:
self._set_params_transformed(self._get_params_transformed()) self._set_params_transformed(self._get_params_transformed())
@ -466,7 +461,7 @@ class ParamConcatenation(object):
return "\n".join(map(repr,self.params)) return "\n".join(map(repr,self.params))
if __name__ == '__main__': if __name__ == '__main__':
X = numpy.random.randn(3,3,2) X = numpy.random.randn(4,2)
p = Param("q_mean", X) p = Param("q_mean", X)
p1 = Param("q_variance", numpy.random.rand(*p.shape)) p1 = Param("q_variance", numpy.random.rand(*p.shape))
p2 = Param("Y", numpy.random.randn(p.shape[0],1)) p2 = Param("Y", numpy.random.randn(p.shape[0],1))

View file

@ -6,7 +6,7 @@ import numpy as np
import pylab as pb import pylab as pb
from scipy.special import gammaln, digamma from scipy.special import gammaln, digamma
from ..util.linalg import pdinv from ..util.linalg import pdinv
from GPy.core.domains import REAL, POSITIVE from GPy.core.domains import _REAL, _POSITIVE
import warnings import warnings
class Prior: class Prior:
@ -32,7 +32,7 @@ class Gaussian(Prior):
.. Note:: Bishop 2006 notation is used throughout the code .. Note:: Bishop 2006 notation is used throughout the code
""" """
domain = REAL domain = _REAL
def __init__(self, mu, sigma): def __init__(self, mu, sigma):
self.mu = float(mu) self.mu = float(mu)
self.sigma = float(sigma) self.sigma = float(sigma)
@ -62,7 +62,7 @@ class LogGaussian(Prior):
.. Note:: Bishop 2006 notation is used throughout the code .. Note:: Bishop 2006 notation is used throughout the code
""" """
domain = POSITIVE domain = _POSITIVE
def __init__(self, mu, sigma): def __init__(self, mu, sigma):
self.mu = float(mu) self.mu = float(mu)
self.sigma = float(sigma) self.sigma = float(sigma)
@ -92,7 +92,7 @@ class MultivariateGaussian:
.. Note:: Bishop 2006 notation is used throughout the code .. Note:: Bishop 2006 notation is used throughout the code
""" """
domain = REAL domain = _REAL
def __init__(self, mu, var): def __init__(self, mu, var):
self.mu = np.array(mu).flatten() self.mu = np.array(mu).flatten()
self.var = np.array(var) self.var = np.array(var)
@ -147,7 +147,7 @@ class Gamma(Prior):
.. Note:: Bishop 2006 notation is used throughout the code .. Note:: Bishop 2006 notation is used throughout the code
""" """
domain = POSITIVE domain = _POSITIVE
def __init__(self, a, b): def __init__(self, a, b):
self.a = float(a) self.a = float(a)
self.b = float(b) self.b = float(b)
@ -198,7 +198,7 @@ class inverse_gamma(Prior):
.. Note:: Bishop 2006 notation is used throughout the code .. Note:: Bishop 2006 notation is used throughout the code
""" """
domain = POSITIVE domain = _POSITIVE
def __init__(self, a, b): def __init__(self, a, b):
self.a = float(a) self.a = float(a)
self.b = float(b) self.b = float(b)

View file

@ -3,10 +3,10 @@
import numpy as np import numpy as np
from GPy.core.domains import POSITIVE, NEGATIVE, BOUNDED from GPy.core.domains import _POSITIVE,_NEGATIVE, _BOUNDED
import sys import sys
import weakref import weakref
lim_val = -np.log(sys.float_info.epsilon) _lim_val = -np.log(sys.float_info.epsilon)
class Transformation(object): class Transformation(object):
domain = None domain = None
@ -29,13 +29,13 @@ class Transformation(object):
raise NotImplementedError raise NotImplementedError
class Logexp(Transformation): class Logexp(Transformation):
domain = POSITIVE domain = _POSITIVE
def f(self, x): def f(self, x):
return np.where(x>lim_val, x, np.log(1. + np.exp(x))) return np.where(x>_lim_val, x, np.log(1. + np.exp(x)))
def finv(self, f): def finv(self, f):
return np.where(f>lim_val, f, np.log(np.exp(f) - 1.)) return np.where(f>_lim_val, f, np.log(np.exp(f) - 1.))
def gradfactor(self, f): def gradfactor(self, f):
return np.where(f>lim_val, 1., 1 - np.exp(-f)) return np.where(f>_lim_val, 1., 1 - np.exp(-f))
def initialize(self, f): def initialize(self, f):
if np.any(f < 0.): if np.any(f < 0.):
print "Warning: changing parameters to satisfy constraints" print "Warning: changing parameters to satisfy constraints"
@ -44,7 +44,7 @@ class Logexp(Transformation):
return '+ve' return '+ve'
class NegativeLogexp(Transformation): class NegativeLogexp(Transformation):
domain = NEGATIVE domain = _NEGATIVE
logexp = Logexp() logexp = Logexp()
def f(self, x): def f(self, x):
return -self.logexp.f(x) # np.log(1. + np.exp(x)) return -self.logexp.f(x) # np.log(1. + np.exp(x))
@ -62,7 +62,7 @@ class LogexpClipped(Logexp):
min_bound = 1e-10 min_bound = 1e-10
log_max_bound = np.log(max_bound) log_max_bound = np.log(max_bound)
log_min_bound = np.log(min_bound) log_min_bound = np.log(min_bound)
domain = POSITIVE domain = _POSITIVE
_instances = [] _instances = []
def __new__(cls, lower=1e-6, *args, **kwargs): def __new__(cls, lower=1e-6, *args, **kwargs):
if cls._instances: if cls._instances:
@ -97,9 +97,9 @@ class LogexpClipped(Logexp):
class Exponent(Transformation): class Exponent(Transformation):
# TODO: can't allow this to go to zero, need to set a lower bound. Similar with negative Exponent below. See old MATLAB code. # TODO: can't allow this to go to zero, need to set a lower bound. Similar with negative Exponent below. See old MATLAB code.
domain = POSITIVE domain = _POSITIVE
def f(self, x): def f(self, x):
return np.where(x<lim_val, np.where(x>-lim_val, np.exp(x), np.exp(-lim_val)), np.exp(lim_val)) return np.where(x<_lim_val, np.where(x>-_lim_val, np.exp(x), np.exp(-_lim_val)), np.exp(_lim_val))
def finv(self, x): def finv(self, x):
return np.log(x) return np.log(x)
def gradfactor(self, f): def gradfactor(self, f):
@ -112,7 +112,7 @@ class Exponent(Transformation):
return '+ve' return '+ve'
class NegativeExponent(Exponent): class NegativeExponent(Exponent):
domain = NEGATIVE domain = _NEGATIVE
def f(self, x): def f(self, x):
return -Exponent.f(x) return -Exponent.f(x)
def finv(self, f): def finv(self, f):
@ -125,7 +125,7 @@ class NegativeExponent(Exponent):
return '-ve' return '-ve'
class Square(Transformation): class Square(Transformation):
domain = POSITIVE domain = _POSITIVE
def f(self, x): def f(self, x):
return x ** 2 return x ** 2
def finv(self, x): def finv(self, x):
@ -138,7 +138,7 @@ class Square(Transformation):
return '+sq' return '+sq'
class Logistic(Transformation): class Logistic(Transformation):
domain = BOUNDED domain = _BOUNDED
_instances = [] _instances = []
def __new__(cls, lower=1e-6, upper=1e-6, *args, **kwargs): def __new__(cls, lower=1e-6, upper=1e-6, *args, **kwargs):
if cls._instances: if cls._instances: