mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-04-30 23:36:23 +02:00
200 lines
No EOL
7.6 KiB
Python
200 lines
No EOL
7.6 KiB
Python
'''
|
|
Created on 4 Sep 2013
|
|
|
|
@author: maxz
|
|
'''
|
|
import re
|
|
import itertools
|
|
import numpy
|
|
from GPy.core.transformations import Logexp, NegativeLogexp
|
|
from GPy.core.index_operations import ParameterIndexOperations
|
|
from types import FunctionType
|
|
_index_re = re.compile('(?:_(\d+))+') # pattern match for indices
|
|
|
|
def translate_param_names_to_parameters(param_names):
|
|
"""
|
|
Naive translation from _get_param_names return to Parameters object.
|
|
Assumptions:
|
|
- array indices are at the and matching _\d+_\d+...
|
|
- names are in order and names match field names
|
|
"""
|
|
|
|
|
|
class Parameters(object):
|
|
def __init__(self, parameterlist, prefix=None, *args, **kwargs):
|
|
self._params = parameterlist
|
|
sizes = numpy.cumsum([0] + self.sizes)
|
|
self._param_slices = itertools.starmap(lambda start,stop: slice(start, stop), zip(sizes, sizes[1:]))
|
|
for p in parameterlist:
|
|
self.__setattr__(p.name, p)
|
|
|
|
def grep_param_names(self, regexp):
|
|
"""
|
|
Wrapper for parameterized.grep_param_names
|
|
"""
|
|
pass
|
|
|
|
def _get_params(self):
|
|
return numpy.fromiter(itertools.chain(*itertools.imap(lambda x: x._get_params(), self._params)), dtype=numpy.float64, count=sum(self.sizes))
|
|
|
|
def _set_params(self, params):
|
|
[p._set_params(params[s]) for s in self._param_slices]
|
|
|
|
def _get_params_transformed(self):
|
|
return numpy.fromiter(itertools.chain(*itertools.imap(lambda x: x._get_params_transformed(), self._params)), dtype=numpy.float64, count=sum(self.sizes))
|
|
|
|
@property
|
|
def names(self):
|
|
return [x.name for x in self._params]
|
|
|
|
@property
|
|
def size(self):
|
|
return sum(self.sizes)
|
|
@property
|
|
def sizes(self):
|
|
return [x.size for x in self._params]
|
|
@property
|
|
def constraints(self):
|
|
return [x.constraints for x in self._params]
|
|
@property
|
|
def shapes(self):
|
|
return [x.shape for x in self._params]
|
|
@property
|
|
def _constrs(self):
|
|
return [x._constr for x in self._params]
|
|
@property
|
|
def _descs(self):
|
|
return [x._desc 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 = " {{self.name:^{0}s}} | {{self._desc:^{1}s}} | {{self._constr:^{2}s}} ".format(nl, sl, cl)
|
|
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])
|
|
pass
|
|
|
|
|
|
class Param(numpy.ndarray):
|
|
tied_to = [] # list of parameters this parameter is tied to
|
|
fixed = False # if this parameter is fixed
|
|
__array_priority__ = -1
|
|
|
|
def __new__(cls, name, input_array, constraints=None):
|
|
obj = numpy.array(input_array).view(cls)
|
|
obj.name = name
|
|
obj._current_slice = slice(None)
|
|
obj._realshape = input_array.shape
|
|
if constraints is None:
|
|
obj.constraints = ParameterIndexOperations(obj)
|
|
else:
|
|
obj.constraints = constraints
|
|
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._current_slice = getattr(obj, '_current_slice', None)
|
|
|
|
def __array_wrap__(self, out_arr, context=None):
|
|
return numpy.ndarray.__array_wrap__(self, out_arr, context)
|
|
|
|
@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.keys()])
|
|
|
|
def _set_params(self, param):
|
|
#with self.slicing():
|
|
self.value.flat = param
|
|
|
|
def _get_params(self):
|
|
#with self.slicing():
|
|
return self.value.flat
|
|
|
|
def _get_params_transformed(self):
|
|
#with self.slicing():
|
|
params = self.value.copy()
|
|
|
|
def constrain(self, constraint):
|
|
#with self.slicing():
|
|
self.constraints.add(constraint, self._current_slice)
|
|
|
|
def constrain_positive(self):
|
|
self.constrain(Logexp())
|
|
|
|
def constrain_negative(self):
|
|
self.constrain(NegativeLogexp())
|
|
|
|
def unconstrain(self, constraints=None):
|
|
#with self.slicing():
|
|
if constraints is None:
|
|
constraints = self.constraints.keys()
|
|
elif not isinstance(constraints, (tuple, list, numpy.ndarray)):
|
|
constraints = [constraints]
|
|
for constr in constraints:
|
|
self.constraints.remove(constr, self._current_slice)
|
|
|
|
def unconstrain_positive(self):
|
|
self.unconstrain(Logexp())
|
|
|
|
def __getitem__(self, s, *args, **kwargs):
|
|
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
|
|
return new_arr
|
|
|
|
def __repr__(self, *args, **kwargs):
|
|
return super(Param, self).__repr__(*args, **kwargs)
|
|
view = repr(self.value)
|
|
return view
|
|
|
|
def __str__(self, format_spec=None):
|
|
#with self.slicing():
|
|
if format_spec is None:
|
|
constr_matrix = numpy.empty(self._realshape, dtype=object)
|
|
constr_matrix[:] = ''
|
|
for constr, indices in self.constraints.iteritems():
|
|
constr_matrix[indices] = numpy.vectorize(lambda x: " ".join([x,str(constr)]) if x else str(constr))(constr_matrix[indices])
|
|
constr_matrix = constr_matrix.astype(numpy.string_)[self._current_slice]
|
|
p = numpy.get_printoptions()['precision']
|
|
constr = constr_matrix.flat
|
|
ind = numpy.array(list(itertools.product(*itertools.imap(range, self._realshape))))[self.constraints.create_raveled_indices(self._current_slice),...]
|
|
c_name, x_name, i_name = "Constraint", "Value", "Index"
|
|
lc = max(reduce(lambda a,b: max(a, len(b)), constr_matrix.flat, 0), len(c_name))
|
|
lx = max(reduce(lambda a,b: max(a, len("{x:=.{0}G}".format(p,x=b))), self.value.flat, 0), len(x_name))
|
|
li = max(reduce(lambda a,b: max(a, len(str(b))), ind, 0), len(i_name))
|
|
header = " {i:^{3}s} | {x:^{1}s} | {c:^{0}s}".format(lc,lx,p,li, x=x_name, c=c_name, i=i_name)
|
|
return "\n".join([header]+[" {i:^{3}s} | {x: >{1}.{2}G} | {c:^{0}s}".format(lc,lx,p,li, x=x, c=constr.next(), i=i) for i,x in itertools.izip(ind,self.value.flat)])
|
|
return format_spec.format(self=self)
|
|
|
|
if __name__ == '__main__':
|
|
X = numpy.random.randn(2,4)
|
|
p = Param("X", X)
|
|
p2 = Param("Y", numpy.random.randn(3,1))
|
|
p3 = Param("rbf_variance", numpy.random.rand(1))
|
|
p4 = Param("rbf_lengthscale", numpy.random.rand(2))
|
|
params = Parameters([p,p2,p3,p4])
|
|
params.X[1].constrain_positive()
|
|
print params.X
|
|
#params.X[1,1].constrain_positive()
|
|
|