mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-05-09 03:52:39 +02:00
fixing now works, removing parameters needs fixing
This commit is contained in:
parent
d2e8807a88
commit
f71af38505
7 changed files with 100 additions and 147 deletions
|
|
@ -4,6 +4,7 @@ import warnings
|
|||
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
||||
|
||||
import core
|
||||
from core.parameterization import transformations
|
||||
import models
|
||||
import mappings
|
||||
import inference
|
||||
|
|
|
|||
|
|
@ -57,9 +57,11 @@ class ParameterIndexOperations(object):
|
|||
You can give an offset to set an offset for the given indices in the
|
||||
index array, for multi-param handling.
|
||||
'''
|
||||
def __init__(self):
|
||||
def __init__(self, constraints=None):
|
||||
self._properties = IntArrayDict()
|
||||
#self._reverse = collections.defaultdict(list)
|
||||
if constraints is not None:
|
||||
for t, i in constraints.iteritems():
|
||||
self.add(t, i)
|
||||
|
||||
def __getstate__(self):
|
||||
return self._properties#, self._reverse
|
||||
|
|
@ -191,7 +193,7 @@ class ParameterIndexOperationsView(object):
|
|||
|
||||
|
||||
def indices(self):
|
||||
[ind for ind in self.iterindices()]
|
||||
return [ind for ind in self.iterindices()]
|
||||
|
||||
|
||||
def properties_for(self, index):
|
||||
|
|
@ -206,6 +208,8 @@ class ParameterIndexOperationsView(object):
|
|||
removed = self._param_index_ops.remove(prop, indices+self._offset)
|
||||
if removed.size > 0:
|
||||
return removed - self._size + 1
|
||||
if self[prop].size == 0:
|
||||
del self[prop]
|
||||
return removed
|
||||
|
||||
|
||||
|
|
@ -223,5 +227,8 @@ class ParameterIndexOperationsView(object):
|
|||
for i, v in parameter_index_view.iteritems():
|
||||
self.add(i, v)
|
||||
|
||||
|
||||
def copy(self):
|
||||
return ParameterIndexOperations(dict(self.iteritems()))
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||
|
||||
from transformations import Transformation, Logexp, NegativeLogexp, Logistic
|
||||
from transformations import Transformation, Logexp, NegativeLogexp, Logistic, __fixed__, FIXED, UNFIXED
|
||||
|
||||
__updated__ = '2013-12-16'
|
||||
|
||||
|
|
@ -10,11 +10,6 @@ def adjust_name_for_printing(name):
|
|||
return name.replace(" ", "_").replace(".", "_").replace("-","").replace("+","").replace("!","").replace("*","").replace("/","")
|
||||
return ''
|
||||
|
||||
#===============================================================================
|
||||
# Printing:
|
||||
__fixed__ = "fixed"
|
||||
#===============================================================================
|
||||
|
||||
class Observable(object):
|
||||
_observers_ = {}
|
||||
def add_observer(self, observer, callble):
|
||||
|
|
@ -120,12 +115,23 @@ class Indexable(object):
|
|||
def _offset_for(self, param):
|
||||
raise NotImplementedError, "shouldnt happen, offset required from non parameterization object?"
|
||||
|
||||
def _raveled_index_for(self, param):
|
||||
"""
|
||||
get the raveled index for a param
|
||||
that is an int array, containing the indexes for the flattened
|
||||
param inside this parameterized logic.
|
||||
"""
|
||||
raise NotImplementedError, "shouldnt happen, raveld index transformation required from non parameterization object?"
|
||||
|
||||
class Constrainable(Nameable, Indexable, Parameterizable):
|
||||
def __init__(self, name, default_constraint=None):
|
||||
super(Constrainable,self).__init__(name)
|
||||
self._default_constraint_ = default_constraint
|
||||
from index_operations import ParameterIndexOperations
|
||||
self.constraints = ParameterIndexOperations()
|
||||
if self._default_constraint_ is not None:
|
||||
self.constrain(self._default_constraint_)
|
||||
|
||||
#===========================================================================
|
||||
# Fixing Parameters:
|
||||
#===========================================================================
|
||||
|
|
@ -138,17 +144,40 @@ class Constrainable(Nameable, Indexable, Parameterizable):
|
|||
if value is not None:
|
||||
self[:] = value
|
||||
self.constrain(__fixed__, warning=warning)
|
||||
self._highest_parent_._set_fixed(self._raveled_index())
|
||||
rav_i = self._highest_parent_._raveled_index_for(self)
|
||||
self._highest_parent_._set_fixed(rav_i)
|
||||
fix = constrain_fixed
|
||||
|
||||
def unconstrain_fixed(self):
|
||||
"""
|
||||
This parameter will no longer be fixed.
|
||||
"""
|
||||
unconstrained = self.unconstrain(__fixed__)
|
||||
import ipdb;ipdb.set_trace()
|
||||
self._highest_parent_._set_unfixed(unconstrained)
|
||||
|
||||
unfix = unconstrain_fixed
|
||||
|
||||
def _set_fixed(self, index):
|
||||
import numpy as np
|
||||
if not self._has_fixes(): self._fixes_ = np.ones(self.size, dtype=bool)
|
||||
self._fixes_[index] = FIXED
|
||||
if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED
|
||||
|
||||
def _set_unfixed(self, index):
|
||||
import numpy as np
|
||||
if not self._has_fixes(): self._fixes_ = np.ones(self.size, dtype=bool)
|
||||
#rav_i = self._raveled_index_for(param)[index]
|
||||
self._fixes_[index] = UNFIXED
|
||||
if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED
|
||||
|
||||
def _connect_fixes(self):
|
||||
import numpy as np
|
||||
fixed_indices = self.constraints[__fixed__]
|
||||
if fixed_indices.size > 0:
|
||||
self._fixes_ = np.ones(self.size, dtype=bool) * UNFIXED
|
||||
self._fixes_[fixed_indices] = FIXED
|
||||
else:
|
||||
self._fixes_ = None
|
||||
|
||||
#===========================================================================
|
||||
# Constrain operations -> done
|
||||
#===========================================================================
|
||||
|
|
@ -174,17 +203,28 @@ class Constrainable(Nameable, Indexable, Parameterizable):
|
|||
self._set_params(transform.initialize(self._get_params()), update=False)
|
||||
reconstrained = self.unconstrain()
|
||||
self.constraints.add(transform, self._raveled_index())
|
||||
if reconstrained.size > 0:
|
||||
if warning and reconstrained.size > 0:
|
||||
print "WARNING: reconstraining parameters {}".format(self.parameter_names)
|
||||
if update:
|
||||
self._highest_parent_.parameters_changed()
|
||||
# if self.has_parent():
|
||||
# self._highest_parent_._add_constrain(self, transform, warning)
|
||||
# else:
|
||||
# for p in self._parameters_:
|
||||
# self._add_constrain(p, transform, warning)
|
||||
# if update:
|
||||
# self.parameters_changed()
|
||||
|
||||
def unconstrain(self, *transforms):
|
||||
"""
|
||||
:param transforms: The transformations to unconstrain from.
|
||||
|
||||
remove all :py:class:`GPy.core.transformations.Transformation`
|
||||
transformats of this parameter object.
|
||||
"""
|
||||
if len(transforms) == 0:
|
||||
transforms = self.constraints.properties()
|
||||
import numpy as np
|
||||
removed = np.empty((0,),dtype=int)
|
||||
for t in transforms:
|
||||
unconstrained = self.constraints.remove(t, self._raveled_index())
|
||||
removed = np.union1d(removed, unconstrained)
|
||||
if t is __fixed__:
|
||||
self._highest_parent_._set_unfixed(unconstrained)
|
||||
return removed
|
||||
|
||||
def constrain_positive(self, warning=True, update=True):
|
||||
"""
|
||||
|
|
@ -211,21 +251,6 @@ class Constrainable(Nameable, Indexable, Parameterizable):
|
|||
"""
|
||||
self.constrain(Logistic(lower, upper), warning=warning, update=update)
|
||||
|
||||
def unconstrain(self, *transforms):
|
||||
"""
|
||||
:param transforms: The transformations to unconstrain from.
|
||||
|
||||
remove all :py:class:`GPy.core.transformations.Transformation`
|
||||
transformats of this parameter object.
|
||||
"""
|
||||
if len(transforms) == 0:
|
||||
transforms = self.constraints.properties()
|
||||
import numpy as np
|
||||
removed = np.empty((0,),dtype=int)
|
||||
for t in transforms:
|
||||
removed = np.union1d(removed, self.constraints.remove(t, self._raveled_index()))
|
||||
return removed
|
||||
|
||||
def unconstrain_positive(self):
|
||||
"""
|
||||
Remove positive constraint of this parameter.
|
||||
|
|
|
|||
|
|
@ -8,15 +8,10 @@ import cPickle
|
|||
import itertools
|
||||
from re import compile, _pattern_type
|
||||
from param import ParamConcatenation, Param
|
||||
from parameter_core import Constrainable, Pickleable, Observable, adjust_name_for_printing, Gradcheckable, __fixed__
|
||||
from parameter_core import Constrainable, Pickleable, Observable, adjust_name_for_printing, Gradcheckable
|
||||
from transformations import __fixed__, FIXED, UNFIXED
|
||||
from array_core import ParamList
|
||||
|
||||
#===============================================================================
|
||||
# constants
|
||||
FIXED = False
|
||||
UNFIXED = True
|
||||
#===============================================================================
|
||||
|
||||
class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable):
|
||||
"""
|
||||
Parameterized class
|
||||
|
|
@ -71,37 +66,6 @@ class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable):
|
|||
self._added_names_ = set()
|
||||
del self._in_init_
|
||||
|
||||
#===========================================================================
|
||||
# Parameter connection for model creation:
|
||||
#===========================================================================
|
||||
# def set_as_parameter(self, name, array, gradient, index=None, gradient_parent=None):
|
||||
# """
|
||||
# :param name: name of the param (in print and plots), can be callable without parameters
|
||||
# :type name: str, callable
|
||||
# :param array: array which the param consists of
|
||||
# :type array: array-like
|
||||
# :param gradient: gradient method of the param
|
||||
# :type gradient: callable
|
||||
# :param index: (optional) index of the param when printing
|
||||
#
|
||||
# (:param gradient_parent: connect these parameters to this class, but tell
|
||||
# updates to highest_parent, this is needed when parameterized classes
|
||||
# contain parameterized classes, but want to access the parameters
|
||||
# of their children)
|
||||
#
|
||||
#
|
||||
# Set array (e.g. self.X) as param with name and gradient.
|
||||
# I.e: self.set_as_parameter('curvature', self.lengthscale, self.dK_dlengthscale)
|
||||
#
|
||||
# Note: the order in which parameters are added can be adjusted by
|
||||
# giving an index, of where to put this param in printing
|
||||
# """
|
||||
# if index is None:
|
||||
# self._parameters_.append(Param(name, array, gradient))
|
||||
# else:
|
||||
# self._parameters_.insert(index, Param(name, array, gradient))
|
||||
# self._connect_parameters(gradient_parent=gradient_parent)
|
||||
|
||||
def _has_fixes(self):
|
||||
return hasattr(self, "_fixes_") and self._fixes_ is not None
|
||||
|
||||
|
|
@ -118,53 +82,22 @@ class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable):
|
|||
# if param.has_parent():
|
||||
# raise AttributeError, "parameter {} already in another model, create new object (or copy) for adding".format(param._short())
|
||||
if param in self._parameters_ and index is not None:
|
||||
# make sure fixes and constraints are indexed right
|
||||
if self._has_fixes():
|
||||
param_slice = slice(self._offset_for(param), self._offset_for(param) + param.size)
|
||||
dest_index = sum((p.size for p in self._parameters_[:index]))
|
||||
dest_slice = slice(dest_index, dest_index + param.size)
|
||||
fixes_param = self._fixes_[param_slice].copy()
|
||||
self._fixes_[param_slice] = self._fixes_[dest_slice]
|
||||
self._fixes_[dest_slice] = fixes_param
|
||||
|
||||
del self._parameters_[param._parent_index_]
|
||||
self._parameters_.insert(index, param)
|
||||
self.remove_parameter(param)
|
||||
self.add_parameter(param, index)
|
||||
elif param not in self._parameters_:
|
||||
# make sure the size is set
|
||||
if not hasattr(self, 'size'):
|
||||
self.size = sum(p.size for p in self._parameters_)
|
||||
if index is None:
|
||||
self._parameters_.append(param)
|
||||
|
||||
# make sure fixes and constraints are indexed right
|
||||
if param._has_fixes(): fixes_param = param._fixes_.copy()
|
||||
else: fixes_param = numpy.ones(param.size, dtype=bool)
|
||||
if self._has_fixes(): self._fixes_ = np.r_[self._fixes_, fixes_param]
|
||||
elif param._has_fixes(): self._fixes_ = np.r_[np.ones(self.size, dtype=bool), fixes_param]
|
||||
|
||||
else:
|
||||
start = sum(p.size for p in self._parameters_[:index])
|
||||
self.constraints.shift(start, param.size)
|
||||
self._parameters_.insert(index, param)
|
||||
|
||||
# make sure fixes and constraints are indexed right
|
||||
if param._has_fixes(): fixes_param = param._fixes_.copy()
|
||||
else: fixes_param = numpy.ones(param.size, dtype=bool)
|
||||
ins = sum((p.size for p in self._parameters_[:index]))
|
||||
if self._has_fixes(): self._fixes_ = np.r_[self._fixes_[:ins], fixes_param, self._fixes[ins:]]
|
||||
elif not np.all(fixes_param):
|
||||
self._fixes_ = np.ones(self.size + param.size, dtype=bool)
|
||||
self._fixes_[ins:ins + param.size] = fixes_param
|
||||
self.size += param.size
|
||||
else:
|
||||
raise RuntimeError, """Parameter exists already added and no copy made"""
|
||||
self._connect_parameters()
|
||||
for p in self._parameters_:
|
||||
p._parent_changed(self)
|
||||
if param._default_constraint_ is not None:
|
||||
param.constrain(param._default_constraint_, False)
|
||||
if self._has_fixes() and np.all(self._fixes_): # ==UNFIXED
|
||||
self._fixes_ = None
|
||||
|
||||
def add_parameters(self, *parameters):
|
||||
"""
|
||||
|
|
@ -173,18 +106,20 @@ class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable):
|
|||
"""
|
||||
[self.add_parameter(p) for p in parameters]
|
||||
|
||||
def remove_parameter(self, *names_params_indices):
|
||||
def remove_parameter(self, param):
|
||||
"""
|
||||
:param names_params_indices: mix of parameter_names, param objects, or indices
|
||||
to remove from being a param of this parameterized object.
|
||||
|
||||
note: if it is a string object it will not (!) be regexp-matched
|
||||
automatically.
|
||||
:param param: param object to remove from being a parameter of this parameterized object.
|
||||
"""
|
||||
self._parameters_ = ParamList([p for p in self._parameters_
|
||||
if not (p._parent_index_ in names_params_indices
|
||||
or p.name in names_params_indices
|
||||
or p in names_params_indices)])
|
||||
if not param in self._parameters_:
|
||||
raise RuntimeError, "Parameter {} does not belong to this object, remove parameters directly from their respective parents".format(param._short())
|
||||
del self._parameters_[param._parent_index_]
|
||||
self.size -= param.size
|
||||
constr = param.constraints.copy()
|
||||
param.constraints.clear()
|
||||
param.constraints = constr
|
||||
param._direct_parent_ = None
|
||||
param._parent_index_ = None
|
||||
param._connect_fixes()
|
||||
self._connect_parameters()
|
||||
|
||||
def _connect_parameters(self):
|
||||
|
|
@ -214,6 +149,8 @@ class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable):
|
|||
elif not (pname in not_unique):
|
||||
self.__dict__[pname] = p
|
||||
self._added_names_.add(pname)
|
||||
self._connect_fixes()
|
||||
|
||||
#===========================================================================
|
||||
# Pickling operations
|
||||
#===========================================================================
|
||||
|
|
@ -337,7 +274,7 @@ class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable):
|
|||
self._added_names_.add(pname)
|
||||
self.__dict__[pname] = param
|
||||
#===========================================================================
|
||||
# Index Handling
|
||||
# Indexable Handling
|
||||
#===========================================================================
|
||||
def _backtranslate_index(self, param, ind):
|
||||
# translate an index in parameterized indexing into the index of param
|
||||
|
|
@ -373,36 +310,10 @@ class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable):
|
|||
#===========================================================================
|
||||
# Fixing parameters:
|
||||
#===========================================================================
|
||||
def _set_fixed(self, param_or_index):
|
||||
if not self._has_fixes(): self._fixes_ = numpy.ones(self.size, dtype=bool)
|
||||
try:
|
||||
param_or_index = self._raveled_index_for(param_or_index)
|
||||
except AttributeError:
|
||||
pass
|
||||
self._fixes_[param_or_index] = FIXED
|
||||
if numpy.all(self._fixes_): self._fixes_ = None # ==UNFIXED
|
||||
def _set_unfixed(self, param_or_index):
|
||||
if not self._has_fixes(): self._fixes_ = numpy.ones(self.size, dtype=bool)
|
||||
try:
|
||||
param_or_index = self._raveled_index_for(param_or_index)
|
||||
except AttributeError:
|
||||
pass
|
||||
self._fixes_[param_or_index] = UNFIXED
|
||||
for constr, ind in self.constraints.iteritems():
|
||||
if constr is __fixed__:
|
||||
self._fixes_[ind] = FIXED
|
||||
if numpy.all(self._fixes_): self._fixes_ = None # ==UNFIXED
|
||||
def _fixes_for(self, param):
|
||||
if self._has_fixes():
|
||||
return self._fixes_[self._raveled_index_for(param)]
|
||||
return numpy.ones(self.size, dtype=bool)[self._raveled_index_for(param)]
|
||||
# def _fix(self, param, warning=True):
|
||||
# f = self._add_constrain(param, __fixed__, warning)
|
||||
# self._set_fixed(f)
|
||||
# def _unfix(self, param):
|
||||
# if self._has_fixes():
|
||||
# f = self._remove_constrain(param, __fixed__)
|
||||
# self._set_unfixed(f)
|
||||
#===========================================================================
|
||||
# Convenience for fixed, tied checking of param:
|
||||
#===========================================================================
|
||||
|
|
|
|||
|
|
@ -6,8 +6,17 @@ import numpy as np
|
|||
from domains import _POSITIVE,_NEGATIVE, _BOUNDED
|
||||
import sys
|
||||
import weakref
|
||||
|
||||
_lim_val = -np.log(sys.float_info.epsilon)
|
||||
|
||||
#===============================================================================
|
||||
# Fixing constants
|
||||
__fixed__ = "fixed"
|
||||
FIXED = False
|
||||
UNFIXED = True
|
||||
#===============================================================================
|
||||
|
||||
|
||||
class Transformation(object):
|
||||
domain = None
|
||||
_instance = None
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class RBF(Kernpart):
|
|||
|
||||
self.variance = Param('variance', variance, Logexp())
|
||||
|
||||
self.lengthscale = Param('lengthscale', lengthscale)
|
||||
self.lengthscale = Param('lengthscale', lengthscale, Logexp())
|
||||
self.lengthscale.add_observer(self, self.update_lengthscale)
|
||||
self.update_lengthscale(self.lengthscale)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import GPy
|
|||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
import time
|
||||
import Image
|
||||
try:
|
||||
import visual
|
||||
visual_available = True
|
||||
|
|
@ -324,6 +323,7 @@ class image_show(matplotlib_show):
|
|||
else:
|
||||
self.vals = 255*(self.vals - self.vals.min())/(self.vals.max() - self.vals.min())
|
||||
if not self.palette == []: # applying using an image palette (e.g. if the image has been quantized)
|
||||
from PIL import Image
|
||||
self.vals = Image.fromarray(self.vals.astype('uint8'))
|
||||
self.vals.putpalette(self.palette) # palette is a list, must be loaded before calling this function
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue