parameterized first beta test

This commit is contained in:
Max Zwiessele 2013-10-11 16:44:34 +01:00
parent 4f56506aa6
commit 152f61acf0

View file

@ -7,7 +7,8 @@ import re
import itertools
import numpy
from GPy.core.transformations import Logexp, NegativeLogexp
from GPy.core.index_operations import ParameterIndexOperations
from GPy.core.index_operations import ConstraintIndexOperations,\
create_raveled_indices, index_empty, TieIndexOperations
from types import FunctionType
from re import compile, _pattern_type
_index_re = re.compile('(?:_(\d+))+') # pattern match for indices
@ -17,319 +18,440 @@ __constraints_name__ = "Constraint"
__index_name__ = "Index"
__tie_name__ = "Tied to"
__precision__ = numpy.get_printoptions()['precision'] # numpy printing precision used, sublassing numpy ndarray after all
__fixed__ = "fixed"
######
def translate_param_names_to_parameters(param_names):
"""
Naive translation from _get_param_names return to Parameterized object.
Assumptions:
- array indices are at the and matching _\d+_\d+...
- names are in order and names match field names
"""
class Parameterized(object):
"""
Parameterized class
Say m is a handle to a parameterized class.
Printing parameters:
>>> print m
# prints a nice summary over all parameters
>>> print m.name
# prints all the parameters which start with name
Getting and setting parameters:
Two ways to get parameters:
- m.name regular expression matches all parameters beginning with name
- m['name'] regular expression matches all parameters with name
Handling of constraining, fixing and tieing parameters together:
"""
def __init__(self, parameterlist, prefix=None, *args, **kwargs):
self._init = True
self._params = []
for p in parameterlist:
if isinstance(p, Parameterized):
self._params.extend(p._params)
else:
self._params.append(p)
sizes = numpy.cumsum([0] + self.sizes)
self._param_slices = itertools.starmap(lambda start,stop: slice(start, stop), zip(sizes, sizes[1:]))
for p in self._params:
self._constraints = ConstraintIndexOperations()
self._ties = TieIndexOperations(self)
self._fixes = ConstraintIndexOperations
self._ties_fixes = None
self._connect_parameters()
self._init = False
def _connect_parameters(self):
sizes = numpy.cumsum([0] + self.parameter_sizes)
self._param_slices = [slice(start, stop) for start,stop in zip(sizes, sizes[1:])]
for i, p in enumerate(self._params):
p._parent = self
self.__setattr__(p.name, p)
p._parent_index = i
not_unique = []
if p.name in self.__dict__:
not_unique.append(p.name)
del self.__dict__[p.name]
elif not (p.name in not_unique):
self.__dict__[p.name] = p
#===========================================================================
# Optimization handling:
#===========================================================================
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.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):
[p._set_params(params[s]) for p,s in itertools.izip(self._params,self._param_slices)]
def _get_params_transformed(self):
return numpy.hstack([x._get_params_transformed() for x in self._params])
return numpy.fromiter(itertools.chain(*itertools.imap(lambda x: x._get_params_transformed(), self._params)), dtype=numpy.float64, count=self.num_params_transformed)
p = self._get_params()
[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:
return p[self._ties_fixes]
return p
def _set_params_transformed(self, params):
current_index = 0
for p in self._params:
s = p.num_params_transformed
p._set_params_transformed(params[current_index:current_index+s])
current_index += s
self._handle_ties()
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
[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()]
self._set_params(p)
def _handle_ties(self):
[p._handle_ties() for p in self._params]
def __getitem__(self, name):
return self.__getattr__(name)
if not self._init:
self._set_params_transformed(self._get_params_transformed())
#===========================================================================
# Index Handling
#===========================================================================
def _backtranslate_index(self, param, ind):
ind = ind-self._offset(param)
ind = ind[ind >= 0]
internal_offset = (numpy.arange(param._realsize).reshape(param._realshape)[param._current_slice]).flat[0]
ind = ind[ind < param.size + internal_offset]
return ind - internal_offset
#===========================================================================
# Handle ties:
#===========================================================================
def _add_tie(self, param, tied_to):
try:
param[...] = tied_to
except ValueError:
raise ValueError("Trying to tie {} with shape {} to {} with shape {}".format(self.name, self.shape, param.name, param.shape))
self._ties.add(param, tied_to)
if self._ties_fixes is None: self._ties_fixes = numpy.ones(self.parameter_size, dtype=bool)
f = create_raveled_indices(param._current_slice, param._realshape, self._offset(param))
self._ties_fixes[f] = False
def _remove_tie(self, param, *params):
if len(params) == 0:
params = self._ties.properties()
for p in self._ties.properties():
if any((p == x).all() for x in params):
ind = create_raveled_indices(p._current_slice, param._realshape, self._offset(param))
self._ties.remove(param, p)
self._ties_fixes[ind] = True
if numpy.all(self._ties_fixes): self._ties_fixes = None
def _ties_iter_items(self, param):
for tied_to, ind in self._ties.iter_from_items():
ind = self._backtranslate_index(param, ind)
if not index_empty(ind):
yield tied_to, ind
def _ties_iter(self, param):
for constr, _ in self._ties_iter_items(param):
yield constr
def _ties_iter_indices(self, param):
for _, ind in self._ties_iter_items(param):
yield ind
#===========================================================================
# Fixing parameters:
#===========================================================================
def _fix(self, param):
reconstrained = self._remove_constrain(param, None)
if any(reconstrained):
# to print whole params: m = str(param[self._backtranslate_index(param, reconstrained)])
m = param.name
if param._realsize > 1:
m += str("".join(map(str,param._indices()[self._backtranslate_index(param, reconstrained)])))
print "Reconstrained parameters:\n{}".format(m)
self._constraints.add(__fixed__, param._current_slice, param._realshape, self._offset(param))
if self._ties_fixes is None: self._ties_fixes = numpy.ones(self.parameter_size, dtype=bool)
f = create_raveled_indices(param._current_slice, param._realshape, self._offset(param))
self._ties_fixes[f] = False
def _unfix(self, param):
self._remove_constrain(param, __fixed__)
ind = create_raveled_indices(p._current_slice, param._realshape, self._offset(param))
self._ties_fixes[ind] = True
if numpy.all(self._ties_fixes): self._ties_fixes = None
#===========================================================================
# Constraint Handling:
#===========================================================================
def constrain(self, regexp, constraint):
self[regexp].constrain(constraint)
def _offset(self, param):
# offset = reduce(lambda a, b:a + (b.stop - b.start), self._param_slices[:param._parent_index], 0)
return self._param_slices[param._parent_index].start
def _add_constrain(self, param, transform):
reconstrained = self._remove_constrain(param, None)
self._constraints.add(transform, param._current_slice, param._realshape, self._offset(param))
if any(reconstrained):
# to print whole params: m = str(param[self._backtranslate_index(param, reconstrained)])
m = param.name + str("".join(map(str,param._indices()[self._backtranslate_index(param, reconstrained)])))
print "Reconstrained parameters:\n{}".format(m)
def _remove_constrain(self, param, transforms):
if transforms is None:
transforms = self._constraints.properties()
elif not isinstance(transforms, (tuple, list, numpy.ndarray)):
transforms = [transforms]
removed_indices = numpy.array([]).astype(int)
for constr in transforms:
removed = self._constraints.remove(constr, param._current_slice, param._realshape, self._offset(param))
removed_indices = numpy.union1d(removed_indices, removed)
return removed_indices
def _constraints_iter_items(self, param):
for constr, ind in self._constraints.iteritems():
ind = self._backtranslate_index(param, ind)
if not index_empty(ind):
yield constr, ind
def _constraints_iter(self, param):
for constr, _ in self._constraints_iter_items(param):
yield constr
def _contraints_iter_indices(self, param):
for _, ind in self._constraints_iter_items(param):
yield ind
def _constraint_indices(self, param, constraint):
return self._backtranslate_index(param, self._constraints[constraint])
#===========================================================================
# Get/set parameters:
#===========================================================================
def grep_param_names(self, regexp):
if not isinstance(regexp, _pattern_type):
regexp = compile(regexp)
paramlist = [param for param in self._params if regexp.search(param.name) is not None]
if not isinstance(regexp, _pattern_type): regexp = compile(regexp)
paramlist = [param for param in self._params if regexp.match(param.name) is not None]
return paramlist
def tie_params(self, regexp):
paramlist = self.grep_param_names(regexp)
def __getattr__(self, name, *args, **kwargs):
if name in self.__dict__:
return object.__getattribute__(self, name, *args, **kwargs)
else:
def __getitem__(self, name, paramlist=None):
if paramlist is None:
paramlist = self.grep_param_names(name)
if len(paramlist) < 1:
raise AttributeError("'{:s}' object has no attribute '{:s}'".format(str(self.__class__.__name__), name))
if len(paramlist) == 1:
return paramlist[-1]
return ParamConcatenation(paramlist)
if len(paramlist) < 1: raise AttributeError, name
if len(paramlist) == 1: return paramlist[-1]
return ParamConcatenation(paramlist)
def __setitem__(self, name, value, paramlist=None):
try: param = self.__getitem__(name, paramlist)
except AttributeError as a: raise a
param[...] = value
def __getattr__(self, name, *args, **kwargs):
return self.__getitem__(name)
def __setattr__(self, name, val):
if hasattr(self, "_params"):
paramlist = self.grep_param_names(name)
if len(paramlist) > 1: object.__setattr__(self, name, val); return# raise AttributeError("Non-unique params identified {}".format([p.name for p in paramlist]))
if len(paramlist) == 1: self.__setitem__(name, val, paramlist); return
object.__setattr__(self, name, val);
#===========================================================================
# Printing:
#===========================================================================
@property
def names(self):
return [x.name for x in self._params]
@property
def size(self):
return sum(self.sizes)
def parameter_size(self):
return sum(self.parameter_sizes)
@property
def sizes(self):
def parameter_sizes(self):
return [x.size for x in self._params]
@property
def sizes_transformed(self):
return [x.num_params_transformed() for x in self._params]
def parameter_size_transformed(self):
return sum(self._ties_fixes)
@property
def num_params_transformed(self):
return reduce(lambda a,b: a+b.num_params_transformed, self._params, 0)
@property
def constraints(self):
return [x.constraints for x in self._params]
@property
def shapes(self):
def parameter_shapes(self):
return [x.shape for x in self._params]
@property
def _constrs(self):
return [x._constr for x in self._params]
return [p._constr for p in self._params]
@property
def _descs(self):
return [x._desc for x in self._params]
@property
def _ts(self):
return [x._t for x in self._params]
def __str__(self, header=True):
nl = max([len(str(x)) for x in self.names + ["Name"]])
sl = max([len(str(x)) for x in self._descs + ["Value"]])
cl = max([len(str(x)) if x else 0 for x in self._constrs + ["Constraint"]])
format_spec = " \033[1m{{self.name:^{0}s}}\033[0;0m | {{self._desc:^{1}s}} | {{self._constr:^{2}s}} ".format(nl, sl, cl)
tl = max([len(str(x)) if x else 0 for x in self._ts + ["Tied to"]])
format_spec = " \033[1m{{p.name:^{0}s}}\033[0;0m | {{p._desc:^{1}s}} | {{p._constr:^{2}s}} | {{p._t:^{2}s}}".format(nl, sl, cl)
to_print = [format_spec.format(p=p) for p in self._params]
sep = '-'*len(to_print[0])
if header:
header = " {{0:^{0}s}} | {{1:^{1}s}} | {{2:^{2}s}} ".format(nl, sl, cl).format("Name", "Value", "Constraint")
header += '\n' + '-'*len(header)
return '\n'.join([header]+[x.__str__(format_spec=format_spec) for x in self._params])
return '\n'.join([x.__str__(format_spec=format_spec) for x in self._params])
header = " {{0:^{0}s}} | {{1:^{1}s}} | {{2:^{2}s}} | {{3:^{3}s}}".format(nl, sl, cl, tl).format("Name", "Value", "Constraint", "Tied to")
header += '\n' + sep
to_print.insert(0, header)
return '\n'.format(sep).join(to_print)
pass
class Param(numpy.ndarray):
"""
Parameter object for GPy models.
- constraining singular entries:
- param[1:2,1:2].constrain{_..}() to keep the shape
- param[1,1,...].constrain{_..}(), which tells numpy to keep the shapes
- param[[1],[1]] to trigger advanced indexin, which keeps shapes
this is because of numpy's ndarray functionality:
it gives back a float, when indexing singular entries
we want a Param object though, with the right shape
workarounds:
- slice paramters and constrain the slices.
- unconstrain slices
"""
fixed = False # if this parameter is fixed
__array_priority__ = -1 # Only give back a param if slicing
def __new__(cls, name, input_array, constraints=None, ties=None):
__array_priority__ = -1. # Allways give back Param
def __new__(cls, name, input_array):
obj = numpy.atleast_1d(numpy.array(input_array)).view(cls)
obj.name = name
obj._parent = None
obj._parent_index = None
obj._current_slice = slice(None)
obj._realshape = obj.shape
#obj.parameters = parameters
if constraints is None:
obj.constraints = ParameterIndexOperations(obj)
else:
obj.constraints = constraints
if ties is None:
obj.ties = ParameterIndexOperations(obj)
else:
obj.ties = ties
return obj
obj._realsize = obj.size
return obj
def __array_finalize__(self, obj):
# see InfoArray.__array_finalize__ for comments
if obj is None: return
self.name = getattr(obj, 'name', None)
self._realshape = getattr(obj, '_realshape', None)
self.constraints = getattr(obj, 'constraints', None)
self._parent = getattr(obj, '_parent', None)
self.ties = getattr(obj, 'ties', None)
self._current_slice = getattr(obj, '_current_slice', None)
@property
def value(self):
return self#self.base[self._current_slice]
@property
def _desc(self):
if self.size <= 1:
return "%f"%self.value
else:
return self.shape
@property
def _constr(self):
return ' '.join([str(c) if c else '' for c in self.constraints.properties()])
self._parent = getattr(obj, '_parent', None)
self._parent_index = getattr(obj, '_parent_index', None)
self._realshape = getattr(obj, '_realshape', None)
self._realsize = getattr(obj, '_realsize', None)
#===========================================================================
# get/set parameters
#===========================================================================
def _set_params(self, param):
self.value.flat = param
self.flat = param
def _get_params(self):
return self.value.flat
@property
def num_params_transformed(self):
return self.size - self.ties.size()
def _get_params_transformed(self):
params = self.base.flatten()
[numpy.put(params, indices, constr.finv(params[indices])) for constr, indices in self.constraints.iteritems()]
return numpy.delete(params, reduce(numpy.union1d, self.ties.iterindices(), numpy.array([],dtype=self.dtype)))
def _set_params_transformed(self, params):
numpy.put(self.base, numpy.setdiff1d(numpy.r_[:self.size],reduce(numpy.union1d, self.ties.iterindices(), numpy.array([],dtype=self.dtype))), params)
[numpy.put(self.base, indices, constraint.f(self.base.flat[indices])) for constraint, indices in self.constraints.iteritems()]
def _handle_ties(self):
# handle all tied values
for tie, indices in self.ties.iteritems():
self.base.flat[indices] = tie.flat
return self.flat
#===========================================================================
# Fixing Parameters:
#===========================================================================
def constrain_fixed(self):
self._parent._fix(self)
def unconstrain_fixed(self):
self._parent._unfix(self)
#===========================================================================
# Constrain operations -> done
#===========================================================================
def constrain(self, transform):
self._parent._add_constrain(self, transform)
self[...] = transform.initialize(self)
def constrain_positive(self):
self.constrain(Logexp())
def constrain_negative(self):
self.constrain(NegativeLogexp())
def unconstrain(self, transforms=None):
self._parent._remove_constrain(self, transforms)
def unconstrain_positive(self):
self.unconstrain(Logexp())
def unconstrain_negative(self):
self.unconstrain(NegativeLogexp())
#===========================================================================
# Tying operations -> done
#===========================================================================
def tie_to(self, param):
assert isinstance(param, Param), "Argument {1} not of type {0}".format(Param,param.__class__)
try:
rav_index = self.ties.create_raveled_indices(self._current_slice)
self.base.flat[rav_index] = param.flat
self.ties.add(param, self._current_slice)
self._handle_ties()
self[...] = param
self._parent._add_tie(self, param)
except ValueError:
raise ValueError("Trying to tie params with shape {} to params with shape {}".format(self.shape, param.shape))
raise ValueError("Trying to tie {} with shape {} to {} with shape {}".format(self.name, self.shape, param.name, param.shape))
def untie(self, *params):
if len(params) == 0:
params = self.ties.properties()
for p in self.ties.properties():
params = self._parent._ties.properties()
for p in self._parent._ties.properties():
if any((p == x).all() for x in params):
self.ties.remove(p, self._current_slice)
def constrain(self, transform):
self.constraints.add(transform, self._current_slice)
self[:] = transform.initialize(self)
def constrain_positive(self):
self.constrain(Logexp())
def constrain_negative(self):
self.constrain(NegativeLogexp())
def unconstrain(self, transforms=None):
if transforms is None:
transforms = self.constraints.properties()
elif not isinstance(transforms, (tuple, list, numpy.ndarray)):
transforms = [transforms]
for constr in transforms:
self.constraints.remove(constr, self._current_slice)
def unconstrain_positive(self):
self.unconstrain(Logexp())
def unconstrain_negative(self):
self.unconstrain(NegativeLogexp())
self._parent._remove_tie(self, params)
#===========================================================================
# Array operations -> done
#===========================================================================
def __getitem__(self, s, *args, **kwargs):
if not isinstance(s, tuple):
s = (s,)
if not( Ellipsis in s):
s = (s + (Ellipsis,))
new_arr = numpy.ndarray.__getitem__(self, s, *args, **kwargs)
try:
new_arr._current_slice = s
except AttributeError:
# returning 0d array or float, double etc:
pass
try: new_arr._current_slice = s
except AttributeError: pass# returning 0d array or float, double etc
return new_arr
def __getslice__(self, start, stop):
return self.__getitem__(slice(start, stop))
def __setitem__(self, *args, **kwargs):
numpy.ndarray.__setitem__(self, *args, **kwargs)
self._parent._handle_ties()
def __repr__(self, *args, **kwargs):
return super(Param, self).__repr__(*args, **kwargs)
view = repr(self.value)
#===========================================================================
# Printing ->
#===========================================================================
@property
def _desc(self):
if self.size <= 1: return "%f"%self
else: return self.shape
@property
def _constr(self):
return ' '.join(map(lambda c: str(c[0]) if len(c[1])==self._realsize else "{"+str(c[0])+"}", self._parent._constraints_iter_items(self)))
@property
def _t(self):
# indices one by one: "".join(map(str,c[0]._indices()))
return ' '.join(map(lambda c: c[0].name if len(c[1])==self._realsize else c[0].name+"[...]", self._parent._ties_iter_items(self)))
def round(self, decimals=0, out=None):
view = super(Param, self).round(decimals, out).view(Param)
view.__array_finalize__(self)
return view
round.__doc__ = numpy.round.__doc__
def __repr__(self, *args, **kwargs):
return "\033[1m{x:s}\033[0;0m:\n".format(x=self.name)+super(Param, self).__repr__(*args,**kwargs)
def _constr_matrix_str(self):
constr_matrix = numpy.empty(self._realshape, dtype=object) # we need the whole constraints matrix
constr_matrix = numpy.empty(self._realsize, dtype=object) # we need the whole constraints matrix
constr_matrix[:] = ''
for constr, indices in self.constraints.iteritems(): # put in all the constraints:
constr_matrix[indices] = numpy.vectorize(lambda x:" ".join([x, str(constr)]) if x else str(constr))(constr_matrix[indices])
return constr_matrix.astype(numpy.string_)[self._current_slice] # and get the slice we did before
for constr, indices in self._parent._constraints_iter_items(self): # put in all the constraints:
cstr = ""+str(constr)+""
constr_matrix[indices] = numpy.vectorize(lambda x:" ".join([x, cstr]) if x else cstr, otypes=[str])(constr_matrix[indices])
return constr_matrix.astype(numpy.string_).reshape(self._realshape)[self._current_slice].flatten() # and get the slice we did before
def _ties_matrix_str(self):
ties_matr = numpy.empty(self._realshape, dtype=object) # we need the whole constraints matrix
ties_matr = numpy.empty(self._realsize, dtype=object) # we need the whole constraints matrix
ties_matr[:] = ''
for tie, indices in self.ties.iteritems(): # go through all ties:
tie_cycle = itertools.cycle(tie._indices())
for tie, indices in self._parent._ties_iter_items(self): # go through all ties:
tie_cycle = itertools.cycle(tie._indices()) if tie._realsize > 1 else itertools.repeat('')
ties_matr[indices] = numpy.vectorize(lambda x:" ".join([x, str(tie.name) + str(str(tie_cycle.next()))]) if x else str(tie.name)+str(str(tie_cycle.next())), otypes=[str])(ties_matr[indices])
return ties_matr.astype(numpy.string_)[self._current_slice] # and get the slice we did before
return ties_matr.astype(numpy.string_).reshape(*(self._realshape+(-1,)))[self._current_slice] # and get the slice we did before
def _indices(self):
return numpy.array(list(itertools.product(*itertools.imap(range, self._realshape))))[self.constraints.create_raveled_indices(self._current_slice),...] # find out which indices to print
flat_indices = numpy.array(list(itertools.product(*itertools.imap(range, self._realshape)))).reshape(self._realshape + (-1,))
return flat_indices[self._current_slice].reshape(self.size, -1) # find out which indices to print
def _max_len_names(self, constr_matrix, header):
return max(reduce(lambda a, b:max(a, len(b)), constr_matrix.flat, 0), len(header))
def _max_len_values(self):
return max(reduce(lambda a, b:max(a, len("{x:=.{0}G}".format(__precision__, x=b))), self.value.flat, 0), len(self.name))
return max(reduce(lambda a, b:max(a, len("{x:=.{0}G}".format(__precision__, x=b))), self.flat, 0), len(self.name))
def _max_len_index(self, ind):
return max(reduce(lambda a, b:max(a, len(str(b))), ind, 0), len(__index_name__))
def __str__(self, format_spec=None, constr_matrix=None, indices=None, ties=None, lc=None, lx=None, li=None, lt=None):
if format_spec is None:
if indices is None:
indices = self._indices()
if constr_matrix is None:
constr_matrix = self._constr_matrix_str()
if ties is None:
ties = self._ties_matrix_str()
if lc is None:
lc = self._max_len_names(constr_matrix, __constraints_name__)
if lx is None:
lx = self._max_len_values()
if li is None:
li = self._max_len_index(indices)
if lt is None:
lt = self._max_len_names(ties, __tie_name__)
def __str__(self, constr_matrix=None, indices=None, ties=None, lc=None, lx=None, li=None, lt=None):
try:
if indices is None: indices = self._indices()
if constr_matrix is None: constr_matrix = self._constr_matrix_str()
if ties is None: ties = self._ties_matrix_str()
if lc is None: lc = self._max_len_names(constr_matrix, __constraints_name__)
if lx is None: lx = self._max_len_values()
if li is None: li = self._max_len_index(indices)
if lt is None: lt = self._max_len_names(ties, __tie_name__)
constr = constr_matrix.flat
ties = ties.flat
header = " {i:^{2}s} | \033[1m{x:^{1}s}\033[0;0m | {c:^{0}s} | {t:^{3}s}".format(lc,lx,li,lt, x=self.name, c=__constraints_name__, i=__index_name__, t=__tie_name__) # nice header for printing
return "\n".join([header]+[" {i:^{3}s} | {x: >{1}.{2}G} | {c:^{0}s} | {t:^{4}} ".format(lc,lx,__precision__,li,lt, x=x, c=constr.next(), t=ties.next(), i=i) for i,x in itertools.izip(indices,self.value.flat)]) # return all the constraints with right indices
return format_spec.format(self=self)
return "\n".join([header]+[" {i:^{3}s} | {x: >{1}.{2}G} | {c:^{0}s} | {t:^{4}} ".format(lc,lx,__precision__,li,lt, x=x, c=constr.next(), t=ties.next(), i=i) for i,x in itertools.izip(indices,self.flat)]) # return all the constraints with right indices
except: return super(Param, self).__str__()
class ParamConcatenation(object):
def __init__(self, params):
"""
Parameter concatenation for convienience of printing regular expression matched arrays
you can index this concatenation as if it was the flattened concatenation
of all the parameters it contains, same for setting parameters
"""
self.params = params
self._param_sizes = [p.size for p in self.params]
startstops = numpy.cumsum([0] + self._param_sizes)
self._param_slices = [slice(start, stop) for start,stop in zip(startstops, startstops[1:])]
def __getitem__(self, s):
raise AttributeError("Cannot index a concatenation of parameters!")
ind = numpy.zeros(sum(self._param_sizes), dtype=bool); ind[s] = True;
params = [p.flatten()[ind[ps]] for p,ps in zip(self.params, self._param_slices) if numpy.any(p.flat[ind[ps]])]
if len(params)==1: return params[0]
return ParamConcatenation(params)
def __setitem__(self, s, val):
ind = numpy.zeros(sum(self._param_sizes), dtype=bool); ind[s] = True;
vals = self._vals(); vals[s] = val; del val
[numpy.place(p, ind[ps], vals[ps]) for p, ps in zip(self.params, self._param_slices)]
def _vals(self):
return numpy.hstack([p._get_params() for p in self.params])
def constrain(self, constraint):
[param.constrain(constraint) for param in self.params]
def constrain_positive(self):
[param.constrain_positive() for param in self.params]
def constrain_fixed(self):
[param.constrain_fixed() for param in self.params]
def constrain_negative(self):
[param.constrain_negative() for param in self.params]
def unconstrain(self, constraints=None):
[param.unconstrain(constraints) for param in self.params]
def unconstrain_negative(self):
[param.unconstrain_negative() for param in self.params]
def unconstrain_positive(self):
[param.unconstrain_positive() for param in self.params]
def unconstrain_fixed(self):
[param.unconstrain_fixed() for param in self.params]
def __str__(self, *args, **kwargs):
constr_matrices = [p._constr_matrix_str() for p in self.params]
ties_matrices = [p._ties_matrix_str() for p in self.params]
@ -338,21 +460,23 @@ class ParamConcatenation(object):
lx = max([p._max_len_values() for p in self.params])
li = max([p._max_len_index(i) for p, i in itertools.izip(self.params, indices)])
lt = max([p._max_len_names(tm, __tie_name__) for p, tm in itertools.izip(self.params, ties_matrices)])
return "\n".join([p.__str__(None, cm, i, tm, lc, lx, li, lt) for p, cm, i, tm in itertools.izip(self.params,constr_matrices,indices,ties_matrices)])
strings = [p.__str__(cm, i, tm, lc, lx, li, lt) for p, cm, i, tm in itertools.izip(self.params,constr_matrices,indices,ties_matrices)]
return "\n{}\n".format(" -"+"- | -".join(['-'*l for l in [li,lx,lc,lt]])).join(strings)
def __repr__(self):
return self.__str__()
return "\n".join(map(repr,self.params))
if __name__ == '__main__':
X = numpy.random.randn(100,8)
p = Param("X", X)
p1 = Param("X_variance", numpy.random.rand(*X.shape))
p2 = Param("Y", numpy.random.randn(3,1))
p3 = Param("rbf_variance", numpy.random.rand(1))
X = numpy.random.randn(3,3,2)
p = Param("q_mean", X)
p1 = Param("q_variance", numpy.random.rand(*p.shape))
p2 = Param("Y", numpy.random.randn(p.shape[0],1))
p3 = Param("rbf_variance", numpy.random.rand())
p4 = Param("rbf_lengthscale", numpy.random.rand(2))
params = Parameterized([p,p1,p2,p3,p4])
params.rbf.constrain_positive()
params[".*variance"].constrain_positive()
params.rbf_l.tie_to(params.rbf_va)
pt = numpy.array(params._get_params_transformed())
ptr = numpy.random.randn(*pt.shape)
m = Parameterized([p,p1,p2,p3,p4])
m[".*variance"].constrain_positive()
m.rbf.constrain_positive()
m.q_v.tie_to(m.rbf_v)
# m.rbf_l.tie_to(m.rbf_va)
# pt = numpy.array(params._get_params_transformed())
# ptr = numpy.random.randn(*pt.shape)
# params.X.tie_to(params.rbf_v)