34
.coveragerc
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# .coveragerc to control coverage.py
|
||||||
|
[run]
|
||||||
|
branch = True
|
||||||
|
source = paramz
|
||||||
|
omit = ./paramz/tests/*.py, travis_tests.py, setup.py, ./paramz/__version__.py
|
||||||
|
|
||||||
|
[report]
|
||||||
|
# Regexes for lines to exclude from consideration
|
||||||
|
exclude_lines =
|
||||||
|
# Have to re-enable the standard pragma
|
||||||
|
pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
|
# Don't complain about missing debug-only code:
|
||||||
|
if self\.debug
|
||||||
|
|
||||||
|
# Don't complain if tests don't hit defensive assertion code:
|
||||||
|
raise AssertionError
|
||||||
|
raise NotImplementedError
|
||||||
|
raise NotImplemented
|
||||||
|
except NotImplementedError
|
||||||
|
except NotImplemented
|
||||||
|
except AssertionError
|
||||||
|
except ImportError
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Don't complain if non-runnable code isn't run:
|
||||||
|
if 0:
|
||||||
|
if __name__ == .__main__.:
|
||||||
|
|
||||||
|
# Don't fail on python3 catch clauses:
|
||||||
|
python3
|
||||||
|
|
||||||
|
ignore_errors = True
|
||||||
|
|
@ -67,8 +67,8 @@ deploy:
|
||||||
password:
|
password:
|
||||||
secure: "vMEOlP7DQhFJ7hQAKtKC5hrJXFl5BkUt4nXdosWWiw//Kg8E+PPLg88XPI2gqIosir9wwgtbSBBbbwCxkM6uxRNMpoNR8Ixyv9fmSXp4rLl7bbBY768W7IRXKIBjpuEy2brQjoT+CwDDSzUkckHvuUjJDNRvUv8ab4P/qYO1LG4="
|
secure: "vMEOlP7DQhFJ7hQAKtKC5hrJXFl5BkUt4nXdosWWiw//Kg8E+PPLg88XPI2gqIosir9wwgtbSBBbbwCxkM6uxRNMpoNR8Ixyv9fmSXp4rLl7bbBY768W7IRXKIBjpuEy2brQjoT+CwDDSzUkckHvuUjJDNRvUv8ab4P/qYO1LG4="
|
||||||
on:
|
on:
|
||||||
tags: true
|
tags: false
|
||||||
branch: master
|
branch: paramz
|
||||||
#server: https://testpypi.python.org/pypi
|
server: https://testpypi.python.org/pypi
|
||||||
distributions: "bdist_wheel sdist"
|
distributions: "bdist_wheel sdist"
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@ import warnings
|
||||||
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
||||||
|
|
||||||
from . import core
|
from . import core
|
||||||
from .core.parameterization import transformations, priors
|
|
||||||
constraints = transformations
|
|
||||||
from . import models
|
from . import models
|
||||||
from . import mappings
|
from . import mappings
|
||||||
from . import inference
|
from . import inference
|
||||||
|
|
@ -13,16 +11,24 @@ from . import util
|
||||||
from . import examples
|
from . import examples
|
||||||
from . import likelihoods
|
from . import likelihoods
|
||||||
from . import testing
|
from . import testing
|
||||||
from numpy.testing import Tester
|
|
||||||
from . import kern
|
from . import kern
|
||||||
from . import plotting
|
from . import plotting
|
||||||
|
|
||||||
|
# backwards compatibility
|
||||||
|
import sys
|
||||||
|
backwards_compatibility = ['lists_and_dicts', 'observable_array', 'ties_and_remappings', 'index_operations']
|
||||||
|
for bc in backwards_compatibility:
|
||||||
|
sys.modules['GPy.core.parameterization.{!s}'.format(bc)] = getattr(core.parameterization, bc)
|
||||||
|
|
||||||
|
|
||||||
# Direct imports for convenience:
|
# Direct imports for convenience:
|
||||||
from .core import Model
|
from .core import Model
|
||||||
from .core.parameterization import Param, Parameterized, ObsAr
|
from .core.parameterization import priors
|
||||||
|
from .core.parameterization import Param, Parameterized, ObsAr, transformations as constraints
|
||||||
|
|
||||||
from .__version__ import __version__
|
from .__version__ import __version__
|
||||||
|
|
||||||
|
from numpy.testing import Tester
|
||||||
#@nottest
|
#@nottest
|
||||||
try:
|
try:
|
||||||
#Get rid of nose dependency by only ignoring if you have nose installed
|
#Get rid of nose dependency by only ignoring if you have nose installed
|
||||||
|
|
@ -41,29 +47,29 @@ def load(file_or_path):
|
||||||
:param file_name: path/to/file.pickle
|
:param file_name: path/to/file.pickle
|
||||||
"""
|
"""
|
||||||
# This is the pickling pain when changing _src -> src
|
# This is the pickling pain when changing _src -> src
|
||||||
|
import inspect
|
||||||
|
sys.modules['GPy.kern._src'] = kern.src # @UndefinedVariable
|
||||||
|
for name, module in inspect.getmembers(kern.src): # @UndefinedVariable
|
||||||
|
if not name.startswith('_'):
|
||||||
|
sys.modules['GPy.kern._src.{}'.format(name)] = module
|
||||||
try:
|
try:
|
||||||
try:
|
import cPickle as pickle
|
||||||
import cPickle as pickle
|
if isinstance(file_or_path, basestring):
|
||||||
if isinstance(file_or_path, basestring):
|
with open(file_or_path, 'rb') as f:
|
||||||
with open(file_or_path, 'rb') as f:
|
m = pickle.load(f)
|
||||||
u = pickle._Unpickler(f)
|
else:
|
||||||
u.encoding = 'latin1'
|
m = pickle.load(file_or_path)
|
||||||
m = u.load()
|
except: # python3
|
||||||
else:
|
import pickle # @Reimport
|
||||||
m = pickle.load(file_or_path)
|
if isinstance(file_or_path, str):
|
||||||
except:
|
with open(file_or_path, 'rb') as f:
|
||||||
import pickle
|
#u = pickle._Unpickler(f) # @UndefinedVariable
|
||||||
if isinstance(file_or_path, str):
|
#u.encoding = 'latin1'
|
||||||
with open(file_or_path, 'rb') as f:
|
#m = u.load()
|
||||||
m = pickle.load(f)
|
m = pickle.load(f, encoding='latin1')#
|
||||||
else:
|
else:
|
||||||
m = pickle.load(file_or_path)
|
#u = pickle._Unpickler(file_or_path) # @UndefinedVariable
|
||||||
except ImportError:
|
#u.encoding = 'latin1'
|
||||||
import sys
|
#m = u.load(protocol=2)
|
||||||
import inspect
|
m = pickle.load(f, encoding='latin1')#
|
||||||
sys.modules['GPy.kern._src'] = kern.src
|
|
||||||
for name, module in inspect.getmembers(kern.src):
|
|
||||||
if not name.startswith('_'):
|
|
||||||
sys.modules['GPy.kern._src.{}'.format(name)] = module
|
|
||||||
m = load(file_or_path)
|
|
||||||
return m
|
return m
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
__version__ = "0.8.8dev5"
|
__version__ = "0.8.21"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,46 @@
|
||||||
# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
|
# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
from .model import *
|
from GPy.core.model import Model
|
||||||
from .parameterization.parameterized import adjust_name_for_printing, Parameterizable
|
from .parameterization import Param, Parameterized
|
||||||
from .parameterization.param import Param, ParamConcatenation
|
from . import parameterization
|
||||||
from .parameterization.observable_array import ObsAr
|
|
||||||
|
|
||||||
from .gp import GP
|
from .gp import GP
|
||||||
from .svgp import SVGP
|
from .svgp import SVGP
|
||||||
from .sparse_gp import SparseGP
|
from .sparse_gp import SparseGP
|
||||||
from .mapping import *
|
from .mapping import *
|
||||||
|
|
||||||
|
|
||||||
|
#===========================================================================
|
||||||
|
# Handle priors, this needs to be
|
||||||
|
# cleaned up at some point
|
||||||
|
#===========================================================================
|
||||||
|
def randomize(self, rand_gen=None, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Randomize the model.
|
||||||
|
Make this draw from the prior if one exists, else draw from given random generator
|
||||||
|
|
||||||
|
:param rand_gen: np random number generator which takes args and kwargs
|
||||||
|
:param flaot loc: loc parameter for random number generator
|
||||||
|
:param float scale: scale parameter for random number generator
|
||||||
|
:param args, kwargs: will be passed through to random number generator
|
||||||
|
"""
|
||||||
|
if rand_gen is None:
|
||||||
|
rand_gen = np.random.normal
|
||||||
|
# first take care of all parameters (from N(0,1))
|
||||||
|
x = rand_gen(size=self._size_transformed(), *args, **kwargs)
|
||||||
|
updates = self.update_model()
|
||||||
|
self.update_model(False) # Switch off the updates
|
||||||
|
self.optimizer_array = x # makes sure all of the tied parameters get the same init (since there's only one prior object...)
|
||||||
|
# now draw from prior where possible
|
||||||
|
x = self.param_array.copy()
|
||||||
|
[np.put(x, ind, p.rvs(ind.size)) for p, ind in self.priors.items() if not p is None]
|
||||||
|
unfixlist = np.ones((self.size,),dtype=np.bool)
|
||||||
|
from paramz.transformations import __fixed__
|
||||||
|
unfixlist[self.constraints[__fixed__]] = False
|
||||||
|
self.param_array.flat[unfixlist] = x.view(np.ndarray).ravel()[unfixlist]
|
||||||
|
self.update_model(updates)
|
||||||
|
|
||||||
|
Model.randomize = randomize
|
||||||
|
Param.randomize = randomize
|
||||||
|
Parameterized.randomize = randomize
|
||||||
|
|
@ -2,14 +2,13 @@
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import sys
|
|
||||||
from .. import kern
|
from .. import kern
|
||||||
from .model import Model
|
from GPy.core.model import Model
|
||||||
from .parameterization import ObsAr
|
from paramz import ObsAr
|
||||||
from .mapping import Mapping
|
from .mapping import Mapping
|
||||||
from .. import likelihoods
|
from .. import likelihoods
|
||||||
from ..inference.latent_function_inference import exact_gaussian_inference, expectation_propagation
|
from ..inference.latent_function_inference import exact_gaussian_inference, expectation_propagation
|
||||||
from .parameterization.variational import VariationalPosterior
|
from GPy.core.parameterization.variational import VariationalPosterior
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import warnings
|
import warnings
|
||||||
|
|
|
||||||
|
|
@ -1,126 +1,18 @@
|
||||||
# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
|
# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
from .parameterization.priorizable import Priorizable
|
||||||
|
from paramz import Model as ParamzModel
|
||||||
|
|
||||||
|
class Model(ParamzModel, Priorizable):
|
||||||
from .. import likelihoods
|
|
||||||
from ..inference import optimization
|
|
||||||
from ..util.misc import opt_wrapper
|
|
||||||
from .parameterization import Parameterized
|
|
||||||
import multiprocessing as mp
|
|
||||||
import numpy as np
|
|
||||||
from numpy.linalg.linalg import LinAlgError
|
|
||||||
import itertools
|
|
||||||
import sys
|
|
||||||
from .verbose_optimization import VerboseOptimization
|
|
||||||
# import numdifftools as ndt
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
class Model(Parameterized):
|
|
||||||
_fail_count = 0 # Count of failed optimization steps (see objective)
|
|
||||||
_allowed_failures = 10 # number of allowed failures
|
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
super(Model, self).__init__(name) # Parameterized.__init__(self)
|
super(Model, self).__init__(name) # Parameterized.__init__(self)
|
||||||
self.optimization_runs = []
|
|
||||||
self.sampling_runs = []
|
|
||||||
self.preferred_optimizer = 'lbfgsb'
|
|
||||||
from .parameterization.ties_and_remappings import Tie
|
|
||||||
self.tie = Tie()
|
|
||||||
self.link_parameter(self.tie, -1)
|
|
||||||
self.obj_grads = None
|
|
||||||
self.add_observer(self.tie, self.tie._parameters_changed_notification, priority=-500)
|
|
||||||
|
|
||||||
def log_likelihood(self):
|
def log_likelihood(self):
|
||||||
raise NotImplementedError("this needs to be implemented to use the model class")
|
raise NotImplementedError("this needs to be implemented to use the model class")
|
||||||
|
|
||||||
def _log_likelihood_gradients(self):
|
def _log_likelihood_gradients(self):
|
||||||
return self.gradient.copy()
|
return self.gradient#.copy()
|
||||||
|
|
||||||
def optimize_restarts(self, num_restarts=10, robust=False, verbose=True, parallel=False, num_processes=None, **kwargs):
|
|
||||||
"""
|
|
||||||
Perform random restarts of the model, and set the model to the best
|
|
||||||
seen solution.
|
|
||||||
|
|
||||||
If the robust flag is set, exceptions raised during optimizations will
|
|
||||||
be handled silently. If _all_ runs fail, the model is reset to the
|
|
||||||
existing parameter values.
|
|
||||||
|
|
||||||
**Notes**
|
|
||||||
|
|
||||||
:param num_restarts: number of restarts to use (default 10)
|
|
||||||
:type num_restarts: int
|
|
||||||
:param robust: whether to handle exceptions silently or not (default False)
|
|
||||||
:type robust: bool
|
|
||||||
:param parallel: whether to run each restart as a separate process. It relies on the multiprocessing module.
|
|
||||||
:type parallel: bool
|
|
||||||
:param num_processes: number of workers in the multiprocessing pool
|
|
||||||
:type numprocesses: int
|
|
||||||
|
|
||||||
\*\*kwargs are passed to the optimizer. They can be:
|
|
||||||
|
|
||||||
:param max_f_eval: maximum number of function evaluations
|
|
||||||
:type max_f_eval: int
|
|
||||||
:param max_iters: maximum number of iterations
|
|
||||||
:type max_iters: int
|
|
||||||
:param messages: whether to display during optimisation
|
|
||||||
:type messages: bool
|
|
||||||
|
|
||||||
.. note:: If num_processes is None, the number of workes in the
|
|
||||||
multiprocessing pool is automatically set to the number of processors
|
|
||||||
on the current machine.
|
|
||||||
|
|
||||||
"""
|
|
||||||
initial_parameters = self.optimizer_array.copy()
|
|
||||||
|
|
||||||
if parallel:
|
|
||||||
try:
|
|
||||||
jobs = []
|
|
||||||
pool = mp.Pool(processes=num_processes)
|
|
||||||
for i in range(num_restarts):
|
|
||||||
if i>0: self.randomize()
|
|
||||||
job = pool.apply_async(opt_wrapper, args=(self,), kwds=kwargs)
|
|
||||||
jobs.append(job)
|
|
||||||
|
|
||||||
pool.close() # signal that no more data coming in
|
|
||||||
pool.join() # wait for all the tasks to complete
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
print("Ctrl+c received, terminating and joining pool.")
|
|
||||||
pool.terminate()
|
|
||||||
pool.join()
|
|
||||||
|
|
||||||
for i in range(num_restarts):
|
|
||||||
try:
|
|
||||||
if not parallel:
|
|
||||||
if i>0: self.randomize()
|
|
||||||
self.optimize(**kwargs)
|
|
||||||
else:
|
|
||||||
self.optimization_runs.append(jobs[i].get())
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
print(("Optimization restart {0}/{1}, f = {2}".format(i + 1, num_restarts, self.optimization_runs[-1].f_opt)))
|
|
||||||
except Exception as e:
|
|
||||||
if robust:
|
|
||||||
print(("Warning - optimization restart {0}/{1} failed".format(i + 1, num_restarts)))
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
if len(self.optimization_runs):
|
|
||||||
i = np.nanargmin([o.f_opt for o in self.optimization_runs])
|
|
||||||
self.optimizer_array = self.optimization_runs[i].x_opt
|
|
||||||
else:
|
|
||||||
self.optimizer_array = initial_parameters
|
|
||||||
|
|
||||||
def ensure_default_constraints(self, warning=True):
|
|
||||||
"""
|
|
||||||
Ensure that any variables which should clearly be positive
|
|
||||||
have been constrained somehow. The method performs a regular
|
|
||||||
expression search on parameter names looking for the terms
|
|
||||||
'variance', 'lengthscale', 'precision' and 'kappa'. If any of
|
|
||||||
these terms are present in the name the parameter is
|
|
||||||
constrained positive.
|
|
||||||
|
|
||||||
DEPRECATED.
|
|
||||||
"""
|
|
||||||
raise DeprecationWarning('parameters now have default constraints')
|
|
||||||
|
|
||||||
def objective_function(self):
|
def objective_function(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -153,285 +45,4 @@ class Model(Parameterized):
|
||||||
(including the MAP prior), so we return it here. If your model is not
|
(including the MAP prior), so we return it here. If your model is not
|
||||||
probabilistic, just return your *negative* gradient here!
|
probabilistic, just return your *negative* gradient here!
|
||||||
"""
|
"""
|
||||||
return -(self._log_likelihood_gradients() + self._log_prior_gradients())
|
return -(self._log_likelihood_gradients() + self._log_prior_gradients())
|
||||||
|
|
||||||
def _grads(self, x):
|
|
||||||
"""
|
|
||||||
Gets the gradients from the likelihood and the priors.
|
|
||||||
|
|
||||||
Failures are handled robustly. The algorithm will try several times to
|
|
||||||
return the gradients, and will raise the original exception if
|
|
||||||
the objective cannot be computed.
|
|
||||||
|
|
||||||
:param x: the parameters of the model.
|
|
||||||
:type x: np.array
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# self._set_params_transformed(x)
|
|
||||||
self.optimizer_array = x
|
|
||||||
self.obj_grads = self._transform_gradients(self.objective_function_gradients())
|
|
||||||
self._fail_count = 0
|
|
||||||
except (LinAlgError, ZeroDivisionError, ValueError):
|
|
||||||
if self._fail_count >= self._allowed_failures:
|
|
||||||
raise
|
|
||||||
self._fail_count += 1
|
|
||||||
self.obj_grads = np.clip(self._transform_gradients(self.objective_function_gradients()), -1e100, 1e100)
|
|
||||||
return self.obj_grads
|
|
||||||
|
|
||||||
def _objective(self, x):
|
|
||||||
"""
|
|
||||||
The objective function passed to the optimizer. It combines
|
|
||||||
the likelihood and the priors.
|
|
||||||
|
|
||||||
Failures are handled robustly. The algorithm will try several times to
|
|
||||||
return the objective, and will raise the original exception if
|
|
||||||
the objective cannot be computed.
|
|
||||||
|
|
||||||
:param x: the parameters of the model.
|
|
||||||
:parameter type: np.array
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.optimizer_array = x
|
|
||||||
obj = self.objective_function()
|
|
||||||
self._fail_count = 0
|
|
||||||
except (LinAlgError, ZeroDivisionError, ValueError):
|
|
||||||
if self._fail_count >= self._allowed_failures:
|
|
||||||
raise
|
|
||||||
self._fail_count += 1
|
|
||||||
return np.inf
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def _objective_grads(self, x):
|
|
||||||
try:
|
|
||||||
self.optimizer_array = x
|
|
||||||
obj_f, self.obj_grads = self.objective_function(), self._transform_gradients(self.objective_function_gradients())
|
|
||||||
self._fail_count = 0
|
|
||||||
except (LinAlgError, ZeroDivisionError, ValueError):
|
|
||||||
if self._fail_count >= self._allowed_failures:
|
|
||||||
raise
|
|
||||||
self._fail_count += 1
|
|
||||||
obj_f = np.inf
|
|
||||||
self.obj_grads = np.clip(self._transform_gradients(self.objective_function_gradients()), -1e10, 1e10)
|
|
||||||
return obj_f, self.obj_grads
|
|
||||||
|
|
||||||
def optimize(self, optimizer=None, start=None, messages=False, max_iters=1000, ipython_notebook=True, clear_after_finish=False, **kwargs):
|
|
||||||
"""
|
|
||||||
Optimize the model using self.log_likelihood and self.log_likelihood_gradient, as well as self.priors.
|
|
||||||
|
|
||||||
kwargs are passed to the optimizer. They can be:
|
|
||||||
|
|
||||||
:param max_iters: maximum number of function evaluations
|
|
||||||
:type max_iters: int
|
|
||||||
:messages: True: Display messages during optimisation, "ipython_notebook":
|
|
||||||
:type messages: bool"string
|
|
||||||
:param optimizer: which optimizer to use (defaults to self.preferred optimizer)
|
|
||||||
:type optimizer: string
|
|
||||||
|
|
||||||
Valid optimizers are:
|
|
||||||
- 'scg': scaled conjugate gradient method, recommended for stability.
|
|
||||||
See also GPy.inference.optimization.scg
|
|
||||||
- 'fmin_tnc': truncated Newton method (see scipy.optimize.fmin_tnc)
|
|
||||||
- 'simplex': the Nelder-Mead simplex method (see scipy.optimize.fmin),
|
|
||||||
- 'lbfgsb': the l-bfgs-b method (see scipy.optimize.fmin_l_bfgs_b),
|
|
||||||
- 'sgd': stochastic gradient decsent (see scipy.optimize.sgd). For experts only!
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
if self.is_fixed or self.size == 0:
|
|
||||||
print('nothing to optimize')
|
|
||||||
|
|
||||||
if not self.update_model():
|
|
||||||
print("updates were off, setting updates on again")
|
|
||||||
self.update_model(True)
|
|
||||||
|
|
||||||
if start == None:
|
|
||||||
start = self.optimizer_array
|
|
||||||
|
|
||||||
if optimizer is None:
|
|
||||||
optimizer = self.preferred_optimizer
|
|
||||||
|
|
||||||
if isinstance(optimizer, optimization.Optimizer):
|
|
||||||
opt = optimizer
|
|
||||||
opt.model = self
|
|
||||||
else:
|
|
||||||
optimizer = optimization.get_optimizer(optimizer)
|
|
||||||
opt = optimizer(x_init=start, model=self, max_iters=max_iters, **kwargs)
|
|
||||||
|
|
||||||
with VerboseOptimization(self, opt, maxiters=max_iters, verbose=messages, ipython_notebook=ipython_notebook, clear_after_finish=clear_after_finish) as vo:
|
|
||||||
opt.run(f_fp=self._objective_grads, f=self._objective, fp=self._grads)
|
|
||||||
vo.finish(opt)
|
|
||||||
|
|
||||||
self.optimization_runs.append(opt)
|
|
||||||
|
|
||||||
self.optimizer_array = opt.x_opt
|
|
||||||
|
|
||||||
def optimize_SGD(self, momentum=0.1, learning_rate=0.01, iterations=20, **kwargs):
|
|
||||||
# assert self.Y.shape[1] > 1, "SGD only works with D > 1"
|
|
||||||
sgd = SGD.StochasticGD(self, iterations, learning_rate, momentum, **kwargs) # @UndefinedVariable
|
|
||||||
sgd.run()
|
|
||||||
self.optimization_runs.append(sgd)
|
|
||||||
|
|
||||||
def _checkgrad(self, target_param=None, verbose=False, step=1e-6, tolerance=1e-3, df_tolerance=1e-12):
|
|
||||||
"""
|
|
||||||
Check the gradient of the ,odel by comparing to a numerical
|
|
||||||
estimate. If the verbose flag is passed, individual
|
|
||||||
components are tested (and printed)
|
|
||||||
|
|
||||||
:param verbose: If True, print a "full" checking of each parameter
|
|
||||||
:type verbose: bool
|
|
||||||
:param step: The size of the step around which to linearise the objective
|
|
||||||
:type step: float (default 1e-6)
|
|
||||||
:param tolerance: the tolerance allowed (see note)
|
|
||||||
:type tolerance: float (default 1e-3)
|
|
||||||
|
|
||||||
Note:-
|
|
||||||
The gradient is considered correct if the ratio of the analytical
|
|
||||||
and numerical gradients is within <tolerance> of unity.
|
|
||||||
|
|
||||||
The *dF_ratio* indicates the limit of numerical accuracy of numerical gradients.
|
|
||||||
If it is too small, e.g., smaller than 1e-12, the numerical gradients are usually
|
|
||||||
not accurate enough for the tests (shown with blue).
|
|
||||||
"""
|
|
||||||
x = self.optimizer_array.copy()
|
|
||||||
|
|
||||||
if not verbose:
|
|
||||||
# make sure only to test the selected parameters
|
|
||||||
if target_param is None:
|
|
||||||
transformed_index = range(len(x))
|
|
||||||
else:
|
|
||||||
transformed_index = self._raveled_index_for(target_param)
|
|
||||||
if self._has_fixes():
|
|
||||||
indices = np.r_[:self.size]
|
|
||||||
which = (transformed_index[:, None] == indices[self._fixes_][None, :]).nonzero()
|
|
||||||
transformed_index = (indices - (~self._fixes_).cumsum())[transformed_index[which[0]]]
|
|
||||||
|
|
||||||
if transformed_index.size == 0:
|
|
||||||
print("No free parameters to check")
|
|
||||||
return
|
|
||||||
|
|
||||||
# just check the global ratio
|
|
||||||
dx = np.zeros(x.shape)
|
|
||||||
dx[transformed_index] = step * (np.sign(np.random.uniform(-1, 1, transformed_index.size)) if transformed_index.size != 2 else 1.)
|
|
||||||
|
|
||||||
# evaulate around the point x
|
|
||||||
f1 = self._objective(x + dx)
|
|
||||||
f2 = self._objective(x - dx)
|
|
||||||
gradient = self._grads(x)
|
|
||||||
|
|
||||||
dx = dx[transformed_index]
|
|
||||||
gradient = gradient[transformed_index]
|
|
||||||
|
|
||||||
denominator = (2 * np.dot(dx, gradient))
|
|
||||||
global_ratio = (f1 - f2) / np.where(denominator == 0., 1e-32, denominator)
|
|
||||||
global_diff = np.abs(f1 - f2) < tolerance and np.allclose(gradient, 0, atol=tolerance)
|
|
||||||
if global_ratio is np.nan:
|
|
||||||
global_ratio = 0
|
|
||||||
return np.abs(1. - global_ratio) < tolerance or global_diff
|
|
||||||
else:
|
|
||||||
# check the gradient of each parameter individually, and do some pretty printing
|
|
||||||
try:
|
|
||||||
names = self._get_param_names()
|
|
||||||
except NotImplementedError:
|
|
||||||
names = ['Variable %i' % i for i in range(len(x))]
|
|
||||||
# Prepare for pretty-printing
|
|
||||||
header = ['Name', 'Ratio', 'Difference', 'Analytical', 'Numerical', 'dF_ratio']
|
|
||||||
max_names = max([len(names[i]) for i in range(len(names))] + [len(header[0])])
|
|
||||||
float_len = 10
|
|
||||||
cols = [max_names]
|
|
||||||
cols.extend([max(float_len, len(header[i])) for i in range(1, len(header))])
|
|
||||||
cols = np.array(cols) + 5
|
|
||||||
header_string = ["{h:^{col}}".format(h=header[i], col=cols[i]) for i in range(len(cols))]
|
|
||||||
header_string = list(map(lambda x: '|'.join(x), [header_string]))
|
|
||||||
separator = '-' * len(header_string[0])
|
|
||||||
print('\n'.join([header_string[0], separator]))
|
|
||||||
if target_param is None:
|
|
||||||
param_index = range(len(x))
|
|
||||||
transformed_index = param_index
|
|
||||||
else:
|
|
||||||
param_index = self._raveled_index_for(target_param)
|
|
||||||
if self._has_fixes():
|
|
||||||
indices = np.r_[:self.size]
|
|
||||||
which = (param_index[:, None] == indices[self._fixes_][None, :]).nonzero()
|
|
||||||
param_index = param_index[which[0]]
|
|
||||||
transformed_index = (indices - (~self._fixes_).cumsum())[param_index]
|
|
||||||
# print param_index, transformed_index
|
|
||||||
else:
|
|
||||||
transformed_index = param_index
|
|
||||||
|
|
||||||
if param_index.size == 0:
|
|
||||||
print("No free parameters to check")
|
|
||||||
return
|
|
||||||
|
|
||||||
gradient = self._grads(x).copy()
|
|
||||||
np.where(gradient == 0, 1e-312, gradient)
|
|
||||||
ret = True
|
|
||||||
for nind, xind in zip(param_index, transformed_index):
|
|
||||||
xx = x.copy()
|
|
||||||
xx[xind] += step
|
|
||||||
f1 = float(self._objective(xx))
|
|
||||||
xx[xind] -= 2.*step
|
|
||||||
f2 = float(self._objective(xx))
|
|
||||||
#Avoid divide by zero, if any of the values are above 1e-15, otherwise both values are essentiall
|
|
||||||
#the same
|
|
||||||
if f1 > 1e-15 or f1 < -1e-15 or f2 > 1e-15 or f2 < -1e-15:
|
|
||||||
df_ratio = np.abs((f1 - f2) / min(f1, f2))
|
|
||||||
else:
|
|
||||||
df_ratio = 1.0
|
|
||||||
df_unstable = df_ratio < df_tolerance
|
|
||||||
numerical_gradient = (f1 - f2) / (2. * step)
|
|
||||||
if np.all(gradient[xind] == 0): ratio = (f1 - f2) == gradient[xind]
|
|
||||||
else: ratio = (f1 - f2) / (2. * step * gradient[xind])
|
|
||||||
difference = np.abs(numerical_gradient - gradient[xind])
|
|
||||||
|
|
||||||
if (np.abs(1. - ratio) < tolerance) or np.abs(difference) < tolerance:
|
|
||||||
formatted_name = "\033[92m {0} \033[0m".format(names[nind])
|
|
||||||
ret &= True
|
|
||||||
else:
|
|
||||||
formatted_name = "\033[91m {0} \033[0m".format(names[nind])
|
|
||||||
ret &= False
|
|
||||||
if df_unstable:
|
|
||||||
formatted_name = "\033[94m {0} \033[0m".format(names[nind])
|
|
||||||
|
|
||||||
r = '%.6f' % float(ratio)
|
|
||||||
d = '%.6f' % float(difference)
|
|
||||||
g = '%.6f' % gradient[xind]
|
|
||||||
ng = '%.6f' % float(numerical_gradient)
|
|
||||||
df = '%1.e' % float(df_ratio)
|
|
||||||
grad_string = "{0:<{c0}}|{1:^{c1}}|{2:^{c2}}|{3:^{c3}}|{4:^{c4}}|{5:^{c5}}".format(formatted_name, r, d, g, ng, df, c0=cols[0] + 9, c1=cols[1], c2=cols[2], c3=cols[3], c4=cols[4], c5=cols[5])
|
|
||||||
print(grad_string)
|
|
||||||
|
|
||||||
self.optimizer_array = x
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def _repr_html_(self):
|
|
||||||
"""Representation of the model in html for notebook display."""
|
|
||||||
model_details = [['<b>Model</b>', self.name + '<br>'],
|
|
||||||
['<b>Log-likelihood</b>', '{}<br>'.format(float(self.log_likelihood()))],
|
|
||||||
["<b>Number of Parameters</b>", '{}<br>'.format(self.size)],
|
|
||||||
["<b>Number of Optimization Parameters</b>", '{}<br>'.format(self._size_transformed())],
|
|
||||||
["<b>Updates</b>", '{}<br>'.format(self._update_on)],
|
|
||||||
]
|
|
||||||
from operator import itemgetter
|
|
||||||
to_print = ["""<style type="text/css">
|
|
||||||
.pd{
|
|
||||||
font-family: "Courier New", Courier, monospace !important;
|
|
||||||
width: 100%;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
</style>\n"""] + ["<p class=pd>"] + ["{}: {}".format(name, detail) for name, detail in model_details] + ["</p>"]
|
|
||||||
to_print.append(super(Model, self)._repr_html_())
|
|
||||||
return "\n".join(to_print)
|
|
||||||
|
|
||||||
def __str__(self, VT100=True):
|
|
||||||
model_details = [['Name', self.name],
|
|
||||||
['Log-likelihood', '{}'.format(float(self.log_likelihood()))],
|
|
||||||
["Number of Parameters", '{}'.format(self.size)],
|
|
||||||
["Number of Optimization Parameters", '{}'.format(self._size_transformed())],
|
|
||||||
["Updates", '{}'.format(self._update_on)],
|
|
||||||
]
|
|
||||||
from operator import itemgetter
|
|
||||||
max_len = reduce(lambda a, b: max(len(b[0]), a), model_details, 0)
|
|
||||||
to_print = [""] + ["{0:{l}} : {1}".format(name, detail, l=max_len) for name, detail in model_details] + ["Parameters:"]
|
|
||||||
to_print.append(super(Model, self).__str__(VT100=VT100))
|
|
||||||
return "\n".join(to_print)
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
from .param import Param, ObsAr
|
from .param import Param
|
||||||
from .parameterized import Parameterized
|
from .parameterized import Parameterized
|
||||||
|
from paramz import transformations
|
||||||
|
|
||||||
|
from paramz.core import lists_and_dicts, index_operations, observable_array, observable
|
||||||
|
from paramz import ties_and_remappings, ObsAr
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
|
||||||
|
|
||||||
"""
|
|
||||||
(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.
|
|
||||||
|
|
||||||
:const:`~GPy.core.domains._REAL` :
|
|
||||||
real domain, all values in the real numbers are allowed
|
|
||||||
|
|
||||||
:const:`~GPy.core.domains._POSITIVE`:
|
|
||||||
positive domain, only positive real values are allowed
|
|
||||||
|
|
||||||
:const:`~GPy.core.domains._NEGATIVE`:
|
|
||||||
same as :const:`~GPy.core.domains._POSITIVE`, but only negative values are allowed
|
|
||||||
|
|
||||||
:const:`~GPy.core.domains._BOUNDED`:
|
|
||||||
only values within the bounded range are allowed,
|
|
||||||
the bounds are specified withing the object with the bounded range
|
|
||||||
"""
|
|
||||||
|
|
||||||
_REAL = 'real'
|
|
||||||
_POSITIVE = "positive"
|
|
||||||
_NEGATIVE = 'negative'
|
|
||||||
_BOUNDED = 'bounded'
|
|
||||||
|
|
@ -1,327 +0,0 @@
|
||||||
# Copyright (c) 2014, Max Zwiessele
|
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
|
||||||
|
|
||||||
import numpy
|
|
||||||
from numpy.lib.function_base import vectorize
|
|
||||||
from .lists_and_dicts import IntArrayDict
|
|
||||||
from functools import reduce
|
|
||||||
from .transformations import Transformation
|
|
||||||
|
|
||||||
def extract_properties_to_index(index, props):
|
|
||||||
prop_index = dict()
|
|
||||||
for i, cl in enumerate(props):
|
|
||||||
for c in cl:
|
|
||||||
ind = prop_index.get(c, list())
|
|
||||||
ind.append(index[i])
|
|
||||||
prop_index[c] = ind
|
|
||||||
|
|
||||||
for c, i in prop_index.items():
|
|
||||||
prop_index[c] = numpy.array(i, dtype=int)
|
|
||||||
|
|
||||||
return prop_index
|
|
||||||
|
|
||||||
|
|
||||||
class ParameterIndexOperations(object):
|
|
||||||
"""
|
|
||||||
This object wraps a dictionary, whos keys are _operations_ that we'd like
|
|
||||||
to apply to a parameter array, and whose values are np integer arrays which
|
|
||||||
index the parameter array appropriately.
|
|
||||||
|
|
||||||
A model instance will contain one instance of this class for each thing
|
|
||||||
that needs indexing (i.e. constraints, ties and priors). Parameters within
|
|
||||||
the model constain instances of the ParameterIndexOperationsView class,
|
|
||||||
which can map from a 'local' index (starting 0) to this global index.
|
|
||||||
|
|
||||||
Here's an illustration:
|
|
||||||
|
|
||||||
#=======================================================================
|
|
||||||
model : 0 1 2 3 4 5 6 7 8 9
|
|
||||||
key1: 4 5
|
|
||||||
key2: 7 8
|
|
||||||
|
|
||||||
param1: 0 1 2 3 4 5
|
|
||||||
key1: 2 3
|
|
||||||
key2: 5
|
|
||||||
|
|
||||||
param2: 0 1 2 3 4
|
|
||||||
key1: 0
|
|
||||||
key2: 2 3
|
|
||||||
#=======================================================================
|
|
||||||
|
|
||||||
The views of this global index have a subset of the keys in this global
|
|
||||||
(model) index.
|
|
||||||
|
|
||||||
Adding a new key (e.g. a constraint) to a view will cause the view to pass
|
|
||||||
the new key to the global index, along with the local index and an offset.
|
|
||||||
This global index then stores the key and the appropriate global index
|
|
||||||
(which can be seen by the view).
|
|
||||||
|
|
||||||
See also:
|
|
||||||
ParameterIndexOperationsView
|
|
||||||
|
|
||||||
"""
|
|
||||||
_offset = 0
|
|
||||||
def __init__(self, constraints=None):
|
|
||||||
self._properties = IntArrayDict()
|
|
||||||
if constraints is not None:
|
|
||||||
#python 3 fix
|
|
||||||
#for t, i in constraints.iteritems():
|
|
||||||
for t, i in constraints.items():
|
|
||||||
self.add(t, i)
|
|
||||||
|
|
||||||
#iteritems has gone in python 3
|
|
||||||
#def iteritems(self):
|
|
||||||
# return self._properties.iteritems()
|
|
||||||
|
|
||||||
def items(self):
|
|
||||||
return self._properties.items()
|
|
||||||
|
|
||||||
def properties(self):
|
|
||||||
return self._properties.keys()
|
|
||||||
|
|
||||||
def iterproperties(self):
|
|
||||||
return iter(self._properties)
|
|
||||||
|
|
||||||
def shift_right(self, start, size):
|
|
||||||
for ind in self.iterindices():
|
|
||||||
toshift = ind>=start
|
|
||||||
ind[toshift] += size
|
|
||||||
|
|
||||||
def shift_left(self, start, size):
|
|
||||||
for v, ind in list(self.items()):
|
|
||||||
todelete = (ind>=start) * (ind<start+size)
|
|
||||||
if todelete.size != 0:
|
|
||||||
ind = ind[~todelete]
|
|
||||||
toshift = ind>=start
|
|
||||||
if toshift.size != 0:
|
|
||||||
ind[toshift] -= size
|
|
||||||
if ind.size != 0: self._properties[v] = ind
|
|
||||||
else: del self._properties[v]
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self._properties.clear()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def size(self):
|
|
||||||
return reduce(lambda a,b: a+b.size, self.iterindices(), 0)
|
|
||||||
|
|
||||||
def iterindices(self):
|
|
||||||
try:
|
|
||||||
return self._properties.itervalues()
|
|
||||||
except AttributeError:
|
|
||||||
#Changed this from itervalues to values for Py3 compatibility. It didn't break the test suite.
|
|
||||||
return self._properties.values()
|
|
||||||
|
|
||||||
def indices(self):
|
|
||||||
return self._properties.values()
|
|
||||||
|
|
||||||
def properties_for(self, index):
|
|
||||||
"""
|
|
||||||
Returns a list of properties, such that each entry in the list corresponds
|
|
||||||
to the element of the index given.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
let properties: 'one':[1,2,3,4], 'two':[3,5,6]
|
|
||||||
|
|
||||||
>>> properties_for([2,3,5])
|
|
||||||
[['one'], ['one', 'two'], ['two']]
|
|
||||||
"""
|
|
||||||
return vectorize(lambda i: [prop for prop in self.iterproperties() if i in self[prop]], otypes=[list])(index)
|
|
||||||
|
|
||||||
def properties_to_index_dict(self, index):
|
|
||||||
"""
|
|
||||||
Return a dictionary, containing properties as keys and indices as index
|
|
||||||
Thus, the indices for each constraint, which is contained will be collected as
|
|
||||||
one dictionary
|
|
||||||
|
|
||||||
Example:
|
|
||||||
let properties: 'one':[1,2,3,4], 'two':[3,5,6]
|
|
||||||
|
|
||||||
>>> properties_to_index_dict([2,3,5])
|
|
||||||
{'one':[2,3], 'two':[3,5]}
|
|
||||||
"""
|
|
||||||
props = self.properties_for(index)
|
|
||||||
prop_index = extract_properties_to_index(index, props)
|
|
||||||
return prop_index
|
|
||||||
|
|
||||||
def add(self, prop, indices):
|
|
||||||
self._properties[prop] = combine_indices(self._properties[prop], indices)
|
|
||||||
|
|
||||||
def remove(self, prop, indices):
|
|
||||||
if prop in self._properties:
|
|
||||||
diff = remove_indices(self[prop], indices)
|
|
||||||
removed = numpy.intersect1d(self[prop], indices, True)
|
|
||||||
if not index_empty(diff):
|
|
||||||
self._properties[prop] = diff
|
|
||||||
else:
|
|
||||||
del self._properties[prop]
|
|
||||||
return removed.astype(int)
|
|
||||||
return numpy.array([]).astype(int)
|
|
||||||
|
|
||||||
def update(self, parameter_index_view, offset=0):
|
|
||||||
#py3 fix
|
|
||||||
#for i, v in parameter_index_view.iteritems():
|
|
||||||
for i, v in parameter_index_view.items():
|
|
||||||
self.add(i, v+offset)
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
return self.__deepcopy__(None)
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
|
||||||
#py3 fix
|
|
||||||
#return ParameterIndexOperations(dict(self.iteritems()))
|
|
||||||
return ParameterIndexOperations(dict(self.items()))
|
|
||||||
|
|
||||||
def __getitem__(self, prop):
|
|
||||||
return self._properties[prop]
|
|
||||||
|
|
||||||
def __delitem__(self, prop):
|
|
||||||
del self._properties[prop]
|
|
||||||
|
|
||||||
def __str__(self, *args, **kwargs):
|
|
||||||
import pprint
|
|
||||||
return pprint.pformat(dict(self._properties))
|
|
||||||
|
|
||||||
def combine_indices(arr1, arr2):
|
|
||||||
return numpy.union1d(arr1, arr2)
|
|
||||||
|
|
||||||
def remove_indices(arr, to_remove):
|
|
||||||
return numpy.setdiff1d(arr, to_remove, True)
|
|
||||||
|
|
||||||
def index_empty(index):
|
|
||||||
return numpy.size(index) == 0
|
|
||||||
|
|
||||||
class ParameterIndexOperationsView(object):
|
|
||||||
def __init__(self, param_index_operations, offset, size):
|
|
||||||
self._param_index_ops = param_index_operations
|
|
||||||
self._offset = offset
|
|
||||||
self._size = size
|
|
||||||
|
|
||||||
def __getstate__(self):
|
|
||||||
return [self._param_index_ops, self._offset, self._size]
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
|
||||||
self._param_index_ops = state[0]
|
|
||||||
self._offset = state[1]
|
|
||||||
self._size = state[2]
|
|
||||||
|
|
||||||
def _filter_index(self, ind):
|
|
||||||
return ind[(ind >= self._offset) * (ind < (self._offset + self._size))] - self._offset
|
|
||||||
|
|
||||||
#iteritems has gone in python 3. It has been renamed items()
|
|
||||||
def items(self):
|
|
||||||
_items_list = list(self._param_index_ops.items())
|
|
||||||
for i, ind in _items_list:
|
|
||||||
ind2 = self._filter_index(ind)
|
|
||||||
if ind2.size > 0:
|
|
||||||
yield i, ind2
|
|
||||||
|
|
||||||
#Python 3 items() is now implemented as per py2 iteritems
|
|
||||||
#def items(self):
|
|
||||||
# return [[i,v] for i,v in self.iteritems()]
|
|
||||||
|
|
||||||
def properties(self):
|
|
||||||
return [i for i in self.iterproperties()]
|
|
||||||
|
|
||||||
|
|
||||||
def iterproperties(self):
|
|
||||||
#py3 fix
|
|
||||||
#for i, _ in self.iteritems():
|
|
||||||
for i, _ in self.items():
|
|
||||||
yield i
|
|
||||||
|
|
||||||
|
|
||||||
def shift_right(self, start, size):
|
|
||||||
self._param_index_ops.shift_right(start+self._offset, size)
|
|
||||||
|
|
||||||
def shift_left(self, start, size):
|
|
||||||
self._param_index_ops.shift_left(start+self._offset, size)
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
for i, ind in self.items():
|
|
||||||
self._param_index_ops.remove(i, ind+self._offset)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def size(self):
|
|
||||||
return reduce(lambda a,b: a+b.size, self.iterindices(), 0)
|
|
||||||
|
|
||||||
|
|
||||||
def iterindices(self):
|
|
||||||
#py3 fix
|
|
||||||
#for _, ind in self.iteritems():
|
|
||||||
for _, ind in self.items():
|
|
||||||
yield ind
|
|
||||||
|
|
||||||
|
|
||||||
def indices(self):
|
|
||||||
return [ind for ind in self.iterindices()]
|
|
||||||
|
|
||||||
|
|
||||||
def properties_for(self, index):
|
|
||||||
"""
|
|
||||||
Returns a list of properties, such that each entry in the list corresponds
|
|
||||||
to the element of the index given.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
let properties: 'one':[1,2,3,4], 'two':[3,5,6]
|
|
||||||
|
|
||||||
>>> properties_for([2,3,5])
|
|
||||||
[['one'], ['one', 'two'], ['two']]
|
|
||||||
"""
|
|
||||||
return vectorize(lambda i: [prop for prop in self.iterproperties() if i in self[prop]], otypes=[list])(index)
|
|
||||||
|
|
||||||
def properties_to_index_dict(self, index):
|
|
||||||
"""
|
|
||||||
Return a dictionary, containing properties as keys and indices as index
|
|
||||||
Thus, the indices for each constraint, which is contained will be collected as
|
|
||||||
one dictionary
|
|
||||||
|
|
||||||
Example:
|
|
||||||
let properties: 'one':[1,2,3,4], 'two':[3,5,6]
|
|
||||||
|
|
||||||
>>> properties_to_index_dict([2,3,5])
|
|
||||||
{'one':[2,3], 'two':[3,5]}
|
|
||||||
"""
|
|
||||||
return extract_properties_to_index(index, self.properties_for(index))
|
|
||||||
|
|
||||||
|
|
||||||
def add(self, prop, indices):
|
|
||||||
self._param_index_ops.add(prop, indices+self._offset)
|
|
||||||
|
|
||||||
|
|
||||||
def remove(self, prop, indices):
|
|
||||||
removed = self._param_index_ops.remove(prop, numpy.array(indices)+self._offset)
|
|
||||||
if removed.size > 0:
|
|
||||||
return removed-self._offset
|
|
||||||
return removed
|
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self, prop):
|
|
||||||
ind = self._filter_index(self._param_index_ops[prop])
|
|
||||||
return ind
|
|
||||||
|
|
||||||
def __delitem__(self, prop):
|
|
||||||
self.remove(prop, self[prop])
|
|
||||||
|
|
||||||
def __str__(self, *args, **kwargs):
|
|
||||||
import pprint
|
|
||||||
#py3 fixes
|
|
||||||
#return pprint.pformat(dict(self.iteritems()))
|
|
||||||
return pprint.pformat(dict(self.items()))
|
|
||||||
|
|
||||||
def update(self, parameter_index_view, offset=0):
|
|
||||||
#py3 fixes
|
|
||||||
#for i, v in parameter_index_view.iteritems():
|
|
||||||
for i, v in parameter_index_view.items():
|
|
||||||
self.add(i, v+offset)
|
|
||||||
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
return self.__deepcopy__(None)
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
|
||||||
#py3 fix
|
|
||||||
#return ParameterIndexOperations(dict(self.iteritems()))
|
|
||||||
return ParameterIndexOperations(dict(self.items()))
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
# Copyright (c) 2014, Max Zwiessele
|
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
|
||||||
|
|
||||||
from collections import defaultdict
|
|
||||||
import weakref
|
|
||||||
|
|
||||||
def intarray_default_factory():
|
|
||||||
import numpy as np
|
|
||||||
return np.int_([])
|
|
||||||
|
|
||||||
class IntArrayDict(defaultdict):
|
|
||||||
def __init__(self, default_factory=None):
|
|
||||||
"""
|
|
||||||
Default will be self._default, if not set otherwise
|
|
||||||
"""
|
|
||||||
defaultdict.__init__(self, intarray_default_factory)
|
|
||||||
|
|
||||||
class ArrayList(list):
|
|
||||||
"""
|
|
||||||
List to store ndarray-likes in.
|
|
||||||
It will look for 'is' instead of calling __eq__ on each element.
|
|
||||||
"""
|
|
||||||
def __contains__(self, other):
|
|
||||||
for el in self:
|
|
||||||
if el is other:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def index(self, item):
|
|
||||||
index = 0
|
|
||||||
for el in self:
|
|
||||||
if el is item:
|
|
||||||
return index
|
|
||||||
index += 1
|
|
||||||
raise ValueError("{} is not in list".format(item))
|
|
||||||
pass
|
|
||||||
|
|
||||||
class ObserverList(object):
|
|
||||||
"""
|
|
||||||
A list which containts the observables.
|
|
||||||
It only holds weak references to observers, such that unbound
|
|
||||||
observers dont dangle in memory.
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
self._poc = []
|
|
||||||
|
|
||||||
def __getitem__(self, ind):
|
|
||||||
p,o,c = self._poc[ind]
|
|
||||||
return p, o(), c
|
|
||||||
|
|
||||||
def remove(self, priority, observer, callble):
|
|
||||||
"""
|
|
||||||
Remove one observer, which had priority and callble.
|
|
||||||
"""
|
|
||||||
self.flush()
|
|
||||||
for i in range(len(self) - 1, -1, -1):
|
|
||||||
p,o,c = self[i]
|
|
||||||
if priority==p and observer==o and callble==c:
|
|
||||||
del self._poc[i]
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self._poc.__repr__()
|
|
||||||
|
|
||||||
def add(self, priority, observer, callble):
|
|
||||||
"""
|
|
||||||
Add an observer with priority and callble
|
|
||||||
"""
|
|
||||||
if observer is not None:
|
|
||||||
ins = 0
|
|
||||||
for pr, _, _ in self:
|
|
||||||
if priority > pr:
|
|
||||||
break
|
|
||||||
ins += 1
|
|
||||||
self._poc.insert(ins, (priority, weakref.ref(observer), callble))
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
from . import ObsAr, Param
|
|
||||||
from .parameter_core import Parameterizable
|
|
||||||
ret = []
|
|
||||||
curr_p = None
|
|
||||||
|
|
||||||
def frmt(o):
|
|
||||||
if isinstance(o, ObsAr):
|
|
||||||
return 'ObsArr <{}>'.format(hex(id(o)))
|
|
||||||
elif isinstance(o, (Param,Parameterizable)):
|
|
||||||
return '{}'.format(o.hierarchy_name())
|
|
||||||
else:
|
|
||||||
return repr(o)
|
|
||||||
for p, o, c in self:
|
|
||||||
curr = ''
|
|
||||||
if curr_p != p:
|
|
||||||
pre = "{!s}: ".format(p)
|
|
||||||
curr_pre = pre
|
|
||||||
else: curr_pre = " "*len(pre)
|
|
||||||
curr_p = p
|
|
||||||
curr += curr_pre
|
|
||||||
|
|
||||||
ret.append(curr + ", ".join([frmt(o), str(c)]))
|
|
||||||
return '\n'.join(ret)
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
"""
|
|
||||||
Make sure all weak references, which point to nothing are flushed (deleted)
|
|
||||||
"""
|
|
||||||
self._poc = [(p,o,c) for p,o,c in self._poc if o() is not None]
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
self.flush()
|
|
||||||
for p, o, c in self._poc:
|
|
||||||
yield p, o(), c
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
self.flush()
|
|
||||||
return self._poc.__len__()
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
|
||||||
s = ObserverList()
|
|
||||||
for p,o,c in self:
|
|
||||||
import copy
|
|
||||||
s.add(p, copy.deepcopy(o, memo), copy.deepcopy(c, memo))
|
|
||||||
s.flush()
|
|
||||||
return s
|
|
||||||
|
|
||||||
def __getstate__(self):
|
|
||||||
self.flush()
|
|
||||||
from ...util.caching import Cacher
|
|
||||||
obs = []
|
|
||||||
for p, o, c in self:
|
|
||||||
if (getattr(o, c.__name__, None) is not None
|
|
||||||
and not isinstance(o, Cacher)):
|
|
||||||
obs.append((p,o,c.__name__))
|
|
||||||
return obs
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
|
||||||
self._poc = []
|
|
||||||
for p, o, c in state:
|
|
||||||
self.add(p,o,getattr(o, c))
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
# Copyright (c) 2014, Max Zwiessele
|
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
|
||||||
|
|
||||||
|
|
||||||
class Observable(object):
|
|
||||||
"""
|
|
||||||
Observable pattern for parameterization.
|
|
||||||
|
|
||||||
This Object allows for observers to register with self and a (bound!) function
|
|
||||||
as an observer. Every time the observable changes, it sends a notification with
|
|
||||||
self as only argument to all its observers.
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(Observable, self).__init__()
|
|
||||||
from .lists_and_dicts import ObserverList
|
|
||||||
self.observers = ObserverList()
|
|
||||||
self._update_on = True
|
|
||||||
|
|
||||||
def set_updates(self, on=True):
|
|
||||||
self._update_on = on
|
|
||||||
|
|
||||||
def add_observer(self, observer, callble, priority=0):
|
|
||||||
"""
|
|
||||||
Add an observer `observer` with the callback `callble`
|
|
||||||
and priority `priority` to this observers list.
|
|
||||||
"""
|
|
||||||
self.observers.add(priority, observer, callble)
|
|
||||||
|
|
||||||
def remove_observer(self, observer, callble=None):
|
|
||||||
"""
|
|
||||||
Either (if callble is None) remove all callables,
|
|
||||||
which were added alongside observer,
|
|
||||||
or remove callable `callble` which was added alongside
|
|
||||||
the observer `observer`.
|
|
||||||
"""
|
|
||||||
to_remove = []
|
|
||||||
for poc in self.observers:
|
|
||||||
_, obs, clble = poc
|
|
||||||
if callble is not None:
|
|
||||||
if (obs is observer) and (callble == clble):
|
|
||||||
to_remove.append(poc)
|
|
||||||
else:
|
|
||||||
if obs is observer:
|
|
||||||
to_remove.append(poc)
|
|
||||||
for r in to_remove:
|
|
||||||
self.observers.remove(*r)
|
|
||||||
|
|
||||||
def notify_observers(self, which=None, min_priority=None):
|
|
||||||
"""
|
|
||||||
Notifies all observers. Which is the element, which kicked off this
|
|
||||||
notification loop. The first argument will be self, the second `which`.
|
|
||||||
|
|
||||||
NOTE: notifies only observers with priority p > min_priority!
|
|
||||||
^^^^^^^^^^^^^^^^
|
|
||||||
:param min_priority: only notify observers with priority > min_priority
|
|
||||||
if min_priority is None, notify all observers in order
|
|
||||||
"""
|
|
||||||
if self._update_on:
|
|
||||||
if which is None:
|
|
||||||
which = self
|
|
||||||
if min_priority is None:
|
|
||||||
[callble(self, which=which) for _, _, callble in self.observers]
|
|
||||||
else:
|
|
||||||
for p, _, callble in self.observers:
|
|
||||||
if p <= min_priority:
|
|
||||||
break
|
|
||||||
callble(self, which=which)
|
|
||||||
|
|
||||||
def change_priority(self, observer, callble, priority):
|
|
||||||
self.remove_observer(observer, callble)
|
|
||||||
self.add_observer(observer, callble, priority)
|
|
||||||
|
|
@ -1,147 +0,0 @@
|
||||||
# Copyright (c) 2014, Max Zwiessele
|
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
|
||||||
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from .parameter_core import Pickleable
|
|
||||||
from .observable import Observable
|
|
||||||
|
|
||||||
class ObsAr(np.ndarray, Pickleable, Observable):
|
|
||||||
"""
|
|
||||||
An ndarray which reports changes to its observers.
|
|
||||||
The observers can add themselves with a callable, which
|
|
||||||
will be called every time this array changes. The callable
|
|
||||||
takes exactly one argument, which is this array itself.
|
|
||||||
"""
|
|
||||||
__array_priority__ = -1 # Never give back ObsAr
|
|
||||||
def __new__(cls, input_array, *a, **kw):
|
|
||||||
# allways make a copy of input paramters, as we need it to be in C order:
|
|
||||||
if not isinstance(input_array, ObsAr):
|
|
||||||
obj = np.atleast_1d(np.require(input_array, dtype=np.float64, requirements=['W', 'C'])).view(cls)
|
|
||||||
else: obj = input_array
|
|
||||||
super(ObsAr, obj).__init__(*a, **kw)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def __array_finalize__(self, obj):
|
|
||||||
# see InfoArray.__array_finalize__ for comments
|
|
||||||
if obj is None: return
|
|
||||||
self.observers = getattr(obj, 'observers', None)
|
|
||||||
|
|
||||||
def __array_wrap__(self, out_arr, context=None):
|
|
||||||
return out_arr.view(np.ndarray)
|
|
||||||
|
|
||||||
def _setup_observers(self):
|
|
||||||
# do not setup anything, as observable arrays do not have default observers
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
|
||||||
def values(self):
|
|
||||||
return self.view(np.ndarray)
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
from .lists_and_dicts import ObserverList
|
|
||||||
memo = {}
|
|
||||||
memo[id(self)] = self
|
|
||||||
memo[id(self.observers)] = ObserverList()
|
|
||||||
return self.__deepcopy__(memo)
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
|
||||||
s = self.__new__(self.__class__, input_array=self.view(np.ndarray).copy())
|
|
||||||
memo[id(self)] = s
|
|
||||||
import copy
|
|
||||||
Pickleable.__setstate__(s, copy.deepcopy(self.__getstate__(), memo))
|
|
||||||
return s
|
|
||||||
|
|
||||||
def __reduce__(self):
|
|
||||||
func, args, state = super(ObsAr, self).__reduce__()
|
|
||||||
return func, args, (state, Pickleable.__getstate__(self))
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
|
||||||
np.ndarray.__setstate__(self, state[0])
|
|
||||||
Pickleable.__setstate__(self, state[1])
|
|
||||||
|
|
||||||
def __setitem__(self, s, val):
|
|
||||||
super(ObsAr, self).__setitem__(s, val)
|
|
||||||
self.notify_observers()
|
|
||||||
|
|
||||||
def __getslice__(self, start, stop):
|
|
||||||
return self.__getitem__(slice(start, stop))
|
|
||||||
|
|
||||||
def __setslice__(self, start, stop, val):
|
|
||||||
return self.__setitem__(slice(start, stop), val)
|
|
||||||
|
|
||||||
def __ilshift__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__ilshift__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
def __irshift__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__irshift__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __ixor__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__ixor__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __ipow__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__ipow__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __ifloordiv__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__ifloordiv__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __isub__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__isub__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __ior__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__ior__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __itruediv__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__itruediv__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __idiv__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__idiv__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __iand__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__iand__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __imod__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__imod__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __iadd__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__iadd__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def __imul__(self, *args, **kwargs):
|
|
||||||
r = np.ndarray.__imul__(self, *args, **kwargs)
|
|
||||||
self.notify_observers()
|
|
||||||
return r
|
|
||||||
|
|
@ -1,496 +1,10 @@
|
||||||
# Copyright (c) 2014, Max Zwiessele
|
# Copyright (c) 2014, Max Zwiessele
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
import itertools
|
from paramz import Param
|
||||||
import numpy
|
from .priorizable import Priorizable
|
||||||
np = numpy
|
from paramz.transformations import __fixed__
|
||||||
from .parameter_core import Parameterizable, adjust_name_for_printing, Pickleable
|
import logging, numpy as np
|
||||||
from .observable_array import ObsAr
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
###### printing
|
class Param(Param, Priorizable):
|
||||||
__constraints_name__ = "Constraint"
|
pass
|
||||||
__index_name__ = "Index"
|
|
||||||
__tie_name__ = "Tied to"
|
|
||||||
__priors_name__ = "Prior"
|
|
||||||
__precision__ = numpy.get_printoptions()['precision'] # numpy printing precision used, sublassing numpy ndarray after all
|
|
||||||
__print_threshold__ = 5
|
|
||||||
######
|
|
||||||
|
|
||||||
class Param(Parameterizable, ObsAr):
|
|
||||||
"""
|
|
||||||
Parameter object for GPy models.
|
|
||||||
|
|
||||||
:param str name: name of the parameter to be printed
|
|
||||||
:param input_array: array which this parameter handles
|
|
||||||
:type input_array: numpy.ndarray
|
|
||||||
:param default_constraint: The default constraint for this parameter
|
|
||||||
:type default_constraint:
|
|
||||||
|
|
||||||
You can add/remove constraints by calling constrain on the parameter itself, e.g:
|
|
||||||
|
|
||||||
- self[:,1].constrain_positive()
|
|
||||||
- self[0].tie_to(other)
|
|
||||||
- self.untie()
|
|
||||||
- self[:3,:].unconstrain()
|
|
||||||
- self[1].fix()
|
|
||||||
|
|
||||||
Fixing parameters will fix them to the value they are right now. If you change
|
|
||||||
the fixed value, it will be fixed to the new value!
|
|
||||||
|
|
||||||
Important Note:
|
|
||||||
Multilevel indexing (e.g. self[:2][1:]) is not supported and might lead to unexpected behaviour.
|
|
||||||
Try to index in one go, using boolean indexing or the numpy builtin
|
|
||||||
np.index function.
|
|
||||||
|
|
||||||
See :py:class:`GPy.core.parameterized.Parameterized` for more details on constraining etc.
|
|
||||||
|
|
||||||
"""
|
|
||||||
__array_priority__ = -1 # Never give back Param
|
|
||||||
_fixes_ = None
|
|
||||||
parameters = []
|
|
||||||
def __new__(cls, name, input_array, default_constraint=None):
|
|
||||||
obj = numpy.atleast_1d(super(Param, cls).__new__(cls, input_array=input_array))
|
|
||||||
obj._current_slice_ = (slice(obj.shape[0]),)
|
|
||||||
obj._realshape_ = obj.shape
|
|
||||||
obj._realsize_ = obj.size
|
|
||||||
obj._realndim_ = obj.ndim
|
|
||||||
obj._original_ = obj
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def __init__(self, name, input_array, default_constraint=None, *a, **kw):
|
|
||||||
self._in_init_ = True
|
|
||||||
super(Param, self).__init__(name=name, default_constraint=default_constraint, *a, **kw)
|
|
||||||
self._in_init_ = False
|
|
||||||
|
|
||||||
def build_pydot(self,G):
|
|
||||||
import pydot
|
|
||||||
node = pydot.Node(id(self), shape='trapezium', label=self.name)#, fontcolor='white', color='white')
|
|
||||||
G.add_node(node)
|
|
||||||
for _, o, _ in self.observers:
|
|
||||||
label = o.name if hasattr(o, 'name') else str(o)
|
|
||||||
observed_node = pydot.Node(id(o), label=label)
|
|
||||||
G.add_node(observed_node)
|
|
||||||
edge = pydot.Edge(str(id(self)), str(id(o)), color='darkorange2', arrowhead='vee')
|
|
||||||
G.add_edge(edge)
|
|
||||||
|
|
||||||
return node
|
|
||||||
|
|
||||||
def __array_finalize__(self, obj):
|
|
||||||
# see InfoArray.__array_finalize__ for comments
|
|
||||||
if obj is None: return
|
|
||||||
super(Param, self).__array_finalize__(obj)
|
|
||||||
self._parent_ = getattr(obj, '_parent_', None)
|
|
||||||
self._parent_index_ = getattr(obj, '_parent_index_', None)
|
|
||||||
self._default_constraint_ = getattr(obj, '_default_constraint_', None)
|
|
||||||
self._current_slice_ = getattr(obj, '_current_slice_', None)
|
|
||||||
self._realshape_ = getattr(obj, '_realshape_', None)
|
|
||||||
self._realsize_ = getattr(obj, '_realsize_', None)
|
|
||||||
self._realndim_ = getattr(obj, '_realndim_', None)
|
|
||||||
self._original_ = getattr(obj, '_original_', None)
|
|
||||||
self._name = getattr(obj, '_name', None)
|
|
||||||
self._gradient_array_ = getattr(obj, '_gradient_array_', None)
|
|
||||||
self._update_on = getattr(obj, '_update_on', None)
|
|
||||||
self.constraints = getattr(obj, 'constraints', None)
|
|
||||||
self.priors = getattr(obj, 'priors', None)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def param_array(self):
|
|
||||||
"""
|
|
||||||
As we are a leaf, this just returns self
|
|
||||||
"""
|
|
||||||
return self
|
|
||||||
|
|
||||||
@property
|
|
||||||
def values(self):
|
|
||||||
"""
|
|
||||||
Return self as numpy array view
|
|
||||||
"""
|
|
||||||
return self.view(np.ndarray)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def gradient(self):
|
|
||||||
"""
|
|
||||||
Return a view on the gradient, which is in the same shape as this parameter is.
|
|
||||||
Note: this is not the real gradient array, it is just a view on it.
|
|
||||||
|
|
||||||
To work on the real gradient array use: self.full_gradient
|
|
||||||
"""
|
|
||||||
if getattr(self, '_gradient_array_', None) is None:
|
|
||||||
self._gradient_array_ = numpy.empty(self._realshape_, dtype=numpy.float64)
|
|
||||||
return self._gradient_array_#[self._current_slice_]
|
|
||||||
|
|
||||||
@gradient.setter
|
|
||||||
def gradient(self, val):
|
|
||||||
self._gradient_array_[:] = val
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Array operations -> done
|
|
||||||
#===========================================================================
|
|
||||||
def __getitem__(self, s, *args, **kwargs):
|
|
||||||
if not isinstance(s, tuple):
|
|
||||||
s = (s,)
|
|
||||||
#if not reduce(lambda a, b: a or numpy.any(b is Ellipsis), s, False) and len(s) <= self.ndim:
|
|
||||||
# s += (Ellipsis,)
|
|
||||||
new_arr = super(Param, self).__getitem__(s, *args, **kwargs)
|
|
||||||
try:
|
|
||||||
new_arr._current_slice_ = s
|
|
||||||
new_arr._gradient_array_ = self.gradient[s]
|
|
||||||
new_arr._original_ = self._original_
|
|
||||||
except AttributeError: pass # returning 0d array or float, double etc
|
|
||||||
return new_arr
|
|
||||||
|
|
||||||
def _raveled_index(self, slice_index=None):
|
|
||||||
# return an index array on the raveled array, which is formed by the current_slice
|
|
||||||
# of this object
|
|
||||||
extended_realshape = numpy.cumprod((1,) + self._realshape_[:0:-1])[::-1]
|
|
||||||
ind = self._indices(slice_index)
|
|
||||||
if ind.ndim < 2: ind = ind[:, None]
|
|
||||||
return numpy.asarray(numpy.apply_along_axis(lambda x: numpy.sum(extended_realshape * x), 1, ind), dtype=int)
|
|
||||||
|
|
||||||
def _raveled_index_for(self, obj):
|
|
||||||
return self._raveled_index()
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Constrainable
|
|
||||||
#===========================================================================
|
|
||||||
def _ensure_fixes(self):
|
|
||||||
if not self._has_fixes(): self._fixes_ = numpy.ones(self._realsize_, dtype=bool)
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Convenience
|
|
||||||
#===========================================================================
|
|
||||||
@property
|
|
||||||
def is_fixed(self):
|
|
||||||
from .transformations import __fixed__
|
|
||||||
return self.constraints[__fixed__].size == self.size
|
|
||||||
|
|
||||||
def _get_original(self, param):
|
|
||||||
return self._original_
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Pickling and copying
|
|
||||||
#===========================================================================
|
|
||||||
def copy(self):
|
|
||||||
return Parameterizable.copy(self, which=self)
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
|
||||||
s = self.__new__(self.__class__, name=self.name, input_array=self.view(numpy.ndarray).copy())
|
|
||||||
memo[id(self)] = s
|
|
||||||
import copy
|
|
||||||
Pickleable.__setstate__(s, copy.deepcopy(self.__getstate__(), memo))
|
|
||||||
return s
|
|
||||||
|
|
||||||
def _setup_observers(self):
|
|
||||||
"""
|
|
||||||
Setup the default observers
|
|
||||||
|
|
||||||
1: pass through to parent, if present
|
|
||||||
"""
|
|
||||||
if self.has_parent():
|
|
||||||
self.add_observer(self._parent_, self._parent_._pass_through_notify_observers, -np.inf)
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Printing -> done
|
|
||||||
#===========================================================================
|
|
||||||
@property
|
|
||||||
def _description_str(self):
|
|
||||||
if self.size <= 1:
|
|
||||||
return [str(self.view(numpy.ndarray)[0])]
|
|
||||||
else: return [str(self.shape)]
|
|
||||||
def parameter_names(self, add_self=False, adjust_for_printing=False, recursive=True):
|
|
||||||
# this is just overwrighting the parameterized calls to parameter names, in order to maintain OOP
|
|
||||||
if adjust_for_printing:
|
|
||||||
return [adjust_name_for_printing(self.name)]
|
|
||||||
return [self.name]
|
|
||||||
@property
|
|
||||||
def flattened_parameters(self):
|
|
||||||
return [self]
|
|
||||||
@property
|
|
||||||
def parameter_shapes(self):
|
|
||||||
return [self.shape]
|
|
||||||
@property
|
|
||||||
def num_params(self):
|
|
||||||
return 0
|
|
||||||
@property
|
|
||||||
def _constraints_str(self):
|
|
||||||
#py3 fix
|
|
||||||
#return [' '.join(map(lambda c: str(c[0]) if c[1].size == self._realsize_ else "{" + str(c[0]) + "}", self.constraints.iteritems()))]
|
|
||||||
return [' '.join(map(lambda c: str(c[0]) if c[1].size == self._realsize_ else "{" + str(c[0]) + "}", self.constraints.items()))]
|
|
||||||
@property
|
|
||||||
def _priors_str(self):
|
|
||||||
#py3 fix
|
|
||||||
#return [' '.join(map(lambda c: str(c[0]) if c[1].size == self._realsize_ else "{" + str(c[0]) + "}", self.priors.iteritems()))]
|
|
||||||
return [' '.join(map(lambda c: str(c[0]) if c[1].size == self._realsize_ else "{" + str(c[0]) + "}", self.priors.items()))]
|
|
||||||
@property
|
|
||||||
def _ties_str(self):
|
|
||||||
return ['']
|
|
||||||
def _ties_for(self, ravi):
|
|
||||||
return [['N/A']]*ravi.size
|
|
||||||
def __repr__(self, *args, **kwargs):
|
|
||||||
name = "\033[1m{x:s}\033[0;0m:\n".format(
|
|
||||||
x=self.hierarchy_name())
|
|
||||||
return name + super(Param, self).__repr__(*args, **kwargs)
|
|
||||||
def _indices(self, slice_index=None):
|
|
||||||
# get a int-array containing all indices in the first axis.
|
|
||||||
if slice_index is None:
|
|
||||||
slice_index = self._current_slice_
|
|
||||||
try:
|
|
||||||
indices = np.indices(self._realshape_, dtype=int)
|
|
||||||
indices = indices[(slice(None),)+slice_index]
|
|
||||||
indices = np.rollaxis(indices, 0, indices.ndim).reshape(-1,self._realndim_)
|
|
||||||
#print indices_
|
|
||||||
#if not np.all(indices==indices__):
|
|
||||||
# import ipdb; ipdb.set_trace()
|
|
||||||
except:
|
|
||||||
indices = np.indices(self._realshape_, dtype=int)
|
|
||||||
indices = indices[(slice(None),)+slice_index]
|
|
||||||
indices = np.rollaxis(indices, 0, indices.ndim)
|
|
||||||
return indices
|
|
||||||
def _max_len_names(self, gen, header):
|
|
||||||
gen = map(lambda x: " ".join(map(str, x)), gen)
|
|
||||||
return reduce(lambda a, b:max(a, len(b)), gen, len(header))
|
|
||||||
def _max_len_values(self):
|
|
||||||
return reduce(lambda a, b:max(a, len("{x:=.{0}g}".format(__precision__, x=b))), self.flat, len(self.hierarchy_name()))
|
|
||||||
def _max_len_index(self, ind):
|
|
||||||
return reduce(lambda a, b:max(a, len(str(b))), ind, len(__index_name__))
|
|
||||||
def _short(self):
|
|
||||||
# short string to print
|
|
||||||
name = self.hierarchy_name()
|
|
||||||
if self._realsize_ < 2:
|
|
||||||
return name
|
|
||||||
ind = self._indices()
|
|
||||||
if ind.size > 4: indstr = ','.join(map(str, ind[:2])) + "..." + ','.join(map(str, ind[-2:]))
|
|
||||||
else: indstr = ','.join(map(str, ind))
|
|
||||||
return name + '[' + indstr + ']'
|
|
||||||
|
|
||||||
def _repr_html_(self, constr_matrix=None, indices=None, prirs=None, ties=None):
|
|
||||||
"""Representation of the parameter in html for notebook display."""
|
|
||||||
filter_ = self._current_slice_
|
|
||||||
vals = self.flat
|
|
||||||
if indices is None: indices = self._indices(filter_)
|
|
||||||
ravi = self._raveled_index(filter_)
|
|
||||||
if constr_matrix is None: constr_matrix = self.constraints.properties_for(ravi)
|
|
||||||
if prirs is None: prirs = self.priors.properties_for(ravi)
|
|
||||||
if ties is None: ties = self._ties_for(ravi)
|
|
||||||
ties = [' '.join(map(lambda x: x, t)) for t in ties]
|
|
||||||
header_format = """
|
|
||||||
<tr>
|
|
||||||
<th><b>{i}</b></th>
|
|
||||||
<th><b>{x}</b></th>
|
|
||||||
<th><b>{c}</b></th>
|
|
||||||
<th><b>{p}</b></th>
|
|
||||||
<th><b>{t}</b></th>
|
|
||||||
</tr>"""
|
|
||||||
header = header_format.format(x=self.hierarchy_name(), c=__constraints_name__, i=__index_name__, t=__tie_name__, p=__priors_name__) # nice header for printing
|
|
||||||
if not ties: ties = itertools.cycle([''])
|
|
||||||
return "\n".join(["""<style type="text/css">
|
|
||||||
.tg {padding:2px 3px;word-break:normal;border-collapse:collapse;border-spacing:0;border-color:#DCDCDC;margin:0px auto;width:100%;}
|
|
||||||
.tg td{font-family:"Courier New", Courier, monospace !important;font-weight:bold;color:#444;background-color:#F7FDFA;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#DCDCDC;}
|
|
||||||
.tg th{font-family:"Courier New", Courier, monospace !important;font-weight:normal;color:#fff;background-color:#26ADE4;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#DCDCDC;}
|
|
||||||
.tg .tg-left{font-family:"Courier New", Courier, monospace !important;font-weight:normal;text-align:left;}
|
|
||||||
.tg .tg-right{font-family:"Courier New", Courier, monospace !important;font-weight:normal;text-align:right;}
|
|
||||||
</style>"""] + ['<table class="tg">'] + [header] + ["<tr><td class=tg-left>{i}</td><td class=tg-right>{x}</td><td class=tg-left>{c}</td><td class=tg-left>{p}</td><td class=tg-left>{t}</td></tr>".format(x=x, c=" ".join(map(str, c)), p=" ".join(map(str, p)), t=(t or ''), i=i) for i, x, c, t, p in zip(indices, vals, constr_matrix, ties, prirs)] + ["</table>"])
|
|
||||||
|
|
||||||
def __str__(self, constr_matrix=None, indices=None, prirs=None, ties=None, lc=None, lx=None, li=None, lp=None, lt=None, only_name=False):
|
|
||||||
filter_ = self._current_slice_
|
|
||||||
vals = self.flat
|
|
||||||
if indices is None: indices = self._indices(filter_)
|
|
||||||
ravi = self._raveled_index(filter_)
|
|
||||||
if constr_matrix is None: constr_matrix = self.constraints.properties_for(ravi)
|
|
||||||
if prirs is None: prirs = self.priors.properties_for(ravi)
|
|
||||||
if ties is None: ties = self._ties_for(ravi)
|
|
||||||
ties = [' '.join(map(lambda x: x, t)) for t in ties]
|
|
||||||
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__)
|
|
||||||
if lp is None: lp = self._max_len_names(prirs, __tie_name__)
|
|
||||||
sep = '-'
|
|
||||||
header_format = " {i:{5}^{2}s} | \033[1m{x:{5}^{1}s}\033[0;0m | {c:{5}^{0}s} | {p:{5}^{4}s} | {t:{5}^{3}s}"
|
|
||||||
if only_name: header = header_format.format(lc, lx, li, lt, lp, ' ', x=self.hierarchy_name(), c=sep*lc, i=sep*li, t=sep*lt, p=sep*lp) # nice header for printing
|
|
||||||
else: header = header_format.format(lc, lx, li, lt, lp, ' ', x=self.hierarchy_name(), c=__constraints_name__, i=__index_name__, t=__tie_name__, p=__priors_name__) # nice header for printing
|
|
||||||
if not ties: ties = itertools.cycle([''])
|
|
||||||
return "\n".join([header] + [" {i!s:^{3}s} | {x: >{1}.{2}g} | {c:^{0}s} | {p:^{5}s} | {t:^{4}s} ".format(lc, lx, __precision__, li, lt, lp, x=x, c=" ".join(map(str, c)), p=" ".join(map(str, p)), t=(t or ''), i=i) for i, x, c, t, p in zip(indices, vals, constr_matrix, ties, prirs)]) # return all the constraints with right indices
|
|
||||||
# except: return super(Param, self).__str__()
|
|
||||||
|
|
||||||
class ParamConcatenation(object):
|
|
||||||
def __init__(self, params):
|
|
||||||
"""
|
|
||||||
Parameter concatenation for convenience 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 (Broadcasting enabled).
|
|
||||||
|
|
||||||
See :py:class:`GPy.core.parameter.Param` for more details on constraining.
|
|
||||||
"""
|
|
||||||
# self.params = params
|
|
||||||
from .lists_and_dicts import ArrayList
|
|
||||||
self.params = ArrayList([])
|
|
||||||
for p in params:
|
|
||||||
for p in p.flattened_parameters:
|
|
||||||
if p not in self.params:
|
|
||||||
self.params.append(p)
|
|
||||||
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:])]
|
|
||||||
|
|
||||||
parents = dict()
|
|
||||||
for p in self.params:
|
|
||||||
if p.has_parent():
|
|
||||||
parent = p._parent_
|
|
||||||
level = 0
|
|
||||||
while parent is not None:
|
|
||||||
if parent in parents:
|
|
||||||
parents[parent] = max(level, parents[parent])
|
|
||||||
else:
|
|
||||||
parents[parent] = level
|
|
||||||
level += 1
|
|
||||||
parent = parent._parent_
|
|
||||||
import operator
|
|
||||||
#py3 fix
|
|
||||||
#self.parents = map(lambda x: x[0], sorted(parents.iteritems(), key=operator.itemgetter(1)))
|
|
||||||
self.parents = map(lambda x: x[0], sorted(parents.items(), key=operator.itemgetter(1)))
|
|
||||||
#===========================================================================
|
|
||||||
# Get/set items, enable broadcasting
|
|
||||||
#===========================================================================
|
|
||||||
def __getitem__(self, s):
|
|
||||||
ind = numpy.zeros(sum(self._param_sizes), dtype=bool); ind[s] = True;
|
|
||||||
params = [p.param_array.flat[ind[ps]] for p,ps in zip(self.params, self._param_slices_) if numpy.any(p.param_array.flat[ind[ps]])]
|
|
||||||
if len(params)==1: return params[0]
|
|
||||||
return ParamConcatenation(params)
|
|
||||||
def __setitem__(self, s, val, update=True):
|
|
||||||
if isinstance(val, ParamConcatenation):
|
|
||||||
val = val.values()
|
|
||||||
ind = numpy.zeros(sum(self._param_sizes), dtype=bool); ind[s] = True;
|
|
||||||
vals = self.values(); vals[s] = val
|
|
||||||
for p, ps in zip(self.params, self._param_slices_):
|
|
||||||
p.flat[ind[ps]] = vals[ps]
|
|
||||||
if update:
|
|
||||||
self.update_all_params()
|
|
||||||
def values(self):
|
|
||||||
return numpy.hstack([p.param_array.flat for p in self.params])
|
|
||||||
#===========================================================================
|
|
||||||
# parameter operations:
|
|
||||||
#===========================================================================
|
|
||||||
def update_all_params(self):
|
|
||||||
for par in self.parents:
|
|
||||||
par.trigger_update(trigger_parent=False)
|
|
||||||
|
|
||||||
def constrain(self, constraint, warning=True):
|
|
||||||
[param.constrain(constraint, trigger_parent=False) for param in self.params]
|
|
||||||
self.update_all_params()
|
|
||||||
constrain.__doc__ = Param.constrain.__doc__
|
|
||||||
|
|
||||||
def constrain_positive(self, warning=True):
|
|
||||||
[param.constrain_positive(warning, trigger_parent=False) for param in self.params]
|
|
||||||
self.update_all_params()
|
|
||||||
constrain_positive.__doc__ = Param.constrain_positive.__doc__
|
|
||||||
|
|
||||||
def constrain_fixed(self, value=None, warning=True, trigger_parent=True):
|
|
||||||
[param.constrain_fixed(value, warning, trigger_parent) for param in self.params]
|
|
||||||
constrain_fixed.__doc__ = Param.constrain_fixed.__doc__
|
|
||||||
fix = constrain_fixed
|
|
||||||
|
|
||||||
def constrain_negative(self, warning=True):
|
|
||||||
[param.constrain_negative(warning, trigger_parent=False) for param in self.params]
|
|
||||||
self.update_all_params()
|
|
||||||
constrain_negative.__doc__ = Param.constrain_negative.__doc__
|
|
||||||
|
|
||||||
def constrain_bounded(self, lower, upper, warning=True):
|
|
||||||
[param.constrain_bounded(lower, upper, warning, trigger_parent=False) for param in self.params]
|
|
||||||
self.update_all_params()
|
|
||||||
constrain_bounded.__doc__ = Param.constrain_bounded.__doc__
|
|
||||||
|
|
||||||
def unconstrain(self, *constraints):
|
|
||||||
[param.unconstrain(*constraints) for param in self.params]
|
|
||||||
unconstrain.__doc__ = Param.unconstrain.__doc__
|
|
||||||
|
|
||||||
def unconstrain_negative(self):
|
|
||||||
[param.unconstrain_negative() for param in self.params]
|
|
||||||
unconstrain_negative.__doc__ = Param.unconstrain_negative.__doc__
|
|
||||||
|
|
||||||
def unconstrain_positive(self):
|
|
||||||
[param.unconstrain_positive() for param in self.params]
|
|
||||||
unconstrain_positive.__doc__ = Param.unconstrain_positive.__doc__
|
|
||||||
|
|
||||||
def unconstrain_fixed(self):
|
|
||||||
[param.unconstrain_fixed() for param in self.params]
|
|
||||||
unconstrain_fixed.__doc__ = Param.unconstrain_fixed.__doc__
|
|
||||||
unfix = unconstrain_fixed
|
|
||||||
|
|
||||||
def unconstrain_bounded(self, lower, upper):
|
|
||||||
[param.unconstrain_bounded(lower, upper) for param in self.params]
|
|
||||||
unconstrain_bounded.__doc__ = Param.unconstrain_bounded.__doc__
|
|
||||||
|
|
||||||
def untie(self, *ties):
|
|
||||||
[param.untie(*ties) for param in self.params]
|
|
||||||
|
|
||||||
def checkgrad(self, verbose=0, step=1e-6, tolerance=1e-3):
|
|
||||||
return self.params[0]._highest_parent_._checkgrad(self, verbose, step, tolerance)
|
|
||||||
#checkgrad.__doc__ = Gradcheckable.checkgrad.__doc__
|
|
||||||
|
|
||||||
__lt__ = lambda self, val: self.values() < val
|
|
||||||
__le__ = lambda self, val: self.values() <= val
|
|
||||||
__eq__ = lambda self, val: self.values() == val
|
|
||||||
__ne__ = lambda self, val: self.values() != val
|
|
||||||
__gt__ = lambda self, val: self.values() > val
|
|
||||||
__ge__ = lambda self, val: self.values() >= val
|
|
||||||
def __str__(self, *args, **kwargs):
|
|
||||||
def f(p):
|
|
||||||
ind = p._raveled_index()
|
|
||||||
return p.constraints.properties_for(ind), p._ties_for(ind), p.priors.properties_for(ind)
|
|
||||||
params = self.params
|
|
||||||
constr_matrices, ties_matrices, prior_matrices = zip(*map(f, params))
|
|
||||||
indices = [p._indices() for p in params]
|
|
||||||
lc = max([p._max_len_names(cm, __constraints_name__) for p, cm in zip(params, constr_matrices)])
|
|
||||||
lx = max([p._max_len_values() for p in params])
|
|
||||||
li = max([p._max_len_index(i) for p, i in zip(params, indices)])
|
|
||||||
lt = max([p._max_len_names(tm, __tie_name__) for p, tm in zip(params, ties_matrices)])
|
|
||||||
lp = max([p._max_len_names(pm, __constraints_name__) for p, pm in zip(params, prior_matrices)])
|
|
||||||
strings = []
|
|
||||||
start = True
|
|
||||||
for p, cm, i, tm, pm in zip(params,constr_matrices,indices,ties_matrices,prior_matrices):
|
|
||||||
strings.append(p.__str__(constr_matrix=cm, indices=i, prirs=pm, ties=tm, lc=lc, lx=lx, li=li, lp=lp, lt=lt, only_name=(1-start)))
|
|
||||||
start = False
|
|
||||||
return "\n".join(strings)
|
|
||||||
def __repr__(self):
|
|
||||||
return "\n".join(map(repr,self.params))
|
|
||||||
|
|
||||||
def __ilshift__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__ilshift__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __irshift__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__irshift__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __ixor__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__ixor__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __ipow__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__ipow__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __ifloordiv__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__ifloordiv__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __isub__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__isub__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __ior__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__ior__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __itruediv__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__itruediv__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __idiv__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__idiv__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __iand__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__iand__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __imod__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__imod__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __iadd__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__iadd__(self.values(), *args, **kwargs)
|
|
||||||
|
|
||||||
def __imul__(self, *args, **kwargs):
|
|
||||||
self[:] = np.ndarray.__imul__(self.values(), *args, **kwargs)
|
|
||||||
|
|
@ -1,34 +1,13 @@
|
||||||
# Copyright (c) 2014, Max Zwiessele, James Hensman
|
# Copyright (c) 2014, Max Zwiessele, James Hensman
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
import six # For metaclass support in Python 2 and 3 simultaneously
|
from paramz import Parameterized
|
||||||
import numpy; np = numpy
|
from .priorizable import Priorizable
|
||||||
import itertools
|
|
||||||
from re import compile, _pattern_type
|
|
||||||
from .param import ParamConcatenation
|
|
||||||
from .parameter_core import HierarchyError, Parameterizable, adjust_name_for_printing
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from .index_operations import ParameterIndexOperationsView
|
|
||||||
logger = logging.getLogger("parameters changed meta")
|
logger = logging.getLogger("parameters changed meta")
|
||||||
|
|
||||||
class ParametersChangedMeta(type):
|
class Parameterized(Parameterized, Priorizable):
|
||||||
def __call__(self, *args, **kw):
|
|
||||||
self._in_init_ = True
|
|
||||||
#import ipdb;ipdb.set_trace()
|
|
||||||
self = super(ParametersChangedMeta, self).__call__(*args, **kw)
|
|
||||||
logger.debug("finished init")
|
|
||||||
self._in_init_ = False
|
|
||||||
logger.debug("connecting parameters")
|
|
||||||
self._highest_parent_._connect_parameters()
|
|
||||||
#self._highest_parent_._notify_parent_change()
|
|
||||||
self._highest_parent_._connect_fixes()
|
|
||||||
logger.debug("calling parameters changed")
|
|
||||||
self.parameters_changed()
|
|
||||||
return self
|
|
||||||
|
|
||||||
@six.add_metaclass(ParametersChangedMeta)
|
|
||||||
class Parameterized(Parameterizable):
|
|
||||||
"""
|
"""
|
||||||
Parameterized class
|
Parameterized class
|
||||||
|
|
||||||
|
|
@ -69,365 +48,5 @@ class Parameterized(Parameterizable):
|
||||||
|
|
||||||
If you want to operate on all parameters use m[''] to wildcard select all paramters
|
If you want to operate on all parameters use m[''] to wildcard select all paramters
|
||||||
and concatenate them. Printing m[''] will result in printing of all parameters in detail.
|
and concatenate them. Printing m[''] will result in printing of all parameters in detail.
|
||||||
"""
|
"""
|
||||||
#===========================================================================
|
pass
|
||||||
# Metaclass for parameters changed after init.
|
|
||||||
# This makes sure, that parameters changed will always be called after __init__
|
|
||||||
# **Never** call parameters_changed() yourself
|
|
||||||
#This is ignored in Python 3 -- you need to put the meta class in the function definition.
|
|
||||||
#__metaclass__ = ParametersChangedMeta
|
|
||||||
#The six module is used to support both Python 2 and 3 simultaneously
|
|
||||||
#===========================================================================
|
|
||||||
def __init__(self, name=None, parameters=[], *a, **kw):
|
|
||||||
super(Parameterized, self).__init__(name=name, *a, **kw)
|
|
||||||
self.size = sum(p.size for p in self.parameters)
|
|
||||||
self.add_observer(self, self._parameters_changed_notification, -100)
|
|
||||||
if not self._has_fixes():
|
|
||||||
self._fixes_ = None
|
|
||||||
self._param_slices_ = []
|
|
||||||
#self._connect_parameters()
|
|
||||||
self.link_parameters(*parameters)
|
|
||||||
|
|
||||||
def build_pydot(self, G=None):
|
|
||||||
import pydot # @UnresolvedImport
|
|
||||||
iamroot = False
|
|
||||||
if G is None:
|
|
||||||
G = pydot.Dot(graph_type='digraph', bgcolor=None)
|
|
||||||
iamroot=True
|
|
||||||
node = pydot.Node(id(self), shape='box', label=self.name)#, color='white')
|
|
||||||
G.add_node(node)
|
|
||||||
for child in self.parameters:
|
|
||||||
child_node = child.build_pydot(G)
|
|
||||||
G.add_edge(pydot.Edge(node, child_node))#, color='white'))
|
|
||||||
|
|
||||||
for _, o, _ in self.observers:
|
|
||||||
label = o.name if hasattr(o, 'name') else str(o)
|
|
||||||
observed_node = pydot.Node(id(o), label=label)
|
|
||||||
G.add_node(observed_node)
|
|
||||||
edge = pydot.Edge(str(id(self)), str(id(o)), color='darkorange2', arrowhead='vee')
|
|
||||||
G.add_edge(edge)
|
|
||||||
|
|
||||||
if iamroot:
|
|
||||||
return G
|
|
||||||
return node
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Add remove parameters:
|
|
||||||
#===========================================================================
|
|
||||||
def link_parameter(self, param, index=None, _ignore_added_names=False):
|
|
||||||
"""
|
|
||||||
:param parameters: the parameters to add
|
|
||||||
:type parameters: list of or one :py:class:`GPy.core.param.Param`
|
|
||||||
:param [index]: index of where to put parameters
|
|
||||||
|
|
||||||
:param bool _ignore_added_names: whether the name of the parameter overrides a possibly existing field
|
|
||||||
|
|
||||||
Add all parameters to this param class, you can insert parameters
|
|
||||||
at any given index using the :func:`list.insert` syntax
|
|
||||||
"""
|
|
||||||
if param in self.parameters and index is not None:
|
|
||||||
self.unlink_parameter(param)
|
|
||||||
self.link_parameter(param, index)
|
|
||||||
# elif param.has_parent():
|
|
||||||
# raise HierarchyError, "parameter {} already in another model ({}), create new object (or copy) for adding".format(param._short(), param._highest_parent_._short())
|
|
||||||
elif param not in self.parameters:
|
|
||||||
if param.has_parent():
|
|
||||||
def visit(parent, self):
|
|
||||||
if parent is self:
|
|
||||||
raise HierarchyError("You cannot add a parameter twice into the hierarchy")
|
|
||||||
param.traverse_parents(visit, self)
|
|
||||||
param._parent_.unlink_parameter(param)
|
|
||||||
# make sure the size is set
|
|
||||||
if index is None:
|
|
||||||
start = sum(p.size for p in self.parameters)
|
|
||||||
self.constraints.shift_right(start, param.size)
|
|
||||||
self.priors.shift_right(start, param.size)
|
|
||||||
self.constraints.update(param.constraints, self.size)
|
|
||||||
self.priors.update(param.priors, self.size)
|
|
||||||
param._parent_ = self
|
|
||||||
param._parent_index_ = len(self.parameters)
|
|
||||||
self.parameters.append(param)
|
|
||||||
else:
|
|
||||||
start = sum(p.size for p in self.parameters[:index])
|
|
||||||
self.constraints.shift_right(start, param.size)
|
|
||||||
self.priors.shift_right(start, param.size)
|
|
||||||
self.constraints.update(param.constraints, start)
|
|
||||||
self.priors.update(param.priors, start)
|
|
||||||
param._parent_ = self
|
|
||||||
param._parent_index_ = index if index>=0 else len(self.parameters[:index])
|
|
||||||
for p in self.parameters[index:]:
|
|
||||||
p._parent_index_ += 1
|
|
||||||
self.parameters.insert(index, param)
|
|
||||||
|
|
||||||
param.add_observer(self, self._pass_through_notify_observers, -np.inf)
|
|
||||||
|
|
||||||
parent = self
|
|
||||||
while parent is not None:
|
|
||||||
parent.size += param.size
|
|
||||||
parent = parent._parent_
|
|
||||||
self._notify_parent_change()
|
|
||||||
|
|
||||||
if not self._in_init_:
|
|
||||||
#self._connect_parameters()
|
|
||||||
#self._notify_parent_change()
|
|
||||||
|
|
||||||
self._highest_parent_._connect_parameters(ignore_added_names=_ignore_added_names)
|
|
||||||
self._highest_parent_._notify_parent_change()
|
|
||||||
self._highest_parent_._connect_fixes()
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise HierarchyError("""Parameter exists already, try making a copy""")
|
|
||||||
|
|
||||||
|
|
||||||
def link_parameters(self, *parameters):
|
|
||||||
"""
|
|
||||||
convenience method for adding several
|
|
||||||
parameters without gradient specification
|
|
||||||
"""
|
|
||||||
[self.link_parameter(p) for p in parameters]
|
|
||||||
|
|
||||||
def unlink_parameter(self, param):
|
|
||||||
"""
|
|
||||||
:param param: param object to remove from being a parameter of this parameterized object.
|
|
||||||
"""
|
|
||||||
if not param in self.parameters:
|
|
||||||
try:
|
|
||||||
raise RuntimeError("{} does not belong to this object {}, remove parameters directly from their respective parents".format(param._short(), self.name))
|
|
||||||
except AttributeError:
|
|
||||||
raise RuntimeError("{} does not seem to be a parameter, remove parameters directly from their respective parents".format(str(param)))
|
|
||||||
|
|
||||||
start = sum([p.size for p in self.parameters[:param._parent_index_]])
|
|
||||||
self.size -= param.size
|
|
||||||
del self.parameters[param._parent_index_]
|
|
||||||
self._remove_parameter_name(param)
|
|
||||||
|
|
||||||
|
|
||||||
param._disconnect_parent()
|
|
||||||
param.remove_observer(self, self._pass_through_notify_observers)
|
|
||||||
self.constraints.shift_left(start, param.size)
|
|
||||||
|
|
||||||
self._connect_parameters()
|
|
||||||
self._notify_parent_change()
|
|
||||||
|
|
||||||
parent = self._parent_
|
|
||||||
while parent is not None:
|
|
||||||
parent.size -= param.size
|
|
||||||
parent = parent._parent_
|
|
||||||
|
|
||||||
self._highest_parent_._connect_parameters()
|
|
||||||
self._highest_parent_._connect_fixes()
|
|
||||||
self._highest_parent_._notify_parent_change()
|
|
||||||
|
|
||||||
def add_parameter(self, *args, **kwargs):
|
|
||||||
raise DeprecationWarning("add_parameter was renamed to link_parameter to avoid confusion of setting variables, use link_parameter instead")
|
|
||||||
def remove_parameter(self, *args, **kwargs):
|
|
||||||
raise DeprecationWarning("remove_parameter was renamed to unlink_parameter to avoid confusion of setting variables, use unlink_parameter instead")
|
|
||||||
|
|
||||||
def _connect_parameters(self, ignore_added_names=False):
|
|
||||||
# connect parameterlist to this parameterized object
|
|
||||||
# This just sets up the right connection for the params objects
|
|
||||||
# to be used as parameters
|
|
||||||
# it also sets the constraints for each parameter to the constraints
|
|
||||||
# of their respective parents
|
|
||||||
if not hasattr(self, "parameters") or len(self.parameters) < 1:
|
|
||||||
# no parameters for this class
|
|
||||||
return
|
|
||||||
if self.param_array.size != self.size:
|
|
||||||
self._param_array_ = np.empty(self.size, dtype=np.float64)
|
|
||||||
if self.gradient.size != self.size:
|
|
||||||
self._gradient_array_ = np.empty(self.size, dtype=np.float64)
|
|
||||||
|
|
||||||
old_size = 0
|
|
||||||
self._param_slices_ = []
|
|
||||||
for i, p in enumerate(self.parameters):
|
|
||||||
if not p.param_array.flags['C_CONTIGUOUS']:
|
|
||||||
raise ValueError("This should not happen! Please write an email to the developers with the code, which reproduces this error. All parameter arrays must be C_CONTIGUOUS")
|
|
||||||
|
|
||||||
p._parent_ = self
|
|
||||||
p._parent_index_ = i
|
|
||||||
|
|
||||||
pslice = slice(old_size, old_size + p.size)
|
|
||||||
|
|
||||||
# first connect all children
|
|
||||||
p._propagate_param_grad(self.param_array[pslice], self.gradient_full[pslice])
|
|
||||||
|
|
||||||
# then connect children to self
|
|
||||||
self.param_array[pslice] = p.param_array.flat # , requirements=['C', 'W']).ravel(order='C')
|
|
||||||
self.gradient_full[pslice] = p.gradient_full.flat # , requirements=['C', 'W']).ravel(order='C')
|
|
||||||
|
|
||||||
p.param_array.data = self.param_array[pslice].data
|
|
||||||
p.gradient_full.data = self.gradient_full[pslice].data
|
|
||||||
|
|
||||||
self._param_slices_.append(pslice)
|
|
||||||
|
|
||||||
self._add_parameter_name(p, ignore_added_names=ignore_added_names)
|
|
||||||
old_size += p.size
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Get/set parameters:
|
|
||||||
#===========================================================================
|
|
||||||
def grep_param_names(self, regexp):
|
|
||||||
"""
|
|
||||||
create a list of parameters, matching regular expression regexp
|
|
||||||
"""
|
|
||||||
if not isinstance(regexp, _pattern_type): regexp = compile(regexp)
|
|
||||||
found_params = []
|
|
||||||
for n, p in zip(self.parameter_names(False, False, True), self.flattened_parameters):
|
|
||||||
if regexp.match(n) is not None:
|
|
||||||
found_params.append(p)
|
|
||||||
return found_params
|
|
||||||
|
|
||||||
def __getitem__(self, name, paramlist=None):
|
|
||||||
if isinstance(name, (int, slice, tuple, np.ndarray)):
|
|
||||||
return self.param_array[name]
|
|
||||||
else:
|
|
||||||
if paramlist is None:
|
|
||||||
paramlist = self.grep_param_names(name)
|
|
||||||
if len(paramlist) < 1: raise AttributeError(name)
|
|
||||||
if len(paramlist) == 1:
|
|
||||||
if isinstance(paramlist[-1], Parameterized):
|
|
||||||
paramlist = paramlist[-1].flattened_parameters
|
|
||||||
if len(paramlist) != 1:
|
|
||||||
return ParamConcatenation(paramlist)
|
|
||||||
return paramlist[-1]
|
|
||||||
return ParamConcatenation(paramlist)
|
|
||||||
|
|
||||||
def __setitem__(self, name, value, paramlist=None):
|
|
||||||
if value is None:
|
|
||||||
return # nothing to do here
|
|
||||||
if isinstance(name, (slice, tuple, np.ndarray)):
|
|
||||||
try:
|
|
||||||
self.param_array[name] = value
|
|
||||||
except:
|
|
||||||
raise ValueError("Setting by slice or index only allowed with array-like")
|
|
||||||
self.trigger_update()
|
|
||||||
else:
|
|
||||||
try: param = self.__getitem__(name, paramlist)
|
|
||||||
except: raise
|
|
||||||
param[:] = value
|
|
||||||
|
|
||||||
def __setattr__(self, name, val):
|
|
||||||
# override the default behaviour, if setting a param, so broadcasting can by used
|
|
||||||
if hasattr(self, "parameters"):
|
|
||||||
try:
|
|
||||||
pnames = self.parameter_names(False, adjust_for_printing=True, recursive=False)
|
|
||||||
if name in pnames:
|
|
||||||
param = self.parameters[pnames.index(name)]
|
|
||||||
param[:] = val; return
|
|
||||||
except AttributeError as a:
|
|
||||||
raise
|
|
||||||
return object.__setattr__(self, name, val);
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Pickling
|
|
||||||
#===========================================================================
|
|
||||||
def __setstate__(self, state):
|
|
||||||
super(Parameterized, self).__setstate__(state)
|
|
||||||
try:
|
|
||||||
self._connect_parameters()
|
|
||||||
self._connect_fixes()
|
|
||||||
self._notify_parent_change()
|
|
||||||
self.parameters_changed()
|
|
||||||
except Exception as e:
|
|
||||||
print("WARNING: caught exception {!s}, trying to continue".format(e))
|
|
||||||
|
|
||||||
def copy(self, memo=None):
|
|
||||||
if memo is None:
|
|
||||||
memo = {}
|
|
||||||
memo[id(self.optimizer_array)] = None # and param_array
|
|
||||||
memo[id(self.param_array)] = None # and param_array
|
|
||||||
copy = super(Parameterized, self).copy(memo)
|
|
||||||
copy._connect_parameters()
|
|
||||||
copy._connect_fixes()
|
|
||||||
copy._notify_parent_change()
|
|
||||||
return copy
|
|
||||||
|
|
||||||
#===========================================================================
|
|
||||||
# Printing:
|
|
||||||
#===========================================================================
|
|
||||||
def _short(self):
|
|
||||||
return self.hierarchy_name()
|
|
||||||
@property
|
|
||||||
def flattened_parameters(self):
|
|
||||||
return [xi for x in self.parameters for xi in x.flattened_parameters]
|
|
||||||
@property
|
|
||||||
def _parameter_sizes_(self):
|
|
||||||
return [x.size for x in self.parameters]
|
|
||||||
@property
|
|
||||||
def parameter_shapes(self):
|
|
||||||
return [xi for x in self.parameters for xi in x.parameter_shapes]
|
|
||||||
@property
|
|
||||||
def _constraints_str(self):
|
|
||||||
return [cs for p in self.parameters for cs in p._constraints_str]
|
|
||||||
@property
|
|
||||||
def _priors_str(self):
|
|
||||||
return [cs for p in self.parameters for cs in p._priors_str]
|
|
||||||
@property
|
|
||||||
def _description_str(self):
|
|
||||||
return [xi for x in self.parameters for xi in x._description_str]
|
|
||||||
@property
|
|
||||||
def _ties_str(self):
|
|
||||||
return [','.join(x._ties_str) for x in self.flattened_parameters]
|
|
||||||
|
|
||||||
def _repr_html_(self, header=True):
|
|
||||||
"""Representation of the parameters in html for notebook display."""
|
|
||||||
name = adjust_name_for_printing(self.name) + "."
|
|
||||||
constrs = self._constraints_str;
|
|
||||||
ts = self._ties_str
|
|
||||||
prirs = self._priors_str
|
|
||||||
desc = self._description_str; names = self.parameter_names()
|
|
||||||
nl = max([len(str(x)) for x in names + [name]])
|
|
||||||
sl = max([len(str(x)) for x in desc + ["Value"]])
|
|
||||||
cl = max([len(str(x)) if x else 0 for x in constrs + ["Constraint"]])
|
|
||||||
tl = max([len(str(x)) if x else 0 for x in ts + ["Tied to"]])
|
|
||||||
pl = max([len(str(x)) if x else 0 for x in prirs + ["Prior"]])
|
|
||||||
format_spec = "<tr><td class=tg-left>{{name:<{0}s}}</td><td class=tg-right>{{desc:>{1}s}}</td><td class=tg-left>{{const:^{2}s}}</td><td class=tg-left>{{pri:^{3}s}}</td><td class=tg-left>{{t:^{4}s}}</td></tr>".format(nl, sl, cl, pl, tl)
|
|
||||||
to_print = []
|
|
||||||
for n, d, c, t, p in zip(names, desc, constrs, ts, prirs):
|
|
||||||
to_print.append(format_spec.format(name=n, desc=d, const=c, t=t, pri=p))
|
|
||||||
sep = '-' * (nl + sl + cl + + pl + tl + 8 * 2 + 3)
|
|
||||||
if header:
|
|
||||||
header = """
|
|
||||||
<tr>
|
|
||||||
<th><b>{name}</b></th>
|
|
||||||
<th><b>Value</b></th>
|
|
||||||
<th><b>Constraint</b></th>
|
|
||||||
<th><b>Prior</b></th>
|
|
||||||
<th><b>Tied to</b></th>
|
|
||||||
</tr>""".format(name=name)
|
|
||||||
to_print.insert(0, header)
|
|
||||||
style = """<style type="text/css">
|
|
||||||
.tg {font-family:"Courier New", Courier, monospace !important;padding:2px 3px;word-break:normal;border-collapse:collapse;border-spacing:0;border-color:#DCDCDC;margin:0px auto;width:100%;}
|
|
||||||
.tg td{font-family:"Courier New", Courier, monospace !important;font-weight:bold;color:#444;background-color:#F7FDFA;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#DCDCDC;}
|
|
||||||
.tg th{font-family:"Courier New", Courier, monospace !important;font-weight:normal;color:#fff;background-color:#26ADE4;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#DCDCDC;}
|
|
||||||
.tg .tg-left{font-family:"Courier New", Courier, monospace !important;font-weight:normal;text-align:left;}
|
|
||||||
.tg .tg-right{font-family:"Courier New", Courier, monospace !important;font-weight:normal;text-align:right;}
|
|
||||||
</style>"""
|
|
||||||
return style + '\n' + '<table class="tg">' + '\n'.format(sep).join(to_print) + '\n</table>'
|
|
||||||
|
|
||||||
def __str__(self, header=True, VT100=True):
|
|
||||||
name = adjust_name_for_printing(self.name) + "."
|
|
||||||
constrs = self._constraints_str;
|
|
||||||
ts = self._ties_str
|
|
||||||
prirs = self._priors_str
|
|
||||||
desc = self._description_str; names = self.parameter_names()
|
|
||||||
nl = max([len(str(x)) for x in names + [name]])
|
|
||||||
sl = max([len(str(x)) for x in desc + ["Value"]])
|
|
||||||
cl = max([len(str(x)) if x else 0 for x in constrs + ["Constraint"]])
|
|
||||||
tl = max([len(str(x)) if x else 0 for x in ts + ["Tied to"]])
|
|
||||||
pl = max([len(str(x)) if x else 0 for x in prirs + ["Prior"]])
|
|
||||||
if VT100:
|
|
||||||
format_spec = " \033[1m{{name:<{0}s}}\033[0;0m | {{desc:>{1}s}} | {{const:^{2}s}} | {{pri:^{3}s}} | {{t:^{4}s}}".format(nl, sl, cl, pl, tl)
|
|
||||||
else:
|
|
||||||
format_spec = " {{name:<{0}s}} | {{desc:>{1}s}} | {{const:^{2}s}} | {{pri:^{3}s}} | {{t:^{4}s}}".format(nl, sl, cl, pl, tl)
|
|
||||||
to_print = []
|
|
||||||
for n, d, c, t, p in zip(names, desc, constrs, ts, prirs):
|
|
||||||
to_print.append(format_spec.format(name=n, desc=d, const=c, t=t, pri=p))
|
|
||||||
sep = '-' * (nl + sl + cl + + pl + tl + 8 * 2 + 3)
|
|
||||||
if header:
|
|
||||||
header = " {{0:<{0}s}} | {{1:^{1}s}} | {{2:^{2}s}} | {{3:^{3}s}} | {{4:^{4}s}}".format(nl, sl, cl, pl, tl).format(name, "Value", "Constraint", "Prior", "Tied to")
|
|
||||||
to_print.insert(0, header)
|
|
||||||
return '\n'.format(sep).join(to_print)
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
82
GPy/core/parameterization/priorizable.py
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
|
||||||
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
import numpy as np
|
||||||
|
from paramz.transformations import Transformation, __fixed__
|
||||||
|
from paramz.core.parameter_core import Parameterizable
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
class Priorizable(Parameterizable):
|
||||||
|
def __init__(self, name, default_prior=None, *a, **kw):
|
||||||
|
super(Priorizable, self).__init__(name=name, *a, **kw)
|
||||||
|
self._default_prior_ = default_prior
|
||||||
|
from paramz.core.index_operations import ParameterIndexOperations
|
||||||
|
self.add_index_operation('priors', ParameterIndexOperations())
|
||||||
|
if self._default_prior_ is not None:
|
||||||
|
self.set_prior(self._default_prior_)
|
||||||
|
|
||||||
|
def __setstate__(self, state):
|
||||||
|
super(Priorizable, self).__setstate__(state)
|
||||||
|
self._index_operations['priors'] = self.priors
|
||||||
|
|
||||||
|
|
||||||
|
#===========================================================================
|
||||||
|
# Prior Operations
|
||||||
|
#===========================================================================
|
||||||
|
def set_prior(self, prior, warning=True):
|
||||||
|
"""
|
||||||
|
Set the prior for this object to prior.
|
||||||
|
:param :class:`~GPy.priors.Prior` prior: a prior to set for this parameter
|
||||||
|
:param bool warning: whether to warn if another prior was set for this parameter
|
||||||
|
"""
|
||||||
|
repriorized = self.unset_priors()
|
||||||
|
self._add_to_index_operations(self.priors, repriorized, prior, warning)
|
||||||
|
|
||||||
|
from paramz.domains import _REAL, _POSITIVE, _NEGATIVE
|
||||||
|
if prior.domain is _POSITIVE:
|
||||||
|
self.constrain_positive(warning)
|
||||||
|
elif prior.domain is _NEGATIVE:
|
||||||
|
self.constrain_negative(warning)
|
||||||
|
elif prior.domain is _REAL:
|
||||||
|
rav_i = self._raveled_index()
|
||||||
|
assert all(all(False if c is __fixed__ else c.domain is _REAL for c in con) for con in self.constraints.properties_for(rav_i)), 'Domain of prior and constraint have to match, please unconstrain if you REALLY wish to use this prior'
|
||||||
|
|
||||||
|
def unset_priors(self, *priors):
|
||||||
|
"""
|
||||||
|
Un-set all priors given (in *priors) from this parameter handle.
|
||||||
|
"""
|
||||||
|
return self._remove_from_index_operations(self.priors, priors)
|
||||||
|
|
||||||
|
def log_prior(self):
|
||||||
|
"""evaluate the prior"""
|
||||||
|
if self.priors.size == 0:
|
||||||
|
return 0.
|
||||||
|
x = self.param_array
|
||||||
|
#evaluate the prior log densities
|
||||||
|
log_p = reduce(lambda a, b: a + b, (p.lnpdf(x[ind]).sum() for p, ind in self.priors.items()), 0)
|
||||||
|
|
||||||
|
#account for the transformation by evaluating the log Jacobian (where things are transformed)
|
||||||
|
log_j = 0.
|
||||||
|
priored_indexes = np.hstack([i for p, i in self.priors.items()])
|
||||||
|
for c,j in self.constraints.items():
|
||||||
|
if not isinstance(c, Transformation):continue
|
||||||
|
for jj in j:
|
||||||
|
if jj in priored_indexes:
|
||||||
|
log_j += c.log_jacobian(x[jj])
|
||||||
|
return log_p + log_j
|
||||||
|
|
||||||
|
def _log_prior_gradients(self):
|
||||||
|
"""evaluate the gradients of the priors"""
|
||||||
|
if self.priors.size == 0:
|
||||||
|
return 0.
|
||||||
|
x = self.param_array
|
||||||
|
ret = np.zeros(x.size)
|
||||||
|
#compute derivate of prior density
|
||||||
|
[np.put(ret, ind, p.lnpdf_grad(x[ind])) for p, ind in self.priors.items()]
|
||||||
|
#add in jacobian derivatives if transformed
|
||||||
|
priored_indexes = np.hstack([i for p, i in self.priors.items()])
|
||||||
|
for c,j in self.constraints.items():
|
||||||
|
if not isinstance(c, Transformation):continue
|
||||||
|
for jj in j:
|
||||||
|
if jj in priored_indexes:
|
||||||
|
ret[jj] += c.log_jacobian_grad(x[jj])
|
||||||
|
return ret
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy.special import gammaln, digamma
|
from scipy.special import gammaln, digamma
|
||||||
from ...util.linalg import pdinv
|
from ...util.linalg import pdinv
|
||||||
from .domains import _REAL, _POSITIVE
|
from paramz.domains import _REAL, _POSITIVE
|
||||||
import warnings
|
import warnings
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
|
|
@ -725,8 +725,9 @@ class DGPLVM(Prior):
|
||||||
|
|
||||||
# ******************************************
|
# ******************************************
|
||||||
|
|
||||||
from .. import Parameterized
|
from . import Parameterized
|
||||||
from .. import Param
|
from . import Param
|
||||||
|
|
||||||
class DGPLVM_Lamda(Prior, Parameterized):
|
class DGPLVM_Lamda(Prior, Parameterized):
|
||||||
"""
|
"""
|
||||||
Implementation of the Discriminative Gaussian Process Latent Variable model paper, by Raquel.
|
Implementation of the Discriminative Gaussian Process Latent Variable model paper, by Raquel.
|
||||||
|
|
|
||||||
|
|
@ -1,225 +0,0 @@
|
||||||
# Copyright (c) 2014, James Hensman, Max Zwiessele
|
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from .parameterized import Parameterized
|
|
||||||
from .param import Param
|
|
||||||
|
|
||||||
class Remapping(Parameterized):
|
|
||||||
def mapping(self):
|
|
||||||
"""
|
|
||||||
The return value of this function gives the values which the re-mapped
|
|
||||||
parameters should take. Implement in sub-classes.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def callback(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def parameters_changed(self):
|
|
||||||
#ensure all out parameters have the correct value, as specified by our mapping
|
|
||||||
index = self._highest_parent_.constraints[self]
|
|
||||||
self._highest_parent_.param_array[index] = self.mapping()
|
|
||||||
[p.notify_observers(which=self) for p in self.tied_parameters]
|
|
||||||
|
|
||||||
class Fix(Remapping):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Tie(Parameterized):
|
|
||||||
"""
|
|
||||||
The new parameter tie framework. (under development)
|
|
||||||
|
|
||||||
All the parameters tied together get a new parameter inside the *Tie* object.
|
|
||||||
Its value should always be equal to all the tied parameters, and its gradient
|
|
||||||
is the sum of all the tied parameters.
|
|
||||||
|
|
||||||
=====Implementation Details=====
|
|
||||||
The *Tie* object should only exist on the top of param tree (the highest parent).
|
|
||||||
|
|
||||||
self.label_buf:
|
|
||||||
It uses a label buffer that has the same length as all the parameters (self._highest_parent_.param_array).
|
|
||||||
The buffer keeps track of all the tied parameters. All the tied parameters have a label (an interger) higher
|
|
||||||
than 0, and the parameters that have the same label are tied together.
|
|
||||||
|
|
||||||
self.buf_index:
|
|
||||||
An auxiliary index list for the global index of the tie parameter inside the *Tie* object.
|
|
||||||
|
|
||||||
================================
|
|
||||||
|
|
||||||
TODO:
|
|
||||||
* EVERYTHING
|
|
||||||
|
|
||||||
"""
|
|
||||||
def __init__(self, name='tie'):
|
|
||||||
super(Tie, self).__init__(name)
|
|
||||||
self.tied_param = None
|
|
||||||
# The buffer keeps track of tie status
|
|
||||||
self.label_buf = None
|
|
||||||
# The global indices of the 'tied' param
|
|
||||||
self.buf_idx = None
|
|
||||||
# A boolean array indicating non-tied parameters
|
|
||||||
self._tie_ = None
|
|
||||||
|
|
||||||
def getTieFlag(self, p=None):
|
|
||||||
if self.tied_param is None:
|
|
||||||
if self._tie_ is None or self._tie_.size != self._highest_parent_.param_array.size:
|
|
||||||
self._tie_ = np.ones((self._highest_parent_.param_array.size,),dtype=np.bool)
|
|
||||||
if p is not None:
|
|
||||||
return self._tie_[p._highest_parent_._raveled_index_for(p)]
|
|
||||||
return self._tie_
|
|
||||||
|
|
||||||
def _init_labelBuf(self):
|
|
||||||
if self.label_buf is None:
|
|
||||||
self.label_buf = np.zeros(self._highest_parent_.param_array.shape, dtype=np.int)
|
|
||||||
if self._tie_ is None or self._tie_.size != self._highest_parent_.param_array.size:
|
|
||||||
self._tie_ = np.ones((self._highest_parent_.param_array.size,),dtype=np.bool)
|
|
||||||
|
|
||||||
def _updateTieFlag(self):
|
|
||||||
if self._tie_.size != self.label_buf.size:
|
|
||||||
self._tie_ = np.ones((self._highest_parent_.param_array.size,),dtype=np.bool)
|
|
||||||
self._tie_[self.label_buf>0] = False
|
|
||||||
self._tie_[self.buf_idx] = True
|
|
||||||
|
|
||||||
def add_tied_parameter(self, p, p2=None):
|
|
||||||
"""
|
|
||||||
Tie the list of parameters p together (p2==None) or
|
|
||||||
Tie the list of parameters p with the list of parameters p2 (p2!=None)
|
|
||||||
"""
|
|
||||||
self._init_labelBuf()
|
|
||||||
if p2 is None:
|
|
||||||
idx = self._highest_parent_._raveled_index_for(p)
|
|
||||||
val = self._sync_val_group(idx)
|
|
||||||
if np.all(self.label_buf[idx]==0):
|
|
||||||
# None of p has been tied before.
|
|
||||||
tie_idx = self._expandTieParam(1)
|
|
||||||
print(tie_idx)
|
|
||||||
tie_id = self.label_buf.max()+1
|
|
||||||
self.label_buf[tie_idx] = tie_id
|
|
||||||
else:
|
|
||||||
b = self.label_buf[idx]
|
|
||||||
ids = np.unique(b[b>0])
|
|
||||||
tie_id, tie_idx = self._merge_tie_param(ids)
|
|
||||||
self._highest_parent_.param_array[tie_idx] = val
|
|
||||||
idx = self._highest_parent_._raveled_index_for(p)
|
|
||||||
self.label_buf[idx] = tie_id
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
self._updateTieFlag()
|
|
||||||
|
|
||||||
def _merge_tie_param(self, ids):
|
|
||||||
"""Merge the tie parameters with ids in the list."""
|
|
||||||
if len(ids)==1:
|
|
||||||
id_final_idx = self.buf_idx[self.label_buf[self.buf_idx]==ids[0]][0]
|
|
||||||
return ids[0],id_final_idx
|
|
||||||
id_final = ids[0]
|
|
||||||
ids_rm = ids[1:]
|
|
||||||
label_buf_param = self.label_buf[self.buf_idx]
|
|
||||||
idx_param = [np.where(label_buf_param==i)[0][0] for i in ids_rm]
|
|
||||||
self._removeTieParam(idx_param)
|
|
||||||
[np.put(self.label_buf, np.where(self.label_buf==i), id_final) for i in ids_rm]
|
|
||||||
id_final_idx = self.buf_idx[self.label_buf[self.buf_idx]==id_final][0]
|
|
||||||
return id_final, id_final_idx
|
|
||||||
|
|
||||||
def _sync_val_group(self, idx):
|
|
||||||
self._highest_parent_.param_array[idx] = self._highest_parent_.param_array[idx].mean()
|
|
||||||
return self._highest_parent_.param_array[idx][0]
|
|
||||||
|
|
||||||
def _expandTieParam(self, num):
|
|
||||||
"""Expand the tie param with the number of *num* parameters"""
|
|
||||||
if self.tied_param is None:
|
|
||||||
new_buf = np.empty((num,))
|
|
||||||
else:
|
|
||||||
new_buf = np.empty((self.tied_param.size+num,))
|
|
||||||
new_buf[:self.tied_param.size] = self.tied_param.param_array.copy()
|
|
||||||
self.remove_parameter(self.tied_param)
|
|
||||||
self.tied_param = Param('tied',new_buf)
|
|
||||||
self.add_parameter(self.tied_param)
|
|
||||||
buf_idx_new = self._highest_parent_._raveled_index_for(self.tied_param)
|
|
||||||
self._expand_label_buf(self.buf_idx, buf_idx_new)
|
|
||||||
self.buf_idx = buf_idx_new
|
|
||||||
return self.buf_idx[-num:]
|
|
||||||
|
|
||||||
def _removeTieParam(self, idx):
|
|
||||||
"""idx within tied_param"""
|
|
||||||
new_buf = np.empty((self.tied_param.size-len(idx),))
|
|
||||||
bool_list = np.ones((self.tied_param.size,),dtype=np.bool)
|
|
||||||
bool_list[idx] = False
|
|
||||||
new_buf[:] = self.tied_param.param_array[bool_list]
|
|
||||||
self.remove_parameter(self.tied_param)
|
|
||||||
self.tied_param = Param('tied',new_buf)
|
|
||||||
self.add_parameter(self.tied_param)
|
|
||||||
buf_idx_new = self._highest_parent_._raveled_index_for(self.tied_param)
|
|
||||||
self._shrink_label_buf(self.buf_idx, buf_idx_new, bool_list)
|
|
||||||
self.buf_idx = buf_idx_new
|
|
||||||
|
|
||||||
def _expand_label_buf(self, idx_old, idx_new):
|
|
||||||
"""Expand label buffer accordingly"""
|
|
||||||
if idx_old is None:
|
|
||||||
self.label_buf = np.zeros(self._highest_parent_.param_array.shape, dtype=np.int)
|
|
||||||
else:
|
|
||||||
bool_old = np.zeros((self.label_buf.size,),dtype=np.bool)
|
|
||||||
bool_old[idx_old] = True
|
|
||||||
bool_new = np.zeros((self._highest_parent_.param_array.size,),dtype=np.bool)
|
|
||||||
bool_new[idx_new] = True
|
|
||||||
label_buf_new = np.zeros(self._highest_parent_.param_array.shape, dtype=np.int)
|
|
||||||
label_buf_new[np.logical_not(bool_new)] = self.label_buf[np.logical_not(bool_old)]
|
|
||||||
label_buf_new[idx_new[:len(idx_old)]] = self.label_buf[idx_old]
|
|
||||||
self.label_buf = label_buf_new
|
|
||||||
|
|
||||||
def _shrink_label_buf(self, idx_old, idx_new, bool_list):
|
|
||||||
bool_old = np.zeros((self.label_buf.size,),dtype=np.bool)
|
|
||||||
bool_old[idx_old] = True
|
|
||||||
bool_new = np.zeros((self._highest_parent_.param_array.size,),dtype=np.bool)
|
|
||||||
bool_new[idx_new] = True
|
|
||||||
label_buf_new = np.empty(self._highest_parent_.param_array.shape, dtype=np.int)
|
|
||||||
label_buf_new[np.logical_not(bool_new)] = self.label_buf[np.logical_not(bool_old)]
|
|
||||||
label_buf_new[idx_new] = self.label_buf[idx_old[bool_list]]
|
|
||||||
self.label_buf = label_buf_new
|
|
||||||
|
|
||||||
def _check_change(self):
|
|
||||||
changed = False
|
|
||||||
if self.tied_param is not None:
|
|
||||||
for i in range(self.tied_param.size):
|
|
||||||
b0 = self.label_buf==self.label_buf[self.buf_idx[i]]
|
|
||||||
b = self._highest_parent_.param_array[b0]!=self.tied_param[i]
|
|
||||||
if b.sum()==0:
|
|
||||||
print('XXX')
|
|
||||||
continue
|
|
||||||
elif b.sum()==1:
|
|
||||||
print('!!!')
|
|
||||||
val = self._highest_parent_.param_array[b0][b][0]
|
|
||||||
self._highest_parent_.param_array[b0] = val
|
|
||||||
else:
|
|
||||||
print('@@@')
|
|
||||||
self._highest_parent_.param_array[b0] = self.tied_param[i]
|
|
||||||
changed = True
|
|
||||||
return changed
|
|
||||||
|
|
||||||
def parameters_changed(self):
|
|
||||||
#ensure all out parameters have the correct value, as specified by our mapping
|
|
||||||
changed = self._check_change()
|
|
||||||
if changed:
|
|
||||||
self._highest_parent_._trigger_params_changed()
|
|
||||||
self.collate_gradient()
|
|
||||||
|
|
||||||
def collate_gradient(self):
|
|
||||||
if self.tied_param is not None:
|
|
||||||
self.tied_param.gradient = 0.
|
|
||||||
[np.put(self.tied_param.gradient, i, self._highest_parent_.gradient[self.label_buf==self.label_buf[self.buf_idx[i]]].sum())
|
|
||||||
for i in range(self.tied_param.size)]
|
|
||||||
|
|
||||||
def propagate_val(self):
|
|
||||||
if self.tied_param is not None:
|
|
||||||
for i in range(self.tied_param.size):
|
|
||||||
self._highest_parent_.param_array[self.label_buf==self.label_buf[self.buf_idx[i]]] = self.tied_param[i]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,518 +1,4 @@
|
||||||
# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
# Copyright (c) 2014, Max Zwiessele, James Hensman
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
|
from paramz.transformations import *
|
||||||
import numpy as np
|
|
||||||
from .domains import _POSITIVE,_NEGATIVE, _BOUNDED
|
|
||||||
import weakref
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
_exp_lim_val = np.finfo(np.float64).max
|
|
||||||
_lim_val = 36.0
|
|
||||||
epsilon = np.finfo(np.float64).resolution
|
|
||||||
|
|
||||||
#===============================================================================
|
|
||||||
# Fixing constants
|
|
||||||
__fixed__ = "fixed"
|
|
||||||
FIXED = False
|
|
||||||
UNFIXED = True
|
|
||||||
#===============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
class Transformation(object):
|
|
||||||
domain = None
|
|
||||||
_instance = None
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
if not cls._instance or cls._instance.__class__ is not cls:
|
|
||||||
cls._instance = super(Transformation, cls).__new__(cls, *args, **kwargs)
|
|
||||||
return cls._instance
|
|
||||||
def f(self, opt_param):
|
|
||||||
raise NotImplementedError
|
|
||||||
def finv(self, model_param):
|
|
||||||
raise NotImplementedError
|
|
||||||
def log_jacobian(self, model_param):
|
|
||||||
"""
|
|
||||||
compute the log of the jacobian of f, evaluated at f(x)= model_param
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
def log_jacobian_grad(self, model_param):
|
|
||||||
"""
|
|
||||||
compute the drivative of the log of the jacobian of f, evaluated at f(x)= model_param
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
def gradfactor(self, model_param, dL_dmodel_param):
|
|
||||||
""" df(opt_param)_dopt_param evaluated at self.f(opt_param)=model_param, times the gradient dL_dmodel_param,
|
|
||||||
|
|
||||||
i.e.:
|
|
||||||
define
|
|
||||||
|
|
||||||
.. math::
|
|
||||||
|
|
||||||
\frac{\frac{\partial L}{\partial f}\left(\left.\partial f(x)}{\partial x}\right|_{x=f^{-1}(f)\right)}
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
def gradfactor_non_natural(self, model_param, dL_dmodel_param):
|
|
||||||
return self.gradfactor(model_param, dL_dmodel_param)
|
|
||||||
def initialize(self, f):
|
|
||||||
""" produce a sensible initial value for f(x)"""
|
|
||||||
raise NotImplementedError
|
|
||||||
def plot(self, xlabel=r'transformed $\theta$', ylabel=r'$\theta$', axes=None, *args,**kw):
|
|
||||||
assert "matplotlib" in sys.modules, "matplotlib package has not been imported."
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from ...plotting.matplot_dep import base_plots
|
|
||||||
x = np.linspace(-8,8)
|
|
||||||
base_plots.meanplot(x, self.f(x), *args, ax=axes, **kw)
|
|
||||||
axes = plt.gca()
|
|
||||||
axes.set_xlabel(xlabel)
|
|
||||||
axes.set_ylabel(ylabel)
|
|
||||||
def __str__(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
def __repr__(self):
|
|
||||||
return self.__class__.__name__
|
|
||||||
|
|
||||||
class Logexp(Transformation):
|
|
||||||
domain = _POSITIVE
|
|
||||||
def f(self, x):
|
|
||||||
return np.where(x>_lim_val, x, np.log1p(np.exp(np.clip(x, -_lim_val, _lim_val)))) + epsilon
|
|
||||||
#raises overflow warning: return np.where(x>_lim_val, x, np.log(1. + np.exp(x)))
|
|
||||||
def finv(self, f):
|
|
||||||
return np.where(f>_lim_val, f, np.log(np.exp(f+1e-20) - 1.))
|
|
||||||
def gradfactor(self, f, df):
|
|
||||||
return np.einsum('i,i->i', df, np.where(f>_lim_val, 1., 1. - np.exp(-f)))
|
|
||||||
def initialize(self, f):
|
|
||||||
if np.any(f < 0.):
|
|
||||||
print("Warning: changing parameters to satisfy constraints")
|
|
||||||
return np.abs(f)
|
|
||||||
def log_jacobian(self, model_param):
|
|
||||||
return np.where(model_param>_lim_val, model_param, np.log(np.exp(model_param+1e-20) - 1.)) - model_param
|
|
||||||
def log_jacobian_grad(self, model_param):
|
|
||||||
return 1./(np.exp(model_param)-1.)
|
|
||||||
def __str__(self):
|
|
||||||
return '+ve'
|
|
||||||
|
|
||||||
class Exponent(Transformation):
|
|
||||||
domain = _POSITIVE
|
|
||||||
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))
|
|
||||||
def finv(self, x):
|
|
||||||
return np.log(x)
|
|
||||||
def gradfactor(self, f, df):
|
|
||||||
return np.einsum('i,i->i', df, f)
|
|
||||||
def initialize(self, f):
|
|
||||||
if np.any(f < 0.):
|
|
||||||
print("Warning: changing parameters to satisfy constraints")
|
|
||||||
return np.abs(f)
|
|
||||||
def log_jacobian(self, model_param):
|
|
||||||
return np.log(model_param)
|
|
||||||
def log_jacobian_grad(self, model_param):
|
|
||||||
return 1./model_param
|
|
||||||
def __str__(self):
|
|
||||||
return '+ve'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NormalTheta(Transformation):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
_instances = []
|
|
||||||
def __new__(cls, mu_indices=None, var_indices=None):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
if cls._instances:
|
|
||||||
cls._instances[:] = [instance for instance in cls._instances if instance()]
|
|
||||||
for instance in cls._instances:
|
|
||||||
if np.all(instance().mu_indices==mu_indices, keepdims=False) and np.all(instance().var_indices==var_indices, keepdims=False):
|
|
||||||
return instance()
|
|
||||||
o = super(Transformation, cls).__new__(cls, mu_indices, var_indices)
|
|
||||||
cls._instances.append(weakref.ref(o))
|
|
||||||
return cls._instances[-1]()
|
|
||||||
|
|
||||||
def __init__(self, mu_indices, var_indices):
|
|
||||||
self.mu_indices = mu_indices
|
|
||||||
self.var_indices = var_indices
|
|
||||||
|
|
||||||
def f(self, theta):
|
|
||||||
# In here abs is only a trick to make sure the numerics are ok.
|
|
||||||
# The variance will never go below zero, but at initialization we need to make sure
|
|
||||||
# that the values are ok
|
|
||||||
# Before:
|
|
||||||
theta[self.var_indices] = np.abs(-.5/theta[self.var_indices])
|
|
||||||
#theta[self.var_indices] = np.exp(-.5/theta[self.var_indices])
|
|
||||||
theta[self.mu_indices] *= theta[self.var_indices]
|
|
||||||
return theta # which is now {mu, var}
|
|
||||||
|
|
||||||
def finv(self, muvar):
|
|
||||||
# before:
|
|
||||||
varp = muvar[self.var_indices]
|
|
||||||
muvar[self.mu_indices] /= varp
|
|
||||||
muvar[self.var_indices] = -.5/varp
|
|
||||||
#muvar[self.var_indices] = -.5/np.log(varp)
|
|
||||||
|
|
||||||
return muvar # which is now {theta1, theta2}
|
|
||||||
|
|
||||||
def gradfactor(self, muvar, dmuvar):
|
|
||||||
mu = muvar[self.mu_indices]
|
|
||||||
var = muvar[self.var_indices]
|
|
||||||
#=======================================================================
|
|
||||||
# theta gradients
|
|
||||||
# This works and the gradient checks!
|
|
||||||
dmuvar[self.mu_indices] *= var
|
|
||||||
dmuvar[self.var_indices] *= 2*(var)**2
|
|
||||||
dmuvar[self.var_indices] += 2*dmuvar[self.mu_indices]*mu
|
|
||||||
#=======================================================================
|
|
||||||
|
|
||||||
return dmuvar # which is now the gradient multiplicator for {theta1, theta2}
|
|
||||||
|
|
||||||
def initialize(self, f):
|
|
||||||
if np.any(f[self.var_indices] < 0.):
|
|
||||||
print("Warning: changing parameters to satisfy constraints")
|
|
||||||
f[self.var_indices] = np.abs(f[self.var_indices])
|
|
||||||
return f
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "theta"
|
|
||||||
|
|
||||||
def __getstate__(self):
|
|
||||||
return [self.mu_indices, self.var_indices]
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
|
||||||
self.mu_indices = state[0]
|
|
||||||
self.var_indices = state[1]
|
|
||||||
|
|
||||||
class NormalNaturalAntti(NormalTheta):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
_instances = []
|
|
||||||
def __new__(cls, mu_indices=None, var_indices=None):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
if cls._instances:
|
|
||||||
cls._instances[:] = [instance for instance in cls._instances if instance()]
|
|
||||||
for instance in cls._instances:
|
|
||||||
if np.all(instance().mu_indices==mu_indices, keepdims=False) and np.all(instance().var_indices==var_indices, keepdims=False):
|
|
||||||
return instance()
|
|
||||||
o = super(Transformation, cls).__new__(cls, mu_indices, var_indices)
|
|
||||||
cls._instances.append(weakref.ref(o))
|
|
||||||
return cls._instances[-1]()
|
|
||||||
|
|
||||||
def __init__(self, mu_indices, var_indices):
|
|
||||||
self.mu_indices = mu_indices
|
|
||||||
self.var_indices = var_indices
|
|
||||||
|
|
||||||
def gradfactor(self, muvar, dmuvar):
|
|
||||||
mu = muvar[self.mu_indices]
|
|
||||||
var = muvar[self.var_indices]
|
|
||||||
|
|
||||||
#=======================================================================
|
|
||||||
# theta gradients
|
|
||||||
# This works and the gradient checks!
|
|
||||||
dmuvar[self.mu_indices] *= var
|
|
||||||
dmuvar[self.var_indices] *= 2*var**2#np.einsum('i,i,i,i->i', dmuvar[self.var_indices], [2], var, var)
|
|
||||||
#=======================================================================
|
|
||||||
|
|
||||||
return dmuvar # which is now the gradient multiplicator
|
|
||||||
|
|
||||||
def initialize(self, f):
|
|
||||||
if np.any(f[self.var_indices] < 0.):
|
|
||||||
print("Warning: changing parameters to satisfy constraints")
|
|
||||||
f[self.var_indices] = np.abs(f[self.var_indices])
|
|
||||||
return f
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "natantti"
|
|
||||||
|
|
||||||
class NormalEta(Transformation):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
_instances = []
|
|
||||||
def __new__(cls, mu_indices=None, var_indices=None):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
if cls._instances:
|
|
||||||
cls._instances[:] = [instance for instance in cls._instances if instance()]
|
|
||||||
for instance in cls._instances:
|
|
||||||
if np.all(instance().mu_indices==mu_indices, keepdims=False) and np.all(instance().var_indices==var_indices, keepdims=False):
|
|
||||||
return instance()
|
|
||||||
o = super(Transformation, cls).__new__(cls, mu_indices, var_indices)
|
|
||||||
cls._instances.append(weakref.ref(o))
|
|
||||||
return cls._instances[-1]()
|
|
||||||
|
|
||||||
def __init__(self, mu_indices, var_indices):
|
|
||||||
self.mu_indices = mu_indices
|
|
||||||
self.var_indices = var_indices
|
|
||||||
|
|
||||||
def f(self, theta):
|
|
||||||
theta[self.var_indices] = np.abs(theta[self.var_indices] - theta[self.mu_indices]**2)
|
|
||||||
return theta # which is now {mu, var}
|
|
||||||
|
|
||||||
def finv(self, muvar):
|
|
||||||
muvar[self.var_indices] += muvar[self.mu_indices]**2
|
|
||||||
return muvar # which is now {eta1, eta2}
|
|
||||||
|
|
||||||
def gradfactor(self, muvar, dmuvar):
|
|
||||||
mu = muvar[self.mu_indices]
|
|
||||||
#=======================================================================
|
|
||||||
# Lets try natural gradients instead: Not working with bfgs... try stochastic!
|
|
||||||
dmuvar[self.mu_indices] -= 2*mu*dmuvar[self.var_indices]
|
|
||||||
#=======================================================================
|
|
||||||
return dmuvar # which is now the gradient multiplicator
|
|
||||||
|
|
||||||
def initialize(self, f):
|
|
||||||
if np.any(f[self.var_indices] < 0.):
|
|
||||||
print("Warning: changing parameters to satisfy constraints")
|
|
||||||
f[self.var_indices] = np.abs(f[self.var_indices])
|
|
||||||
return f
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "eta"
|
|
||||||
|
|
||||||
class NormalNaturalThroughTheta(NormalTheta):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
_instances = []
|
|
||||||
def __new__(cls, mu_indices=None, var_indices=None):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
if cls._instances:
|
|
||||||
cls._instances[:] = [instance for instance in cls._instances if instance()]
|
|
||||||
for instance in cls._instances:
|
|
||||||
if np.all(instance().mu_indices==mu_indices, keepdims=False) and np.all(instance().var_indices==var_indices, keepdims=False):
|
|
||||||
return instance()
|
|
||||||
o = super(Transformation, cls).__new__(cls, mu_indices, var_indices)
|
|
||||||
cls._instances.append(weakref.ref(o))
|
|
||||||
return cls._instances[-1]()
|
|
||||||
|
|
||||||
def __init__(self, mu_indices, var_indices):
|
|
||||||
self.mu_indices = mu_indices
|
|
||||||
self.var_indices = var_indices
|
|
||||||
|
|
||||||
def gradfactor(self, muvar, dmuvar):
|
|
||||||
mu = muvar[self.mu_indices]
|
|
||||||
var = muvar[self.var_indices]
|
|
||||||
|
|
||||||
#=======================================================================
|
|
||||||
# This is just eta direction:
|
|
||||||
dmuvar[self.mu_indices] -= 2*mu*dmuvar[self.var_indices]
|
|
||||||
#=======================================================================
|
|
||||||
|
|
||||||
#=======================================================================
|
|
||||||
# This is by going through theta fully and then going into eta direction:
|
|
||||||
#dmu = dmuvar[self.mu_indices]
|
|
||||||
#dmuvar[self.var_indices] += dmu*mu*(var + 4/var)
|
|
||||||
#=======================================================================
|
|
||||||
return dmuvar # which is now the gradient multiplicator
|
|
||||||
|
|
||||||
def gradfactor_non_natural(self, muvar, dmuvar):
|
|
||||||
mu = muvar[self.mu_indices]
|
|
||||||
var = muvar[self.var_indices]
|
|
||||||
#=======================================================================
|
|
||||||
# theta gradients
|
|
||||||
# This works and the gradient checks!
|
|
||||||
dmuvar[self.mu_indices] *= var
|
|
||||||
dmuvar[self.var_indices] *= 2*(var)**2
|
|
||||||
dmuvar[self.var_indices] += 2*dmuvar[self.mu_indices]*mu
|
|
||||||
#=======================================================================
|
|
||||||
|
|
||||||
return dmuvar # which is now the gradient multiplicator for {theta1, theta2}
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "natgrad"
|
|
||||||
|
|
||||||
|
|
||||||
class NormalNaturalWhooot(NormalTheta):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
_instances = []
|
|
||||||
def __new__(cls, mu_indices=None, var_indices=None):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
if cls._instances:
|
|
||||||
cls._instances[:] = [instance for instance in cls._instances if instance()]
|
|
||||||
for instance in cls._instances:
|
|
||||||
if np.all(instance().mu_indices==mu_indices, keepdims=False) and np.all(instance().var_indices==var_indices, keepdims=False):
|
|
||||||
return instance()
|
|
||||||
o = super(Transformation, cls).__new__(cls, mu_indices, var_indices)
|
|
||||||
cls._instances.append(weakref.ref(o))
|
|
||||||
return cls._instances[-1]()
|
|
||||||
|
|
||||||
def __init__(self, mu_indices, var_indices):
|
|
||||||
self.mu_indices = mu_indices
|
|
||||||
self.var_indices = var_indices
|
|
||||||
|
|
||||||
def gradfactor(self, muvar, dmuvar):
|
|
||||||
#mu = muvar[self.mu_indices]
|
|
||||||
#var = muvar[self.var_indices]
|
|
||||||
|
|
||||||
#=======================================================================
|
|
||||||
# This is just eta direction:
|
|
||||||
#dmuvar[self.mu_indices] -= 2*mu*dmuvar[self.var_indices]
|
|
||||||
#=======================================================================
|
|
||||||
|
|
||||||
#=======================================================================
|
|
||||||
# This is by going through theta fully and then going into eta direction:
|
|
||||||
#dmu = dmuvar[self.mu_indices]
|
|
||||||
#dmuvar[self.var_indices] += dmu*mu*(var + 4/var)
|
|
||||||
#=======================================================================
|
|
||||||
return dmuvar # which is now the gradient multiplicator
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "natgrad"
|
|
||||||
|
|
||||||
class NormalNaturalThroughEta(NormalEta):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
_instances = []
|
|
||||||
def __new__(cls, mu_indices=None, var_indices=None):
|
|
||||||
"Do not use, not officially supported!"
|
|
||||||
if cls._instances:
|
|
||||||
cls._instances[:] = [instance for instance in cls._instances if instance()]
|
|
||||||
for instance in cls._instances:
|
|
||||||
if np.all(instance().mu_indices==mu_indices, keepdims=False) and np.all(instance().var_indices==var_indices, keepdims=False):
|
|
||||||
return instance()
|
|
||||||
o = super(Transformation, cls).__new__(cls, mu_indices, var_indices)
|
|
||||||
cls._instances.append(weakref.ref(o))
|
|
||||||
return cls._instances[-1]()
|
|
||||||
|
|
||||||
def __init__(self, mu_indices, var_indices):
|
|
||||||
self.mu_indices = mu_indices
|
|
||||||
self.var_indices = var_indices
|
|
||||||
|
|
||||||
def gradfactor(self, muvar, dmuvar):
|
|
||||||
mu = muvar[self.mu_indices]
|
|
||||||
var = muvar[self.var_indices]
|
|
||||||
#=======================================================================
|
|
||||||
# theta gradients
|
|
||||||
# This works and the gradient checks!
|
|
||||||
dmuvar[self.mu_indices] *= var
|
|
||||||
dmuvar[self.var_indices] *= 2*(var)**2
|
|
||||||
dmuvar[self.var_indices] += 2*dmuvar[self.mu_indices]*mu
|
|
||||||
#=======================================================================
|
|
||||||
return dmuvar
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "natgrad"
|
|
||||||
|
|
||||||
|
|
||||||
class LogexpNeg(Transformation):
|
|
||||||
domain = _POSITIVE
|
|
||||||
def f(self, x):
|
|
||||||
return np.where(x>_lim_val, -x, -np.log(1. + np.exp(np.clip(x, -np.inf, _lim_val))))
|
|
||||||
#raises overflow warning: return np.where(x>_lim_val, x, np.log(1. + np.exp(x)))
|
|
||||||
def finv(self, f):
|
|
||||||
return np.where(f>_lim_val, 0, np.log(np.exp(-f) - 1.))
|
|
||||||
def gradfactor(self, f, df):
|
|
||||||
return np.einsum('i,i->i', df, np.where(f>_lim_val, -1, -1 + np.exp(-f)))
|
|
||||||
def initialize(self, f):
|
|
||||||
if np.any(f < 0.):
|
|
||||||
print("Warning: changing parameters to satisfy constraints")
|
|
||||||
return np.abs(f)
|
|
||||||
def __str__(self):
|
|
||||||
return '+ve'
|
|
||||||
|
|
||||||
|
|
||||||
class NegativeLogexp(Transformation):
|
|
||||||
domain = _NEGATIVE
|
|
||||||
logexp = Logexp()
|
|
||||||
def f(self, x):
|
|
||||||
return -self.logexp.f(x) # np.log(1. + np.exp(x))
|
|
||||||
def finv(self, f):
|
|
||||||
return self.logexp.finv(-f) # np.log(np.exp(-f) - 1.)
|
|
||||||
def gradfactor(self, f, df):
|
|
||||||
return np.einsum('i,i->i', df, -self.logexp.gradfactor(-f))
|
|
||||||
def initialize(self, f):
|
|
||||||
return -self.logexp.initialize(f) # np.abs(f)
|
|
||||||
def __str__(self):
|
|
||||||
return '-ve'
|
|
||||||
|
|
||||||
class LogexpClipped(Logexp):
|
|
||||||
max_bound = 1e100
|
|
||||||
min_bound = 1e-10
|
|
||||||
log_max_bound = np.log(max_bound)
|
|
||||||
log_min_bound = np.log(min_bound)
|
|
||||||
domain = _POSITIVE
|
|
||||||
_instances = []
|
|
||||||
def __new__(cls, lower=1e-6, *args, **kwargs):
|
|
||||||
if cls._instances:
|
|
||||||
cls._instances[:] = [instance for instance in cls._instances if instance()]
|
|
||||||
for instance in cls._instances:
|
|
||||||
if instance().lower == lower:
|
|
||||||
return instance()
|
|
||||||
o = super(Transformation, cls).__new__(cls, lower, *args, **kwargs)
|
|
||||||
cls._instances.append(weakref.ref(o))
|
|
||||||
return cls._instances[-1]()
|
|
||||||
def __init__(self, lower=1e-6):
|
|
||||||
self.lower = lower
|
|
||||||
def f(self, x):
|
|
||||||
exp = np.exp(np.clip(x, self.log_min_bound, self.log_max_bound))
|
|
||||||
f = np.log(1. + exp)
|
|
||||||
# if np.isnan(f).any():
|
|
||||||
# import ipdb;ipdb.set_trace()
|
|
||||||
return np.clip(f, self.min_bound, self.max_bound)
|
|
||||||
def finv(self, f):
|
|
||||||
return np.log(np.exp(f - 1.))
|
|
||||||
def gradfactor(self, f, df):
|
|
||||||
ef = np.exp(f) # np.clip(f, self.min_bound, self.max_bound))
|
|
||||||
gf = (ef - 1.) / ef
|
|
||||||
return np.einsum('i,i->i', df, gf) # np.where(f < self.lower, 0, gf)
|
|
||||||
def initialize(self, f):
|
|
||||||
if np.any(f < 0.):
|
|
||||||
print("Warning: changing parameters to satisfy constraints")
|
|
||||||
return np.abs(f)
|
|
||||||
def __str__(self):
|
|
||||||
return '+ve_c'
|
|
||||||
|
|
||||||
class NegativeExponent(Exponent):
|
|
||||||
domain = _NEGATIVE
|
|
||||||
def f(self, x):
|
|
||||||
return -Exponent.f(x)
|
|
||||||
def finv(self, f):
|
|
||||||
return Exponent.finv(-f)
|
|
||||||
def gradfactor(self, f, df):
|
|
||||||
return np.einsum('i,i->i', df, f)
|
|
||||||
def initialize(self, f):
|
|
||||||
return -Exponent.initialize(f) #np.abs(f)
|
|
||||||
def __str__(self):
|
|
||||||
return '-ve'
|
|
||||||
|
|
||||||
class Square(Transformation):
|
|
||||||
domain = _POSITIVE
|
|
||||||
def f(self, x):
|
|
||||||
return x ** 2
|
|
||||||
def finv(self, x):
|
|
||||||
return np.sqrt(x)
|
|
||||||
def gradfactor(self, f, df):
|
|
||||||
return np.einsum('i,i->i', df, 2 * np.sqrt(f))
|
|
||||||
def initialize(self, f):
|
|
||||||
return np.abs(f)
|
|
||||||
def __str__(self):
|
|
||||||
return '+sq'
|
|
||||||
|
|
||||||
class Logistic(Transformation):
|
|
||||||
domain = _BOUNDED
|
|
||||||
_instances = []
|
|
||||||
def __new__(cls, lower=1e-6, upper=1e-6, *args, **kwargs):
|
|
||||||
if cls._instances:
|
|
||||||
cls._instances[:] = [instance for instance in cls._instances if instance()]
|
|
||||||
for instance in cls._instances:
|
|
||||||
if instance().lower == lower and instance().upper == upper:
|
|
||||||
return instance()
|
|
||||||
newfunc = super(Transformation, cls).__new__
|
|
||||||
if newfunc is object.__new__:
|
|
||||||
o = newfunc(cls)
|
|
||||||
else:
|
|
||||||
o = newfunc(cls, lower, upper, *args, **kwargs)
|
|
||||||
cls._instances.append(weakref.ref(o))
|
|
||||||
return cls._instances[-1]()
|
|
||||||
def __init__(self, lower, upper):
|
|
||||||
assert lower < upper
|
|
||||||
self.lower, self.upper = float(lower), float(upper)
|
|
||||||
self.difference = self.upper - self.lower
|
|
||||||
def f(self, x):
|
|
||||||
if (x<-300.).any():
|
|
||||||
x = x.copy()
|
|
||||||
x[x<-300.] = -300.
|
|
||||||
return self.lower + self.difference / (1. + np.exp(-x))
|
|
||||||
def finv(self, f):
|
|
||||||
return np.log(np.clip(f - self.lower, 1e-10, np.inf) / np.clip(self.upper - f, 1e-10, np.inf))
|
|
||||||
def gradfactor(self, f, df):
|
|
||||||
return np.einsum('i,i->i', df, (f - self.lower) * (self.upper - f) / self.difference)
|
|
||||||
def initialize(self, f):
|
|
||||||
if np.any(np.logical_or(f < self.lower, f > self.upper)):
|
|
||||||
print("Warning: changing parameters to satisfy constraints")
|
|
||||||
#return np.where(np.logical_or(f < self.lower, f > self.upper), self.f(f * 0.), f)
|
|
||||||
#FIXME: Max, zeros_like right?
|
|
||||||
return np.where(np.logical_or(f < self.lower, f > self.upper), self.f(np.zeros_like(f)), f)
|
|
||||||
def __str__(self):
|
|
||||||
return '{},{}'.format(self.lower, self.upper)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
'''
|
|
||||||
Created on 11 Nov 2014
|
|
||||||
|
|
||||||
@author: maxz
|
|
||||||
'''
|
|
||||||
from .observable import Observable
|
|
||||||
|
|
||||||
|
|
||||||
class Updateable(Observable):
|
|
||||||
"""
|
|
||||||
A model can be updated or not.
|
|
||||||
Make sure updates can be switched on and off.
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(Updateable, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def update_model(self, updates=None):
|
|
||||||
"""
|
|
||||||
Get or set, whether automatic updates are performed. When updates are
|
|
||||||
off, the model might be in a non-working state. To make the model work
|
|
||||||
turn updates on again.
|
|
||||||
|
|
||||||
:param bool|None updates:
|
|
||||||
|
|
||||||
bool: whether to do updates
|
|
||||||
None: get the current update state
|
|
||||||
"""
|
|
||||||
if updates is None:
|
|
||||||
return self._update_on
|
|
||||||
assert isinstance(updates, bool), "updates are either on (True) or off (False)"
|
|
||||||
p = getattr(self, '_highest_parent_', None)
|
|
||||||
def turn_updates(s):
|
|
||||||
s._update_on = updates
|
|
||||||
p.traverse(turn_updates)
|
|
||||||
self.trigger_update()
|
|
||||||
|
|
||||||
def toggle_update(self):
|
|
||||||
print("deprecated: toggle_update was renamed to update_toggle for easier access")
|
|
||||||
self.update_toggle()
|
|
||||||
def update_toggle(self):
|
|
||||||
self.update_model(not self.update_model())
|
|
||||||
|
|
||||||
def trigger_update(self, trigger_parent=True):
|
|
||||||
"""
|
|
||||||
Update the model from the current state.
|
|
||||||
Make sure that updates are on, otherwise this
|
|
||||||
method will do nothing
|
|
||||||
|
|
||||||
:param bool trigger_parent: Whether to trigger the parent, after self has updated
|
|
||||||
"""
|
|
||||||
if not self.update_model() or (hasattr(self, "_in_init_") and self._in_init_):
|
|
||||||
#print "Warning: updates are off, updating the model will do nothing"
|
|
||||||
return
|
|
||||||
self._trigger_params_changed(trigger_parent)
|
|
||||||
|
|
@ -7,9 +7,7 @@ Created on 6 Nov 2013
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .parameterized import Parameterized
|
from .parameterized import Parameterized
|
||||||
from .param import Param
|
from .param import Param
|
||||||
from .transformations import Logexp, Logistic,__fixed__
|
from paramz.transformations import Logexp, Logistic,__fixed__
|
||||||
from GPy.util.misc import param_to_array
|
|
||||||
from GPy.util.caching import Cache_this
|
|
||||||
|
|
||||||
class VariationalPrior(Parameterized):
|
class VariationalPrior(Parameterized):
|
||||||
def __init__(self, name='latent space', **kw):
|
def __init__(self, name='latent space', **kw):
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,9 @@ from .gp import GP
|
||||||
from .parameterization.param import Param
|
from .parameterization.param import Param
|
||||||
from ..inference.latent_function_inference import var_dtc
|
from ..inference.latent_function_inference import var_dtc
|
||||||
from .. import likelihoods
|
from .. import likelihoods
|
||||||
from .parameterization.variational import VariationalPosterior, NormalPosterior
|
from GPy.core.parameterization.variational import VariationalPosterior
|
||||||
from ..util.linalg import mdot
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import itertools
|
|
||||||
logger = logging.getLogger("sparse gp")
|
logger = logging.getLogger("sparse gp")
|
||||||
|
|
||||||
class SparseGP(GP):
|
class SparseGP(GP):
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class SVGP(SparseGP):
|
||||||
#create the SVI inference method
|
#create the SVI inference method
|
||||||
inf_method = svgp_inf()
|
inf_method = svgp_inf()
|
||||||
|
|
||||||
SparseGP.__init__(self, X_batch, Y_batch, Z, kernel, likelihood, mean_function=mean_function, inference_method=inf_method,
|
super(SVGP, self).__init__(X_batch, Y_batch, Z, kernel, likelihood, mean_function=mean_function, inference_method=inf_method,
|
||||||
name=name, Y_metadata=Y_metadata, normalizer=False)
|
name=name, Y_metadata=Y_metadata, normalizer=False)
|
||||||
|
|
||||||
#assume the number of latent functions is one per col of Y unless specified
|
#assume the number of latent functions is one per col of Y unless specified
|
||||||
|
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
||||||
# Copyright (c) 2012-2014, Max Zwiessele.
|
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
import numpy as np
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
def exponents(fnow, current_grad):
|
|
||||||
exps = [np.abs(np.float(fnow)), 1 if current_grad is np.nan else current_grad]
|
|
||||||
return np.sign(exps) * np.log10(exps).astype(int)
|
|
||||||
|
|
||||||
class VerboseOptimization(object):
|
|
||||||
def __init__(self, model, opt, maxiters, verbose=False, current_iteration=0, ipython_notebook=True, clear_after_finish=False):
|
|
||||||
self.verbose = verbose
|
|
||||||
if self.verbose:
|
|
||||||
self.model = model
|
|
||||||
self.iteration = current_iteration
|
|
||||||
self.p_iter = self.iteration
|
|
||||||
self.maxiters = maxiters
|
|
||||||
self.len_maxiters = len(str(maxiters))
|
|
||||||
self.opt_name = opt.opt_name
|
|
||||||
self.model.add_observer(self, self.print_status)
|
|
||||||
self.status = 'running'
|
|
||||||
self.clear = clear_after_finish
|
|
||||||
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
try:
|
|
||||||
from notebook.display import display
|
|
||||||
from ipywidgets.widgets import IntProgress, HTML, Box, VBox, FlexBox
|
|
||||||
self.text = HTML(width='100%')
|
|
||||||
self.progress = IntProgress(min=0, max=maxiters)
|
|
||||||
#self.progresstext = Text(width='100%', disabled=True, value='0/{}'.format(maxiters))
|
|
||||||
self.model_show = HTML()
|
|
||||||
self.ipython_notebook = ipython_notebook
|
|
||||||
except:
|
|
||||||
# Not in Jupyter notebook
|
|
||||||
self.ipython_notebook = False
|
|
||||||
|
|
||||||
if self.ipython_notebook:
|
|
||||||
left_col = VBox(children=[self.progress, self.text], padding=2, width='40%')
|
|
||||||
right_col = Box(children=[self.model_show], padding=2, width='60%')
|
|
||||||
self.hor_align = FlexBox(children = [left_col, right_col], width='100%', orientation='horizontal')
|
|
||||||
|
|
||||||
display(self.hor_align)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.text.set_css('width', '100%')
|
|
||||||
left_col.set_css({
|
|
||||||
'padding': '2px',
|
|
||||||
'width': "100%",
|
|
||||||
})
|
|
||||||
|
|
||||||
right_col.set_css({
|
|
||||||
'padding': '2px',
|
|
||||||
})
|
|
||||||
|
|
||||||
self.hor_align.set_css({
|
|
||||||
'width': "100%",
|
|
||||||
})
|
|
||||||
|
|
||||||
self.hor_align.remove_class('vbox')
|
|
||||||
self.hor_align.add_class('hbox')
|
|
||||||
|
|
||||||
left_col.add_class("box-flex1")
|
|
||||||
right_col.add_class('box-flex0')
|
|
||||||
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
#self.text.add_class('box-flex2')
|
|
||||||
#self.progress.add_class('box-flex1')
|
|
||||||
else:
|
|
||||||
self.exps = exponents(self.fnow, self.current_gradient)
|
|
||||||
print('Running {} Code:'.format(self.opt_name))
|
|
||||||
print(' {3:7s} {0:{mi}s} {1:11s} {2:11s}'.format("i", "f", "|g|", "runtime", mi=self.len_maxiters))
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
self.start = time.time()
|
|
||||||
self._time = self.start
|
|
||||||
return self
|
|
||||||
|
|
||||||
def print_out(self, seconds):
|
|
||||||
if seconds<60:
|
|
||||||
ms = (seconds%1)*100
|
|
||||||
self.timestring = "{s:0>2d}s{ms:0>2d}".format(s=int(seconds), ms=int(ms))
|
|
||||||
else:
|
|
||||||
m, s = divmod(seconds, 60)
|
|
||||||
if m>59:
|
|
||||||
h, m = divmod(m, 60)
|
|
||||||
if h>23:
|
|
||||||
d, h = divmod(h, 24)
|
|
||||||
self.timestring = '{d:0>2d}d{h:0>2d}h{m:0>2d}'.format(m=int(m), h=int(h), d=int(d))
|
|
||||||
else:
|
|
||||||
self.timestring = '{h:0>2d}h{m:0>2d}m{s:0>2d}'.format(m=int(m), s=int(s), h=int(h))
|
|
||||||
else:
|
|
||||||
ms = (seconds%1)*100
|
|
||||||
self.timestring = '{m:0>2d}m{s:0>2d}s{ms:0>2d}'.format(m=int(m), s=int(s), ms=int(ms))
|
|
||||||
if self.ipython_notebook:
|
|
||||||
names_vals = [['optimizer', "{:s}".format(self.opt_name)],
|
|
||||||
['runtime', "{:>s}".format(self.timestring)],
|
|
||||||
['evaluation', "{:>0{l}}".format(self.iteration, l=self.len_maxiters)],
|
|
||||||
['objective', "{: > 12.3E}".format(self.fnow)],
|
|
||||||
['||gradient||', "{: >+12.3E}".format(float(self.current_gradient))],
|
|
||||||
['status', "{:s}".format(self.status)],
|
|
||||||
]
|
|
||||||
#message = "Lik:{:5.3E} Grad:{:5.3E} Lik:{:5.3E} Len:{!s}".format(float(m.log_likelihood()), np.einsum('i,i->', grads, grads), float(m.likelihood.variance), " ".join(["{:3.2E}".format(l) for l in m.kern.lengthscale.values]))
|
|
||||||
html_begin = """<style type="text/css">
|
|
||||||
.tg-opt {font-family:"Courier New", Courier, monospace !important;padding:2px 3px;word-break:normal;border-collapse:collapse;border-spacing:0;border-color:#DCDCDC;margin:0px auto;width:100%;}
|
|
||||||
.tg-opt td{font-family:"Courier New", Courier, monospace !important;font-weight:bold;color:#444;background-color:#F7FDFA;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#DCDCDC;}
|
|
||||||
.tg-opt th{font-family:"Courier New", Courier, monospace !important;font-weight:normal;color:#fff;background-color:#26ADE4;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#DCDCDC;}
|
|
||||||
.tg-opt .tg-left{font-family:"Courier New", Courier, monospace !important;font-weight:normal;text-align:left;}
|
|
||||||
.tg-opt .tg-right{font-family:"Courier New", Courier, monospace !important;font-weight:normal;text-align:right;}
|
|
||||||
</style>
|
|
||||||
<table class="tg-opt">"""
|
|
||||||
html_end = "</table>"
|
|
||||||
html_body = ""
|
|
||||||
for name, val in names_vals:
|
|
||||||
html_body += "<tr>"
|
|
||||||
html_body += "<td class='tg-left'>{}</td>".format(name)
|
|
||||||
html_body += "<td class='tg-right'>{}</td>".format(val)
|
|
||||||
html_body += "</tr>"
|
|
||||||
self.text.value = html_begin + html_body + html_end
|
|
||||||
self.progress.value = (self.iteration+1)
|
|
||||||
#self.progresstext.value = '0/{}'.format((self.iteration+1))
|
|
||||||
self.model_show.value = self.model._repr_html_()
|
|
||||||
else:
|
|
||||||
n_exps = exponents(self.fnow, self.current_gradient)
|
|
||||||
if self.iteration - self.p_iter >= 20 * np.random.rand():
|
|
||||||
a = self.iteration >= self.p_iter * 2.78
|
|
||||||
b = np.any(n_exps < self.exps)
|
|
||||||
if a or b:
|
|
||||||
self.p_iter = self.iteration
|
|
||||||
print('')
|
|
||||||
if b:
|
|
||||||
self.exps = n_exps
|
|
||||||
print('\r', end=' ')
|
|
||||||
print('{3:} {0:>0{mi}g} {1:> 12e} {2:> 12e}'.format(self.iteration, float(self.fnow), float(self.current_gradient), "{:>8s}".format(self.timestring), mi=self.len_maxiters), end=' ') # print 'Iteration:', iteration, ' Objective:', fnow, ' Scale:', beta, '\r',
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def print_status(self, me, which=None):
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
t = time.time()
|
|
||||||
seconds = t-self.start
|
|
||||||
#sys.stdout.write(" "*len(self.message))
|
|
||||||
if t-self._time > .3 or seconds < .3:
|
|
||||||
self.print_out(seconds)
|
|
||||||
self._time = t
|
|
||||||
|
|
||||||
self.iteration += 1
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
self.fnow = self.model.objective_function()
|
|
||||||
if self.model.obj_grads is not None:
|
|
||||||
grad = self.model.obj_grads
|
|
||||||
self.current_gradient = np.dot(grad, grad)
|
|
||||||
else:
|
|
||||||
self.current_gradient = np.nan
|
|
||||||
|
|
||||||
def finish(self, opt):
|
|
||||||
self.status = opt.status
|
|
||||||
if self.verbose and self.ipython_notebook:
|
|
||||||
if 'conv' in self.status.lower():
|
|
||||||
self.progress.bar_style = 'success'
|
|
||||||
elif self.iteration >= self.maxiters:
|
|
||||||
self.progress.bar_style = 'warning'
|
|
||||||
else:
|
|
||||||
self.progress.bar_style = 'danger'
|
|
||||||
|
|
||||||
def __exit__(self, type, value, traceback):
|
|
||||||
if self.verbose:
|
|
||||||
self.stop = time.time()
|
|
||||||
self.model.remove_observer(self)
|
|
||||||
self.print_out(self.stop - self.start)
|
|
||||||
|
|
||||||
if not self.ipython_notebook:
|
|
||||||
print()
|
|
||||||
print('Runtime: {}'.format("{:>9s}".format(self.timestring)))
|
|
||||||
print('Optimization status: {0}'.format(self.status))
|
|
||||||
print()
|
|
||||||
elif self.clear:
|
|
||||||
self.hor_align.close()
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ...util.linalg import jitchol, DSYR, dtrtrs, dtrtri
|
from ...util.linalg import jitchol, DSYR, dtrtrs, dtrtri
|
||||||
from ...core.parameterization.observable_array import ObsAr
|
from paramz import ObsAr
|
||||||
from . import ExactGaussianInference, VarDTC
|
from . import ExactGaussianInference, VarDTC
|
||||||
from ...util import diag
|
from ...util import diag
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,8 @@
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ...core import Model
|
from ...core import Model
|
||||||
from ...core.parameterization import variational
|
from GPy.core.parameterization import variational
|
||||||
from ...util.linalg import tdot
|
from ...util.linalg import tdot
|
||||||
from GPy.core.parameterization.variational import VariationalPosterior
|
|
||||||
|
|
||||||
def infer_newX(model, Y_new, optimize=True, init='L2'):
|
def infer_newX(model, Y_new, optimize=True, init='L2'):
|
||||||
"""
|
"""
|
||||||
|
|
@ -62,14 +61,12 @@ class InferenceX(Model):
|
||||||
# self.kern.GPU(True)
|
# self.kern.GPU(True)
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
self.posterior = deepcopy(model.posterior)
|
self.posterior = deepcopy(model.posterior)
|
||||||
from ...core.parameterization.variational import VariationalPosterior
|
if isinstance(model.X, variational.VariationalPosterior):
|
||||||
if isinstance(model.X, VariationalPosterior):
|
|
||||||
self.uncertain_input = True
|
self.uncertain_input = True
|
||||||
from ...models.ss_gplvm import IBPPrior
|
from ...models.ss_gplvm import IBPPrior
|
||||||
from ...models.ss_mrd import IBPPrior_SSMRD
|
from ...models.ss_mrd import IBPPrior_SSMRD
|
||||||
if isinstance(model.variational_prior, IBPPrior) or isinstance(model.variational_prior, IBPPrior_SSMRD):
|
if isinstance(model.variational_prior, IBPPrior) or isinstance(model.variational_prior, IBPPrior_SSMRD):
|
||||||
from ...core.parameterization.variational import SpikeAndSlabPrior
|
self.variational_prior = variational.SpikeAndSlabPrior(pi=0.5, learnPi=False, group_spike=False)
|
||||||
self.variational_prior = SpikeAndSlabPrior(pi=0.5, learnPi=False, group_spike=False)
|
|
||||||
else:
|
else:
|
||||||
self.variational_prior = model.variational_prior.copy()
|
self.variational_prior = model.variational_prior.copy()
|
||||||
else:
|
else:
|
||||||
|
|
@ -105,17 +102,16 @@ class InferenceX(Model):
|
||||||
idx = dist.argmin(axis=1)
|
idx = dist.argmin(axis=1)
|
||||||
|
|
||||||
from ...models import SSGPLVM
|
from ...models import SSGPLVM
|
||||||
from ...util.misc import param_to_array
|
|
||||||
if isinstance(model, SSGPLVM):
|
if isinstance(model, SSGPLVM):
|
||||||
X = variational.SpikeAndSlabPosterior(param_to_array(model.X.mean[idx]), param_to_array(model.X.variance[idx]), param_to_array(model.X.gamma[idx]))
|
X = variational.SpikeAndSlabPosterior((model.X.mean[idx].values), (model.X.variance[idx].values), (model.X.gamma[idx].values))
|
||||||
if model.group_spike:
|
if model.group_spike:
|
||||||
X.gamma.fix()
|
X.gamma.fix()
|
||||||
else:
|
else:
|
||||||
if self.uncertain_input and self.sparse_gp:
|
if self.uncertain_input and self.sparse_gp:
|
||||||
X = variational.NormalPosterior(param_to_array(model.X.mean[idx]), param_to_array(model.X.variance[idx]))
|
X = variational.NormalPosterior((model.X.mean[idx].values), (model.X.variance[idx].values))
|
||||||
else:
|
else:
|
||||||
from ...core import Param
|
from ...core import Param
|
||||||
X = Param('latent mean',param_to_array(model.X[idx]).copy())
|
X = Param('latent mean',(model.X[idx].values).copy())
|
||||||
|
|
||||||
return X
|
return X
|
||||||
|
|
||||||
|
|
@ -160,8 +156,7 @@ class InferenceX(Model):
|
||||||
self.X.gradient = X_grad
|
self.X.gradient = X_grad
|
||||||
|
|
||||||
if self.uncertain_input:
|
if self.uncertain_input:
|
||||||
from ...core.parameterization.variational import SpikeAndSlabPrior
|
if isinstance(self.variational_prior, variational.SpikeAndSlabPrior):
|
||||||
if isinstance(self.variational_prior, SpikeAndSlabPrior):
|
|
||||||
# Update Log-likelihood
|
# Update Log-likelihood
|
||||||
KL_div = self.variational_prior.KL_divergence(self.X)
|
KL_div = self.variational_prior.KL_divergence(self.X)
|
||||||
# update for the KL divergence
|
# update for the KL divergence
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
from .posterior import Posterior
|
from .posterior import Posterior
|
||||||
from ...util.linalg import mdot, jitchol, backsub_both_sides, tdot, dtrtrs, dtrtri, dpotri, dpotrs, symmetrify
|
from ...util.linalg import mdot, jitchol, backsub_both_sides, tdot, dtrtrs, dtrtri, dpotri, dpotrs, symmetrify
|
||||||
from ...util import diag
|
from ...util import diag
|
||||||
from ...core.parameterization.variational import VariationalPosterior
|
from GPy.core.parameterization.variational import VariationalPosterior
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from . import LatentFunctionInference
|
from . import LatentFunctionInference
|
||||||
log_2_pi = np.log(2*np.pi)
|
log_2_pi = np.log(2*np.pi)
|
||||||
|
|
@ -23,8 +23,7 @@ class VarDTC(LatentFunctionInference):
|
||||||
"""
|
"""
|
||||||
const_jitter = 1e-8
|
const_jitter = 1e-8
|
||||||
def __init__(self, limit=1):
|
def __init__(self, limit=1):
|
||||||
#self._YYTfactor_cache = caching.cache()
|
from paramz.caching import Cacher
|
||||||
from ...util.caching import Cacher
|
|
||||||
self.limit = limit
|
self.limit = limit
|
||||||
self.get_trYYT = Cacher(self._get_trYYT, limit)
|
self.get_trYYT = Cacher(self._get_trYYT, limit)
|
||||||
self.get_YYTfactor = Cacher(self._get_YYTfactor, limit)
|
self.get_YYTfactor = Cacher(self._get_YYTfactor, limit)
|
||||||
|
|
@ -45,7 +44,7 @@ class VarDTC(LatentFunctionInference):
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state):
|
||||||
# has to be overridden, as Cacher objects cannot be pickled.
|
# has to be overridden, as Cacher objects cannot be pickled.
|
||||||
self.limit = state
|
self.limit = state
|
||||||
from ...util.caching import Cacher
|
from paramz.caching import Cacher
|
||||||
self.get_trYYT = Cacher(self._get_trYYT, self.limit)
|
self.get_trYYT = Cacher(self._get_trYYT, self.limit)
|
||||||
self.get_YYTfactor = Cacher(self._get_YYTfactor, self.limit)
|
self.get_YYTfactor = Cacher(self._get_YYTfactor, self.limit)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
from .posterior import Posterior
|
from .posterior import Posterior
|
||||||
from ...util.linalg import jitchol, backsub_both_sides, tdot, dtrtrs, dtrtri,pdinv
|
from ...util.linalg import jitchol, backsub_both_sides, tdot, dtrtrs, dtrtri,pdinv
|
||||||
from ...util import diag
|
from ...util import diag
|
||||||
from ...core.parameterization.variational import VariationalPosterior
|
from GPy.core.parameterization.variational import VariationalPosterior
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from . import LatentFunctionInference
|
from . import LatentFunctionInference
|
||||||
log_2_pi = np.log(2*np.pi)
|
log_2_pi = np.log(2*np.pi)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from .independent_outputs import index_to_slices
|
from .independent_outputs import index_to_slices
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
class ODE_UY(Kern):
|
class ODE_UY(Kern):
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .independent_outputs import index_to_slices
|
from .independent_outputs import index_to_slices
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .independent_outputs import index_to_slices
|
from .independent_outputs import index_to_slices
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .independent_outputs import index_to_slices
|
from .independent_outputs import index_to_slices
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import itertools
|
import itertools
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
from .kern import CombinationKernel, Kern
|
from .kern import CombinationKernel, Kern
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization.param import Param
|
from ...core.parameterization.param import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
from ...util.linalg import tdot, mdot
|
from ...util.linalg import tdot, mdot
|
||||||
|
|
||||||
class BasisFuncKernel(Kern):
|
class BasisFuncKernel(Kern):
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
class Brownian(Kern):
|
class Brownian(Kern):
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
from ...util.config import config # for assesing whether to use cython
|
from ...util.config import config # for assesing whether to use cython
|
||||||
try:
|
try:
|
||||||
from . import coregionalize_cython
|
from . import coregionalize_cython
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import numpy as np
|
||||||
from scipy.special import wofz
|
from scipy.special import wofz
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
|
|
||||||
class EQ_ODE2(Kern):
|
class EQ_ODE2(Kern):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
import sys
|
import sys
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ...core.parameterization.parameterized import Parameterized
|
from ...core.parameterization.parameterized import Parameterized
|
||||||
from ...core.parameterization.observable_array import ObsAr
|
from paramz.core.observable_array import ObsAr
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
from .kernel_slice_operations import KernCallsViaSlicerMeta
|
from .kernel_slice_operations import KernCallsViaSlicerMeta
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
import six
|
import six
|
||||||
|
|
@ -30,18 +30,16 @@ class Kern(Parameterized):
|
||||||
tight dimensionality of inputs.
|
tight dimensionality of inputs.
|
||||||
You most likely want this to be the integer telling the number of
|
You most likely want this to be the integer telling the number of
|
||||||
input dimensions of the kernel.
|
input dimensions of the kernel.
|
||||||
If this is not an integer (!) we will work on the whole input matrix X,
|
|
||||||
and not check whether dimensions match or not (!).
|
|
||||||
|
|
||||||
_all_dims_active:
|
active_dims:
|
||||||
|
|
||||||
is the active_dimensions of inputs X we will work on.
|
is the active_dimensions of inputs X we will work on.
|
||||||
All kernels will get sliced Xes as inputs, if _all_dims_active is not None
|
All kernels will get sliced Xes as inputs, if _all_dims_active is not None
|
||||||
Only positive integers are allowed in _all_dims_active!
|
Only positive integers are allowed in active_dims!
|
||||||
if _all_dims_active is None, slicing is switched off and all X will be passed through as given.
|
if active_dims is None, slicing is switched off and all X will be passed through as given.
|
||||||
|
|
||||||
:param int input_dim: the number of input dimensions to the function
|
:param int input_dim: the number of input dimensions to the function
|
||||||
:param array-like|None _all_dims_active: list of indices on which dimensions this kernel works on, or none if no slicing
|
:param array-like|None active_dims: list of indices on which dimensions this kernel works on, or none if no slicing
|
||||||
|
|
||||||
Do not instantiate.
|
Do not instantiate.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ This module provides a meta class for the kernels. The meta class is for
|
||||||
slicing the inputs (X, X2) for the kernels, before K (or any other method involving X)
|
slicing the inputs (X, X2) for the kernels, before K (or any other method involving X)
|
||||||
gets calls. The `_all_dims_active` of a kernel decide which dimensions the kernel works on.
|
gets calls. The `_all_dims_active` of a kernel decide which dimensions the kernel works on.
|
||||||
'''
|
'''
|
||||||
from ...core.parameterization.parameterized import ParametersChangedMeta
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
from paramz.parameterized import ParametersChangedMeta
|
||||||
|
|
||||||
def put_clean(dct, name, func):
|
def put_clean(dct, name, func):
|
||||||
if name in dct:
|
if name in dct:
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import numpy as np
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...util.linalg import tdot
|
from ...util.linalg import tdot
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
from .psi_comp import PSICOMP_Linear
|
from .psi_comp import PSICOMP_Linear
|
||||||
|
|
||||||
class Linear(Kern):
|
class Linear(Kern):
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
four_over_tau = 2./np.pi
|
four_over_tau = 2./np.pi
|
||||||
|
|
||||||
class MLP(Kern):
|
class MLP(Kern):
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from .kern import Kern
|
||||||
from ...util.linalg import mdot
|
from ...util.linalg import mdot
|
||||||
from ...util.decorators import silence_errors
|
from ...util.decorators import silence_errors
|
||||||
from ...core.parameterization.param import Param
|
from ...core.parameterization.param import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
|
|
||||||
class Periodic(Kern):
|
class Periodic(Kern):
|
||||||
def __init__(self, input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name):
|
def __init__(self, input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name):
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
|
|
||||||
class Poly(Kern):
|
class Poly(Kern):
|
||||||
"""
|
"""
|
||||||
Polynomial kernel
|
Polynomial kernel
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .kern import CombinationKernel
|
from .kern import CombinationKernel
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
import itertools
|
import itertools
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
from ....core.parameterization.parameter_core import Pickleable
|
from paramz.core.pickleable import Pickleable
|
||||||
from ....util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
from ....core.parameterization import variational
|
from GPy.core.parameterization import variational
|
||||||
#from linear_psi_comp import LINEAr
|
#from linear_psi_comp import LINEAr
|
||||||
|
|
||||||
class PSICOMP(Pickleable):
|
class PSICOMP(Pickleable):
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ An approximated psi-statistics implementation based on Gauss-Hermite Quadrature
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from ....core.parameterization import Param
|
from ....core.parameterization import Param
|
||||||
from ....util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
from ....util.linalg import tdot
|
from ....util.linalg import tdot
|
||||||
from . import PSICOMP
|
from . import PSICOMP
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ class PSICOMP_GH(PSICOMP):
|
||||||
@Cache_this(limit=10, ignore_args=(0,))
|
@Cache_this(limit=10, ignore_args=(0,))
|
||||||
def comp_K(self, Z, qX):
|
def comp_K(self, Z, qX):
|
||||||
if self.Xs is None or self.Xs.shape != qX.mean.shape:
|
if self.Xs is None or self.Xs.shape != qX.mean.shape:
|
||||||
from ....core.parameterization import ObsAr
|
from paramz import ObsAr
|
||||||
self.Xs = ObsAr(np.empty((self.degree,)+qX.mean.shape))
|
self.Xs = ObsAr(np.empty((self.degree,)+qX.mean.shape))
|
||||||
mu, S = qX.mean.values, qX.variance.values
|
mu, S = qX.mean.values, qX.variance.values
|
||||||
S_sq = np.sqrt(S)
|
S_sq = np.sqrt(S)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ The module for psi-statistics for RBF kernel
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from GPy.util.caching import Cacher
|
from paramz.caching import Cacher
|
||||||
|
|
||||||
def psicomputations(variance, lengthscale, Z, variational_posterior, return_psi2_n=False):
|
def psicomputations(variance, lengthscale, Z, variational_posterior, return_psi2_n=False):
|
||||||
# here are the "statistics" for psi0, psi1 and psi2
|
# here are the "statistics" for psi0, psi1 and psi2
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ The module for psi-statistics for RBF kernel
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ....util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
from . import PSICOMP_RBF
|
from . import PSICOMP_RBF
|
||||||
from ....util import gpu_init
|
from ....util import gpu_init
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ The module for psi-statistics for RBF kernel for Spike-and-Slab GPLVM
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ....util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
from . import PSICOMP_RBF
|
from . import PSICOMP_RBF
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import numpy as np
|
||||||
from .stationary import Stationary
|
from .stationary import Stationary
|
||||||
from .psi_comp import PSICOMP_RBF, PSICOMP_RBF_GPU
|
from .psi_comp import PSICOMP_RBF, PSICOMP_RBF_GPU
|
||||||
from ...core import Param
|
from ...core import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
|
|
||||||
class RBF(Stationary):
|
class RBF(Stationary):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
|
|
||||||
class Spline(Kern):
|
class Spline(Kern):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ Neural Networks and Machine Learning, pages 133-165. Springer, 1998.
|
||||||
|
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
|
|
||||||
class Static(Kern):
|
class Static(Kern):
|
||||||
def __init__(self, input_dim, variance, active_dims, name):
|
def __init__(self, input_dim, variance, active_dims, name):
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,15 @@
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
|
|
||||||
from .kern import Kern
|
|
||||||
from ...core.parameterization import Param
|
|
||||||
from ...core.parameterization.transformations import Logexp
|
|
||||||
from ...util.linalg import tdot
|
|
||||||
from ... import util
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy import integrate
|
from scipy import integrate
|
||||||
|
from .kern import Kern
|
||||||
|
from ...core.parameterization import Param
|
||||||
|
from ...util.linalg import tdot
|
||||||
|
from ... import util
|
||||||
from ...util.config import config # for assesing whether to use cython
|
from ...util.config import config # for assesing whether to use cython
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
|
from paramz.transformations import Logexp
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from . import stationary_cython
|
from . import stationary_cython
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .kern import Kern
|
from .kern import Kern
|
||||||
from ...core.parameterization import Param
|
from ...core.parameterization import Param
|
||||||
from ...core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
from ...util.caching import Cache_this
|
from paramz.caching import Cache_this
|
||||||
|
|
||||||
class TruncLinear(Kern):
|
class TruncLinear(Kern):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ from scipy import stats, special
|
||||||
from . import link_functions
|
from . import link_functions
|
||||||
from .likelihood import Likelihood
|
from .likelihood import Likelihood
|
||||||
from ..core.parameterization import Param
|
from ..core.parameterization import Param
|
||||||
from ..core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
from scipy import stats
|
from scipy import stats
|
||||||
|
|
||||||
class Gaussian(Likelihood):
|
class Gaussian(Likelihood):
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from . import link_functions
|
||||||
from .likelihood import Likelihood
|
from .likelihood import Likelihood
|
||||||
from .gaussian import Gaussian
|
from .gaussian import Gaussian
|
||||||
from ..core.parameterization import Param
|
from ..core.parameterization import Param
|
||||||
from ..core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
from ..core.parameterization import Parameterized
|
from ..core.parameterization import Parameterized
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from scipy import stats, integrate
|
||||||
from scipy.special import gammaln, gamma
|
from scipy.special import gammaln, gamma
|
||||||
from .likelihood import Likelihood
|
from .likelihood import Likelihood
|
||||||
from ..core.parameterization import Param
|
from ..core.parameterization import Param
|
||||||
from ..core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
from scipy.special import psi as digamma
|
from scipy.special import psi as digamma
|
||||||
|
|
||||||
class StudentT(Likelihood):
|
class StudentT(Likelihood):
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import numpy as np
|
||||||
from .. import kern
|
from .. import kern
|
||||||
from ..core.sparse_gp_mpi import SparseGP_MPI
|
from ..core.sparse_gp_mpi import SparseGP_MPI
|
||||||
from ..likelihoods import Gaussian
|
from ..likelihoods import Gaussian
|
||||||
from ..core.parameterization.variational import NormalPosterior, NormalPrior
|
from GPy.core.parameterization.variational import NormalPosterior, NormalPrior
|
||||||
from ..inference.latent_function_inference.var_dtc_parallel import VarDTC_minibatch
|
from ..inference.latent_function_inference.var_dtc_parallel import VarDTC_minibatch
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,12 @@
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import logging
|
||||||
from .. import kern
|
from .. import kern
|
||||||
from ..likelihoods import Gaussian
|
from ..likelihoods import Gaussian
|
||||||
from ..core.parameterization.variational import NormalPosterior, NormalPrior
|
from GPy.core.parameterization.variational import NormalPosterior, NormalPrior
|
||||||
from ..inference.latent_function_inference.var_dtc_parallel import VarDTC_minibatch
|
from .sparse_gp_minibatch import SparseGPMiniBatch
|
||||||
import logging
|
from ..core.parameterization.param import Param
|
||||||
from GPy.models.sparse_gp_minibatch import SparseGPMiniBatch
|
|
||||||
from GPy.core.parameterization.param import Param
|
|
||||||
from GPy.core.parameterization.observable_array import ObsAr
|
|
||||||
|
|
||||||
class BayesianGPLVMMiniBatch(SparseGPMiniBatch):
|
class BayesianGPLVMMiniBatch(SparseGPMiniBatch):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
# Copyright (c) 2015 the GPy Austhors (see AUTHORS.txt)
|
# Copyright (c) 2015 the GPy Austhors (see AUTHORS.txt)
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from .. import kern
|
|
||||||
from .bayesian_gplvm import BayesianGPLVM
|
from .bayesian_gplvm import BayesianGPLVM
|
||||||
from ..core.parameterization.variational import NormalPosterior, NormalPrior
|
|
||||||
|
|
||||||
class DPBayesianGPLVM(BayesianGPLVM):
|
class DPBayesianGPLVM(BayesianGPLVM):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ..core.model import Model
|
from ..core import Model
|
||||||
from ..core.parameterization import ObsAr
|
from paramz import ObsAr
|
||||||
from .. import likelihoods
|
from .. import likelihoods
|
||||||
|
|
||||||
class GPKroneckerGaussianRegression(Model):
|
class GPKroneckerGaussianRegression(Model):
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ..core import GP
|
from ..core import GP
|
||||||
from ..core.parameterization import ObsAr
|
|
||||||
from .. import kern
|
|
||||||
from ..core.parameterization.param import Param
|
from ..core.parameterization.param import Param
|
||||||
from ..inference.latent_function_inference import VarGauss
|
from ..inference.latent_function_inference import VarGauss
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
# ## Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
# ## Copyright (c) 2012, GPy authors (see AUTHORS.txt).
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
from ..core.model import Model
|
|
||||||
import itertools
|
|
||||||
import numpy
|
import numpy
|
||||||
from ..core.parameterization import Param
|
|
||||||
np = numpy
|
np = numpy
|
||||||
|
|
||||||
|
from ..core.parameterization import Param
|
||||||
|
from GPy.core.model import Model
|
||||||
from ..util.block_matrices import get_blocks, get_block_shapes, unblock, get_blocks_3d, get_block_shapes_3d
|
from ..util.block_matrices import get_blocks, get_block_shapes, unblock, get_blocks_3d, get_block_shapes_3d
|
||||||
|
|
||||||
def get_shape(x):
|
def get_shape(x):
|
||||||
|
|
@ -62,7 +62,7 @@ class GradientChecker(Model):
|
||||||
grad.randomize()
|
grad.randomize()
|
||||||
grad.checkgrad(verbose=1)
|
grad.checkgrad(verbose=1)
|
||||||
"""
|
"""
|
||||||
Model.__init__(self, 'GradientChecker')
|
super(GradientChecker, self).__init__(name='GradientChecker')
|
||||||
if isinstance(x0, (list, tuple)) and names is None:
|
if isinstance(x0, (list, tuple)) and names is None:
|
||||||
self.shapes = [get_shape(xi) for xi in x0]
|
self.shapes = [get_shape(xi) for xi in x0]
|
||||||
self.names = ['X{i}'.format(i=i) for i in range(len(x0))]
|
self.names = ['X{i}'.format(i=i) for i in range(len(x0))]
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,14 @@ import numpy as np
|
||||||
import itertools, logging
|
import itertools, logging
|
||||||
|
|
||||||
from ..kern import Kern
|
from ..kern import Kern
|
||||||
from ..core.parameterization.variational import NormalPosterior, NormalPrior
|
from GPy.core.parameterization.variational import NormalPrior
|
||||||
from ..core.parameterization import Param, Parameterized
|
from ..core.parameterization import Param
|
||||||
from ..core.parameterization.observable_array import ObsAr
|
from paramz import ObsAr
|
||||||
from ..inference.latent_function_inference.var_dtc import VarDTC
|
from ..inference.latent_function_inference.var_dtc import VarDTC
|
||||||
from ..inference.latent_function_inference import InferenceMethodList
|
from ..inference.latent_function_inference import InferenceMethodList
|
||||||
from ..likelihoods import Gaussian
|
from ..likelihoods import Gaussian
|
||||||
from ..util.initialization import initialize_latent
|
from ..util.initialization import initialize_latent
|
||||||
from ..core.sparse_gp import SparseGP, GP
|
|
||||||
from GPy.core.parameterization.variational import VariationalPosterior
|
|
||||||
from GPy.models.bayesian_gplvm_minibatch import BayesianGPLVMMiniBatch
|
from GPy.models.bayesian_gplvm_minibatch import BayesianGPLVMMiniBatch
|
||||||
from GPy.models.bayesian_gplvm import BayesianGPLVM
|
|
||||||
from GPy.models.sparse_gp_minibatch import SparseGPMiniBatch
|
|
||||||
|
|
||||||
class MRD(BayesianGPLVMMiniBatch):
|
class MRD(BayesianGPLVMMiniBatch):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
# Copyright (c) 2013, the GPy Authors (see AUTHORS.txt)
|
# Copyright (c) 2013, the GPy Authors (see AUTHORS.txt)
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
from ..core import GP
|
|
||||||
from . import SparseGPClassification
|
from . import SparseGPClassification
|
||||||
from .. import likelihoods
|
from .. import likelihoods
|
||||||
from .. import kern
|
from .. import kern
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ class SparseGPClassificationUncertainInput(SparseGP):
|
||||||
.. Note:: Multiple independent outputs are allowed using columns of Y
|
.. Note:: Multiple independent outputs are allowed using columns of Y
|
||||||
"""
|
"""
|
||||||
def __init__(self, X, X_variance, Y, kernel=None, Z=None, num_inducing=10, Y_metadata=None, normalizer=None):
|
def __init__(self, X, X_variance, Y, kernel=None, Z=None, num_inducing=10, Y_metadata=None, normalizer=None):
|
||||||
from ..core.parameterization.variational import NormalPosterior
|
from GPy.core.parameterization.variational import NormalPosterior
|
||||||
if kernel is None:
|
if kernel is None:
|
||||||
kernel = kern.RBF(X.shape[1])
|
kernel = kern.RBF(X.shape[1])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ..core import SparseGP
|
from ..core import SparseGP
|
||||||
from ..inference.latent_function_inference import VarDTC
|
from ..inference.latent_function_inference import VarDTC
|
||||||
from .. import likelihoods
|
|
||||||
from .. import kern
|
from .. import kern
|
||||||
from .. import util
|
from .. import util
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,15 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ..core.parameterization.param import Param
|
from ..core.parameterization.param import Param
|
||||||
|
from GPy.core.parameterization.variational import VariationalPosterior
|
||||||
from ..core.sparse_gp import SparseGP
|
from ..core.sparse_gp import SparseGP
|
||||||
from ..core.gp import GP
|
from ..core.gp import GP
|
||||||
from ..inference.latent_function_inference import var_dtc
|
from ..inference.latent_function_inference import var_dtc
|
||||||
from .. import likelihoods
|
from .. import likelihoods
|
||||||
from ..core.parameterization.variational import VariationalPosterior
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from GPy.inference.latent_function_inference.posterior import Posterior
|
from ..inference.latent_function_inference.posterior import Posterior
|
||||||
from GPy.inference.optimization.stochastics import SparseGPStochastics,\
|
from ..inference.optimization.stochastics import SparseGPStochastics, SparseGPMissing
|
||||||
SparseGPMissing
|
|
||||||
#no stochastics.py file added! from GPy.inference.optimization.stochastics import SparseGPStochastics,\
|
|
||||||
#SparseGPMissing
|
|
||||||
logger = logging.getLogger("sparse gp")
|
logger = logging.getLogger("sparse gp")
|
||||||
|
|
||||||
class SparseGPMiniBatch(SparseGP):
|
class SparseGPMiniBatch(SparseGP):
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,11 @@
|
||||||
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ..core import SparseGP
|
|
||||||
from ..core.sparse_gp_mpi import SparseGP_MPI
|
from ..core.sparse_gp_mpi import SparseGP_MPI
|
||||||
from .. import likelihoods
|
from .. import likelihoods
|
||||||
from .. import kern
|
from .. import kern
|
||||||
from ..inference.latent_function_inference import VarDTC
|
from ..inference.latent_function_inference import VarDTC
|
||||||
from ..core.parameterization.variational import NormalPosterior
|
from GPy.core.parameterization.variational import NormalPosterior
|
||||||
|
|
||||||
class SparseGPRegression(SparseGP_MPI):
|
class SparseGPRegression(SparseGP_MPI):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@
|
||||||
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import sys
|
import sys
|
||||||
from GPy.models.sparse_gp_regression import SparseGPRegression
|
from .sparse_gp_regression import SparseGPRegression
|
||||||
|
|
||||||
class SparseGPLVM(SparseGPRegression):
|
class SparseGPLVM(SparseGPRegression):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from ..core.sparse_gp_mpi import SparseGP_MPI
|
||||||
from .. import kern
|
from .. import kern
|
||||||
from ..core.parameterization import Param
|
from ..core.parameterization import Param
|
||||||
from ..likelihoods import Gaussian
|
from ..likelihoods import Gaussian
|
||||||
from ..core.parameterization.variational import SpikeAndSlabPrior, SpikeAndSlabPosterior,VariationalPrior
|
from GPy.core.parameterization.variational import SpikeAndSlabPrior, SpikeAndSlabPosterior,VariationalPrior
|
||||||
from ..inference.latent_function_inference.var_dtc_parallel import update_gradients, VarDTC_minibatch
|
from ..inference.latent_function_inference.var_dtc_parallel import update_gradients, VarDTC_minibatch
|
||||||
from ..kern.src.psi_comp.ssrbf_psi_gpucomp import PSICOMP_SSRBF_GPU
|
from ..kern.src.psi_comp.ssrbf_psi_gpucomp import PSICOMP_SSRBF_GPU
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ class IBPPosterior(SpikeAndSlabPosterior):
|
||||||
"""
|
"""
|
||||||
binary_prob : the probability of the distribution on the slab part.
|
binary_prob : the probability of the distribution on the slab part.
|
||||||
"""
|
"""
|
||||||
from ..core.parameterization.transformations import Logexp
|
from paramz.transformations import Logexp
|
||||||
super(IBPPosterior, self).__init__(means, variances, binary_prob, group_spike=True, name=name)
|
super(IBPPosterior, self).__init__(means, variances, binary_prob, group_spike=True, name=name)
|
||||||
self.sharedX = sharedX
|
self.sharedX = sharedX
|
||||||
if sharedX:
|
if sharedX:
|
||||||
|
|
@ -60,7 +60,7 @@ class IBPPosterior(SpikeAndSlabPosterior):
|
||||||
class IBPPrior(VariationalPrior):
|
class IBPPrior(VariationalPrior):
|
||||||
def __init__(self, input_dim, alpha =2., name='IBPPrior', **kw):
|
def __init__(self, input_dim, alpha =2., name='IBPPrior', **kw):
|
||||||
super(IBPPrior, self).__init__(name=name, **kw)
|
super(IBPPrior, self).__init__(name=name, **kw)
|
||||||
from ..core.parameterization.transformations import Logexp, __fixed__
|
from paramz.transformations import Logexp, __fixed__
|
||||||
self.input_dim = input_dim
|
self.input_dim = input_dim
|
||||||
self.variance = 1.
|
self.variance = 1.
|
||||||
self.alpha = Param('alpha', alpha, __fixed__)
|
self.alpha = Param('alpha', alpha, __fixed__)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ The Maniforld Relevance Determination model with the spike-and-slab prior
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from ..core import Model
|
from ..core import Model
|
||||||
from .ss_gplvm import SSGPLVM
|
from .ss_gplvm import SSGPLVM
|
||||||
from ..core.parameterization.variational import SpikeAndSlabPrior,NormalPosterior,VariationalPrior
|
from GPy.core.parameterization.variational import SpikeAndSlabPrior,NormalPosterior,VariationalPrior
|
||||||
from ..util.misc import param_to_array
|
from ..util.misc import param_to_array
|
||||||
from ..kern import RBF
|
from ..kern import RBF
|
||||||
from ..core import Param
|
from ..core import Param
|
||||||
|
|
@ -214,7 +214,7 @@ class SpikeAndSlabPrior_SSMRD(SpikeAndSlabPrior):
|
||||||
class IBPPrior_SSMRD(VariationalPrior):
|
class IBPPrior_SSMRD(VariationalPrior):
|
||||||
def __init__(self, nModels, input_dim, alpha =2., tau=None, name='IBPPrior', **kw):
|
def __init__(self, nModels, input_dim, alpha =2., tau=None, name='IBPPrior', **kw):
|
||||||
super(IBPPrior_SSMRD, self).__init__(name=name, **kw)
|
super(IBPPrior_SSMRD, self).__init__(name=name, **kw)
|
||||||
from ..core.parameterization.transformations import Logexp, __fixed__
|
from paramz.transformations import Logexp, __fixed__
|
||||||
self.nModels = nModels
|
self.nModels = nModels
|
||||||
self._b_prob_all = 0.5
|
self._b_prob_all = 0.5
|
||||||
self.input_dim = input_dim
|
self.input_dim = input_dim
|
||||||
|
|
|
||||||
|
|
@ -337,7 +337,7 @@ def x_frame1D(X,plot_limits=None,resolution=None):
|
||||||
"""
|
"""
|
||||||
assert X.shape[1] ==1, "x_frame1D is defined for one-dimensional inputs"
|
assert X.shape[1] ==1, "x_frame1D is defined for one-dimensional inputs"
|
||||||
if plot_limits is None:
|
if plot_limits is None:
|
||||||
from ...core.parameterization.variational import VariationalPosterior
|
from GPy.core.parameterization.variational import VariationalPosterior
|
||||||
if isinstance(X, VariationalPosterior):
|
if isinstance(X, VariationalPosterior):
|
||||||
xmin,xmax = X.mean.min(0),X.mean.max(0)
|
xmin,xmax = X.mean.min(0),X.mean.max(0)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import time
|
import time
|
||||||
from ...core.parameterization.variational import VariationalPosterior
|
from ...core.parameterization.variational import VariationalPosterior
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib as mpl
|
import matplotlib as mpl
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
GPy/testing/baseline/coverage_gradient.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3 KiB |