From c307b989cca32b6da4e88c2abb19bb4f5200ef64 Mon Sep 17 00:00:00 2001 From: Mike Croucher Date: Sun, 15 Mar 2015 11:10:45 +0000 Subject: [PATCH 01/14] Bug fix for issue #161 --- GPy/testing/linalg_test.py | 12 +++++++++++- GPy/util/linalg.py | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/GPy/testing/linalg_test.py b/GPy/testing/linalg_test.py index b734f6af..3a65735c 100644 --- a/GPy/testing/linalg_test.py +++ b/GPy/testing/linalg_test.py @@ -1,6 +1,6 @@ import numpy as np import scipy as sp -from ..util.linalg import jitchol +from ..util.linalg import jitchol,trace_dot class LinalgTests(np.testing.TestCase): def setUp(self): @@ -33,3 +33,13 @@ class LinalgTests(np.testing.TestCase): return False except sp.linalg.LinAlgError: return True + + def test_trace_dot(self): + N = 5 + A = np.random.rand(N,N) + B = np.random.rand(N,N) + trace = np.trace(A.dot(B)) + test_trace = trace_dot(A,B) + np.testing.assert_allclose(trace,test_trace,atol=1e-13) + + diff --git a/GPy/util/linalg.py b/GPy/util/linalg.py index 2c02357c..66254685 100644 --- a/GPy/util/linalg.py +++ b/GPy/util/linalg.py @@ -191,7 +191,7 @@ def trace_dot(a, b): """ Efficiently compute the trace of the matrix product of a and b """ - return np.sum(a * b) + return np.einsum('ij,ji->', a, b) def mdot(*args): """ From 072c540f0c7b018af428a21e055cec13532a07d8 Mon Sep 17 00:00:00 2001 From: mellorjc Date: Thu, 30 Apr 2015 14:01:54 +0100 Subject: [PATCH 02/14] Added Exponential prior. Made some minor (and not exhaustive) formatting changes based on pep8. --- GPy/core/parameterization/priors.py | 111 +++++++++++++++++++++------- 1 file changed, 83 insertions(+), 28 deletions(-) diff --git a/GPy/core/parameterization/priors.py b/GPy/core/parameterization/priors.py index 84b6357e..4a346877 100644 --- a/GPy/core/parameterization/priors.py +++ b/GPy/core/parameterization/priors.py @@ -13,6 +13,7 @@ import weakref class Prior(object): domain = None _instance = None + def __new__(cls, *args, **kwargs): if not cls._instance or cls._instance.__class__ is not cls: cls._instance = super(Prior, cls).__new__(cls, *args, **kwargs) @@ -83,6 +84,7 @@ class Gaussian(Prior): # self.sigma2 = np.square(self.sigma) # self.constant = -0.5 * np.log(2 * np.pi * self.sigma2) + class Uniform(Prior): domain = _REAL _instances = [] @@ -121,6 +123,7 @@ class Uniform(Prior): # self.lower = state[0] # self.upper = state[1] + class LogGaussian(Gaussian): """ Implementation of the univariate *log*-Gaussian probability function, coupled with random variables. @@ -234,6 +237,7 @@ class MultivariateGaussian(Prior): self.inv, self.hld = pdinv(self.var) self.constant = -0.5 * self.input_dim * np.log(2 * np.pi) - self.hld + def gamma_from_EV(E, V): warnings.warn("use Gamma.from_EV to create Gamma Prior", FutureWarning) return Gamma.from_EV(E, V) @@ -311,6 +315,7 @@ class Gamma(Prior): self.b = state[1] self.constant = -gammaln(self.a) + self.a * np.log(self.b) + class InverseGamma(Gamma): """ Implementation of the inverse-Gamma probability function, coupled with random variables. @@ -323,7 +328,8 @@ class InverseGamma(Gamma): """ domain = _POSITIVE _instances = [] - def __new__(cls, a=1, b=.5): # Singleton: + + def __new__(cls, a=1, b=.5): # Singleton: if cls._instances: cls._instances[:] = [instance for instance in cls._instances if instance()] for instance in cls._instances: @@ -350,6 +356,7 @@ class InverseGamma(Gamma): def rvs(self, n): return 1. / np.random.gamma(scale=1. / self.b, shape=self.a, size=n) + class DGPLVM_KFDA(Prior): """ Implementation of the Discriminative Gaussian Process Latent Variable function using @@ -496,6 +503,7 @@ class DGPLVM_KFDA(Prior): self.A = self.compute_A(lst_ni) self.x_shape = x_shape + class DGPLVM(Prior): """ Implementation of the Discriminative Gaussian Process Latent Variable model paper, by Raquel. @@ -708,6 +716,7 @@ class DGPLVM(Prior): def __str__(self): return 'DGPLVM_prior' + class HalfT(Prior): """ Implementation of the half student t probability function, coupled with random variables. @@ -718,15 +727,17 @@ class HalfT(Prior): """ domain = _POSITIVE _instances = [] - def __new__(cls, A, nu): # Singleton: + + def __new__(cls, A, nu): # Singleton: if cls._instances: cls._instances[:] = [instance for instance in cls._instances if instance()] for instance in cls._instances: if instance().A == A and instance().nu == nu: - return instance() + return instance() o = super(Prior, cls).__new__(cls, A, nu) cls._instances.append(weakref.ref(o)) return cls._instances[-1]() + def __init__(self, A, nu): self.A = float(A) self.nu = float(nu) @@ -735,37 +746,81 @@ class HalfT(Prior): def __str__(self): return "hT({:.2g}, {:.2g})".format(self.A, self.nu) - def lnpdf(self,theta): - return (theta>0) * ( self.constant -.5*(self.nu+1) * np.log( 1.+ (1./self.nu) * (theta/self.A)**2 ) ) + def lnpdf(self, theta): + return (theta > 0) * (self.constant - .5*(self.nu + 1) * np.log(1. + (1./self.nu) * (theta/self.A)**2)) - #theta = theta if isinstance(theta,np.ndarray) else np.array([theta]) - #lnpdfs = np.zeros_like(theta) - #theta = np.array([theta]) - #above_zero = theta.flatten()>1e-6 - #v = self.nu - #sigma2=self.A - #stop - #lnpdfs[above_zero] = (+ gammaln((v + 1) * 0.5) - # - gammaln(v * 0.5) - # - 0.5*np.log(sigma2 * v * np.pi) - # - 0.5*(v + 1)*np.log(1 + (1/np.float(v))*((theta[above_zero][0]**2)/sigma2)) - #) - #return lnpdfs + # theta = theta if isinstance(theta,np.ndarray) else np.array([theta]) + # lnpdfs = np.zeros_like(theta) + # theta = np.array([theta]) + # above_zero = theta.flatten()>1e-6 + # v = self.nu + # sigma2=self.A + # stop + # lnpdfs[above_zero] = (+ gammaln((v + 1) * 0.5) + # - gammaln(v * 0.5) + # - 0.5*np.log(sigma2 * v * np.pi) + # - 0.5*(v + 1)*np.log(1 + (1/np.float(v))*((theta[above_zero][0]**2)/sigma2)) + # ) + # return lnpdfs - def lnpdf_grad(self,theta): - theta = theta if isinstance(theta,np.ndarray) else np.array([theta]) + def lnpdf_grad(self, theta): + theta = theta if isinstance(theta, np.ndarray) else np.array([theta]) grad = np.zeros_like(theta) - above_zero = theta>1e-6 + above_zero = theta > 1e-6 v = self.nu - sigma2=self.A + sigma2 = self.A grad[above_zero] = -0.5*(v+1)*(2*theta[above_zero])/(v*sigma2 + theta[above_zero][0]**2) return grad def rvs(self, n): - #return np.random.randn(n) * self.sigma + self.mu - from scipy.stats import t - #[np.abs(x) for x in t.rvs(df=4,loc=0,scale=50, size=10000)]) - ret = t.rvs(self.nu,loc=0,scale=self.A, size=n) - ret[ret<0] = 0 - return ret + # return np.random.randn(n) * self.sigma + self.mu + from scipy.stats import t + # [np.abs(x) for x in t.rvs(df=4,loc=0,scale=50, size=10000)]) + ret = t.rvs(self.nu, loc=0, scale=self.A, size=n) + ret[ret < 0] = 0 + return ret + +class Exponential(Prior): + """ + Implementation of the Exponential probability function, + coupled with random variables. + + :param l: shape parameter + + """ + domain = _POSITIVE + _instances = [] + + def __new__(cls, l): # Singleton: + if cls._instances: + cls._instances[:] = [instance for instance in cls._instances if instance()] + for instance in cls._instances: + if instance().l == l: + return instance() + o = super(Exponential, cls).__new__(cls, l) + cls._instances.append(weakref.ref(o)) + return cls._instances[-1]() + + def __init__(self, l): + self.l = l + + def __str__(self): + return "Exp({:.2g})".format(self.l) + + def summary(self): + ret = {"E[x]": 1. / self.l, + "E[ln x]": np.nan, + "var[x]": 1. / self.l**2, + "Entropy": 1. - np.log(self.l), + "Mode": 0.} + return ret + + def lnpdf(self, x): + return np.log(self.l) - self.l * x + + def lnpdf_grad(self, x): + return - self.l + + def rvs(self, n): + return np.random.exponential(scale=self.l, size=n) From 3a150198e8ebe7065df495806e5f0773f8e3c842 Mon Sep 17 00:00:00 2001 From: Homer Strong Date: Sun, 19 Jul 2015 13:44:24 -0700 Subject: [PATCH 03/14] fix links in readme the ! is for adding images, but these are just links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5e98af85..403f4a46 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ The simplest way to install GPy is using pip. Ubuntu users can do: sudo apt-get install python-pip pip install gpy -On windows, we recommend the ![anaconda python distribution](http://continuum.io/downloads). We've also had luck with ![enthought](http://www.enthought.com). +On windows, we recommend the [anaconda python distribution](http://continuum.io/downloads). We've also had luck with [enthought](http://www.enthought.com). On a fresh install of windows 8.1, we downloaded the Anaconda python distribution, started the anaconda command prompt and typed @@ -56,7 +56,7 @@ clone this git repository and add it to your path: ### OSX -Everything appears to work out-of-the box using ![enthought](http://www.enthought.com) on osx Mavericks. Download/clone GPy, and then add GPy to your PYTHONPATH +Everything appears to work out-of-the box using [enthought](http://www.enthought.com) on osx Mavericks. Download/clone GPy, and then add GPy to your PYTHONPATH git clone git@github.com:SheffieldML/GPy.git ~/SheffieldML echo 'PYTHONPATH=$PYTHONPATH:~/SheffieldML' >> ~/.profile From 1d7712ecc8ef477815967f2140d6c6d2b513d1b5 Mon Sep 17 00:00:00 2001 From: Homer Strong Date: Sun, 19 Jul 2015 14:30:27 -0700 Subject: [PATCH 04/14] update kernel tutorial --- doc/_build/doctrees/GPy.core.doctree | Bin 0 -> 217818 bytes .../GPy.core.parameterization.doctree | Bin 0 -> 890339 bytes doc/_build/doctrees/GPy.doctree | Bin 0 -> 9037 bytes doc/_build/doctrees/GPy.examples.doctree | Bin 0 -> 127661 bytes doc/_build/doctrees/GPy.inference.doctree | Bin 0 -> 3789 bytes ...nference.latent_function_inference.doctree | Bin 0 -> 176597 bytes .../doctrees/GPy.inference.mcmc.doctree | Bin 0 -> 27924 bytes .../GPy.inference.optimization.doctree | Bin 0 -> 114951 bytes doc/_build/doctrees/GPy.kern._src.doctree | Bin 0 -> 781079 bytes .../doctrees/GPy.kern._src.psi_comp.doctree | Bin 0 -> 62100 bytes doc/_build/doctrees/GPy.kern.doctree | Bin 0 -> 3636 bytes doc/_build/doctrees/GPy.likelihoods.doctree | Bin 0 -> 512444 bytes doc/_build/doctrees/GPy.mappings.doctree | Bin 0 -> 54654 bytes doc/_build/doctrees/GPy.models.doctree | Bin 0 -> 305145 bytes doc/_build/doctrees/GPy.plotting.doctree | Bin 0 -> 3691 bytes .../doctrees/GPy.plotting.matplot_dep.doctree | Bin 0 -> 324363 bytes ...t_space_visualizations.controllers.doctree | Bin 0 -> 58650 bytes ...ot_dep.latent_space_visualizations.doctree | Bin 0 -> 4171 bytes doc/_build/doctrees/GPy.testing.doctree | Bin 0 -> 397517 bytes doc/_build/doctrees/GPy.util.doctree | Bin 0 -> 701457 bytes doc/_build/doctrees/environment.pickle | Bin 0 -> 1879784 bytes doc/_build/doctrees/index.doctree | Bin 0 -> 10195 bytes doc/_build/doctrees/installation.doctree | Bin 0 -> 10172 bytes .../doctrees/kernel_implementation.doctree | Bin 0 -> 47289 bytes doc/_build/doctrees/modules.doctree | Bin 0 -> 2705 bytes .../doctrees/tuto_GP_regression.doctree | Bin 0 -> 24548 bytes .../tuto_creating_new_kernels.doctree | Bin 0 -> 39580 bytes .../doctrees/tuto_creating_new_models.doctree | Bin 0 -> 21287 bytes .../tuto_interacting_with_models.doctree | Bin 0 -> 63473 bytes .../doctrees/tuto_kernel_overview.doctree | Bin 0 -> 38768 bytes .../doctrees/tuto_parameterized.doctree | Bin 0 -> 11754 bytes doc/_build/html/.buildinfo | 4 + doc/_build/html/GPy.core.html | 889 ++ .../html/GPy.core.parameterization.html | 2528 ++++ doc/_build/html/GPy.examples.html | 464 + doc/_build/html/GPy.html | 439 + doc/_build/html/GPy.inference.html | 174 + ...y.inference.latent_function_inference.html | 651 + doc/_build/html/GPy.inference.mcmc.html | 221 + .../html/GPy.inference.optimization.html | 456 + doc/_build/html/GPy.kern._src.html | 2052 +++ doc/_build/html/GPy.kern._src.psi_comp.html | 305 + doc/_build/html/GPy.kern.html | 181 + doc/_build/html/GPy.likelihoods.html | 2134 ++++ doc/_build/html/GPy.mappings.html | 323 + doc/_build/html/GPy.models.html | 1048 ++ doc/_build/html/GPy.plotting.html | 181 + doc/_build/html/GPy.plotting.matplot_dep.html | 1098 ++ ...tent_space_visualizations.controllers.html | 260 + ...tplot_dep.latent_space_visualizations.html | 151 + doc/_build/html/GPy.testing.html | 1282 ++ doc/_build/html/GPy.util.html | 2085 ++++ ...aad80690e06cd5a29e87d6e696222f9b3a2f39.png | Bin 0 -> 534 bytes ...03b7b9ecad878eac8336d77abfce94453f7943.png | Bin 0 -> 1073 bytes ...e9a0a290af1db274c2ea2ef1cae298bc701ce4.png | Bin 0 -> 1610 bytes ...2c6d94605f31bddb3f52529408cf14d2a03456.png | Bin 0 -> 2324 bytes ...3f49a801c035369b4e0e7ca765346063e4686d.png | Bin 0 -> 981 bytes ...3e15220d6bec90ed9f8e0c870c3c808eae75aa.png | Bin 0 -> 1035 bytes ...2b408025f9da95787112c13a2e7401032a0063.png | Bin 0 -> 510 bytes ...e9c98e88e9896c1f62c6486c77b6a83231ccbc.png | Bin 0 -> 418 bytes ...bfcdadd1abee6b044daaa51d5a195606ee453c.png | Bin 0 -> 467 bytes ...20c5bbd4ca1928f464fd3873b10a9b0bde8c18.png | Bin 0 -> 639 bytes ...038e5468fa3f743e11b649cd49e30d4bf2d9aa.png | Bin 0 -> 245 bytes ...d17fb3a403d131bb3eef5cfb5c32587282b0d5.png | Bin 0 -> 1107 bytes ...84fd9b4b48bc7212f5b97e2ffabbc4060cb544.png | Bin 0 -> 785 bytes ...b07cfe9d64b0e6d96edc415ebaaf936b5820ca.png | Bin 0 -> 595 bytes ...ad6994800a13c9387535b07ae468a4784b120d.png | Bin 0 -> 878 bytes ...68be8ed48ce0799d2da0027b48dfc94dade8d3.png | Bin 0 -> 2146 bytes ...943d4fc1aea61edc8246a049f058483725f902.png | Bin 0 -> 769 bytes ...ccf5d08b634e400733f5568da0e3d0c64383ac.png | Bin 0 -> 1303 bytes ...69809108e9e054f33c34a3a488f6f65caf7c59.png | Bin 0 -> 1124 bytes ...ecdfc10af100dfbbc3ec3b19efda0433ba1580.png | Bin 0 -> 1564 bytes ...23a5c5edaef294453f24e767d1772c0bc233ca.png | Bin 0 -> 328 bytes ...7f2299194c0bf019dd646a9e9c76092e57d919.png | Bin 0 -> 626 bytes ...33f6b5623760a1facf22800afd4214b73538b0.png | Bin 0 -> 1790 bytes ...19c5c53c58678e9292c8e646b72103694e99f2.png | Bin 0 -> 507 bytes ...7d40be0b140d6249e2761f424632441eb1f475.png | Bin 0 -> 2110 bytes ...d3f22296f0a10cf5a10a200669957cf04dc550.png | Bin 0 -> 1410 bytes ...8a60521b12d9341a7d63d315e8c4d6d4944769.png | Bin 0 -> 824 bytes ...bab675639838c2c3f11f9ad372ec258a842318.png | Bin 0 -> 1224 bytes ...8c8b33737f7c90395256d7c1efbfc68f346ce8.png | Bin 0 -> 339 bytes ...f8e051e69685f0bad7e87ab3d5a189b1c713b6.png | Bin 0 -> 1549 bytes ...21f26082a79756b532348fdc05c458a1b4d96c.png | Bin 0 -> 1194 bytes ...17c31c81502afdd1553e394d07efd32af07f80.png | Bin 0 -> 439 bytes ...7004dd45c58bd71e97c825ae1e74559b30bfbd.png | Bin 0 -> 298 bytes ...b1ead7a3ae880faf3e493e050ee55a0e435038.png | Bin 0 -> 987 bytes ...4066808935cbbebeeb48a5590ae334a9511f26.png | Bin 0 -> 1202 bytes ...987fe37668cce0640009518e7aa9451c370b03.png | Bin 0 -> 1500 bytes ...acd55b473d8ea01ea4c1533bb6b4d9b652423a.png | Bin 0 -> 2319 bytes ...e9ec52652f5885327c00676d9a4a1c4d4f7f47.png | Bin 0 -> 2640 bytes ...a3ca8b772a75e4d54fe3e40f9e567f00b66f2f.png | Bin 0 -> 788 bytes ...a2d79b5ad6f38311ea4b1bc63bdbc4b67df02b.png | Bin 0 -> 845 bytes ...a7f1a9ea162f83dbb18eb5eeada4da9ec1805d.png | Bin 0 -> 1077 bytes ...92b5aded6d4eb0dd8b17739862bf1d347d3ea3.png | Bin 0 -> 1244 bytes ...73988fc18d98dd1fa609563743c060408c44d5.png | Bin 0 -> 1143 bytes ...c94abc177c437d0c0be762987594d986bcf711.png | Bin 0 -> 1026 bytes ...ccd2a09fe1d38b26319c571d7072d31e08bce3.png | Bin 0 -> 1483 bytes ...5e11e817ec90bc434b37341dd7c56d71ae492e.png | Bin 0 -> 1930 bytes ...f08794d1aed52b66ce2b784d263d3e7376acf0.png | Bin 0 -> 1658 bytes ...9b78bdb36f2fbd5ca087212e58fc74dde40e86.png | Bin 0 -> 248 bytes ...f82c540112d04a12bed95744925acfebcedf6e.png | Bin 0 -> 289 bytes ...2f92da6db61fb4e16c0060582e4cab04c5cb60.png | Bin 0 -> 251 bytes ...6d46125c08b336c780001fd9b6cfa2ecd6f6d6.png | Bin 0 -> 363 bytes ...b292d863fb6fc858ea26b35516ef78fc853543.png | Bin 0 -> 367 bytes ...8550a4d7fbf593ce9180499b72adbf17b50d99.png | Bin 0 -> 1218 bytes ...e371af90a73ea4ad53551cb110df130bfd0990.png | Bin 0 -> 989 bytes ...c29bfedc993de115781b4fbb7e3a8b9e8d6b51.png | Bin 0 -> 262 bytes ...d57b731d01eff6d0e66b973f5d2768e5347a4a.png | Bin 0 -> 645 bytes ...8e0e11a8d6647b1763eb35ad4aa6c01478b0a9.png | Bin 0 -> 1653 bytes ...a5b90f5f53332b472e7f022af254db7c92c86c.png | Bin 0 -> 713 bytes ...f67d8f787d95df1e400b2a998bc16206095c72.png | Bin 0 -> 613 bytes ...1d2cde832e2fe0f2df87be7c62ffc60a456418.png | Bin 0 -> 1332 bytes ...9a66c531afd1167c497e377131e38dba8e0dfd.png | Bin 0 -> 333 bytes ...ab03f1f7e4f60328e1b8d96389e2d5a31e6e24.png | Bin 0 -> 261 bytes ...3bd00b8434112f53b49d89e8e598ca33f5cc34.png | Bin 0 -> 1970 bytes ...9f0580cb8ea29c74c8e96c3d9d7d4d77ba3e46.png | Bin 0 -> 1013 bytes ...b7f8aa812a6bafd2d1c4423555e766bce85146.png | Bin 0 -> 1492 bytes ...e71d9f26a15da7a8f28a7b3a66fd7f477b5df7.png | Bin 0 -> 1230 bytes ...f3fa8d6aec4217077dd92bd58d218dcc0dc663.png | Bin 0 -> 1221 bytes ...06edea521a130e1064a48a5147e4930dc8b55c.png | Bin 0 -> 363 bytes ...71e3f640198fb9b743e2e405aad0dfcd645984.png | Bin 0 -> 1142 bytes ...5a7991cbb1a7fc99730d8856ca842ee8171eae.png | Bin 0 -> 1931 bytes ...164be40b826a2f164f45571034ed55764d3b7e.png | Bin 0 -> 1636 bytes ...4a71659d7a772231846371a575382ab5ecb4dc.png | Bin 0 -> 931 bytes ...82b5b606a2c3060394219159d4b17ff4611044.png | Bin 0 -> 300 bytes ...550fb5636af16f487a8b9739f9abe82dbf07b8.png | Bin 0 -> 346 bytes ...a5452e08d6d9f15b2b63894d4554bfeb9d951d.png | Bin 0 -> 416 bytes ...6f1c279ce0c199db52748ba5f2feb62a46363b.png | Bin 0 -> 1560 bytes ...5e31c763326e79ede203940e047624c0428f2c.png | Bin 0 -> 1716 bytes ...91af7e39e0ff3708b97ef66c7e246a93aee52e.png | Bin 0 -> 2324 bytes ...1c19e81a73403c46fc57af8f02014851713dbe.png | Bin 0 -> 2302 bytes ...6e77999bb2b0a71f5089b6a48aabd729045633.png | Bin 0 -> 1062 bytes ...7edbe203d60c70e432522604959c63318ca2c4.png | Bin 0 -> 1638 bytes ...0d5f1b33598371cd2960cbd61cdc79f720732f.png | Bin 0 -> 567 bytes ...9f908da0039cda866af0e06264a6fad9dbed48.png | Bin 0 -> 2144 bytes ...6e06331b1ae3c96e126c035b09ee277f6fc50d.png | Bin 0 -> 1604 bytes ...a932e370ada3f336aca285ab12d4b239473624.png | Bin 0 -> 1234 bytes ...939fafeac3df2cd993cd6d46762f5c9e184253.png | Bin 0 -> 1479 bytes doc/_build/html/_images/tick.png | Bin 0 -> 175 bytes .../html/_images/tuto_GP_regression_m1.png | Bin 0 -> 32641 bytes .../html/_images/tuto_GP_regression_m2.png | Bin 0 -> 51925 bytes .../html/_images/tuto_GP_regression_m3.png | Bin 0 -> 78550 bytes .../_images/tuto_kern_overview_allkern.png | Bin 0 -> 132224 bytes .../_images/tuto_kern_overview_basicplot.png | Bin 0 -> 38628 bytes .../_images/tuto_kern_overview_mANOVA.png | Bin 0 -> 77246 bytes .../_images/tuto_kern_overview_mANOVAdec.png | Bin 0 -> 132944 bytes .../_images/tuto_kern_overview_multadd.png | Bin 0 -> 63026 bytes .../tuto_kern_overview_multperdecay.png | Bin 0 -> 40904 bytes doc/_build/html/_modules/GPy.html | 141 + doc/_build/html/_modules/GPy/core/gp.html | 553 + .../html/_modules/GPy/core/mapping.html | 238 + doc/_build/html/_modules/GPy/core/model.html | 509 + .../parameterization/index_operations.html | 395 + .../parameterization/lists_and_dicts.html | 233 + .../parameterization/observable_array.html | 241 + .../GPy/core/parameterization/param.html | 570 + .../core/parameterization/parameter_core.html | 1130 ++ .../core/parameterization/parameterized.html | 510 + .../GPy/core/parameterization/priors.html | 864 ++ .../parameterization/ties_and_remappings.html | 314 + .../parameterization/transformations.html | 525 + .../core/parameterization/variational.html | 314 + .../html/_modules/GPy/core/sparse_gp.html | 226 + .../html/_modules/GPy/core/sparse_gp_mpi.html | 213 + .../_modules/GPy/examples/classification.html | 322 + .../examples/dimensionality_reduction.html | 762 ++ .../_modules/GPy/examples/non_gaussian.html | 389 + .../_modules/GPy/examples/regression.html | 601 + .../inference/latent_function_inference.html | 192 + .../latent_function_inference/dtc.html | 256 + .../exact_gaussian_inference.html | 155 + .../expectation_propagation.html | 218 + .../expectation_propagation_dtc.html | 447 + .../latent_function_inference/fitc.html | 183 + .../latent_function_inference/inferenceX.html | 257 + .../latent_function_inference/laplace.html | 346 + .../latent_function_inference/posterior.html | 282 + .../latent_function_inference/var_dtc.html | 345 + .../var_dtc_parallel.html | 575 + .../html/_modules/GPy/inference/mcmc/hmc.html | 267 + .../_modules/GPy/inference/mcmc/samplers.html | 175 + .../conjugate_gradient_descent.html | 378 + .../gradient_descent_update_rules.html | 145 + .../inference/optimization/optimization.html | 335 + .../GPy/inference/optimization/scg.html | 285 + .../inference/optimization/stochastics.html | 150 + .../html/_modules/GPy/kern/_src/ODE_UY.html | 375 + .../html/_modules/GPy/kern/_src/ODE_UYC.html | 383 + .../html/_modules/GPy/kern/_src/ODE_st.html | 360 + .../html/_modules/GPy/kern/_src/ODE_t.html | 259 + .../html/_modules/GPy/kern/_src/add.html | 282 + .../html/_modules/GPy/kern/_src/brownian.html | 141 + .../_modules/GPy/kern/_src/coregionalize.html | 267 + .../GPy/kern/_src/independent_outputs.html | 294 + .../html/_modules/GPy/kern/_src/kern.html | 374 + .../kern/_src/kernel_slice_operations.html | 237 + .../html/_modules/GPy/kern/_src/linear.html | 269 + .../html/_modules/GPy/kern/_src/mlp.html | 223 + .../html/_modules/GPy/kern/_src/periodic.html | 498 + .../html/_modules/GPy/kern/_src/poly.html | 135 + .../html/_modules/GPy/kern/_src/prod.html | 160 + .../html/_modules/GPy/kern/_src/psi_comp.html | 149 + .../kern/_src/psi_comp/linear_psi_comp.html | 173 + .../GPy/kern/_src/psi_comp/rbf_psi_comp.html | 257 + .../kern/_src/psi_comp/rbf_psi_gpucomp.html | 506 + .../kern/_src/psi_comp/sslinear_psi_comp.html | 188 + .../kern/_src/psi_comp/ssrbf_psi_comp.html | 490 + .../kern/_src/psi_comp/ssrbf_psi_gpucomp.html | 568 + .../html/_modules/GPy/kern/_src/rbf.html | 164 + .../_modules/GPy/kern/_src/splitKern.html | 297 + .../html/_modules/GPy/kern/_src/static.html | 215 + .../_modules/GPy/kern/_src/stationary.html | 576 + .../_modules/GPy/kern/_src/trunclinear.html | 296 + .../_modules/GPy/likelihoods/bernoulli.html | 318 + .../_modules/GPy/likelihoods/exponential.html | 234 + .../html/_modules/GPy/likelihoods/gamma.html | 239 + .../_modules/GPy/likelihoods/gaussian.html | 411 + .../_modules/GPy/likelihoods/likelihood.html | 567 + .../GPy/likelihoods/link_functions.html | 282 + .../_modules/GPy/likelihoods/mixed_noise.html | 176 + .../_modules/GPy/likelihoods/poisson.html | 251 + .../_modules/GPy/likelihoods/student_t.html | 373 + .../html/_modules/GPy/mappings/additive.html | 155 + .../html/_modules/GPy/mappings/kernel.html | 154 + .../html/_modules/GPy/mappings/linear.html | 137 + .../html/_modules/GPy/mappings/mlp.html | 224 + .../_modules/GPy/models/bayesian_gplvm.html | 328 + .../GPy/models/bayesian_gplvm_minibatch.html | 363 + .../html/_modules/GPy/models/bcgplvm.html | 141 + .../GPy/models/gp_classification.html | 123 + .../models/gp_coregionalized_regression.html | 138 + .../models/gp_heteroscedastic_regression.html | 135 + .../gp_kronecker_gaussian_regression.html | 213 + .../_modules/GPy/models/gp_regression.html | 129 + .../_modules/GPy/models/gp_var_gauss.html | 202 + .../html/_modules/GPy/models/gplvm.html | 177 + .../_modules/GPy/models/gradient_checker.html | 207 + doc/_build/html/_modules/GPy/models/mrd.html | 435 + .../GPy/models/sparse_gp_classification.html | 140 + .../sparse_gp_coregionalized_regression.html | 160 + .../GPy/models/sparse_gp_minibatch.html | 442 + .../GPy/models/sparse_gp_regression.html | 203 + .../_modules/GPy/models/sparse_gplvm.html | 137 + .../html/_modules/GPy/models/ss_gplvm.html | 201 + .../html/_modules/GPy/models/ss_mrd.html | 128 + .../html/_modules/GPy/models/warped_gp.html | 193 + .../GPy/plotting/matplot_dep/Tango.html | 260 + .../GPy/plotting/matplot_dep/base_plots.html | 251 + .../matplot_dep/dim_reduction_plots.html | 432 + .../GPy/plotting/matplot_dep/img_plots.html | 152 + .../plotting/matplot_dep/inference_plots.html | 125 + .../plotting/matplot_dep/kernel_plots.html | 265 + .../controllers/axis_event_controller.html | 241 + .../controllers/imshow_controller.html | 165 + .../plotting/matplot_dep/mapping_plots.html | 178 + .../GPy/plotting/matplot_dep/maps.html | 269 + .../plotting/matplot_dep/models_plots.html | 282 + .../GPy/plotting/matplot_dep/netpbmfile.html | 425 + .../plotting/matplot_dep/priors_plots.html | 126 + .../GPy/plotting/matplot_dep/ssgplvm.html | 122 + .../GPy/plotting/matplot_dep/svig_plots.html | 137 + .../matplot_dep/variational_plots.html | 194 + .../GPy/plotting/matplot_dep/visualize.html | 656 + doc/_build/html/_modules/GPy/testing.html | 108 + .../_modules/GPy/testing/examples_tests.html | 201 + .../html/_modules/GPy/testing/fitc.html | 129 + .../GPy/testing/index_operations_tests.html | 231 + .../_modules/GPy/testing/inference_tests.html | 180 + .../_modules/GPy/testing/kernel_tests.html | 525 + .../GPy/testing/likelihood_tests.html | 806 ++ .../_modules/GPy/testing/model_tests.html | 605 + .../GPy/testing/observable_tests.html | 228 + .../GPy/testing/parameterized_tests.html | 353 + .../_modules/GPy/testing/pickle_tests.html | 316 + .../_modules/GPy/testing/prior_tests.html | 210 + .../_modules/GPy/util/block_matrices.html | 120 + .../html/_modules/GPy/util/caching.html | 289 + .../_modules/GPy/util/classification.html | 127 + .../html/_modules/GPy/util/datasets.html | 1563 +++ doc/_build/html/_modules/GPy/util/debug.html | 129 + .../html/_modules/GPy/util/decorators.html | 112 + doc/_build/html/_modules/GPy/util/diag.html | 209 + doc/_build/html/_modules/GPy/util/erfcx.html | 156 + .../html/_modules/GPy/util/functions.html | 121 + .../html/_modules/GPy/util/gpu_init.html | 142 + .../_modules/GPy/util/initialization.html | 117 + doc/_build/html/_modules/GPy/util/linalg.html | 627 + .../html/_modules/GPy/util/ln_diff_erfs.html | 204 + doc/_build/html/_modules/GPy/util/misc.html | 192 + doc/_build/html/_modules/GPy/util/mocap.html | 796 ++ .../html/_modules/GPy/util/multioutput.html | 194 + .../html/_modules/GPy/util/netpbmfile.html | 425 + .../html/_modules/GPy/util/normalizer.html | 139 + .../html/_modules/GPy/util/parallel.html | 135 + doc/_build/html/_modules/GPy/util/pca.html | 235 + .../html/_modules/GPy/util/squashers.html | 110 + .../GPy/util/subarray_and_sorting.html | 156 + .../GPy/util/univariate_Gaussian.html | 180 + .../_modules/GPy/util/warping_functions.html | 376 + doc/_build/html/_modules/index.html | 242 + .../_modules/multiprocessing/synchronize.html | 436 + doc/_build/html/_modules/unittest/case.html | 1168 ++ .../_sources/GPy.core.parameterization.txt | 102 + doc/_build/html/_sources/GPy.core.txt | 77 + doc/_build/html/_sources/GPy.examples.txt | 70 + ...Py.inference.latent_function_inference.txt | 102 + .../html/_sources/GPy.inference.mcmc.txt | 30 + .../_sources/GPy.inference.optimization.txt | 62 + doc/_build/html/_sources/GPy.inference.txt | 19 + .../html/_sources/GPy.kern._src.psi_comp.txt | 62 + doc/_build/html/_sources/GPy.kern._src.txt | 197 + doc/_build/html/_sources/GPy.kern.txt | 17 + doc/_build/html/_sources/GPy.likelihoods.txt | 86 + doc/_build/html/_sources/GPy.mappings.txt | 46 + doc/_build/html/_sources/GPy.models.txt | 198 + ...atent_space_visualizations.controllers.txt | 30 + ...atplot_dep.latent_space_visualizations.txt | 17 + .../_sources/GPy.plotting.matplot_dep.txt | 141 + doc/_build/html/_sources/GPy.plotting.txt | 17 + doc/_build/html/_sources/GPy.testing.txt | 102 + doc/_build/html/_sources/GPy.txt | 26 + doc/_build/html/_sources/GPy.util.txt | 230 + doc/_build/html/_sources/index.txt | 38 + doc/_build/html/_sources/installation.txt | 31 + .../html/_sources/kernel_implementation.txt | 49 + doc/_build/html/_sources/modules.txt | 7 + .../html/_sources/tuto_GP_regression.txt | 142 + .../_sources/tuto_creating_new_kernels.txt | 212 + .../_sources/tuto_creating_new_models.txt | 100 + .../_sources/tuto_interacting_with_models.txt | 341 + .../html/_sources/tuto_kernel_overview.txt | 285 + .../html/_sources/tuto_parameterized.txt | 23 + doc/_build/html/_static/ajax-loader.gif | Bin 0 -> 673 bytes doc/_build/html/_static/basic.css | 599 + doc/_build/html/_static/classic.css | 261 + doc/_build/html/_static/comment-bright.png | Bin 0 -> 3500 bytes doc/_build/html/_static/comment-close.png | Bin 0 -> 3578 bytes doc/_build/html/_static/comment.png | Bin 0 -> 3445 bytes doc/_build/html/_static/default.css | 256 + doc/_build/html/_static/doctools.js | 263 + doc/_build/html/_static/down-pressed.png | Bin 0 -> 347 bytes doc/_build/html/_static/down.png | Bin 0 -> 347 bytes doc/_build/html/_static/file.png | Bin 0 -> 358 bytes doc/_build/html/_static/jquery-1.11.1.js | 10308 ++++++++++++++++ doc/_build/html/_static/jquery.js | 4 + doc/_build/html/_static/minus.png | Bin 0 -> 173 bytes doc/_build/html/_static/plus.png | Bin 0 -> 173 bytes doc/_build/html/_static/pygments.css | 63 + doc/_build/html/_static/searchtools.js | 622 + doc/_build/html/_static/sidebar.js | 159 + doc/_build/html/_static/underscore-1.3.1.js | 999 ++ doc/_build/html/_static/underscore.js | 31 + doc/_build/html/_static/up-pressed.png | Bin 0 -> 345 bytes doc/_build/html/_static/up.png | Bin 0 -> 345 bytes doc/_build/html/_static/websupport.js | 808 ++ doc/_build/html/genindex.html | 7636 ++++++++++++ doc/_build/html/index.html | 136 + doc/_build/html/installation.html | 135 + doc/_build/html/kernel_implementation.html | 341 + doc/_build/html/modules.html | 248 + doc/_build/html/objects.inv | Bin 0 -> 12223 bytes doc/_build/html/py-modindex.html | 959 ++ doc/_build/html/search.html | 105 + doc/_build/html/searchindex.js | 1 + doc/_build/html/tuto_GP_regression.html | 237 + .../html/tuto_creating_new_kernels.html | 258 + doc/_build/html/tuto_creating_new_models.html | 201 + .../html/tuto_interacting_with_models.html | 453 + doc/_build/html/tuto_kernel_overview.html | 315 + doc/_build/html/tuto_parameterized.html | 122 + doc/log.txt | 305 +- doc/tuto_kernel_overview.rst | 59 +- 372 files changed, 92313 insertions(+), 121 deletions(-) create mode 100644 doc/_build/doctrees/GPy.core.doctree create mode 100644 doc/_build/doctrees/GPy.core.parameterization.doctree create mode 100644 doc/_build/doctrees/GPy.doctree create mode 100644 doc/_build/doctrees/GPy.examples.doctree create mode 100644 doc/_build/doctrees/GPy.inference.doctree create mode 100644 doc/_build/doctrees/GPy.inference.latent_function_inference.doctree create mode 100644 doc/_build/doctrees/GPy.inference.mcmc.doctree create mode 100644 doc/_build/doctrees/GPy.inference.optimization.doctree create mode 100644 doc/_build/doctrees/GPy.kern._src.doctree create mode 100644 doc/_build/doctrees/GPy.kern._src.psi_comp.doctree create mode 100644 doc/_build/doctrees/GPy.kern.doctree create mode 100644 doc/_build/doctrees/GPy.likelihoods.doctree create mode 100644 doc/_build/doctrees/GPy.mappings.doctree create mode 100644 doc/_build/doctrees/GPy.models.doctree create mode 100644 doc/_build/doctrees/GPy.plotting.doctree create mode 100644 doc/_build/doctrees/GPy.plotting.matplot_dep.doctree create mode 100644 doc/_build/doctrees/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.doctree create mode 100644 doc/_build/doctrees/GPy.plotting.matplot_dep.latent_space_visualizations.doctree create mode 100644 doc/_build/doctrees/GPy.testing.doctree create mode 100644 doc/_build/doctrees/GPy.util.doctree create mode 100644 doc/_build/doctrees/environment.pickle create mode 100644 doc/_build/doctrees/index.doctree create mode 100644 doc/_build/doctrees/installation.doctree create mode 100644 doc/_build/doctrees/kernel_implementation.doctree create mode 100644 doc/_build/doctrees/modules.doctree create mode 100644 doc/_build/doctrees/tuto_GP_regression.doctree create mode 100644 doc/_build/doctrees/tuto_creating_new_kernels.doctree create mode 100644 doc/_build/doctrees/tuto_creating_new_models.doctree create mode 100644 doc/_build/doctrees/tuto_interacting_with_models.doctree create mode 100644 doc/_build/doctrees/tuto_kernel_overview.doctree create mode 100644 doc/_build/doctrees/tuto_parameterized.doctree create mode 100644 doc/_build/html/.buildinfo create mode 100644 doc/_build/html/GPy.core.html create mode 100644 doc/_build/html/GPy.core.parameterization.html create mode 100644 doc/_build/html/GPy.examples.html create mode 100644 doc/_build/html/GPy.html create mode 100644 doc/_build/html/GPy.inference.html create mode 100644 doc/_build/html/GPy.inference.latent_function_inference.html create mode 100644 doc/_build/html/GPy.inference.mcmc.html create mode 100644 doc/_build/html/GPy.inference.optimization.html create mode 100644 doc/_build/html/GPy.kern._src.html create mode 100644 doc/_build/html/GPy.kern._src.psi_comp.html create mode 100644 doc/_build/html/GPy.kern.html create mode 100644 doc/_build/html/GPy.likelihoods.html create mode 100644 doc/_build/html/GPy.mappings.html create mode 100644 doc/_build/html/GPy.models.html create mode 100644 doc/_build/html/GPy.plotting.html create mode 100644 doc/_build/html/GPy.plotting.matplot_dep.html create mode 100644 doc/_build/html/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.html create mode 100644 doc/_build/html/GPy.plotting.matplot_dep.latent_space_visualizations.html create mode 100644 doc/_build/html/GPy.testing.html create mode 100644 doc/_build/html/GPy.util.html create mode 100644 doc/_build/html/_images/math/07aad80690e06cd5a29e87d6e696222f9b3a2f39.png create mode 100644 doc/_build/html/_images/math/0b03b7b9ecad878eac8336d77abfce94453f7943.png create mode 100644 doc/_build/html/_images/math/0ee9a0a290af1db274c2ea2ef1cae298bc701ce4.png create mode 100644 doc/_build/html/_images/math/112c6d94605f31bddb3f52529408cf14d2a03456.png create mode 100644 doc/_build/html/_images/math/143f49a801c035369b4e0e7ca765346063e4686d.png create mode 100644 doc/_build/html/_images/math/153e15220d6bec90ed9f8e0c870c3c808eae75aa.png create mode 100644 doc/_build/html/_images/math/1e2b408025f9da95787112c13a2e7401032a0063.png create mode 100644 doc/_build/html/_images/math/1ee9c98e88e9896c1f62c6486c77b6a83231ccbc.png create mode 100644 doc/_build/html/_images/math/21bfcdadd1abee6b044daaa51d5a195606ee453c.png create mode 100644 doc/_build/html/_images/math/2520c5bbd4ca1928f464fd3873b10a9b0bde8c18.png create mode 100644 doc/_build/html/_images/math/26038e5468fa3f743e11b649cd49e30d4bf2d9aa.png create mode 100644 doc/_build/html/_images/math/26d17fb3a403d131bb3eef5cfb5c32587282b0d5.png create mode 100644 doc/_build/html/_images/math/2984fd9b4b48bc7212f5b97e2ffabbc4060cb544.png create mode 100644 doc/_build/html/_images/math/30b07cfe9d64b0e6d96edc415ebaaf936b5820ca.png create mode 100644 doc/_build/html/_images/math/36ad6994800a13c9387535b07ae468a4784b120d.png create mode 100644 doc/_build/html/_images/math/3a68be8ed48ce0799d2da0027b48dfc94dade8d3.png create mode 100644 doc/_build/html/_images/math/3c943d4fc1aea61edc8246a049f058483725f902.png create mode 100644 doc/_build/html/_images/math/3eccf5d08b634e400733f5568da0e3d0c64383ac.png create mode 100644 doc/_build/html/_images/math/4069809108e9e054f33c34a3a488f6f65caf7c59.png create mode 100644 doc/_build/html/_images/math/42ecdfc10af100dfbbc3ec3b19efda0433ba1580.png create mode 100644 doc/_build/html/_images/math/4323a5c5edaef294453f24e767d1772c0bc233ca.png create mode 100644 doc/_build/html/_images/math/437f2299194c0bf019dd646a9e9c76092e57d919.png create mode 100644 doc/_build/html/_images/math/4533f6b5623760a1facf22800afd4214b73538b0.png create mode 100644 doc/_build/html/_images/math/4b19c5c53c58678e9292c8e646b72103694e99f2.png create mode 100644 doc/_build/html/_images/math/4c7d40be0b140d6249e2761f424632441eb1f475.png create mode 100644 doc/_build/html/_images/math/4cd3f22296f0a10cf5a10a200669957cf04dc550.png create mode 100644 doc/_build/html/_images/math/4f8a60521b12d9341a7d63d315e8c4d6d4944769.png create mode 100644 doc/_build/html/_images/math/4fbab675639838c2c3f11f9ad372ec258a842318.png create mode 100644 doc/_build/html/_images/math/508c8b33737f7c90395256d7c1efbfc68f346ce8.png create mode 100644 doc/_build/html/_images/math/57f8e051e69685f0bad7e87ab3d5a189b1c713b6.png create mode 100644 doc/_build/html/_images/math/5821f26082a79756b532348fdc05c458a1b4d96c.png create mode 100644 doc/_build/html/_images/math/5a17c31c81502afdd1553e394d07efd32af07f80.png create mode 100644 doc/_build/html/_images/math/5d7004dd45c58bd71e97c825ae1e74559b30bfbd.png create mode 100644 doc/_build/html/_images/math/5fb1ead7a3ae880faf3e493e050ee55a0e435038.png create mode 100644 doc/_build/html/_images/math/604066808935cbbebeeb48a5590ae334a9511f26.png create mode 100644 doc/_build/html/_images/math/61987fe37668cce0640009518e7aa9451c370b03.png create mode 100644 doc/_build/html/_images/math/62acd55b473d8ea01ea4c1533bb6b4d9b652423a.png create mode 100644 doc/_build/html/_images/math/66e9ec52652f5885327c00676d9a4a1c4d4f7f47.png create mode 100644 doc/_build/html/_images/math/67a3ca8b772a75e4d54fe3e40f9e567f00b66f2f.png create mode 100644 doc/_build/html/_images/math/68a2d79b5ad6f38311ea4b1bc63bdbc4b67df02b.png create mode 100644 doc/_build/html/_images/math/68a7f1a9ea162f83dbb18eb5eeada4da9ec1805d.png create mode 100644 doc/_build/html/_images/math/6b92b5aded6d4eb0dd8b17739862bf1d347d3ea3.png create mode 100644 doc/_build/html/_images/math/7073988fc18d98dd1fa609563743c060408c44d5.png create mode 100644 doc/_build/html/_images/math/72c94abc177c437d0c0be762987594d986bcf711.png create mode 100644 doc/_build/html/_images/math/72ccd2a09fe1d38b26319c571d7072d31e08bce3.png create mode 100644 doc/_build/html/_images/math/775e11e817ec90bc434b37341dd7c56d71ae492e.png create mode 100644 doc/_build/html/_images/math/78f08794d1aed52b66ce2b784d263d3e7376acf0.png create mode 100644 doc/_build/html/_images/math/7a9b78bdb36f2fbd5ca087212e58fc74dde40e86.png create mode 100644 doc/_build/html/_images/math/7af82c540112d04a12bed95744925acfebcedf6e.png create mode 100644 doc/_build/html/_images/math/812f92da6db61fb4e16c0060582e4cab04c5cb60.png create mode 100644 doc/_build/html/_images/math/836d46125c08b336c780001fd9b6cfa2ecd6f6d6.png create mode 100644 doc/_build/html/_images/math/8fb292d863fb6fc858ea26b35516ef78fc853543.png create mode 100644 doc/_build/html/_images/math/908550a4d7fbf593ce9180499b72adbf17b50d99.png create mode 100644 doc/_build/html/_images/math/90e371af90a73ea4ad53551cb110df130bfd0990.png create mode 100644 doc/_build/html/_images/math/93c29bfedc993de115781b4fbb7e3a8b9e8d6b51.png create mode 100644 doc/_build/html/_images/math/93d57b731d01eff6d0e66b973f5d2768e5347a4a.png create mode 100644 doc/_build/html/_images/math/988e0e11a8d6647b1763eb35ad4aa6c01478b0a9.png create mode 100644 doc/_build/html/_images/math/98a5b90f5f53332b472e7f022af254db7c92c86c.png create mode 100644 doc/_build/html/_images/math/9af67d8f787d95df1e400b2a998bc16206095c72.png create mode 100644 doc/_build/html/_images/math/a51d2cde832e2fe0f2df87be7c62ffc60a456418.png create mode 100644 doc/_build/html/_images/math/a59a66c531afd1167c497e377131e38dba8e0dfd.png create mode 100644 doc/_build/html/_images/math/a8ab03f1f7e4f60328e1b8d96389e2d5a31e6e24.png create mode 100644 doc/_build/html/_images/math/ae3bd00b8434112f53b49d89e8e598ca33f5cc34.png create mode 100644 doc/_build/html/_images/math/ae9f0580cb8ea29c74c8e96c3d9d7d4d77ba3e46.png create mode 100644 doc/_build/html/_images/math/afb7f8aa812a6bafd2d1c4423555e766bce85146.png create mode 100644 doc/_build/html/_images/math/afe71d9f26a15da7a8f28a7b3a66fd7f477b5df7.png create mode 100644 doc/_build/html/_images/math/b0f3fa8d6aec4217077dd92bd58d218dcc0dc663.png create mode 100644 doc/_build/html/_images/math/b606edea521a130e1064a48a5147e4930dc8b55c.png create mode 100644 doc/_build/html/_images/math/b671e3f640198fb9b743e2e405aad0dfcd645984.png create mode 100644 doc/_build/html/_images/math/b75a7991cbb1a7fc99730d8856ca842ee8171eae.png create mode 100644 doc/_build/html/_images/math/b9164be40b826a2f164f45571034ed55764d3b7e.png create mode 100644 doc/_build/html/_images/math/c44a71659d7a772231846371a575382ab5ecb4dc.png create mode 100644 doc/_build/html/_images/math/c582b5b606a2c3060394219159d4b17ff4611044.png create mode 100644 doc/_build/html/_images/math/c6550fb5636af16f487a8b9739f9abe82dbf07b8.png create mode 100644 doc/_build/html/_images/math/cea5452e08d6d9f15b2b63894d4554bfeb9d951d.png create mode 100644 doc/_build/html/_images/math/d46f1c279ce0c199db52748ba5f2feb62a46363b.png create mode 100644 doc/_build/html/_images/math/d65e31c763326e79ede203940e047624c0428f2c.png create mode 100644 doc/_build/html/_images/math/d891af7e39e0ff3708b97ef66c7e246a93aee52e.png create mode 100644 doc/_build/html/_images/math/d91c19e81a73403c46fc57af8f02014851713dbe.png create mode 100644 doc/_build/html/_images/math/dd6e77999bb2b0a71f5089b6a48aabd729045633.png create mode 100644 doc/_build/html/_images/math/e67edbe203d60c70e432522604959c63318ca2c4.png create mode 100644 doc/_build/html/_images/math/e70d5f1b33598371cd2960cbd61cdc79f720732f.png create mode 100644 doc/_build/html/_images/math/ec9f908da0039cda866af0e06264a6fad9dbed48.png create mode 100644 doc/_build/html/_images/math/f66e06331b1ae3c96e126c035b09ee277f6fc50d.png create mode 100644 doc/_build/html/_images/math/f8a932e370ada3f336aca285ab12d4b239473624.png create mode 100644 doc/_build/html/_images/math/f9939fafeac3df2cd993cd6d46762f5c9e184253.png create mode 100644 doc/_build/html/_images/tick.png create mode 100644 doc/_build/html/_images/tuto_GP_regression_m1.png create mode 100644 doc/_build/html/_images/tuto_GP_regression_m2.png create mode 100644 doc/_build/html/_images/tuto_GP_regression_m3.png create mode 100644 doc/_build/html/_images/tuto_kern_overview_allkern.png create mode 100644 doc/_build/html/_images/tuto_kern_overview_basicplot.png create mode 100644 doc/_build/html/_images/tuto_kern_overview_mANOVA.png create mode 100644 doc/_build/html/_images/tuto_kern_overview_mANOVAdec.png create mode 100644 doc/_build/html/_images/tuto_kern_overview_multadd.png create mode 100644 doc/_build/html/_images/tuto_kern_overview_multperdecay.png create mode 100644 doc/_build/html/_modules/GPy.html create mode 100644 doc/_build/html/_modules/GPy/core/gp.html create mode 100644 doc/_build/html/_modules/GPy/core/mapping.html create mode 100644 doc/_build/html/_modules/GPy/core/model.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/index_operations.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/lists_and_dicts.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/observable_array.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/param.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/parameter_core.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/parameterized.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/priors.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/ties_and_remappings.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/transformations.html create mode 100644 doc/_build/html/_modules/GPy/core/parameterization/variational.html create mode 100644 doc/_build/html/_modules/GPy/core/sparse_gp.html create mode 100644 doc/_build/html/_modules/GPy/core/sparse_gp_mpi.html create mode 100644 doc/_build/html/_modules/GPy/examples/classification.html create mode 100644 doc/_build/html/_modules/GPy/examples/dimensionality_reduction.html create mode 100644 doc/_build/html/_modules/GPy/examples/non_gaussian.html create mode 100644 doc/_build/html/_modules/GPy/examples/regression.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/dtc.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/exact_gaussian_inference.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/expectation_propagation.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/expectation_propagation_dtc.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/fitc.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/inferenceX.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/laplace.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/posterior.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/var_dtc.html create mode 100644 doc/_build/html/_modules/GPy/inference/latent_function_inference/var_dtc_parallel.html create mode 100644 doc/_build/html/_modules/GPy/inference/mcmc/hmc.html create mode 100644 doc/_build/html/_modules/GPy/inference/mcmc/samplers.html create mode 100644 doc/_build/html/_modules/GPy/inference/optimization/conjugate_gradient_descent.html create mode 100644 doc/_build/html/_modules/GPy/inference/optimization/gradient_descent_update_rules.html create mode 100644 doc/_build/html/_modules/GPy/inference/optimization/optimization.html create mode 100644 doc/_build/html/_modules/GPy/inference/optimization/scg.html create mode 100644 doc/_build/html/_modules/GPy/inference/optimization/stochastics.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/ODE_UY.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/ODE_UYC.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/ODE_st.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/ODE_t.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/add.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/brownian.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/coregionalize.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/independent_outputs.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/kern.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/kernel_slice_operations.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/linear.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/mlp.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/periodic.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/poly.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/prod.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/psi_comp.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/psi_comp/linear_psi_comp.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/psi_comp/rbf_psi_comp.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/psi_comp/rbf_psi_gpucomp.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/psi_comp/sslinear_psi_comp.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/psi_comp/ssrbf_psi_comp.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/psi_comp/ssrbf_psi_gpucomp.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/rbf.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/splitKern.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/static.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/stationary.html create mode 100644 doc/_build/html/_modules/GPy/kern/_src/trunclinear.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/bernoulli.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/exponential.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/gamma.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/gaussian.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/likelihood.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/link_functions.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/mixed_noise.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/poisson.html create mode 100644 doc/_build/html/_modules/GPy/likelihoods/student_t.html create mode 100644 doc/_build/html/_modules/GPy/mappings/additive.html create mode 100644 doc/_build/html/_modules/GPy/mappings/kernel.html create mode 100644 doc/_build/html/_modules/GPy/mappings/linear.html create mode 100644 doc/_build/html/_modules/GPy/mappings/mlp.html create mode 100644 doc/_build/html/_modules/GPy/models/bayesian_gplvm.html create mode 100644 doc/_build/html/_modules/GPy/models/bayesian_gplvm_minibatch.html create mode 100644 doc/_build/html/_modules/GPy/models/bcgplvm.html create mode 100644 doc/_build/html/_modules/GPy/models/gp_classification.html create mode 100644 doc/_build/html/_modules/GPy/models/gp_coregionalized_regression.html create mode 100644 doc/_build/html/_modules/GPy/models/gp_heteroscedastic_regression.html create mode 100644 doc/_build/html/_modules/GPy/models/gp_kronecker_gaussian_regression.html create mode 100644 doc/_build/html/_modules/GPy/models/gp_regression.html create mode 100644 doc/_build/html/_modules/GPy/models/gp_var_gauss.html create mode 100644 doc/_build/html/_modules/GPy/models/gplvm.html create mode 100644 doc/_build/html/_modules/GPy/models/gradient_checker.html create mode 100644 doc/_build/html/_modules/GPy/models/mrd.html create mode 100644 doc/_build/html/_modules/GPy/models/sparse_gp_classification.html create mode 100644 doc/_build/html/_modules/GPy/models/sparse_gp_coregionalized_regression.html create mode 100644 doc/_build/html/_modules/GPy/models/sparse_gp_minibatch.html create mode 100644 doc/_build/html/_modules/GPy/models/sparse_gp_regression.html create mode 100644 doc/_build/html/_modules/GPy/models/sparse_gplvm.html create mode 100644 doc/_build/html/_modules/GPy/models/ss_gplvm.html create mode 100644 doc/_build/html/_modules/GPy/models/ss_mrd.html create mode 100644 doc/_build/html/_modules/GPy/models/warped_gp.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/Tango.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/base_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/dim_reduction_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/img_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/inference_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/kernel_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/latent_space_visualizations/controllers/axis_event_controller.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/latent_space_visualizations/controllers/imshow_controller.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/mapping_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/maps.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/models_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/netpbmfile.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/priors_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/ssgplvm.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/svig_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/variational_plots.html create mode 100644 doc/_build/html/_modules/GPy/plotting/matplot_dep/visualize.html create mode 100644 doc/_build/html/_modules/GPy/testing.html create mode 100644 doc/_build/html/_modules/GPy/testing/examples_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/fitc.html create mode 100644 doc/_build/html/_modules/GPy/testing/index_operations_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/inference_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/kernel_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/likelihood_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/model_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/observable_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/parameterized_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/pickle_tests.html create mode 100644 doc/_build/html/_modules/GPy/testing/prior_tests.html create mode 100644 doc/_build/html/_modules/GPy/util/block_matrices.html create mode 100644 doc/_build/html/_modules/GPy/util/caching.html create mode 100644 doc/_build/html/_modules/GPy/util/classification.html create mode 100644 doc/_build/html/_modules/GPy/util/datasets.html create mode 100644 doc/_build/html/_modules/GPy/util/debug.html create mode 100644 doc/_build/html/_modules/GPy/util/decorators.html create mode 100644 doc/_build/html/_modules/GPy/util/diag.html create mode 100644 doc/_build/html/_modules/GPy/util/erfcx.html create mode 100644 doc/_build/html/_modules/GPy/util/functions.html create mode 100644 doc/_build/html/_modules/GPy/util/gpu_init.html create mode 100644 doc/_build/html/_modules/GPy/util/initialization.html create mode 100644 doc/_build/html/_modules/GPy/util/linalg.html create mode 100644 doc/_build/html/_modules/GPy/util/ln_diff_erfs.html create mode 100644 doc/_build/html/_modules/GPy/util/misc.html create mode 100644 doc/_build/html/_modules/GPy/util/mocap.html create mode 100644 doc/_build/html/_modules/GPy/util/multioutput.html create mode 100644 doc/_build/html/_modules/GPy/util/netpbmfile.html create mode 100644 doc/_build/html/_modules/GPy/util/normalizer.html create mode 100644 doc/_build/html/_modules/GPy/util/parallel.html create mode 100644 doc/_build/html/_modules/GPy/util/pca.html create mode 100644 doc/_build/html/_modules/GPy/util/squashers.html create mode 100644 doc/_build/html/_modules/GPy/util/subarray_and_sorting.html create mode 100644 doc/_build/html/_modules/GPy/util/univariate_Gaussian.html create mode 100644 doc/_build/html/_modules/GPy/util/warping_functions.html create mode 100644 doc/_build/html/_modules/index.html create mode 100644 doc/_build/html/_modules/multiprocessing/synchronize.html create mode 100644 doc/_build/html/_modules/unittest/case.html create mode 100644 doc/_build/html/_sources/GPy.core.parameterization.txt create mode 100644 doc/_build/html/_sources/GPy.core.txt create mode 100644 doc/_build/html/_sources/GPy.examples.txt create mode 100644 doc/_build/html/_sources/GPy.inference.latent_function_inference.txt create mode 100644 doc/_build/html/_sources/GPy.inference.mcmc.txt create mode 100644 doc/_build/html/_sources/GPy.inference.optimization.txt create mode 100644 doc/_build/html/_sources/GPy.inference.txt create mode 100644 doc/_build/html/_sources/GPy.kern._src.psi_comp.txt create mode 100644 doc/_build/html/_sources/GPy.kern._src.txt create mode 100644 doc/_build/html/_sources/GPy.kern.txt create mode 100644 doc/_build/html/_sources/GPy.likelihoods.txt create mode 100644 doc/_build/html/_sources/GPy.mappings.txt create mode 100644 doc/_build/html/_sources/GPy.models.txt create mode 100644 doc/_build/html/_sources/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.txt create mode 100644 doc/_build/html/_sources/GPy.plotting.matplot_dep.latent_space_visualizations.txt create mode 100644 doc/_build/html/_sources/GPy.plotting.matplot_dep.txt create mode 100644 doc/_build/html/_sources/GPy.plotting.txt create mode 100644 doc/_build/html/_sources/GPy.testing.txt create mode 100644 doc/_build/html/_sources/GPy.txt create mode 100644 doc/_build/html/_sources/GPy.util.txt create mode 100644 doc/_build/html/_sources/index.txt create mode 100644 doc/_build/html/_sources/installation.txt create mode 100644 doc/_build/html/_sources/kernel_implementation.txt create mode 100644 doc/_build/html/_sources/modules.txt create mode 100644 doc/_build/html/_sources/tuto_GP_regression.txt create mode 100644 doc/_build/html/_sources/tuto_creating_new_kernels.txt create mode 100644 doc/_build/html/_sources/tuto_creating_new_models.txt create mode 100644 doc/_build/html/_sources/tuto_interacting_with_models.txt create mode 100644 doc/_build/html/_sources/tuto_kernel_overview.txt create mode 100644 doc/_build/html/_sources/tuto_parameterized.txt create mode 100644 doc/_build/html/_static/ajax-loader.gif create mode 100644 doc/_build/html/_static/basic.css create mode 100644 doc/_build/html/_static/classic.css create mode 100644 doc/_build/html/_static/comment-bright.png create mode 100644 doc/_build/html/_static/comment-close.png create mode 100644 doc/_build/html/_static/comment.png create mode 100644 doc/_build/html/_static/default.css create mode 100644 doc/_build/html/_static/doctools.js create mode 100644 doc/_build/html/_static/down-pressed.png create mode 100644 doc/_build/html/_static/down.png create mode 100644 doc/_build/html/_static/file.png create mode 100644 doc/_build/html/_static/jquery-1.11.1.js create mode 100644 doc/_build/html/_static/jquery.js create mode 100644 doc/_build/html/_static/minus.png create mode 100644 doc/_build/html/_static/plus.png create mode 100644 doc/_build/html/_static/pygments.css create mode 100644 doc/_build/html/_static/searchtools.js create mode 100644 doc/_build/html/_static/sidebar.js create mode 100644 doc/_build/html/_static/underscore-1.3.1.js create mode 100644 doc/_build/html/_static/underscore.js create mode 100644 doc/_build/html/_static/up-pressed.png create mode 100644 doc/_build/html/_static/up.png create mode 100644 doc/_build/html/_static/websupport.js create mode 100644 doc/_build/html/genindex.html create mode 100644 doc/_build/html/index.html create mode 100644 doc/_build/html/installation.html create mode 100644 doc/_build/html/kernel_implementation.html create mode 100644 doc/_build/html/modules.html create mode 100644 doc/_build/html/objects.inv create mode 100644 doc/_build/html/py-modindex.html create mode 100644 doc/_build/html/search.html create mode 100644 doc/_build/html/searchindex.js create mode 100644 doc/_build/html/tuto_GP_regression.html create mode 100644 doc/_build/html/tuto_creating_new_kernels.html create mode 100644 doc/_build/html/tuto_creating_new_models.html create mode 100644 doc/_build/html/tuto_interacting_with_models.html create mode 100644 doc/_build/html/tuto_kernel_overview.html create mode 100644 doc/_build/html/tuto_parameterized.html diff --git a/doc/_build/doctrees/GPy.core.doctree b/doc/_build/doctrees/GPy.core.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e9ed8678f31f3602225795a5bf459e05fd3ad695 GIT binary patch literal 217818 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.core.parameterization.doctree b/doc/_build/doctrees/GPy.core.parameterization.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e493b79a285163edd4307c098cf26bd7ac7bc3df GIT binary patch literal 890339 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�vN{Y;pVCJajhL(H!!>yTw~V{DoxlBSc&56MgX+& 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

RzMNRinzwzqKf1EdMdULAlASXma|hjwhvO^ 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�{=;?Hs_Fzw>d}R8kKY0OzzTC-P|J0 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�oHuR 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�WD=On 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 HRVV)&vrTlt literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.examples.doctree b/doc/_build/doctrees/GPy.examples.doctree new file mode 100644 index 0000000000000000000000000000000000000000..db46b57dd89c01121938830caa49a479b2512445 GIT binary patch literal 127661 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 z zlRb-w7%U?4x3?sJJ0y?75r2C};@WWDm7M(TJ(+vonrlU}T-k9#-trHL%gx0dV&Odb z0n^fFokB;M`4A#R^$`+$91ClIx};-772_q5?;e9A;3`Bc){ zNIrucNGc1P&mjSjFOcAYCz-L;OSe%VUrOgIt5coRel1~b9N$0=9DK|na(ZX}4FO<$ zi^MhG$%=(Rr%@Qo;T|^EERQwntU9M%LBiTFR)pMx5gE?RN)P}>A0&8rpR8CIbQ*=x zPdfdrPL!LnMFvPv8$uK0fDq-hDB zd1#Iek+^0fto`wVuGAcL==H`bxk;#`otwQGB%s%$q*2~wO7wa(apNR+GW0=mnS@F1b}~bfyFIpCGe!F?t)1wC zRk;@;EStQ`zE?Xj@@Q-wmfMx;D)C#!{XO8f=n^{+iN|kuRE>b&?!?R?_4(~o=;7Gd z8HsCl!8*!sTRbyM;kQ5#r&cAu-4)rE-%i7pYj)FqU4F~9#mL}=C4M_yB`ZdTfZy)U zB6axf4Co-zJ&@p+q?58b0hAKI)z#`b5|>9-g3<WmD?7G=={O3dT{>B-Q^`_Esd5t52I4>tAe9Vv9t42Vfdr2e$%=(Rr%@PP(#cz$ z>I}DA!rCwnhunh^Ww-_cz$hTWtM+8Y!l2VAj2`LCw>nX#%9>apL2U>NAqRvg!(D_- zxIY33UbQC+);*m?-5(_#*XqbjF!a*>(Gt{le+=ZF`=FdT7MXB=91=WqBMa6&odxbg zto8(Ho*2@!hh3P}o`^;zx7GJQ&58Zn(JOTEczIn4IqI<5vsCh@p^|n+ z_U4U%)t)Vl^3GCXwdX)CR(q}t{>&N-am?`zvD))!Chiaw=B}-nc&zq(S*!q1Vzn1g zIm~Js^LQbOp$0EP;+l))q{Z=IFcwsz{(M&Zb17b86+^5R{n>tw^iqjx(#gvtUfens zWD76xO-`NFD197G`gl2tSD}wrARCYT$hJKmEqx>^QO93O)Hrp#68fNyOv2RhDw!d5 zyc%10OPuywT4#r%iTo}R+!2^8F6z!q8P$>N%B0LF%OCyUbM!8imMIgKe#0PR1Xb*U zt7Y^Pxz|4C8hZAq;kAkw)bKiH4zEuQuZJEw*bPW?J{Wl9>M9L z5f!{c@;j~EQDku^3Q1J(E@{+;bT{OH6t1Sa?y1V;E%U{v~DAcKNGgJk^gNl+WY`;Y@dlzILGnQ;FB z64!hv3)VfI1@1%C?;~mcGo)z`yD;_pn9|0m-zQM@so$qE{aIidF?}vey-EEzw2}HT zZXV-bAoZ!=zp(9^FR>1&-&fjEBbcwLT1ovFCM|u#w2b=w8+mAsZ;{{!f2{p+g09pY zb*SHRctH^^17Pi!v@@(XPXyF&1!y| zeR{&1dc99YHTVPD)?`TiV5JH}>W^$(RFDhXZA;+9keVcFoFT0YeJ~^@VTLqNX2_5R zVaqjxwcnzTWt0UK9r*o6C!&M*e?pWPDu~iDe6k`Mm>EI<9$y-&_`#P}VdmEL`O+}x zper^~IRQyyFi&IHH-rzU%v z2suD)jRbE@lQCP-gb)R_t#l??oof7tcqU6+8_#x-15Y*fv^_+CG6f0VnkG9I3LQtG z>?oa`td7rx=zglQYP;VVa=7=|(=OPB%N8VfOPb1Bmvj(yxvO-hS)ED-MCZFnSljt@ z$l<(_J?#zwV9Y?`nmuI2!l2VAj6J0@)9OT75FzX(L2U?oLk5Q5+8BE}0IEKFYL)2&1Jj7Is|bId{Fnl`Ncae}VY9Cg@JS|u}~ zl6Knlri*|*&6P%ZXQ{%T+GQ{sGH3}(>v0&lm*Ec{-FVMi0k;C0IdhX+rjs4sr;Bp{ zhB;k4&JoC(JZ_%Ei(7Z{rkv^)8{~8wlGAm-Viiu;iEP(&$(=ozY?V14Sn;~N#EtX1 zZs>#8F$wd!!)1oN&S1+m1?{)!QD4rhHG+(s!G&)2Zj#5Iesj&immJTpsL*IH_qFh^3clD{2=Y|GzVY~jj<_UrODHWc`q z7n%6mF)CT}Xf(&NNFDxm9CQ%u@km^Af(+WuM{pQAJpOi~b3Dk#KPS3Daux^;r-gqMssh&DmJ{BQ%``6Q-ElInp`T>O|*VLim{k84&A8c+S0MH0>tA3S&y-*t%-2_HM~z^vqH5)Q%`j={YNloL^{^)2*+ae+e$j@%MdF&2f#&fU4jWeF#Lm!NXNtp56Co^O`_hZX74`{!obt7*M_kvm)!y#NS zoWpyiy&j}|itxGjm*hM)L^t&{zL}#5Ip%9c46+d1mZmrKKh|k5f>|V4gs> zWiWrl7QQm1{kjZ>6_2Cai$o0ONtLWPx`PXMPq9cH2JuMtTa?pFCZ5n{))skFUo`kLAMqJ8OuwOzZ{ZB z5s0z8B5`d5uS!nF@;8}#&6=yuSYEGcEbb5qr>8fVR%0x0LV$?=j>I)@VeQXRbgDTj zxN`Tlbl$N#QRYF$@~#Bs@suFE2RR@_8O!^~g!_LWam@#^U@Mf)0{0=t@}V?83TfJ^ z4KtR1QrZ|}`53A`WBEj;KMhPHrq5)lHyI0iFc}NuWlEbU>z`)FSVma zFkex%lCdyMTKbx48Dsedd1#J*BXP~QSo^(!uGAcL7|VAmx!kZ)Njsc+!$H7UmX}6( zXDKn36(AR5SrHqqS;-n)_S1hK;)pv83uBr$VTrNy6{Ly?N{po+i}nIz=?}kX!vRQK z(Hz^kr$BhLHw& z%V6@Bp)gW~x2%F}*9?<~2ygN5iMI@wxN+XHD)hlyn1p%D2$>;oSq)pRSzY@rt)n9I z593-Ibs=I}6fg%o0t2k+wGL zQC3M{V#u}xW_@hob3EFwOJLXnIM}^lL|`^l$%=zLATS%TNF4&RF?0~$CP-W}N(ODO zA~+qCA~2&RA7kZ?B8xjwNFp$sN~1QU%^(LPUQ>ux*5(iZ$5gPtu8a+q!6w4{?~O(%d5s?nT~DO?2dK7VP*^=0KL|1rBo%{GtsHM&g=7 zgtEo);$UrRmiVRJ?WM)dva1`a`aG-;kf2Tkf==A`;GsS|oQG`f(u zCXaQLCUtvemb7lrP-U9KS)h_T8Dv}TRKOM<8q$7U?!@-QAmc?S?$o1_6@yH`o#wMh z9qzOMItY3p5?rg3LEA?OPJ@BC(-D#%Y2}V0i#t(B;!a0Nqc$WLazJXZ29Jg|z#W6c zHOI=d1xGj*90}ENk{=(EN0Et8ogi^-WG6~aLUoeN{lJgtO-< zOf8{`lr^V9fQU{*;+oU3_NP!f)f5^KsxzeXL#tDr*DaQ?Jf;$iA3^THh@9M*Ga&$s zA0xqoLb75jmQJHE&XUegtxlAmu_n%zpf-eaAP0mfuR9l+aQ`zTt~pN@ta~~O+=qDG z`O>@~q-k3?%wwo?p&d1X`2|%gc^$)~rC%~F<8@ae56y8E64zXfwcjb}O3hJ+*ZoQ*uL+g3vx7HU z1-$NBX_R-C60f@sa`C$BW$*@TuyrcN+s0ppfY+_!-KxQ4hcB3uGc=oD(|Ft=R*a+G z+$*wnqx@9BDv`CDSSI~n!f`W9f=71by2bIpF>X}2{?PsLmz|c~6=Tw^(*CX0 zCJoC@&(6s1fw^ubkHXs|2t{C)ASW@hy?fEv%tHG%s%^ldtHj%o_*fx7mb_I5nJDE2duJ6KzYwpGx-J*3Q+G5(?i<*6_&4E>Z43buV z$AWQ(h&_lYLcB)?LJ;9N;_zM;NH^f%_fSLy-iHJq$&uL>$MZ_Ceg&%H9+1|9R;#k& z9+Du0$~?@R*5L@##xph?t$75}#1K!?mhUQNx{3w!2jpg0k&j{{yOt_)s$Y?h(V%Mb zacsHf3GKJ&e#|{pWw?^-8Tup3#~p$W*WI5~B!tqdyTHejEMRZ(EI0WSM5wK&k>Kkx zGSuRDeh5glr7zh3MJmr&6;XYQqxC>k#(#2wH3`0+D<+f8OZy;{c@_?R>i(RZ*QD;x zOT4&sL|G?{jkYZ^rdGR=oxgy>YMJG|meKLWLo9S4{Z$@9HEmu*PGa52fmA5w+wgtV zVy?|Ul3t>1c7T_$kzGx0w(vW^E6n4O^eQ&+#1PgzlGZH?qPb+&Ka^f$$vB1pi%`eW z>na{X==Fub-5V^FZp8eX&_vhxI}%)>lHC@^`gDjjIFRH%F}Sd(P|WaqqJ=^V-%5KM zDm=2^QOSK~C;D_`=4U!)tdLa$Ci)ie$=J3GMyXk|0Wz@?pZ1(FKCu#?{Y>;bVCt-y z(`QaI@6uDYGzq*%vuC2Z-p2-B3MT8M2XOU)cFKc~XLsg^^&t!5k>BOn&c%E>-!?fm zHAe$I#l(ew$sbJ=jJ;)@(XwqMrL7Krn`u@A;uP@3Ne$) z6*B3`P5T*qPIpeKZ63Q`p@?_!v|%KOwWT^bVjbujVoZG9RJZ&wGApGfV~ zkXmV=cl;jlnZ%9uh{?7`IOQGTb68PF_(DGa75GF)_|o&huC?!Mb~w%^afk5O7rtVe zZXNR<^o3wT`~T4uf^eJ6*Qhk~gl~}G%Sc%JJdh0#?g^R1;Itb0COAO2UST?}2A(oA>Y>Z_SETgcD#xe%WrdT%1 z9+ll3%UCSUSjJ)50?U?I#$(wkyMJ~9mWf!l#uQp4pTr{b!0>0DTi7$7r1i{S2prHOtW^TdsQFZmjI?*2)ti^)qr_BD$99me^ zIVazd^h*`Y0A$ZLO%$#YX%E?3S<-=&u3AMy9JR zhZb2MvYCm2W^Nk_6f(&k(_uD1USgeWvDjUhJZ@YupNH#QrZ~4bZ`#LYi=7?g%!X7M zfQqxzi`fYKrz8eqTE3k+d~*f(O@6Q z%_1|J+k-k%UF|)Xz)>)rF=Lpw0zSOCDK`e-Zo>=?)6QHb?KCpDW~WI%jrJ?ufRId}>}Y(+RqhOr_I&fir4+ zM+i?zj6|rN!EjLOM*JBa6}uCZPED+s>6&k*%9stjyO8NgBg)PWv$L{?W)|`#-{ABJ z0pBqxm|c`VjI~$jnN!Ra5vZ-g7TH|cP7X;PEG91H!8{&99eG#f4k>FfGY#2^K0U>` zW4ATCal6Sg#iMAtwWRalIdI_H3zu7O58(b2VkV>28!H5 zvnSPf#HHro8*k}i*33lCjQ)wi(N1diqGF%Ke!BwF-rVlz&wcw~FS|!#2u7PC=o^nm zRBX}ALjEa<0qq$Kh$*(!zQ~xF7_5F(s>S`3JFtK+_Z5?e_h6nZm;~}pO$=oB2?me- zk(Y@1gU5me3&0Qg)m#l8>CF6b&@PNK2T%=jKvyxfFqzG@XFKp;G(0l`1J8H0n*+JI zPPF>Uj=_VV;^^2I%rQ7ws;`4tc!gZr9KwykI2gk1J{y^*Cf2scJ-(NxaS8QW%qH8s zQQ%Oh;3)DML`O%#B#}8gv6>E*Tvq{Cd-(eCOc$FjZ4QIM|JB z=g@Y~oWzLodCU@zHWpegu_8%F8r!bPU=7mYT#Mf)K{v9Rn;ktiw6b$~e`F4HR>9Y@ zL@=Cv4AsAxcXE)S-l69E)tv(gYYk@rt*)sLwK-!Dq~pQpfGNCOO~x$@Rly8r z8`i|0j_o`Z?+0g7r=N*6%^>Y;Lw$6@yks%H@&AAE?eOTRs zb$AGt8e)cXt7<2JWkRqDgheBDVa1%|ac^pNeP>s;{|3%t#=4<>R%avUe)fjvLv>UX zn4SCR^gxnuV_cT)1{b*;cKJYun>1ML2GZXz6+;)0)bLR>+4r#glrEjeB9T7G=`v75f zoV_u43;Pc9EuC+eIo?^9u}pBzXRn*+e9Zbi(huY)1>%+h$u7Xp9;bzR+0mg8j=^^J z$h!EqwvWhflf5pxp3{z|%dYFZg>yok2H2n3CfUnaN5S28&Qy*A+dHoz+MdKPOln{` zI6>lIWO??nLU|m$?+Mz+By{{wL$vd;hj literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.inference.doctree b/doc/_build/doctrees/GPy.inference.doctree new file mode 100644 index 0000000000000000000000000000000000000000..42162daae4ae35a3d4820a59e31e35c1bcf89fe3 GIT binary patch literal 3789 zcmaJ^2YVb>6_sU6TCG)VxnSHPk{GW6X^j(bFocc+5m^H94NH>AFgx>h-{5I?-Wy8_ z48%Z;MDM-#7JBc!_uhN|6L8+_>`J@-foP*w9X z6p^m-mSg96H0P}~nv9%K=+#6h-j?%Nt+{7pWTcalakCW8w5{SSbp=m1sOkwfP91ZbXBsr;WIArgv5sObY^9x4^X$?VnlSi%Pw|eN zch=-M?E(0OKKO+m_&GU2vt8&5edxPng|=@7zB{9eEB(L&7~W&?-eC%ra1Ej=-wh1z z%lYnLFm;wo*!yXO#t|PP;RAA%#>@8)Hcx<|x{O0n{7UOC5>i(>jiZjNUvvFx9l0@o zH)vl>mF7b6|a2s-t!4w=xX^=X1VCjVfN2m~)CRwP?Z(9HsF8WfoOh zNMCB`zucm&hN&YK-&4*xG}b+T)MD`FWV9{tBf-a(Mq#W}3g1hPO7L*++AtBwY#^$9 zAJDLn^I}czFO)M7LSH#`c|h)y2jwAon8u2md|U$eeQWYkOI~Kl%Po1tl1Hsf!o4h= zo*4FdMyx=)SNtDGSKe`+@0aua0Y@6A3t7v_TGAxzWX@ONZ5r9YA}=u@9xwocPs!a5 zknjU##W8TkdT<_8lP21$bAGUi)@c5QO`3lQ?4In#D2w18I$*a9u5ayO@`{U0JRImB zk@F)BdSmYD0{t)xZX70Y7I{^E6yTiB`I=r>rF%%YJi?DQ0Y0V#!q?KQj$NG!v9O#v zNg`5Sat64c>IM5)S0&PqRu&!4>o$+_W|gml*GA5d>v=t0CU&Ac!Pgt7kB20qENr2N zc>IK=5t{ZRH^@98ea}O2-LNhXG^fGgfMWOzwCf~A(NlxAb%MCXH?A9TK)uyMIx3EW zRes`nDV?K`JL)a@Pst2K0USP2B**4#U+i1}JK3&-va`V3EW4x zF}$B^@$(F-Th058t@CA0%s@KelI8-u+g zuvNU&;+IiH39Ui8;+Jn4Ky6G-l(Sd8(FroFHT;U0Uzzi(YBblQ!Zt$>z|SgvHDK(5 z={WVUg(SF#rN%Ui*EDDz6I*}J3aqp%bCMtz15)K1I$?u^tPqeZQzqdg< z1Uk7%>?&HC6hia+*6C23=_J#4W%KdA0|<+B)S zWyGIb$39xDz_w8@e;zQ6MmMSK3ve++Jb#hKGTmOdioZnF^12c9mvP&VHm8WcLX*YG z1qBkmO0zcFsM7+KB`;rV&?G82fkS_VzmCQ0pePQ&%L zXri~he_I}+SyZvczGi9x6lwm>8clXYB(Tzh?C%0vA%G1^z6Y_Z5PQAN8FqZd-^VC5 zsqPo(4`{wupv%k4Xzpef6b0&ub9Ee5b^f7gi;;F#Z0UDofFI32!fJ~}n}19P2k989 zf}hAcX~uLcdxL_X(x~t8&wv)2li7L8O#OVF4s`2G1fnQ*kff#E+q{1PHJ79oT2=f@ zi}n_(^&=(H;;BePhI@~HwMN_V6oE?WzW%joodrGp2Kbvs)}lSbExh|2^joY~#b*Dz zoPS@FyRnDv!UUJYn`5`PR{0N@wSUa{Pn%|~G_!ELdw~CJhT&g|p^s;Uze;JAL`+JB zA-87M_3om+G05bc+?PSno1gf)gX(WN|6Lx&K!L@7lopM#^2rEK1YL79*=ya3|7r2R RXxu0e4=ex9`9E1}@qeCZZpr`v literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.inference.latent_function_inference.doctree b/doc/_build/doctrees/GPy.inference.latent_function_inference.doctree new file mode 100644 index 0000000000000000000000000000000000000000..bd09a240cfb813a34e2ccb148b03b324ed61d0f4 GIT binary patch literal 176597 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�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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.inference.mcmc.doctree b/doc/_build/doctrees/GPy.inference.mcmc.doctree new file mode 100644 index 0000000000000000000000000000000000000000..df137ca07984f4884e0929300b8fe522d34bf4eb GIT binary patch literal 27924 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 KTey~bJO2+!Uo3Y3 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.inference.optimization.doctree b/doc/_build/doctrees/GPy.inference.optimization.doctree new file mode 100644 index 0000000000000000000000000000000000000000..23042df5a7727474c2e2a7657826744498c1d1c2 GIT binary patch literal 114951 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Π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 K4fkAA?f(J2o+9f2 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.kern._src.doctree b/doc/_build/doctrees/GPy.kern._src.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8f666e832e279778a1fcf12a4fb92f04990fbaed GIT binary patch literal 781079 zcmd2^2Yehg_6|Lm-aD9@LgJ9nJ0WyKsD`DQjlGGzIJQ^2P638qOz-XJ{isLpy&b)G zINF7J9G#;b@c-T?jYiYFvpAPO{K81qyz=QudV11~W)GRUrM0W2r_$b0Zs_c4EtKoz z&xwW3N?mEDA%~V`_DZu1Zkn?*Ke14m+FdA@X7x(54bH7OV8DPacbM9+UqN*?G?!IN zLq~gOA+H*?)yV{vZ*7N=a&sxyT$s{bXsP5Y?OmPa((Jvt<-k0l+hs26yLmOWeqvW^ zPe-9N$JpHRF&*Pn*W}Ljd}qU^ex|WBus1g%M%dD&3KO6%-_gE*p4Zpn8Pnx*>X(p*|c zxT@W%tJSaM++%Y~$8^x7jbhjCj;=~+p5ENB7>xl+3@r_Tv2)F=+`PTHLCHKC`%d}F zjy?I-hQ{Wu@y)617U|8c9%JY(sP?Yb_LhbnOlCXa zQ=O}iYS>ccCpJ&aS5*6y(xSb&C1b2=-1vr_Hr=8DmK<4HtO~_yrNw)5OF>4s@8~x1 zd(RSMbL+*_q$BLk17ZPi%grrq`OXQ2*3y!_xw#;r+%v8_-?CqR0*3ceV-t)keYRl- zxx|di7FoJCVX!*J)mB<_RB4%{dgohP8%E=Q_OWHFP>d`sSA}A=Qhjf3k(gnOmeTUQ zxm9B~E2^in#q{`HByZf9_7yAi=GMy05*v&w>Xr<9OTRbhzP3_tZgD6GH}=GiZoj2h z9-CVsc0c6fe9BeE(z}M0IV~}!s|*KS8q{0OgKvRBlhWFQb!&&wwzU^jUbVEf!~gkU zhKx;cLw;+wcXszwn#+aGa(ktHQhQ};X=qZj!3quAZM#Eh)!y95SQ~7=+2+mVN`pya zeUk%!SZ{9g7-M^9YoWV!mz{+N#Tr0`AF>CowzO;64ZW+`p z-1GgQ#JATvNs)^)1h;Q$(4&6cBu^9?)zQeMw4MeK9^Tzu9a9^2kc)O#>nB+&Zp zM7!Dsy}5N`4d)dmbf7h-3i0Di8taZ)5u?(S%> zFn-$E&o#HGu5#I!XA>QOhHc1NwlwV4)?O*-iD-0U@CGaU?Y!yO1Z!34u%SqJOmA** ztT!ciCST!ZNzq~mcw=evqz)2xlZ~YEt5KKA0DBhv9wihZk1$} z;fPd^jIDLd8y;uUg9{za<&O52LUR{-m0nQz*4bukt_~Uy%jgwExzsq8_DyJLtZQwk=C8JpyUX<)6{alghFY@f8+NHJ-A+%O2+A!&XQ_jex-Qy!I;*ZjX&DzJ0-?GrzHL<|q+gNJq&21Cw zH3=gmY3`17VH#=Iq)1ha)U-Rp2qfBx?$(_MXPW?k^(R|8 zYr)o}DKUMDifQH;E%Z|en}2)~{P27gkI5$_Efk#Qa_k>xZtJ6ClCecP@M@*@q(PZr zqf#-6FkA&adiP86(;>nwWK*CcX~khiL}_A`DGN@Vfw!KrIuoN7+oRm5rK>l$L2Oi~ z%x(?h3CH9+I?B7Y=XaK=PiE$lgF4zc??3x zLz2R?(3mbAn$!^z9Eq9Z4@(M1g1s(h%<65`!xOh+Z9k8OFKoplvc?e!+Yh>dkL=BD z9BYA;-Yx6zcz5FXKB_mjT1<@7>U79DJasExIy%WO_#sN)exWzXgZiD`RYFT0lQha~ zYm|;n+OYR=AT1r2wDhr~)HM0=NkOs@C9EtOq$js@6!M*=6O!7Xucdm-Fl>Vpdvj~Y z+90JV8{+fnNl7z!P{Wu`n)T$Qi78-mnxS+`l4A%+RiV{wot~sS=JHJ|o{`iXDRxXA5;V=3Nqg*g28KOFKTtd?Dd6o(lVeZqG|o<{ zn7?P_Jjf!Vb5bKFyKt14qx6@gjuaT*&bTSQ;M}CCC1&i>c}XMEAHR*I^OI_p>`@v^ z7bMBDJ6EL(Q!C!0pR_Sl99g<3X)8WyS(fBZOBW|OdZRhlNoRJt)~ z*0J+)yyEO@HzfsY?#O8@-JBE|^);tD?XO+yElC~JDB(gP4vwvIYj19)Sm)tDh=t6h z+mdQ;bnL8KFg{V=o)n5ic9}|dB=rqHpmFM2y0Z^kY6zvfdij7bvauFyP2ib>acOt! z#Y)^a^-OK?C%t>dCcIL?I_p`8N@Jm7>E7PlW-+r?>xJDe8=_36clH{Yis0 zWy%h1*gcT+APf!So8`f=2~Upw21~~BP}0Ut%uU&8Ct1kDN!>ijZ%3Y}J(9E<3VSWL zn?0JeEfK^N;eamQY#dpSB?X&_J*V{dOf&wd(&LGtjvjg31C1Fiv^ViY(%j<5Ffms4 zy(jgY5FR2lgc#lL4Nr|tcqt&+i6n&bPbWRJOlzA+yFQZ`c?W~ttl!Ome>Q12gnd!6 z8JE$AZzDE%YJ6|z62#?ACg?X+xne=H%Lcn&fMf#*CCrX|8nXr`hGwXQ_TNq2{^LzmmLLUsl%R|MR3r zW96w6$93VsfHEZRC4n@#2mL3j*A1_^ zIre@?awc|*C1u+9F{u^f&Fu^pz4rP^n?CH~WsjrBz992+_GJX8|K>^U`Q}{dmp&d3 z@%^0Af0Mj7Aq|W@#G9J%w8N@DXW^&6b$Kgd}P+!CnY8Fz}$Ee~qRkM;b{?d;hl0VC$&PVdcsjmUbCGM4nAwu1op`9`VpVge0PveE*5ldl<{?-7K!^i-=OAow zTCthuCe*y-m-i~eJulMB)qJFrH|D~0froQt6WaV_iNE(Bbn4jNjaq;_@uMGoO|Nk& z3sOq_HCW%20o3r~PAx>n_^bc4rawumg+Voz@1jO*VPBKfU1||Zi`zEbUmMk;Lf6x@ z0N$P}SK2E$4%F4z+*%l4R*T_|rxwSxXeMQl zZ4lW8N7;(z_7L748ok{%bJOgmmaF1kZWOxjh&H_8#)}%!f+=%ExuUu{C$x<~TaEw< zNu7gL3b%)Ww`q<_euA9CQp5R|0jL_}uey8%M^DD}RM0LXP~fT6a2?z(5wGFqfxTJ_ zxAIN1X}N2YdL3Nb4$k*9%_?0>t&2Y!XNGojmQ1ZD_fdcY0v)YrWwk!pHo!I3dC&nn z3Uz8j+(R30gv3)D3nAM$eze1Xkw9$%B6fhHv_?@3UKGm}X|UNSSB;heZK6$)9bBYg zinK?ORw&W{MOLh*sH;-c6)0-hW55{g^1BqKRO-}bxYGy1&2jt4L)8{YJhdgRx=zIa zxm34jT)t9?eT}Fc3_bVKprRBIXF(Fc0{3W5~)X|Ns3Ne>_izUctdRw!Lzf-rP<{u zldF3d+<~#1ka%iW$`_2q0F%I{v7?RI(lxQWtEaQIPVEK~^uinxPwkFt$kP-PYK2a2 zxYZt@H|?<}S)KZ+y-?CLU!@C=m;|D>NrfxU7a0MRXguG zM$;XkX%3kt+Tq2DAlO^&CjxVeM%Bv8g_trXcB>8$9Hl1Wns1uj0Pe(J$284tYB9dO z1LC?+wzulWwJ0q4rhyalQ*ctK(xyuIdz;_!pBWW%Xjj1AQwT<@0-2}ExQ30L;E>$W zS|Nj5QO6Uh9^7rJ!)P^cwyQ}f@CWN;;VS zM!xN5zlG)tw@|O>^PA`x{Nbr%StJG^jwAqPvql{UBHd6&&%m_K9K0-ro=$^VBLK6g5 z?VS_qyT;ci+1R{#s7?nC6G0HBIztMyZ#*{cFQD<%xq`qAm5bJH)39nz~}T|&ceniXF#Xi*n~ z!nDvO!qPNHXP0ifOY!G1O|!RlP0Y7|?KZf2nEo@#TxYeg#~_<6&oQrF2HJrJ*_o!D2^-;i(n1~a|!#W&#Z zXn>~*-FOhuF3Ybvbt4FJ3&XrgZb03HyYOo_Bk|NNxQ;X7S*(|+TX9!350vdYF4b;B zNp5!Aa_V;c-87r-J9kJPe~oXKCElI*>zKrDa~JNUbenuGu$$?k9#@X0fT28i7N^vgQ+2TSAA|*vidt@nR-7?v9;Ix z2@%11$3H?~rXTerXkdn?ka+58Dss&r_3Fb6+6K>n2sU_@GM=+Ciqgf>t2-yF%f9)% z5b8F5f$X){^+ge3+gR65y@Wzk?qwvNdWDkR$_d~;Dre7(bzmB=Q?G&=wS0}jUXKY& z>dXtWiXl1b4RD&ezDXgq*Yz#oOZMJYSDktrRKWWWB%XSQs-*I{IWY>Y+crqv(wi0TNIB6W8!OFMwcm*O6M(Y8r1A4fYQy;v*{}H!rY< z=NVIhk4aNw1wH|ju0UL_`V==&i_egF>R%M^_8o!d*P<9k{W)3wZCS#oInNo?Uy!Co z)L()r0X5~SuW%EnzeeJzZz$eHEznX>e@m9{EK6Nd^4K8*8n1cOhvixFMV%S}y|CeMnV*eFP$=J2sf5UxX{~d{^1|X0N_jv)B zf_)|sdunFOlA9lPk48bp?6Z)nM(DGGNkdPPtY*V)AfFwHr{W2a8d2V%I% z`6+9Gm@Mno{ji?fK?{P;RBj<*X_^&}TvgMoZIy`~YGJv_05B~)OAM|S0b2~Cd>RIe zwB{+;8n07}f&^F>LxLwExY}N(C(k9MsA&$+${L_);H37#WC<+QlDN?{JIb-vERIKK z#6u7HL)IQmvy>~XYAH~-pqu6b0V;*}G1@D~BrGOHKqaqm(ynQlW*y%qFL9e@17&+F zqk$eB4v4YMB(gNJ(U7>kQ?~Bw)H1k->Mo1KQ_JBRsct=soPMR2M@iE>ezk`~%zkPG zlqK$Cay}DV8YnADmh;&_^te6s!;-z#N+?EWTN#O`R>9Sxpa4PVcebY4HFPz|Eu7nJ zL^W97>KP|{b@gZp)NlyOJT(;8uY0hYMe{ z31mjblfmw`I@N&tz&HX4p5;)93^smHY12HO;H+1_9;5p8_6@IE?6b{%b*oD)XZWH` zhZ%F)`lykDLJyZwtV{-rHHP;x)aqnpSD6D{#aKbDfnxNOHIaB~Ez;0Z4vn^i*b=R8 zhV$B_Uniiihs=>|Ua$eyH7$}aRN6-UW zZGeJ=&q3G*b-ah!v``z0LdWS<^&iF?sf~n@E@>e4!t{D{V=0r>L(`lnGmGa<1XSwU zcr@;s4e^0yJa3AkXurk>dGNWGjyg34H_@v%L*l8;an&QQNVDqhu?0(=?xD7nlBQY3 z8LO?3FG{U*;w|uSQbXSwC55DsM`s~TZP0BaS$3iLcQ>q|RU@d-rM5-lsqJtLI|zYq zozEPma%!wD)h^}~m=P7-o)UJ5Nw9-5zU#IliJdl0m<9ajAA75vNX=b0c{8GM@R0h! zVSiwjoMt}`9{_CYY8}#chwQuU4CX5PZo7cQQ%%(3PWI6XI6H2;l9(H9#miuZOdD*) z%Y{-l3N%8s8>AGuohG@&sapgOE}HGK-SLN~_Fxf*zkE2w)V*Xe|W0EBHA6r z0~)o9ls3^WGN`Px=`fy5&PY!h!0SR@Wa^wCVmXGX3l(oeiKp5r&+VlG4g(cV-)tik zNw{B(FbS!%Wza!}+L2BqpIKISQg@ftofGsq)9~F{G|-tz6^t`0N!A)72SX^7;PE4c zxrPwkzQ>BJn=54Lu`D^6H_c!%;3n~AmFh>qO$L(&=Ll3&Pzsz=k>FV*<+?ZpObX5e z$a0`%p<5Z6HxNCR*9h?-FlmU$3>cbM2O|Z#Ly&mtP+Y@)Um&EQJB%!cTbA6cA`xE3 z;5&kMYQ%RWm^40LnmP(aKzK9~PxVr$Yd?VzK_~(5d??0PJ%(Jz#<*Q;>M-R9qt!IgLe5L#xwKQd|L-^yQG4#V9#LvK-T)<B&$>3Bio4*bPMCVcU z`7zZtp2$taz?osQFy9irK&s7|*m?MQAt5@wEZ*ClC%YGsnqio{9L$$5vxZ{3Nho$P z1XKydE&++BE~O@S%v;kHgNiue*kxqsZ#Z^2r08%=a*5;o3Mw+;*p>LhQ-5WVfaS;5 z{ZK=!E+JVY5|aw*NNmRUfvZG!G#a~_@O3nH4f1WfWs1hG1u4erbx1sQJ+A4|*x!s) zMq_iM=eQT-_>S z>A0*ubsNfHiQAEQ>JAEad#)g*Z}P*lJ4tv~j4%nZ6Q12ohT0+DLp~Fp-Amo~S>2)V z?EWko=!vBY#+5%H*-&`)AWA&-5QVvh5Z%^&Ps4D*oNZt|OqNG1OE~O#l;u@w9>w(- zm^3bAB<%S+QZ&=!NIdlfuHnf=Af%vsk}OYImT1`XH1E`i?-?*@d^YTP7DYh#91>4G zPob{;1V#j*6ZX77t`}omwpYc&o|lBUe__wd5aEYCuMokjE&?6)yhc6#*75&$*dzYN zggs(2(~V!3tOLH{ zt5wTREpTkR4|4w)tp5mwJ@2E;Qy<_OmSX3fV&D*+u;-s-aH^Iq>`~LeS8Tuq;o^r# zJoOPJ(I?9{_3*I~d||9mUui4U%an*Cza8>2n*80;_cZL47RpX$Gm7_UJ(bFjC5N+k8T`87dInaQ#$duu-N1+|M8kP5Cb*p8A}S#1h4z z8e$~0CjZIsJq5R6yML483(MiZ`ZWY4I$ZEz%o!Cj#?CdPg9a2gzF{J!~ zicCoPBmTe>Y8G(}$C(2-Iz46c4L82oWOK83d-QdBHM+tgHL<0RQ+lW(7c-#CpG6BN4ylHjfESP~eZ7S56sHzM z8LYAp5>G9RYk1xiAa?c*N3DyHWl_r#3Z@rhaTO~>@huJ}jSsWJ0NLwYf;yJ8I{bM- zbf>^tiY!Z8mV~{|Wq7kjaLa;8gLC&fmqRIV)+6!M@|5d#DghJ0=>)ASkZZ*lm+fKk zpmil7?qATlGDP@6>ncPr$VH&ziNVzKX9-%xH<_SSY-YOi5XqXLbtv+lS`}B@e|1HM zvB+s_HC)*G4qC-5MoEKY<3Z~P6rllVazvV&E*D zpmhy0I91CSw5|z0KWJTxs@Jxvb7RCa;D^s9;hWNv3hANhX2fx}L~o%Z!;$nAe9yH0lOOJhdUNx>1WkUBp~y zSN_95w*UNtoEwpKW6SFMt058vuPT?|MS=$TQ+Lu$$dFVe7i5(jk3mwT&n~O&Oz|t1@0|!}I#3?@hbA~#w7~`K3 z+6uI~?ZqC^dXEn3y)}iV)Z2aSJPL3dk;}HP3Z@aHXw+?y;5k1PN-c^3NU0!O)L)H^ zCGGZ>)^9~yn_Lk+t{`Hwz%q??2(Uc!G7^E}+4y1=Q`%i`J6ycO!Nsan@?>Mru||-i`1(;$VFkBIQWZ zm?6da&;_ItIq+9mK8YcwO zBit2O+QE)7ss-fmD6L5FRs^o;OR({QWUj&_bToZbO^|zcupbuhM3Q_ks0~zui{{)< zJO1!gkwt9c;M9%wx6%i+zYQvVA7q<(W&G`SBzRX~Kw^&s)oBx-Ui zCw0-4dq!7oG6|^r7T4i`>Jg`*5o}@%+pYSv1kkQWX=lA1PV(*YNq7qfid( z9E}8TR^S?r+654-qkY9RG;HvQ<`}XZYgxi4Pk1iVjIrZLQ^hnlpw{O$PRC84J_CuT&ZKx3wLnWj zeHK~Hwk)wTCp_b7%zX~YY6SilFlpe)=Vi{tePBNiiKot|1{b>kOu>EuSuV6JG3>6< zFCtlu*e?cCGInkEOK>09FGb?1%c#M{E&x-oUrv@QEDOh@o#&0cujK6-G5-}z8ncW? zD^gvBa$vn0364QivWry!rC`05EZ13=GsGZ%a zyU2BSjLS|H@!hI>gt&jZRrf-Kzgu-55!~-0(Cg<1sONvbTeWPT$8pB^=W%52H``TW zG&3nZC|R>z^$_wn8;z@-fpkqCVUg43>QQ0qd%H^PVw5~4S zmLWQ-a5lc4XC*S&Bf9bR0vXxJ68iaPWL`uu+V~|To_d)yGPt?_ZD@2{EjC1CvnU?L zAS{1{^sff=^^jThjLd7G52Qu6c;v~vabmBFVEfW%a7L!MK4^|9Zh&iz=V9Iu)z1Dv zwO2!n8wnaY2UFZwaxyxLn~2`@CElB$(JSso|IEu8Pcc4XY{T_*@{)21!PRb8P zEVof4inNAOKjM~ta?PQgzL)Y72 zaVGm!#BvBz7i#_+O7Iw;^4z{E;5an>htUJ@nw+O*!ZkdglaM;=^qI*}JJMOmXV&Sn zQul0DcTUjzhgxROqJcq%RKfVNIV5WhArE>7q6AOnDaGaGeJ?%4E=I|!lI5TdEj@;z7!5xhiKiNH zwQ4!=1deU^s!NX%l(Je(ik%RPfx~u|9wW)%R4tps4n;zKPzPrJFP&jy zQ6CM?HenTXa5h>9q{XtuXPbf?V|NS^Pi=;4dVIEdAekYWd|D=CEwzPE$n!3}0!t6m zwgjOK)3(ANp4ys4YzBMsL@z(3nRKWYRNe{IwjpE9BVRR&SUNMSPi>1bSYtaRo*GNR zZZ8(3@MH*3%(Ip4Nw`CdFbT2~v+YQR+9B^mJ`=O;Ox?R!-JzJRDT@YrXQ_g5@4HGi z6tnGy5>H9M5O(RJ+q(2{%(gpO_OLABSZGg{SE+dv*Ir=KxJ)dxHww^9`yj#NaEf%B zNg$-4+m|eP%OX`9;2iKB$2&FRYXOtS=Sx$q$N^yiiKoWn8n&Onh#+)gp$X(_i*ear z6_175g}8sQP!S^hSZF^Y=x`C}SZE^k{Apq#aX2Ox5~G=Z+$mWT3w0syscu|t3+S4Z zSmd;{Qo`1EEF^X@O3IRr$3hhpqv3my;HfgMRxNwAz_ATqH5QsoDN|xn>>N}KJfaf| zO(laB`t;v5feow(|>>VCXjw39G|8kiPf^vtz>&(D7GVyJF zbtC}B;>x3lI%`~cG^rU^iop~0q@8w&#hGpQOOV+MkyV1sV?cuMt5dh@_pN=4LDiff z^Efi}H^@95Qgo0hxx^sz1S&E?=85QMAlDeH(LFqa8 z!&84@5t}Xb)QR?J(#+bU1!i%A)N?5)gGYKO z&_nq_>qR8II7XOM1t(~|gbcM;;ZpLMp!G89zTE1LoqD+gBH}gH^6V;;E}~4Nt@Z#7@N1FfM~#$7{%Ptz`)X*4MGPiWQ>xt_PFG2Sq&f@;BqfHNWLXk6LvQBI8o}KHCJoNr480YlFyC!RJas$ex}8eEL~uF*>>cE~ zGsb0mSUiBeONjdyz}^iJegJz95!~w{&|%+w)bpnaV8uC^09K4<`t$vgH394c$b0HR zTx|!|HF=0dPGhTwg{|)ZR_tPwJR(^Rn$Tw6qbNqhKZe9pf5+9TWv>=Ew&AM=u#Z#9 z6EP`vCMyQs(g|RnB!g46i~;OZ;PV66r>XiGt2#GET*GuY_VTPKp)I6#+UE!Hh7-j; zN8K4}5shM>7rAVi>4o_PNJOK)h{RJb5toeSVo(<`7uuEoFp}**|JcjRWPQc5`VMP| zh)F;8@+uipY@l9~yM6yO3Vu@IbxPNs4TYP*> za9I~0pOBi1kN8hxYBj-e7cpq+ahGz1FCIXi-*M7TyL<*3ym>&)?tEyC7=L-{6}_Y1>Zle*xAiE2l3(g7*=qqc8Z*s_API$5u`18X#0y8=u8 z_$UVC&me_I`2~rm{)=n+0_;~Kl?yO=JI0LZ-%wutxXbULvd3KppnKq@2V8ZS!EeXv z&aPdpbOP;agUa3)xZ0V?nZeaY)>X5BPkUPDxXY|4gb8Lt;;Gpw*&QT;ReRJ&008?u zbC7VLB}{qS3{Ee-F3xF}IVq_2y3~PB*CqLFH|SS$fd*BZ8;Pgpp(3|xQWIUZXLQx( zCEWHELAa)`qGkRSP(wzvJA>$on?{W6aTn| zLv;ZJ>u3it4ec5%aqG#lyk+4soQ~9lFe~s@6^lf1t_UWL6PW=Nr&dB17*|Gu9{|8L zj8TB3U>ro2!Ip&>>E#W^A-q*1#-U&eFjAaa6=lFU42h?PQ>xp`1V{?T2C|H>EX2qu z$Y5NJw`#;V5=;R`ic_Od28^pC@zffW>S7ciDHzuz%UYHtHy;`&GCvx$Ym=x(wCjLL zqfHR3*2P`mUJr?<)~9?Iw}4B*y#ZM^v@8+aoSqHtjYw1@?v25egqwoZCb$dSqmg)O zQ_6R73%C^AW5}|ZWyviFd%M2{q@xW3eRI;)2z?7MY3Rwa)s`Rt`mK=Q$vRcI=mla5 z`fbS4Xj$UuUBhonx*E}M2c{JC+V*2X0QB1gn;h{RK!xLUQG*9DGk_o^FxU6j%tlVaCJ#UOllHu_3raH^JZqfe2~ z92hE7cg5&=Mp~&ME0bKPMD$*L-4IR!>r&ZMvEa71xfgV0AbRsT@#XBl(rqcg}a>=ZiW(@;Gf zmG&R%v3e?quqkmG#hh-%_}jeJ+qU+T8Ab{2jkl?YnP=}}0i&&IJ zs{l7zFP1D@y$%Cm2mH_*&aM?ySzUq~Xv9mA;7mTQRvUo}3V)#arWcs%a^6U;$GEOm z{Kn!Hpg=vYM1oK8<7y>q>s`g78tZX2n4(I@;n%JU71Nup0RgmLi^NmcQAMcDu4hpe ztpeOw?{C5sRV%%>8NVzxu}fFwvERqGBk$i_R#eQ|t{E(PDo48UcXOP_|S$5O#j?w)nM=yN<37#qAY7NX@Dj01qoi|(&^$>4rsq!9f z{b2PliXiS0B%XQ{*RVJN6vP#ek?QX*mF~cgOOcHTnr7)5S5!}+tjOv*KdqO;$rt?k zaz#CfyUx$(6{F80szm^CgFOX_(T-V|*xi;dx0mbG)3}Q!d-+Ydx zSvru|!8FtJl4UdbHG2Uiu;`0O@Sqmgutf!dZJ>cZK=rayYJm! zoPww`4e$d?v-BXTt1QI?i)#_}9s^2hQ(N}e+=xh}J00cYBHE;5<1JU9NpLpc_4EXywlIUC0Q zaGsYG*@v@0Hu~n1EE_f|Tg{JKXqE+#cxpjh!woFpY}a}Sy#V8rf=mdokY-<)?2E+M z1w$~R7bVqVE|nh9i%U`V5xoS+r^ASL474O9`XhQNI-{YdI+ ztiP;eBO`h_l)>!vNbps0T*GD;4A$&bNAwDmvSLh%v3__&uLLq^UYR_r^vNTWvC|Rb zgSx(caJi%^gI6Ci!l7##q6TRtgQ;YQRl@1rq0BB(`vF~{>V9A-^{#65T0bz1MOoU< z@dLxbL-x22M~3p0miU2OAnH|8q;qk*@y?&9Az;37D({zZCt}< z7Yx?yRXxB~l(Kb9im`s!18f5_Xl^9Wwte!fh@LXY?<#}*;aXAo&hmH!{NsB%TVw}N zZKp+!rO55A$XrH#J-Rj6>Z5xHYT40hv7>t@7G-H0XLRojCVzDALdi{W$-8EjEZ|J5 z??xswy5-F#Jm6zd(k$-}@I6S8eSiyOqi;{ivZ*7p{O)Qm+(MJ@jRX(*a1D1h0cSf~ z!WeJX?E8{EA7d8`!5AM$suq_@kMUM1%09*mAfFCn+%eF2Nc6|}1my9!O(5wpF6zt} zZ)a(iek64@)-OsnGRF5q8O+{+#8VS-4VzssShH6hDUO#xGJJ0VvM3uFg3f1&jHMxGs)V@GhD%}_8J56&ro0e)4^!w)YH(6y5 zRZZp%!!jE;&D9i^70urCRQ!csvc}c6knXbwuqaDcI1RzE=?Vvu>3kGm*T|#jgW{qO z&MaEc8PSJGmQ6hunr){-rAKwvSEhCs)Sd{>QSUkzuh0mO zAj^?1i>~}pEXq=O2jS6R^8INqB_9))d~9aP0?yR^ILVr)l*c3QsS_wh+^L-dPL!f* zPDb8>Fi)|t+gNC+Ob0(Bbu~awk}Ml3rbwNPduXOpkl>f6an;Sl_dP<8^f-`u+Gdl- zsP+$ea%}%_dw5ZIZFx)M6j%mb@H8qr-715z*eC2Wp?a1dkT>Pe26L4+<<9{L9#&C{ z>0e=!6@yARZ_A%chS=Nk?&InB_M3iD9-IU8hY;0y$m=)dC71Z7{P|R5-ju%pf8ZGx zix^wT?|+&*;ZzFXj?&w3pd>bJB%Qb%mp*2CQWnwf=%oG!2Bl5(YY;(Y zo!6wVA(Pv~SC<}cItqJxV!K}}V(D6_3l+Z(CHR4A%5!_FfP;U47cehJ|BZw<#0Zm+ zIxk1xNQT;x-b6n0a`esAeT&r{I#YXV77ZMIQU&8Zr-d?{V2G5z@)*sXKL?7DRAD0#8dZEu8UK^q~LsjEDu_i z@JDqXVtI`a9|n_#C_8!h`RGSb0CbNc@zi4!>7o+|Dd_%Amd7niP97yWAJut+cWT7< zB$zZlUz&OfML_s85>Gutp)Nv!5kcs@srW3po{MqW-XDKc@p&Qc-99>S7;uPip|V$dquM5O~qG{_ta~++7MG$E$uy_ z$a^vGgU^qKKcMP=TGcuE>09^bqvJmpJ+4rhTqtzb=j!vFt@XK44QiSQWWA*(dWH!? z5$AQn52+^u;^>=AABkMH!XLr+F}TrKpCIwnr^FzGv>4zPGoZcr&k0gLBgeliM?6TK z2y@M_AeEn9{2XXvf$F~rF>9du1*sXR4g>x^KD`(ZR$rE2^-Bn-60Cj&5>I_iO|D0@ z@qICV$kv(75T?H@dqB5vPi(@mVjCOKrH2>i&8-yr_T63 z@Pp`%#;QLOzK&IYLcZc6ui!pMFah{RKZMi^GY@p zyv~Obe07?_TtkR%JGq5}*9FM3pk)aMg$uE~O3kCV76y~XWrD&*P=IDy6bZgMO_44- zfslf3ak4C7S)xJVlDtzRzNNsV@!6noX%qqBGDz^%X$o}_3XBLsCn#KwT=g+7+pFS1 z;qpSmu>gdW0lHxENGJjD*(YKPO~dpBx)lj(EuEVS<}cA!Fjl{M3d(7YiXb zBIK+g8D~s`va+rjan?PWdka9Fg@CclmU4I&cltIOuka7$e`WsSi z1}QqElw4v+xj7Y?ka7$BfoJF}60lrYnRqGLT4|qHlxpih^Z&o+Y$aHtf#=q&qz*i{ zLB4HRrogiiq!?n`BEe5&THK)^02?iW8XbOhFmkSR^prMa0sJrRrBrpn>IfMS>%}ROF5asR`YZAE?R} zBA)Zd2$QPd1gd+Gq4p~5Nj?*(?nT{uTirQ{x7pRrgYA8?XyL>m)i4uqvt(%{D^Bf; zGFT;##8cyN4bQ#;#Lm9cFd~C3*A}w0T9!~SU0`t)D@5^)2b0DJMf|$r1nOwBI{bM- zbf>^-Cri5R8c$6riEu?nZFjRTrxuxgSv>h(60Q4fo%WzA6Gn{tS4Aj-(L+8 zG3g&yJdq43Hc%(YUA|qP`rW&VIvGSwOHAmVI$Yj87+zK_!*Q^5xc#)^DY)-{TJcom z+b%P4W83d!O@oEUsOC-r9E|IRG9a%?+Q7pzGKI4YP^`bJmlKLBMp;uBjAm8?a zyOLTcx$mnRK?(nG6B19|jBENr>J}rE3n^(ic06?}imQJm@itJ|uO!}%Kk#M)i`aPB zjnn<0Ub{_cUF|l5s@@m4%{$4N!EHv?M|X)>dd)zgx*LVCz&%JjbuT5m9bd3&_xK0^ z;N`RXNO->`%q4$i!~aNPQdOLfBtAenwO8dq@ad|gsaFqy1QmN2iKiZ+9=Bpr4_&cm zbj2Pe;bWGt$d+aBl2i$2z4~|Z)Lx0l!KW(`bf+g!2Gma?@zhfk?4lNs8nt-~=xGu@ z6C+H5?5t0pB}46ypCg}HpFU6BFIe4)XW(DVqKQ_Ps+f5DCCRdesr2rU5o-G1>=Wg`N*=w zKI6A~!)hkF`QvTb8~*g!cvM zYJ~nJm^Ad*XZ-Ys@V){8(0`4@Q{Pa9i(Vk6p#PRE-&q!pG&@xrdwtP=u@KTV^1Y%FkY*|u2+BXYHYJ@#2m^5s8i(I}Iv*92t&hTN8L25SK1LoP0cxnzx zcdaeJBAA^Gq=Dp`Gsb17fcOSdoe=kL18FXZ@Hdd=CW3if1bTrtFZKNIH;|TY)@zvZ z2rO_$$g*^VEK5f)MDxGdC-b@4KN6Ffsb)UOn*F2sk@wUB0y_NAb3qn44Xzdvw!Zg| z#41L~!jk2DhRlFH%UwOHrLebJ1b?B~7e#`{@wi&GoM;4&ZT71BM~hR+5-}+@KraTt zq_cmtBpIBlW!yhnihSlnJWEseGFEqP5UROpzFa7;S6}U0b2{V|^fPuDp`!$64{BM$ z&tQq@9@KJVWb>kn`Sn)yC`RipkHk|ekVXb|&Y{tD7waKXF-KumB>hSOeLZAWGoo4< z^ntYKo{RIrzEwo9Jy4@VjE;P{TwEXTh#XVg0M}d}pP+M2*6;I>(IIi^4IVH31{G8?_d(IjtW*591v3S)0_{x>*IlQ;zwV?Js-C=WE%# zSqH3DHgDDi3EnuM4tM&r)+z>7a5iw(C&M4wz>#&dIpnher05+S$tCXKY)D0B2WKPv z;i-*TM7QAo^j)RzGd@yD?I>qp({Cb5qdP96iCyowY>Ir_*I9O4#()w-VlyP3+8o#P z9hWVPQ0};h*W`4Lp137$=%>{59d}}|9Fu7Atw3m>Qg4kvJhcsrXmPOl$9tqTw9^c# z>a6e^$>eyEjFaTHB9>l)x=`=!P=ep0raZTg3OKj|Oao?NzdZ?eh!G|sbr$wJlA(5_ zJCV;U?02T_U99fVL*1q<8W_Jw6^y&wRkGF)a=d3Zl;F3hDaLL^v5roc~rjuM>|(+MTL6)Bx@S+gl0`6 zCNrb0N3v#3GYNT5O~%#69=aY=Smd;`nksC4uW7_8M#=t?<&Z`uSkoMUztHRlBJq@m zt5wTkCva@DS6$N_L@5Wyq}WNY7`SU^O>+ntoT_DX*N1}7ewm>>pm)*eSvPX@%%wZ~B+m#y$ePWK!QZZuXe5`0gZ7-WnV1KeT;v={%$_&f!- z@f6@#avWzl{D-7A)QUgkJD$W@BgGR)%}8;mOw&9`GNgWR!UIhI;d7zV*3~+s?Er}u zPXv3FXz?VFcwwpz#8ZExFxL>G+fFUhKpjMmH<0B<%My;rZen?r znn!Wn3?_}sL}a(10L^qO5`2@IB3*O>AqCy-WVyq#L?g00d8bBvcY#Ucvk}?dC<4NJ zkl;}-g}Mj@Mg*Y~k=;kG`(s?TSH&Z;2ZXqP5!r(f;YVZ-5y8VQ0v*XbLOp+yh)mp# ziO9rcrWZddSrd^xhCF_Y8CM$`>3TfQBB!0z6T;SaL?%`-N}iM~hYB)5MD`T^LbE@O z1n2B=wQAX?1&(d@su9_wu6b9`mVbH4(S0xO34J4j=oqAnw zV69pVs^x@2Z;+wCq0pO|pDlmx?P<={4H9HXXnTVxNOx3Uc1sWLcb0nVn zHx;=fL23dA8EnmcLBcO%gh^F!0<5pdP~y z$8_!!IqfJ^yYaaYl5wL zk@wVm0y_Lie|{D@O|2FXw!VWcv5HZ$pk(90)j_p7HNXQCgUD2}o?rMmL zNk0;@5*bo#pjMW<+zm=R5|VFiRjYucX|d3O5EKvB^lA|9`o}>ABj5I*2^JeigpY#^ z5l#MakfHbkkK0+qnO*jy!uxX2QEzk%1D$Sfu|c%1qow}Zu?(lcl)8ovgG9hJh+MXJ zpFl={42`%N5>Jh!GB#oWP%6e2^j93CNV~eF^;^x>B)1Q${)bi^uuwzy)b;QKaQI;< z`7yn&@%TMG_ehOUj7Af#0rjy}#hS#Fbycwzsky3%pO=xgvPVF~f@z&e78GkklHW(t z4uGr!8c(fDo$i!ptrp)KUXR3CtFu0-S)F>|g^^N^f1q+h+LjmO8-S_GQfNbvcxod` z?+duI4BD8)e`pybk(NIEu?d9eRgmNoS3#qx$E<=j#UGv;!y*nq`Q#F;Fu2?^PTqYh z53AR&7ozrqhUmd3b>rZh5nXmOQ5Id)Y)-s-QL_c|ZOglhngvjWSpQdBf(~PLDWjQiBWQhWNjCM1~~GNYmb?Estw-m$Dj27^Qwc*l{Et?ax@t&T@A8u?M@V3>zmk|SotP)ayWK6R%zK4B=s5I|kpNYJu&cam>uOjWD2lm-4bsAfp z!xFxSEx0*L;ll+wB>oFZ(%-|DCNl&6T*=Ogjd1-OQtfz-k}gV0Oa zW(;0P#)~XtZZuj9;dlLn_DT4*ulz8ntmdTE3LWxmsT1&KNH0Dp}uPpe)LLy z@Kzsnm*2T9OVhPi29@hg#3W7Fjq?$OR{R)lgSr}WBdt_SG~qP_ki~?vhWA>o6%91u zbOnAL#KMx-Bf-lP1V>8-6%xZ~OP&G~V>NLDX>YW&{`N;OYwQct{%^NG@V56&0HAxQ z^T~*tiOTVHeV#kGh1A?JSOJg|&K)3pk=+)1=3o!mGq@FORrU;S1Bs_@r+hb#v^FXR z@SS~wJIL^d_6?jf2X{h>-Z+q4;>N*URAe>|?#3UUx`#!a8s*U+YTfsV1F5185@twq z-z(~(n+Nw1v)(+oANjUDs&5`V06O&e2a$N{Azafp4<0rmxp^QPGc<~N1jYKvCuhbx zF)WhL89WL?`{eU6{DJp7SVSv>%|B-#EuiCrpqkEt^>H#~a2k=#gC|5ReFk-*)=#1Y z9}u8Cw_gf4J;=>U^=T456C+GQ>a0|sB}45S^6qjUb8F-4+>xB%_`N8f_no@8l3x}@J*Bg z=UYfT^)}_YI0Z}!&VP{Q9m^7atL7o+|Dd?t= z|1T0pa=**MdGQ?DAYwLFd_(@1^vIs^?8iT_Wt;S{@+5} zzXkml5aBOBz9fRLTm(8|{+fFJ6bpLsgJwZ51~X&r8_Ajl{kO<_>N{L*Fs*CxJ&T-H zR{s&Uz8Caj6Qkq@$#Ou;o|9eB|A=BV`cFta^)s$kEeD;zv5j7JLH`S-{5K}WPJG3{ zSvw2*U&-K9EiFinIP2fQ=Lf65Q}qDsQRxcg&eW4neI7Atd^@1zcgIWxE4IW>#4MNlp8wnDTi`hrM=QoXjTRMm~Nr7rBJ74hiXL9a}dYC0Ec`6 zBGgW1uX9e4RIwksxBxI?qz+7ajL5t1PV1|=a0h0X8wq}rp0ZuvD6srt(llQLyqcGH zwcu?ac=~lEH6KI+*ZfHEy#-uN@1MSE+?ImR#~M*Q|0(DPXp#k~dm*bkwz!EurCgZA zS=StkkeX|bRbai86D-kn#~ZTlSQM;P)*Xw1#8Zn?hufq__~X;Sch($Bkhs5VjwK;Q zuQ?=_xaL@jip-j0Y5d`-Wmv=^xG0Rl@H*w}iquRmH(EjYzg}JP)XK7=GP>kgj*#_| zqaOLTH>xi=mIodB^$JKlwIZ(ROOBO{NG>_hXn{@C%D9zj*|7=;?XqJK{=hFbu!x4X zCrI=-kcQBnJE*R+^cX_MDxPOujGf4AHdMsYZ(Dt8Rg}RD!;pAtI0d_XRFHBw`X^Qz zNH`)!m;~8bgRDk|+98i5pIL*9qVCnL?$8=!jVv1Ij-?959j_@_S_IbOiIufb;;FSM z%r%7Q_Wf^h8mNOc$U0w`(-GO_&zC_po9hy<@aP^61aAf%w% zm@J!EmS}80ns;i%w<(x3J{#MQK@kvch6EoApimc~z=$ApV*4$~wPlRU_NsVnzm*X8 zFSg$rBK+8X8zN|Q5$LFRTk82!#P;HBOl&U(GkthF$(q=HEb^Y(9#ssu6V=Y%ex3N_LVg2TCZm-x`v8t#8gM8XlGY*PZDR1F!mxfBMf=?flwlTG$a~d94GO`-e9Z} zU+e=CeD;7E+#weQ@5C4TlDNO|MIKUgd?C5S_+lItnfRgwe|V~uMFKQ8ubE5599{C@ z#k>I}HPUg#I8gkL;|eHO1yLA{D#jD2jw&V~-*#N}sG<#Y7!d79JXORsJ*wExh-6eD zyG*08yDMNia3fPpF%g6|rs%{U_(cO2(YW$H48-Y(LQJnCilC}aMA1z)$30|RAD2Wd z-Gb4k6iQ%#G7?W!DAw(hf)XA9lc(9!>>=T#7-14%C!Uy0hS~v70iXX9#8atyf2*43 zGuREy3h#g{O6cgM7RFN^C|R0Bf-H(t9?D>pgOK3I2XGC$NdaQrq>e4bLi1tn$Li-0 zavd7uvKETZjfV+w|K`TSA;O;yM(9aOTLrkT^C+s&i59zPS+!J^1tS#mi-Ka~}SkCoET@ zuqe62iSm4EGZWtOv>R zkY!1DsQEB&)(GwqFllh^L(NA~3iCaN1dqZg*X>jSCW6yhxIa#=Ct_T-hsA@FCxy6w z!O2q);Rh#A6Tves0zIuiOFe&z;6$8|2~NadrY}DySreQ*kG!W|z}0qMU5gi4)ia5>LH`t5wS$EpTk3R}D^Hr<6BhQtV7r4E&=LoV-Z} zr)t@P6ZIDP%qwJXQ};itZoc7%7clK(G2d&;%VP4FtZQ7c&{DzcfA!;gI+5w>#9L;S zwt7`4cjJaURm(M~cOXzZd8yq0$8@S^Qs;TyyR2gdb48!my(cwb7Z?qn)PLK&4|(W2 zA0WYd21F$eqZrss8U@`4YnW592*Mg>8fibYw7wIx#x-u@43L|}*GDAIP~FHT_s8HX zo~_k>Lbac|YW1l4EQ@fC1VL_w(!a=bz83vC{=gRqSY+I#7X1Z_s^F$*L1#pNDOolV zG6QzVD|~XkQcz{}75;{;zea-JA;2{}P6dS>rW@1qm$pX$uo|#N{YS6Rb4^Pc%MaLqY*?7xc4&4jR-uS}7%n^dsD4HFtx?_OD zeC=Tll%Y=yMB=GADchZ}1&-|#4}lGRf?Z11 zZMONO$i5z5d;)rktQFsNujCcpq~@pPJG&b?Tk}fgr`8Yd?3vhH&QI*_z-!f0>gBKY z&eon5oT(k6=7&J%J^A9fVg$!#)n1T~+in3!EItij@(3AuPc0;%`E7xss572sVU}j; z0b&i)FpEf*W*r2xX07C+;6l?ah6GQ9akZV19zjsrrhA!9XAWb@!34h@C9)g>DN9hw zk})Z!1qn_b&(seeUayt{8F-c^&oX`TjFSa3Acek$q&0U33O+XB4Sccd2w6tRY3!+>Sh9Ngt8zorn#aaeiQk zS`*TygU@m7wH74$K4)#@J++P?);>qnnZC3xOSAMPF@~10?{^FRfn??rEDCNV%je3a5e!MG><0FrhW3r@4{_Au3S))aB`zHU&-V62HL2s z#%LLvQO4$027kvci9ru^4X64*--2Sdv|{Z*--<<98pj#vTZ73T=-W_oV_fpKnI#K2 z)9l-k$qe+d_ybRPS;T=ZvwCin=~g?iJo`u&phnA%l4TQWiE1YlpaFMA;;CJ54R;*@ zV!KYlcyH3|yOMpk7`tc=#(R!bySr3+yze1J)yDhE3FF-lED&cn1Ab44n+^lsG232{ z=nwe4k@wU-0$C4uQD<7FnWb6!l-R;Ob`sCra024+$UXksVC3(JMSbb|@e7>hcj@@BJK18)^=|xK4 z&q~*y6|6~=_7b`Z>0ZLznS^b8Yp==t!`zvo@AzL3@?Tc$Ai#+hpug0OK51|smvoZY z9kp&h;Ufj-hgrHv&BrAp(eZ6`)||tnmY-1dnMrXrOy%;}q#J^&JT@tT#8ZkI-N`;$ z8RxM{nZ&WjCT=Jn4?JQ|Oe&C~pO{E4@rg+f6`3a{lkf*VozEh=#T8(h$g==#9_|^7 zp@yMX>8>EP)LT6A)4Vh8i3tIzDWX04*kmee!Y-lq7XoRt>Q7D%04avxfk<#>AJ_CJ zCkF*m`S3(0;Ut5pgN5)8sMjC!xD&bLlU0X+&^|#q6n}W?Fcz^v0Qmu}}ZJ6pPB%V5&I@}&E_%ZG=MVS{BdP#Upj4%nk z^DO09GSrU#IP#fiDaTXy308MbUP84U*~~B}X3@lDrc}kuFegctMhb~kC!-wJIR%NQ zPQ^7miwGd=6{n#`z)lA1X=FLwvV>M5XRx@6HKG{L1e3-HMO=fNMIC2b9lnnh-4R&M zvx;-b^_LizZNd1nigSgyf6pq;g9v{&<$NNzz(t_LoC~SvPw}imhP&BI5rdh2a*<@s zvxW4YTi?$r#3n|`<&tG*483G{1&YxZuSA01d&kwPWls?} zw$ZCTtGJ3%u8v8ub3ie0Le8^_YslbKE!(q-(2Eq;QuTE))zQh+i43kMan{J-Z=_~q zux`lP?$KPBA`dtCRgrS_2w@=%G>H&yfWRsd!i^yD)J@dv`p;;koCx7&68ASkxCK&l zgdn-Z2;o*LG7-XU_yecES;Prx7nmqK;YG|O4z|18z8XSNof~O$qlVS*F|2-4UbWMt z`Htr9t}-_4+q?W%7{x9+rkD&pGc2YES3%t&D59~&owR|DE$$KmY3}N=#oZvqFuVr| zev$y!^w{FQKq_O4rK^})-7gGTVvGksXk&~A@du8JvxrS9pF|8|jIb?qtRcNX#~OiY zoLJ*w%Bp#ot4BmEJy%~4)T1DS2_Hj(NA1+*jv1*>DCT&agipi>lWO6_98Z#=_F6ne zJ~NL$P2JB}-Tdf_KO{`Z@oW}Fbkb52@|to8D~MD;w1VVf6_c&qCI9oO+l^eZ9mUnKf9MEH^DH$?EQi$KS4-%-z>A`+EJ!9=2BFylVH zm#m3I|AV}ze!$f_3tfvJS>!ak`bpUOjzq;KM#;~TwLZ!oW&Z`mX!QRg@zk%lTD5c? z0>?Ib)kyR=O8Gq|#YPUrV2W}g(E)RdTBmA%AQGJkGCVaiCAqye8nii)=qx188i~$I zYDS{++bF@DT*}oJinhHXap-IiS0xUe9VDKbgL?a_k`spxByoS^&^aMR$Dxu-j6>_F z$i$&@;SW#E%_0GsYl4BoacI;?{v2t;&sqXeF^mpGr$EsR3q&JzQ1b|kXe2r>t)L^( z`H*jWrFs}TKj<(97eL~v1#wLeLl-h48H37iHuq^}wJ^vt1)+<8&<3H4;tx+P#v-<- zeBn8@!|Nzi`hbo?1G6|$=;9Ps^AJ}{h*)~9J~5~zK?f5qg~U@!Q<*ztq(*RK!PeI@ zBwRK|m{biX3|)>4wO6B_d?pNCp1N1Cy4{dzH8aVtm_-piwA947_?0AUUA#ZU)XFG^ zZB{|zsX@4gUA(}tEcczqGVp43}Pz>fMCk$;OgHyFX5Qgqb)w{)1_YsEXNSrkc-JR47Lq}m& z)-M8-3!UY5ya3)_nOb!xv~8$_pL;+|mGE;T?HRv?@;cxi^XX8-DHsDLVX= zTw?gyOhqRA+!ue~v-m6$pgDQ7K;ojfamqatCt`Z4&~3u~jp$X4XrhE@+F3!uXo8jr+N6L3urBioEfhLPfm6V0XCL6#|eEP~L6 zkNe>de2Sk%Y!CUIbFAJvY?QXsVPjwhCv2QZAvF(4)hS}>WfFC(F5HKyx{-LQL?vz) zmm0v`1mU70VL3*a1m6i4D`co0eh>KkhmVt}da_l`FARkHv56U{WYI=jpjof1BS*2BIppn;>!28ywOM>BK3ItRHx(ZO5&l$s zC=ndyBG8lA;nee|n2KeHnW#}$5>FkEt5wUsBXDe^SDlJapp+A1QmoG{2IJnDiccbgQ?)-Z6`xGi zr^Hl8=PzeR=u{GCor+H*HK$^kapbvL_1U*xX5Z7nS!MP;10rWuK-f#iN@$` zdp^-+&mMjh8ue)zSiKlL* zFxL>G+xkpBQTo&SZDhIKvQ%An-$BwU#)v|_6HFRv`nvlr(4aBzMuM-jQ;S;%0UD`; zv+ll^T=&JeY|F+c`}>8sf0O+K5aCbu4-&ycE&@GGK1@A-ipgGvyP538V5T2EB3U!p zKZ?Ak9>dkny1EvBXOYwF>TzM~d$Jds7$r|gHa^)uiDESRQ%F4ZG_F=HyO6-Kjb3%K ze}+D1!Z zL4Zc;;7sI4t+1)Ka+Vp5dr=9GkrV$KF@K$5Hg}<5Jum4sBA>RPaIz#i2M94k;x~ zuDx8-B+MlhU~%{2?(XjH?(S0DU0?V=-)ClLXXUbc%}dGq|NK6boypwS<~#Px?98k_ z20lE)cL=4qo55ZjX6n&Qk_$7~&&*uR63@k~Omd1{%_eMJ5BA~{qhxl8#s~XeNJgR0 zfdH@T@wCok6%uo7p{EY^b5Y9NF)6l}F9jWvGuY2V1}AG%G1$*b)$_$vM~6#iu%DmA zSqJ+CNbL^x1JeilrDd>R5S%H4{X!t|)WTHZwz;VF&S1X?iMu=4FA6Dou$NfkV80j@ znZbT>{Nbr3m?Va}gZ;p?!CrDXEeHF7YDv);9qgB)^?I;h8u8-N>4W_;phGjsA@J0) zcvc?lmop-xgZ)6YJbuYE*slOWJJ_#?KRmS(ljw3Y*bmf$y_AR^?1RiYgMDxERo%8! zjfiyz`+=$!N$^1*1fE)%a^1Qrc7_J~IuiDc5hhve4EFV8sNUj!R`VnNmHB=HFYg8r49Cj zK!d_u8-b_Rp%ym}VrV1}&R{>7Tti}9wq)aj{klTjy}^Dxi0}vdp|oIq*8)A*Z$Ldg zVrDPR-3<2PFjJ2H0 z3;|x`<7w5h3W+(k&{GHdEh%NIm=xQ~mx2z-8SJ+vgOjzX80@#9>TP4Hqr;^$*l$PT ztb_gbq~>71I@VD;+i_h(VPvq~E!zp?xddDS0PFy1DF9$NNIbP8)w=C4nj;4Q>_p=3 z0)RZEXaFFwL;$ce6&V1q3;yubu1pd`dHIp7T_^iUHk|Q0Gr=)r$*M*H9sm6Lexg-s zH!&d!3q~+c8W!v>1X6tI$Y3N$(Wdr5fDH$DRz?P+0;vQCvVF0l>r|sq-v%4f4kR~$ z(4vI`{_xajCb4{EaW~Nm8a_yQYWNU1#eolFD5&bzs){0(9Z*I6su?u!TnT}v#!``6 z^(7}EJkdhJaWTTAEI4?gl?>Hqp^bb7Pqb6_o>q6_(PWiH6MI_8is`D$5~ZiYN0U2{ z4)1g#@YHxb!+o_FWc%tc$e2KuiI#=fCvP?cOk#41H=;J~1tx7Hsw0mk?@b;1SRMXu zLeU*D%fSsEx%Q25*%FN7hW&)Nd$?hLi12a40kq&i*8)A_9z;Do0yjv*_h0`bYU;_s z67^sIBaYYqc-l&#b8#4xoYGZ?3tQK?L40DA93jy-Za5OjsEbD-!0UfJtytejH}-+De|S4VY@l`Xq0SOhqOjv^dPBpGa}X~co{l-r1s&Ss zc?hu20ME*p;{qd+fMeM#?p7CqB@^(t2!s}RT#P@k0f9*@TRDl+r9aHh1ktv#z?{H6 z4gk570;_KJ>M{|_o-EZ4bvbC^&MOdL%K{a;%}8<<0wPzD@ah=h8Ayp{#Q`GMkfHjl zTuVNG%L4xJ)b&iFn`Q5a-$2Y5e?t~U?71Z;rt7~^qPFYzC90c{4By<0z*D#28SeV8 zLyGPC!!YDlvfO4_+~XJiL6O_}Yl=&vmfiuTn56^Mok)hIcOk&ReF}C`1QLt;Nm{Y;hhspAYWg)cl&nrL5k z3{2WYfp&6U`Elxa!s_s$o#?J$){|s;%Ce*`YduZUDouR`Oxo1S8&;kL4f60D0^BoC zEv{?D&`2H}c=`glUW{?sb{&VOF9~t?;OWZ{;ltBcXu+$l1sd4BMm;?Op33lG;Hfyw zbRVxv)WFj>5XX)HJZ)#8bMY3FoMKmR3tQLlRD5ETydzQDN7;iS?;;t6{vHCniO18b zW!E9**g{W*ryo$thcPJ@M>yk@15c-r!O7ZGz|)VY`s0}DD2{XB=_e%43Qs>JHQ{OE zvexL%mX`FFS`P>;{S2Z~VCm-|!L9)6bQ@tbI}R-UlEmGGrC&jchNTiqgr#3ok%6V( z;15rI%Oo*0Usnky(Lr3(!g?0|4II2xTdRL&MDnYV=D)G9C8nwG#Dplq{GJ)p2=fQT ziw~qD%pXCACiN2nPyLK%WrX>Q5!v;U7R~z=q?wTAZy>bD@^}2oUmbolTXen!MCZ~8IYTrCy()J17k(<8frH=Wm4j=D`?h0njPnHEN zOTw3n7UYjr8n+Obv~lj2ixx&I>|6u^Zquh+w>uSMB6d2MW-)Rt9^!=B3A|B{~<&Gs!7v zwSus9jcLRuM#+j2jboaXkc>j_jR2oe$J451jTUokp{HV+T1x2?lVV4#QqWU6m}X@% zI9aO#)1V6Kf2Ebs(C}%BI@-`TWOH8}BzAGD4KlwE;GyHLFO`R=; zzME__seWuhwbqX;tH%0Ks%=7Rb3?1@54zz?j%lCNSAOh^-}?H$_0^ne07wcY-a@Pf zB3@k6z?)%flm@|`;tZz1RuP@0!AL@`R>dFK1HdGXO=3&35jmr1br9=;N?a1n`p_Wj zYfx$i_eU*UQ{=KrrCYNWXi?7wA@J1N)F}BV1y)KHQPnVLP1bo{hqQw&t>0nV?BvJ6 z2~)Mw<`+tR`=mkGo>%Tr_-KlJ(kj`d_3QfuJOtM0y5oT3b!lQ&aJ(L=367VkT!=Ng z6l>EfouK5Qkm*;W=|j~haOe7<@ze&??)K}}ou-F&GPWU!vu11~QZr+HkTKt9xthk7 zhH@GA##iueZSi`^!^U7wLHe73#8aD6PghxRkp5;Qjv;-uInvz?n4v46oX?I5x}g1P zm~il`qY_I*`&&?%LHk?c4^M5yBsSTN9jDajGs*aD#^3?w=F8T`!r%e*{p)fK{GOV8 zQlm`RUzcme_p1i?_8r>WoE;Z$=y|}jZwFh8?&t(y8|GC{0JcTEc)dFTSh!+kSKEOY zox}DB@NEPwRZwlP3cbE!^nANPwmVk77^~C z*QK4)J*SkR?m2@D-y_|Y9yE3#XNI0L@=>*2MJzkcK%v?ViEzRQ1o-L!CA)Q8Y}MW4 zL)!R}B;3Oi<`=2x;QGqBc{IpP14UJzn^EA?x#_|J)d(tNuL*&t3RLB0PjaKP_q5L5 zXcCUGge8_QK}k}nI1{fTd8*GxGx!38Wb0K4$uN8@0^BS>*{UQ#(xz?W4t*q`muER6eAF!)2^|qWv7hNrxF?ggyqO7zLp{f(Vz(eB^ z;G+R}hB2fV1rO=&VhWsuG0E6Fkt~xeOCFom^#zosH#7$CMT!*XL=D~>Oxob6RJ9L& zg2f&JPwh+LZkdW%6)fJ5Ec;uQyxfK#?Xiv32au{ts}BT|wmM0&ItV|*@`Dk0>JTb$ zEf@1DSbiv34znzI`Mz^xWHE*xPNFIeKLSkJ@C3o?Nc;-Bk3xV~`;_n6EyhLcb|#m{ zkn7kOmu*t<$>niE+`Y-=@etupE+^B16I=`Q5O5;({PUB`Wkza1Sndai+D~Q|{bcIV zZS7hQqGAb}70=9a|u8_I?9pxhv0#6f$6=MS7A4ntY(p$A~G{$E0Dy7zUye|sVGk-;U= z@84cTMwYXz9vKIyi;;|Cz661%E+vgLa4uOH8tnveBSrx8Ma;`ce|bQkgUmEw+ldgHI(QX#<1B;>$*ntZU8>423(7{r>?_Ox1|#Op*y7Ond+3Q zx`8R1igGcYZ=JD1p=UKWBBhYj8rV3cbd3I+B+62cqde;`bu*|?3vNMxuLIy2ZtP;X zZR}gYBK)C0>R{T~ZDhRNGUk_%DrWjPtZeWD)0jyP*f7`D+A^tL-2u{ny>Y2K#R^V` zoECN$bK#UklAG5;#fY}ByG0sZotFE1KnZu>i@;O&QJ*xrQs5PFD4pzoOz(cuK459{ zGA-SzFa}>40n#bW|vJDC`Rlr{Krd$L5%#{o6_=s{xAy+f1p>gbl2Gvwvwl)_j zmwNReq(%y(l<1m=s6LBpW(=)nsE0)ZUGrZw`w<9*7av97smEvU}b*q0ii*Pn+vD`H2=g4Hf z!2LY_z?TA;WRRH_{UVc6?51e3&WL_VqAVwTci8;`_sjSJzJ3LPr(VS~+(C#Hwu1J@CWt^Fe&8K515q2 zXtB?Ur3adL$;z@!Rkw-qi%eKz*Ar28Lk^*maQ8JpUC`1vwutW?_%s?K!7{G zC)E!wm99-cN|Hqk6~4qhBkk@`KY`f62&K*OcQxR^Aa%z#KZ^wOmF-^;_tdX=nqgkl z8TbFj)GVbeIW>;|U7~cnpMgJ+0+;`Z09Wwi8Fsl?U|pX2dCR{jvfLi6+p@Map%ux6KMY4FGwuzDKjUXUu*zcU)4cpOdvg|Zjjs75%EEQ!s`-(O0$u=trxwIBT)<+Kty&4K zc_GcdFxeN0v5WqoH7`o4#at@gnirR(wAL(Z{G(gi8amVxApbA4XU929LZaWEmqOfA zON&YRgSMj1_~^uix;?c;uRtj)#-teU zhghA=m-&{1q_sx8hY@3i_tK*~FVzCl~420)5_pCz%x_gMp}$h^;51%G&IRVJ|)$w8Js1*jiZ6YNu~%k^o%|9!?z zFmI|Pk9yss4LsBIjcxrfwVG&;zN=cD`Cvs*Yam{nE#teYH9?G8z7_&c4Z^eXyQ;N~ zT)wLk92|H{t%Kk67BwyiRDNMK7=(6<+7SHVsdbseGC<9qZkQgzqmD%d%kEIV2ju72SjaNUdU#Pljn zl=ltVM6CNv*QY`4j09M>3j&<Wxpw>y8S(!P;k()Rh% z)E-EJg$)QiHHt!A3&o6xh0aThMshX9xNPl@zqBX_ara(YjD`q*ZFLMSD7qHt@@uA^ zp7YW|IzuxR60eyCSCXiCX)zXYynV&f!Wo^FaZGZGTD1yW*Do!^F-A$7MA@oCFD=@U zjFR6I0Y2D{r&Y_AC+66aPkm`orj(AD6gw=If*#v>Y0*grCu^0~55o&ap^xN_r|JnY z)lqceZ2Fl<;;ay95~&H1`pa09d}Bprm~^_pq`e>{1t#qc65In%ZEhQkX2gL>9*MgP zllFxa4U;662$S}sA_J55#~+?LfJtI#Xa&1o`v*`df{-M88X=Y8#c7O?q|DTTVnGxo z9mH&ClyorS#nUsQq(eZA_H!r#d=4JZ$|&h@BbO)%YX=TWqG3ni_e@CXNDx}2bQJ!; zi)JRV7-WV-?`yOq#iY?vkZ}hs9Ye;d+nzdB#IifF`qXhqgD;Lp;Hk+J?ABnh6n#km zn@%9%i7~1+yf z9U;1Hry7P$XOZP>%Myko=P*4b=TW=P1(UYRz>)KifMPly0Y1l0k*;-OLIvwCB+EsX zB??C_<}X#+cL|uZeHM;fiX>Qg83IpTPNA-aVn)P52aa4pt}A0)wpPXA$W=nzJveeT zMEG#z8d`9zYk?laucMxx14pFCF>pk@W-9Xa5;bt-2E;veBc2u)=&antB&Vp=&BE3- z91+JDCAUa44o7Z9GD`k71fIGbPpg*ITFkK}p9)9rpp-jfQtTL13c5rGj@(5CCu>sy zNA9NTdt$1iqqqY{?j>`Pu2VQbANes;oa7Wx^e^ok&D4Euv ze{*-2H@uU-KS zeD^8>PrXJ(Zo812pvMY8&+8<7BSx5%1qbxJNrvjP@D}+D=y{vE-?6%5Clue!qJ=%N zWW#jj?@5$i5-7+vq~1pwyz&78Pko4IxE~ioY(E}GKvT%_k!1-1vyYja;)SSvpMXi* zCkuPBp7kkpd}ej{n;JxS1+zXU%NLd6)t_2!3{6alF2LMU$WB`zO%~a@L zC29cBZ-{&9cRXzk)>-+3Nlt02KZUJp03?nvO8z6!H~{(!$td~15#Ycxc1ByZtkz1wHE1 zd#`~cjRnob8Azf zy?{q+$H=zMj`q%uvRVWz!+VE{*dgm{$o!IC6x9BS)5Q=kZs?cv*5Q&~TrBa6dI|i2 z&zUocSVJrf7qz3)H_b2crNF04Tzu9=i7!nB6?~(sr`ZS_F?Jb|%M!23upHP>@XI2= zF>5Mk!3PFQ#&xMrMvcI3+vQ2Sf~ECK-R3NR7+f<|@HfGODMwP1I5u^fw^|W)Y6$F1 zqE@2uStn7wNzF-=9OO(dbbDB}np!L~s~TwXD`TZ|tF@r8mN-`&NIhn*xC;Kj8-FIT3+NqjPmOH+F0_>W6RLjSKgmC$Dmi82?@>);HL)r> zOI)4V)U(7j5HDWm&JyFJN7`{6*LS|5pU#0CgF zwIL-GoxB&)BBm(-~V1#glG~+6)ZH z^yUaWHH=!_OiLbhrk~cC-hzZ%TEY@boiHgWOU}f7EAmvIrLDoIvlOdw+u$b{zbyh! zZAba8@nWks-t6tzo`gHZ2$L*#=Ig`BP`%|llF!W7ccN}Nd1+9n%n?mjWPs$(S@h7= zk`Xia*hQkO%8o#_D^lT^-4J+c1fJokhZqCT=>B91N;cT+u{&8tS{9xa)h8~4p3)e+ z2dPpV6E(O2Oxj>X%vsJrvKoa{Sl)=hQ%!h=Ef@15mOIns0=Y)VxNHH(r^{o6xO>y( zB1HJpnwj%B#68uDr!5Vg zt2QP%H9)lsTh}vZ@sUxor$kwMXG3MMmli4{qY{)6c&Y`ejDdS^O z>^NTv#ujJhJb?^O*0Rl<)kN}{0}qp^doQayzbdkse*AKSwsE7HTXDLnt#ugD${u<+ zl&thPXrg-&=M352%x(tHMbD7!Lq^+~`KL5JB%?O$i@;O+kw&`t_$f{CHhMC1N^^hG z9}v*@h3~sKr5Sg+IuOj-^CCJrBXo{z9wb`qmhI#tn=3$lctqwA#F$!VFSmbw^I*~L zObx0%zsW(G=Qo#)8IjO2s6(L7%wYYaoQH}D<|yZ3hqmWYhD5n&m=_!tuD62+RKdNKEf_if-0#6->XSf%UT-aVD>0IaWWSndn z^D@&Kn$v@JZUR=Oin+#y)|@J|t3nxT9dhWfd0cx-A?FWhvUnxS3x$??bpizS;AX5& z6#F>CaN6=o%)L{bm3qNwTRvH&vAnwHwNoGmg?K6gPn||kP)rK^1Uhsh2tr1X!6npV_$}$c_w4Rn-V}A(#yWzewcpi>;lixx^ow zaUy=A!r(kH)^w~FOOzF$dP6P&FG}cA1fIGK&u|YbS@nBZj%wN!>T;$FZZ|FV3JSQ= z3dnDQCcZ;kt`W!NI#g$4N3NsTTsA##U2alaXKoxCQ?6a^Xlux|G$W1^c4j(N59&g0 zbhARLPUTt}PyC1kxv;WCWgRpw?VqfwV*>$a*dqm;;7JAoCLz=j$*F{+1=Z$p4RX|#|& z4RR$e)IObzJ_!Bw9i+X}()w>w?1&s+%D;=mUG~GnXO$rz0Ahr?o77y&UmL}ha9}S1 zqSw16WY6ziCX4y^KwipX{=Fc<-5XRa`LC2GXEFbN5>M4)zH@%>0Z7rS`4UT9&3}-J z%xeBa_`_2VGl^rrfPXjZU7z8TeCqk~5#Z|~Z@X~1?-8*px|shcbEy~eA49x&S@nzg zkAn~O`w0Y|dJ@mdi}_C(6?O}I*sbbm{H}L@TPb*?$o!o_dM$-0CgH>9%bagkL7%D>1?( zOPvMbSIJPlrLU3CEC|0&-EUakq0LcmX3@a4Fv)^Ja&Jl0Izl!_y^R!4y+dKHBSg0k z%t}+>wqX7DU9!AqSrRr!z0V(0vL7|>12AdhWS!c49727FRMXmj6hupJH6L_QzMte-`5It(N}+5&jb0ue9Jd z*8;tY^gH$R$klS`7tJh69BA6!9}+dI<$ofMi%Iab(;=O!znJ8dy82t#x?U|89~mXn z&4(x(cxbhJdL*L~%z(gCGvaC0vJr|owi2YSmd`{fGsmRZp|liq-p*?IEM#!9R%x9m z+&mc{eC{tZ+WJM%)*O(Tg0|)aiKphGa<_Fx z^W~texk=nzv^5W;XtX7Dp5fE8G$~UJx&l8qplfL|R^4vZG9s2;k=3ViNP|C?MSyK;6zo=a zu@wCfpoT$T%ad@07-5ph4*FV=4Aq;w68Q}J>P_7>R(A+})n?JazE!edI_EwT4WX}< zk>aU33UeJHx^0IXMqho&Qg2zpsHPv&Q*s`)t3Q~uT?W+*Kmv+sAOcUVLXoa@VnPM$ zRwc`7mL-a6R_8BO+P4Onw0#!UtcfI8xE2CzNup5KLNOy^p@VAHCf7PKE?cYOsAjMb zcMsJJfe0VftV;{lb1l&0|4{1bk*G#GAA@Sdfu>HcFHwVPHb5NvqVTlvLg#8DCOM_9 zHWs$7QH}V>DA`1!aa6M@l2HjZL*S{+@w94L!^Iq12~ttbFiP1XCdH0hrJ#3oP|cQP zaI!WPsAemw-a4i_I{G_1U$-G~R#dYssflVf!pJg4H8eG2aj85qAHVu3Gq%YKw%HDn zQ?SkUAi*^)G{J47(cC%MW;ltvi*0s<6pd{pmWXY3q9TKB^7sRv&0vxknqN6O3cHT0 zbb3&-t8vbWJqYJGmaARF!YJC=mD$#4XE(%)`RdWm2=Jjj?vB7yBk`<^cJ?qTh;|n3 z!q2J!l$kKkC=goA(}+K?IgCjxOZm8i;{=U-q{KDy34G!pp90ydZrf_Kh-G&b(W=Ja z7kH?Mz*Ef>?=}gs8a-Bke@Y}A8zW3I+`&IBWT@WoapW`jr`FLNDwwr5S@y9k2`gkCf2`8DeZi!Sb63drLn`dt9|3M?pbPY z0;QZ7lVZoVQqW&ISm-1&I9ZztEOatepAu6YMGFoVI+es(vCwIxCKlQnEj;lYdpA(g zJ%Wl(hmI6fbOuOpTMUhHTWd6*4k|i}#N9p*AEIYW0`qed{f&Z>WfDeXHk=uwQC+O`09CbYjZ-@~lWx>HwH>F%ix&3ck_|Hq+$PZoj=CLb@X8$sJas3Y;W0oAv133ON8Lr1yDduyN8Q8Z z6fZ>WyBAE_J|9QjM;-TD9X^f{-4)DwfGiJMmINI25Pz)FxQD@{jdO9-BS?k&9z}qw zWGL6IRANlTP6tOlPOc|nT(*YAanzGS+&vui6h!zq>S)TQK{6`As|awx3!YXj zYq*$WD?uubdYw|T( zgQ=AcntF%CS<%$Hq$Zk@_hp*}r~0?nhx)5KYW$|4r}rQ;1wFkF5>I_Vg(38wm^-<#~5Te18#1g^NN7Q4$)5rM3Q=c%2L+YSJCj|$NW%X^Md?R;oUwlAU zAFA_LJnBq8tuy^M38%x$RNaY} zSnBM@ld|Ms*XhYqeU@ebpU#rJ!A+=lGa?;Xm z40}e5u>8oOAXoes5#+;v}ll=q13UjZP4(mc*~Hdnp9?YzyVP zc8hTlyB(an47qYKE?XhvICohg?jFuv4kCPjm!WF5fN8()Rcnr=J2bzYk zl0*&8?TxsnY9tHc&)3#6$*BOUkFa%(bHztS$;uLCYYXiNt3xs>L0<%(s>jo+WeX5< zY$Zs=x&0`me@u!+Dy3jVba3tfGB{bwhI7?G@|lA{t5ElF@q

$uIUn8Ew8V8qxH%ua9^#%F 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.kern._src.psi_comp.doctree b/doc/_build/doctrees/GPy.kern._src.psi_comp.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9cbde4d1a747882d9346c379e815231d6c1df4d2 GIT binary patch literal 62100 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 QE%^iww)zy;_Qvu52T$Z~-F-W= zD!@VvBuMn$dk?+$-h1!8{~Pel?%wHi3I55FZZ-4X_rCYNvbT@AUgW0Q57crPc|ujq z$F2xX=Q5tJ z$#I$k?z+KU@8MpM6Es_(uJ=(NkQLfLi1}bj6<7L!2ONCJ;tPg}Q^GZ1s(df-c45Z% z25*V8ULwATMra(NAqYM!M`^r#zPMTkISmmxJW}o=_Cp}vT@ywn+;^d{LIN- zPL$>&G@+f235<`@MCq3=rmCZL;rV#!M_d6^}TS@O7*N_du~zsrZ+ zofR9<=@s|v&Mf9?|Y3Gi_x5Wb#fb>!+qi28cs#IZb%LnHw`?0pK(5tXFe(azO@7jL zDVXEXH)<>Kq3>0TpWIxX9x%9UtHkA7@8qXAG+ugr>NZW4INE-IYnH`Nleaol={g&p zh_z(<`v2me$@~QLo@YRm61pv8rx$gp{a6sII5)a#^aYZ}A+|W%}~4nE(pwW*oweG$uQR!iID0ho0D| za)eCB8KWr_Wdi`KH^FKnRY@a=TqkG*eyb60Y8i!>FQ007zS6xGtMWc(nr_3k{m|F8 zy&P|zMn6HH^TWO`7h{mAqqaX8a7Q;Mby4J~QKI(VW`s zwxYo9om8Az{A`-vHI?$)&$0M+IyiLP&i{1Y;^)$&>+5`~DSn>C&o=;RsyF`fUVI0p zT_54jpuE%K7Z_M^lxX1IYEs4b%1OA5NjN=-Mez$Qei2RgoD~3GobgL&4&3_*hMA2a z+7X!GFSYn(R8c}}P_6jo18u*JF@-VjRc~>E6x##8BH~wO{Hhu)^r*1Sr~&YEieC*F z2Vgo%JWTu;_eAKLihWI!rjoXcqZs{Z67XwjQEDBl(~X9XA}lAq(Cy_Y=`^J71`U24 zO@abf7~A~%Eo==UHZh>Zgf0xep-D4FTd|G)XVw|TZ$u)|mImOwiN;LJ*yK0Ubl`-Y z6blE=dxGCWqv%U-rAg1hFx5^s=C>J$Ik|Qq)$4Hz)7+7M$Vhwo*wi4+Cx;*gC zl`)zwL6npCT}^qiNsA&$qQnN$$OEHx@liUV7a(!(ra2Rp!W9XJ0ixvh(3mG$X@}q2 zq&b03Y7)DNrX_{Y{Jw2E5~Vs$_5ZW^ev}E=a5dirNXRYPvAtmw&L2QdX1%l<+kH(b z{vfzQb^2jDDvx~#$7a@@Bs73wOE_KraFY%h-c9>7S+lk10pWl82UEi2rBcT+az=X#h*nz8BVb6 z<&&k1_;cG>0P}UzHtOZi1E$gFfXcoA7emDJ7ilcj?fO;xC90O!jiA4b+kQBhBK`_Z z<|pe4Bz%=-ZM00M1u9EkzSg8kRB#N3{sw;?jcHOlEqmSfFq*!xQlXjMI^u8A7@a)> z*WaRv-lqI*d4y(B#Tu)UsRdA^`8!)Q*%6_@`V6wa3uw6jb}0EC#ICy7p>0mFPb>aD zhNVe$zd(OLOT7YJUtdQzH+?@ZP*1Eia8xz;ho&ut+S#zB-;n|SYyJ@yN^G|LV_Muz z$50jgMBYU+reoPV6#SG%eUEg9AXlv)Dv{)GAR;u}d;F^{+K;szl~jEGwP~F>J^cpwn`YXgL&Gh+c<1;n)|-5v z{$0kuugL?L)CaK(E@0jDhPSt(zgGDVn5}=z_)i0~RhlU{UL4>*n=$y8e8^)<|Eu)O zqJ|l%Fypq&wp{GVJHsr6pax^}|L3Wip6Q*SaJ=tlzVGkxZ+g4CQdd={>Y33I^ENcLHgt9r zo7-z!S{w82Rm@Jww{%pM=czfeJg--tuexqXOKwWOV@6xPy*$5HUZ6U=&VT^}cAPMy zwz+t4zPVUvZEb9?%};M@Z2@92*Ic`O_`5u?D_fla-qu=dZ*Og>o#3Z!jZO8<#g>E1 zgSxV{3GnS5osFPg-%-1#{@Sayxpi`YHMlFgaROE-VC}d-*4j3cZ!9)+6sP9vr{`%e-l?Zz$wiCg&T=3wC9PB_Kx? z)addpFVvMCnShks-caVIk>!QEvP1ifsXWVzbY*K2aasiJG$=$Mws= z#2tlvN3OhdS9VMSZlJ{4ZLB)c`Em^%^~IK^yvd_&^^;Amv54-{US6gvJ3N6%L|~e( zaikirz7bxsY*%*EM6{md7NU(R{Bmgxuh8z!?9;`L8I{bJ@5-(Q=27nny~4WB3gfe* z6QrC{oStv2Z^6ituicfu$IH)(Ztpw6ie1@F`c7eTuCu)z-V-{}N?qBF67Vfx?T$W% zJLZ%-b7*ukhMkqWvYYh@JKesk^s50CDv*(H)wF>m#ZG~blrw$utQ{xpB|}21nUZ4< zEU(s;T^((X8rPXVtaVo(pV)Wex()h`Iv_{nHIm&gI;bWN3~P2}*Gsg@lqoqFl=sHS zP_$OE8zfBt?%d-$;o5x~UiZj16x&Q|L$0~JPFJGehaDtwRB^j!b@D7585V->=@08Q zUD+yVroD5Lj^FL&b;l>pCP`ydFjueFl^v0&U+r9BpNVRDXjgWX1lRG6YTaho_{1(5 zXl(3KsP$g2X!PPmPuf}v(qdBd*6HD_Eg zlQ41aTiz(SL&d?{b5q(l5O18^<&)glqHL1f<&%xqfTIz2>p z7x9s_yk)XG#UX2B+TSX9^h;ScSc`9++&hySXOXtiwM?`!qUu(-?h;71V zOUKup(*~`Ify5c%{po9$K5rOo+eE{b?bx&)U%@uI;IX6Mxa5Ue%n`V)t#{UGSRuD# zgS@;y6?QCnzb-4S0@oDo~&%#%X!n<{4*GL$^6I`@BA-QwLTWd?gCH3xI*|ie5 zMEqH&mhv9S<7nFCXM5$IeHG6!gdZx{D;YIG39(gTUGiGnsvsB(YGc;hJ9$4H^h(=% z_Zgo!#ipslT}EV+$DfGWgV{NloXh(rw?-_nl8LW>ET( zTMEnAY=?cEd5_9oUs!6wTBna|V-9hwRMjlWmpcNRAiE>fxZ|0WhgS zcF9Iflyk`nPquM+QgW+%;39k>Eh4E!S{xZgRfd(w}f)w9~XEiKI=iy# zCOUL87h%>sfD<-xt2ndxA>Feq) z(&6k3GqX?X5AE*8Y7b4G4bn#1zzAO2E;(pcBv^1*@;H~`Bjv;U1a8|@J|cNjmfSys zMjV;E08E-i{Vq*$%SR>aEYcJ|e&O`8qm$zvDbtchBaZ2--$i_*d~Di=v!a(kfo}ge zF1cmVxhu9OK0bM}h~l|Q>`ESTk}Vc&shX_M&r0seDK>D!K_?^+I0<8bouW@n9&i#c zV#~Lay0Tj(^!^l+r$_2fPF_w$n(ORZE5_JUlCk51SHy|*fb!I2<0dpe=vb%qb3}6O zb9%D26NGi#NhLj_Uryl;gJ%hZdiuonq&>@F9?d9{6Eglge*gd)e zT#&4|2x=(3AI!P1PyXq4r*N%wQS!i*G-)K6`r_n?Gg)QmP~}UKo0#4oG_rST+A&Wr zz7aO`vSh{)-O3E&_TS6Xrs4|5K+{#IZ;>mK-7sO03FZP3L>{5IGWl508D(vZ%`i{r$r9p}_|P^Pt|zA@j_UjBnuzP4@=JkHUc zub+}{Z^!ney?ouo^7VC#G;|uA!gtiSw{{vlXYj}Ibybb|hE}8JpEr!JTO!xl(c0A7 z+R@UA7+rfu&UBP-96L|lAU2(CqO zEmoI-GKPij*FG%pYv5WF*IKyN#w* ztcPnTu3>enL}~lOtEGEKp%&M0T zQ@3iAzU`ux!JUOIaBYceD_mRS+6LFQxVFQ!J+2+ZE3WalcEdFR*Y3FXz_ll?y>Qjx+8ftCaeMoHY*>foa(5w%YhPUZ;o2Y90k|gO zIuKWV-JtI~XxTfH0sarPMV7p(x zx6q2K4ObbL!PSnd16L=msko-$nvQD*u0wFm#C0ex57%M14##x_t|M_Bh3jZs$KW~^ z*KxRx$JK>v7OoR;orvosTqol?1=p##PQ!INt}}3*iR&y}XX82t*SWaP!*xEc3vgYC z>mpni|F=avTFI-c& zrn7EvL!sE*h@qqWz{K){(FgO|G1+4DsVe^o&*eSjl^@1)c_uf_A7p0N4X7K4(Fo&C zc}`*8x`BTABk~Bv@B$746;4Q}jgBV2p=sfl%i8k%$M?fCul#Ja(g z5V$cME}xlLHy=l~XD61QE8Lr_TR`ETpICmO(30z{n;)9Vm;XF=UJ&!2KrFvln705; zyi^@k1xDiLd{y~nDB=~b{Fmy&Y>6608WBW|UMDt40p7UF*DHvZog zLivpkSbT@Z_lfTJP{|Ko`A4dRJiZo{G_rnM=Ps@3p;!16EjbrG!mE1b*>m}kI%YI-?*U7h}UbXANNrkHP^Xy#!x z1`Tj%&YO9WlZUiYIc2KV!Zm%ecHMvuGaqP*rRVW2jcx&rnfX!fnFYw-?;OzE_`+ia z5qqGNr;0s@)g=*^&kS#4pNGs;%OI2~wxlborZ9nW4F(CyH9in4W?wuO-B4wQ01)z4 zA@R(DWLzO{-TVYI3!#GgUYGz_(6x#U%p%CnsvFqYIwe zTARfPvjAYEC1!DCF*JgO)GmQ+iDi!DW=Z6$6Q!?jFJd6?=rs8%vlO7vj-`=!W*MUR z!)Ktq>d9^LDE64~c%ZwcFsH;e&qZf8%aZ?Nb&Ih1VN=XYQdpwrLxn0O)P(qf2oA6jO z=QOh#O0q*-Z#1i;sBQr@v>A#LC}bEC&(sRK zOll`c>iD$MF3MwyU=t17#RfJ~DLse#LKtu3tgv_=MnMzMuLZq(1HQNE2;%_fl z>EiEz`sDE`pjTyf1Q6ud35jQR7K*d83&B0yQHk7kk-8|iIVH9L>qaw{X?G0Oj6*r} zwJQ?OjK|#{$V+4ieFY;;Ae7lnYdR;zq;G9$o>65cpdK>sj>I#2;BHB(?l7Iz%}+?P zC+aBsUWBQeA3I}HH-DjHO0%hBP31)AjthIEI>x*$kJlPnCf85L61&Rm0}u$2MdF!# zaaSS0Z9it}1_6qbN8RA5#r!l5fM$PG)D1*A))(@OLS!5?2M}P00C482o3Fj2(M&|4 zidwfIs?dn$VneZGR=BVr2BI31^Br}o*Xv;1!vd#n0e}}9rI&P~n^283;DJb^!*{WT z8-*%Uk2*B=AS9m2;T|-0l4Qg!Oap$`Eo_^M2uaJqrV(X1XURXOM2(SOo@sY>Fnn!) z-9Ak;O(=u2Oh)3F0`AtbYFssMCn z2f+>emYZoPgBMIk;+Yu&Fxv${W2v^zNhQA%9wLx4eMqiN`=>o~C{TT>y0IzIjo1K> zM1#&8E)k_@TF$hX!vHZ$dad?Bb2ti8o~cWCfWhhS{vy>JLEbVrrS*7!5HUvrvLvI% zU~F4-$#WFTR>uwYm@(R4n;ngOFH5gu0D>`a>|l1zW08qEZ*vhZ(&d_~%yFoM>mHB9 zGhMi&-;_j!P}nTV>ws_qf7i{=0n?m_-zBz8dOQNCD(y)q$ybaIG$utjnQ3?56=_ZZ z0^H_QB%V19ciWvQs16>3{5F`=wMa&ZlHV225X3VTF}oBUGT7mSTSapg0Oo#oGiOtb z$4a)Nog-rR(9zB%e0O@Y&O<%4cRmu&Tp-kDm;AO;Gf-eSpdvO?iznR+lQ33QVPoCa zoSVUXmAMe0@QsUv%*9HEK^T8{Dyi6Y3pz;V5`eL-M!Ydz{Y8;Z}I-5IcNG&+Ki)np+%4+@q>8S2&Mar1V z1e=lTP;dLj_4w_XKMKZNZ1^z85npR)og#0Go7(^cce`B(+@S>IMeaTG`An|4y>;|xcvCRl zw9OcrX@YCejW9_g5S5YPH}H_`F>uwn5jw-`VD9q)Be9GaM{2L6Lz{EiDw?b-A*Y~yckKM zY7a{NpPYJKj0J(Uhoq`fL?<5jFsn7N#)ktUDygo?R7Y2VVYo7!qwu18p|!E5Fol7( z*&taNXe$jt5qxG263;wBmKsv?hh_*{S_q}o_@k^XErR>3(xSNAmC0kQuWUwXG1fB} zqWsO{$d{JjjlbMo)f329mzKgEVmyh&Gf%MyBju*R4_XrSiRxm@R0)yQHx13ellR3D za7PYrT;zh785@Pg@9)Kn&C`_UvC?u(pwDNdnTVM^%YrGn(uzn+E8*75qUrV9 zAMr^H95f(CU%#cBF^87^MQ~!HZ!oF6O1SPMlIAs3p{=hY@yuU^jz(4}jdZrs*7ybS zx&`D72c%M%?NCEu-V}&*VcueWX-C{a^lc=b`J15VflugmB=&cyi4vPrqA;9V-eIce zJRzca7o}*_dq_O@fHGP~p(k-m$LgCXof?IDW_)M5%H1HRh1 z~n}kA%k`&}4EAGaC<_Inq0zxh0db_w{Br27BKc!g|~d3#z~4of)kk z=GS9)EPLV_Zzg_*P)eq%s&qL7i*ArhSD;YF!cwpywhuSNHz`fUd~+k#Ydq#y0?osC zv7~5YshBnxs;>&+&C-D2xUq~t#+)u#MJ&tu=;lc1RGH;a2bRkt@yrTBh!YN|t|*x( z)j1_f$Dwj1)+bV}*VCqz0RYmgAi?P*q3s-!kxZO4r6B3mnCjwSLhwy0vpP!QQEMRa z%$m5{ahM!r9Jbn#=)_u5nk?X?)<&F+tPKbVxDFB=RN@{8SRMwtYD3qqONB^#~|VsWR)M9+XEQ@ytj9Tdj_gOq?=> zAmt5^+Sy}6{PxU7g5e9cv1H=t$s-Bu`Pve+#Cu72}pDg;Q*W#4}stZk>V> zs8cLbDWlm&YCsC%g)`=Az}v%*!k`Dy*0oivttl|8bU0XRM=!Iq?2*NY`zIdQ8saGaCcpfB~xTbAi%%R@)#YuwR z;G#FCppz2~m1lj)?`uuScxJMo%ntWJ1u2j&rv6ybtH_j;icG_uPzhPj94x51@gQ|+ ze<|8;no$E|O%aq92Zgl5e$y)TZ9zT!u*^)*Z%TdXG6pF9?lQKK?LaR1J);A^aneQ! z&@)JuJ!7im?zk5=Lp9$l(*?MlAk*2N=bi^!DgSGd=4>T%j*vN5$;gw5 zyuG zsQF^a#7({=%BkQ>SYKKhci>-2$%$gV;zmrNX=tcZUFQ$4}nBaf&4TH4K(D1vpa zLgJaLakthXd9}`3@~gBq60p4niD&+Rd%*Tu$)vNr4)xYkuNU+`y688gppz4&zL9Bn zwgiK3SIkZ3$2z&m#Wpx&chES|GsWqd>iA~a2MkXbGI^eFVHRuT4jQkC;9FQplh{q* z3dP)v#51?xj^_R!mH|#kb*U9Pu(8o!fnSv>9qLvQ^)?k%$B^446Ss_Ys5@A19qLZO zzstqHI|ZMtXqtPNc4rraY1E-I@)YX5D2DFtL*kkHakoxI7D-O^fIvPNK%y`FNiuQK zE$fF+Z=LF4L7(lS&q+ZiCrbVZQX6S|6u&+5m|*w|^2eF!*DTrZ36ernk|&r(r?)3j z2n{}k#4}IhPVeKxqrut`&Oy0Vn||cWT{4xTZo;VLRd6Eo;b(;Gvp(6!L3SU8pp1+O znMS9R`5kO%22X%DY^y0Af;D0* z&@v5tTBxd8&WEw3k~c;0-in;|%|O7aG0&%?0F3A1aEtdzz;KjLtg0@pHm1l&lIKOE z5bGbpe|8g-^Hy7xTltuwuV-=6uiV9d_`zoQ)UBANsZ(fFZ;IIM7ne@WUK z)6m$(>7p+arThOSUA%%8p@01aiDzDww$Cp43Zes`TgiWP8vK`|)7J#{b%n+7Y9AB{ zj!yq7Rh7Yg=jgPX)y~mr<(FdndvsdIqtiD)GWqEAP1JbiEs;p~62UodaCG{%2oyg$ z{Ts?7XB4rc)4u~ok52i^J;HcLs4k@g&AZ5W<~Vu=x z&yexV=PZJ8=*pwhUj=f&e5!hARgX^Rk%DMbLhkdT9^3^U{N_UzCs#^E zMkLZr;V2z*+b4Oh!3;qa1gb)Ucc6rhT9u4lft;h$g#>tE z2UzXv9-S`2+P)o~E(%b)pj%8xFCLJ_{I-NpvX8pYougCsPDT^iayrwJNbS+-Quyte zr75M|%`GDtv4>ffpz)(qHk6c>V;VU+T^?ny$qGntpn$t|O0rU$^n7%>l3=dvVCn#D zM+19wx{5$V{U%&ot;%}4y2=RA)s$$q0iM5Cp=cWMG$2kmBd46smkYvY4SB+vcI=sU zwrN%eKPa9p`aMk`Yfzr>0CP=blU`5_9zkD=@ZJB%w6-?b!GqR8f-@QsZg$C6CG7|& z!k)rEMywI2brnhmBh_}vZ=^j&T#pcXjCd5R9~>i&^6->wPv?jS&K!l4M*qp$n(!QP zq&_)YagI0&=Zy9oail#+jGrR{tRLry;e)lMCD4p!hr4jU*H0Kc_@i#NU`{?7VLi zl*06zBJs><-0k2&4mx;LhJ`j0$jt*tNIpg~>72JfeQ7;y_?Cjcm5aW03OYGa@NHOc zj{&wt#xvUqir?_a={sU4Me#BUra35Jipvt;7v_MwLZHQVHUfox9)_QP+_>`w`BIzY1QKLiDwSN-Rg`yRA+mM&iGWD22VhP>nfg>bj*|pcm!G7b+(o9L2KJjSC^H-s(hj@GAyPjxsE0!y%1r;dhzFE@cM;pj!+>nN z$l>_ynIk9xx(La#iySHWxV8Q7Ee1@Q( z>7t*Nf=*7<>e;NfZhQ_ho;g=gk`B<$lbSStCU=rNpK0s>?E;iSj~61rc@gf`Qe+zO z?qGbnSdlIfq)Qzn^6L8m+GR@Sav^htlIiOKnsQ1q8q3ZL#@}e5+8&TyDNL_YrfSlw zB@;KPT?}2rdb=3gF71iKS&=F6Pu~p>-}KsUJ>Iy6+<22e#yi&Y8~ML)>}t-Q1Jic;y;vv zPgYdv!%X7`TeDFNz05&^7gKPz&OjDP&hV%}J{Ca286KBRTy)F&3DjF>cv8@xa?zho zK_@3l{tQwZ2YD91J@cGk_{-Yond#T;)$fUmLQ|3#m`10aKcf&Dd=Uu_9dM^-MGv+p zw`#MG2U|{<{$-*3ic*HN#KQD{k*d@%{j03jFg^d?SH%}8`x~U+jzRj@KrlH-|2k^$ z{)ot<>y>zrzFWkJ2kGBHd2d1bHvywTdj4{Q^lu4OKS=*JGI*VYMX&|`TB`GIj{C}6 zAKq?alMrD!3Pk44J9@6X=I@jy4A8$LO+#j{B5Y z-Eo5EGgP3JpCj?i7eYn7l9Hf1VpY5~wn&J3d?_IRazH9Yv7z~|1R`COuUT(H^WO;3 zZb&e#G65*kq?;Ol4^PCxQHrLWWQD{VWC1 zri9#oK|Q$J(EP7LWdN3AmLKUR@tX%Qo|#u6(?av}Np(8+`B4wfbpz+W=8%jz`F^z=gmqrEQ`B!60%a8 z^cRyV}T9LuOJXnzX`{J6bS{$C5`<5u!Qc4JfY z4X4VNh|&V^wPqENg?=gc?`M8kmC}Uq_lz_>rmgS=qSXlB{Xeam)j<{Bum%#mTOl&c zF8TVRP2dn=n0+mQT3exHd7~;V`E9Xb_H_uMVfI5|Nk7cqbA&x9x*iR#%O@?u;Cl54 z#M#5wbQpBEA$tAz#cvC+S4(SaVy$%p?CVNx%xb}5^m?KRKfpdz2o4JfV)&^|#Gg|l zZ+76}thZZ<^^x(+2tn~z)FUMm<&OY8%85UUX)M6L0ZL)?4Uyno5Zvt$Kn^+tRBkIb z7RXHkNJze^WYRg0M!gNNZzkxQyXa$5(8-B{Z^3#SCfpJkd__)B{DyBWnK*m0BK|f= z?bxy{ej`3F7(V*;l8K{}6VZ2Iy^XKzhztVsf|3+q-&tzX;w$7%lDjaCEfL0|6s8!5 z#523%ZcRa^YKmxpeY~RVCMXje6mklqhr3Jt9zi{9wkI?F+JBk7fZ}e#!li!?0e0Ku zIw0HV;okU-5I-eA^pIp3JRBQiD)xR7%-CB4f%@(UQVgwr}Kx za+6Zl_{3z%#Fc9MMgjG_jv82~Lr^*$6w(em!BnZA7SzM#rZdyOPA~%~{q6*|k%s`; zc7mDsjUYZHKqnwsb^=fGaeGmCs_8JM(N1tU3ZZ}_kRS+;yX^$z(Q79-O3;pW&{S`3 zCpZSR;Bc&f9+w6xA@t)Fv`au|DX8=&{~Z)1-jf@jAgCuQs=Dz>l8LLuy79@Vw{Coj zpr7iZpO%77PSon@tha7_1~Q&GQ&5sZ=x0eynm>~}NuJF#7D7JN^egWwMB%ZktcZ)<`eGj2uq+~7@GM6ZszJ}11Q!@+_{4FcDZw<;9uq9U!8(aRy4phOe;g^e?Sowc`XvpT!*_=B+0AxE7v;L3*;XI zNOaH}Boi0gvb_=Y))Q|M^qXDuTT;-;iBjLnv^%>sY>%&AHWvAgW4}V@;kOrR&21ot z_TG-fGk4&Q_WsY1#&pESsm^*2oZl%D+@%tz`R|rYT#wfL_psiY|6akr&&9t#1)r>_ z$Oo9l1LqH-7%KS_63;w@yLADwNOFOP1#)%(2^W|nnYied^&_aaF7T+JKjxx8o`OzJ zl>7;#HcIg%e&dr*g5fV$pJt|Cb5_5nD+*0Xo?#lDY@S6SH2546&peMiohlkQr`)Q| z{s+!q5Xyg6%5aug;QU3YN)4R9#A*$k?}ToY`uFbo8$@4*LG+hFJUNK|3Tp5%Cy`B8 zEb$=vt0Gz~h~8WL{57Cy{G7ks`1$KX(2t-06&cTTvj`^H5^WFTzv)_N99Q2smap0* zekF{pLY(9j5SuG;^i;Xc8R=Wkd;F zlPlwYCDNKxqAVP&zGA9_Re)!{Mj@K?4HD0Mi@P1}$xH{R%BcIl1@b$EOp0Sul<%cF z+N@BNA5afblA_>0q6z~2gv2xd5jv`4GIj-WqToLZ@GlOqYTJ#1|H|6FMZpK)k9OGk zWgh%S&>weI3>r5dGvWNQKTZ<G{C8R2K3S5%aIt7l#c;cT$@~d3^o%D|4q_-5vB~N-wqXyp|5^2&V zy=6t1*raEcLwRpA-|~RbnUBBRnQsN5>d$;DBIB8rScD;T!-`SbZG7*qcCkU2?~VY8 zxia55(wdbiOE|-=BF)1Lw<^nz>iZ0r0X+PBH6)%{9rwx^ZVjKD%y3Jm>CUVPu%70$ zwNM|-X=@|nnRQqMgYdO%r(x*WG#F+vzlC-ds}}gw{$Xl}rE7YJoLLveXy1BBJTp{i zs4r5Aig|08fYdr5m4euLYq&t93$i}z?YuQYh>ldE3FpP55{b>U?ZBPXTY>NZ|d!eINC1Y10XQtdHNt6j$=3nOiS5a6BO&zU zcX!yNha+EnicyYk55TBid2E|mFJs@Ds$ng2`lkwh)B93+X+l%13GQ+3WT}lQJUGrR zNb~&T+@cUH1q9L64o<|MQzCEnuV&WU0M`^`aC9Ol9OZ!DDw!z%IVG|pejC%+ac&u< zu%tnPzmbEx?V;qLJ+v~!*&&df0VFt2l}tM4X{fiyxzh!GhKqhk3OYGa@R_W)M^=X- zgHsPd@f&`aWa8|}iui{kwc)iR@Eb=Sg5jedC7C!nIT8J6*4tSBG05Pp13^hT&OJ_Q z(qjGOPLjtnjm_X)D1|9zA@R%!xLZ?@shT2soO`08oFphGJ1FE7o@AXO^`{2)u-R$M zguAw#@lbnjA0Rv(C~jzQIplRc-otUOZSolawkKI<;Wn;8XFVL}ULa@}I%ujlu)#)B4^u8eEjU~(pqC_p_VGm4 zT&k2V6H1pWrG6aes%S|^DzDs;+Z+_q z4m-i^Qh!HK50|@>nf`TxyMWT~PGB2(H;`>7xCg&Ib1x-8Cm>mNg8L*Nw-<${n(k*B z?F0{?5DIt@2|hoCyX^$z(Q7AoNYEa3&{S`3Czy>|aF`>YkEDUhaqgoE`j~(|uAtJJ z{Nr3D-jf?YA*fF(s=D!0l8LLuy7AMfw{HB5pg-%PKbL||PSoo2tha9b0y6lFlAt6V z=e{U4Y5q*^B>584*m3U5D1{zhL4wdf?$%Od8u9L61bS7GUK6C(9VGJV`*H4Hl}xvg zc|*zc^*C2KB^j-6$GL9`)3=nVn)GeS#7%0KJAY%nUGDr{@ZWLq-%Y_MD;nTErj^IJ z@1qFX{|6G!e1N;vKFO>0E7v+73gkxtBs%EFl8K9L+5Qvt))PMw^iN&%&r;CIiBf;g zv|A!lT)jG9CF|qY|GoeLwDC(M2!Z2{HvaeIu*G2`R5!gJ+kPcnzgDhl=5Hhu*OxW( zx2(5j{_pJd|bF#xN=G>|5R6dJ-(vZP^izh^*30(8H3e}fo5{BdU4d?13V&B}JlG zu)4Q6^-@67I5mH{aq6XopdY7R1{pkP&mvf1Jv2EyO^h{u-}>TE{3X0jCR6L>qk?P! z;uFULajrzCqcWQ1C{P%pUS3*;5cLWy->mN;>Jwx>9C2K7OldNpJa6K4?&vRHx-!l!991grhF+Ff)pJO!VuM(#Oh9@Y1Tp= zn!7dLv~+n({77l)<+i27=Z-ehrwM3OFVLp-#VsLp017($PE-yMj`QUvffY%qYVgI zZ-jb(U=tj(F$%zZ6C`*7U9eS$WRk>uv_NjAkkSV9Dze^Oiqct+LA~E-G| zAiyoS%9spX#!g^*YXRQI0ai1*f$42o+qb~G3FoO?E@#nF+XCPb4d~ zNzZ}l-34 zUgXE5b8YzJq|=M2Z?2@k@>Kq2g2D`x9UNtw_k(E z3B5@HJveVeBKn*XS<_=1S#KA`d1O4(Bq$s=fInF>QTB66WJUY}(^#mth*D^wgapxM z+^x@(gZg~s_NQ4Orv#AT+#;ED&aJ4oq24w@FT3a_1)ZEIcsuKDII9C0{LuwL@f$u> zGI91~Mf_<unt1P-GBk78DI<$>4vO6r^qc$&{21 zXR6_>B6NNPvIsj1s*e4nt~w85y1|D3DAWPzXhAy0K_Ye8@UMuWp`~-mBz$=g5Bs)G z;vZ?%K>)A1chs0;mBMjC;drHx?F9)#h0;&j=3AR|3B_4TQJwJw$;6dvZE_;&txZl6 z^pjomQ&P~$iJCl>_0}e*A%nlgASk*k3DyH=NMV{?$e7g5WUAX8T@{>#0_gf|B%V13 zciSn*D$PLWD$;p^biRW`He#TmFcAKDZbPx1BeVY&YC~>nv10~4Q|^33yjr$zHRb{( zd7+TJNJ(bJL(sWyU-{u1A8wm z&xEJsb1lQ=&js-V@_jJj%}VwbA$zNmmE+a^Qi2&(k|Zv5ZX7icAKv+qU?KGq|m=-?Pg z8Emuf6-i>-Y;zyVd)sT@4;bBR^Ow8Ven6=Dd+i62LHL|S*xK1Un3N{0{wsM#9$GZ=2m(KP|w~@he;gM#qjs)N5!QBprWT(Sn{6a^qO2)20&R+XN z0shDVR{Oep?T=a8x4rg10c!W!p9tws1JY>RXF_T2?zPz;xz}dP=}ey^wR`O^@Y^$A z;;y~}k^dzbv4{DJpz*yn8%j!FGmY%Ezd;#n@+}h2{2O=clw_qg>3OgHonU_NVCo=i zhXK3S{y`w3eiIG@KeFDgV}25%|52i{((2a(U_S#98l-5yi_!iU3KBm3^{cciri$?C zuK|O^P+Vd5tKIVe55}Aq363~$hcQdOGN@A66C>w^daN zqTnmD-flNnK?Z*YSWx_iXCxD6PgcZV4XN$ptK+w4)({LIeND;4(aDMEYq8$$Rn|rZ z@peH;dfKa6YSOkWAX7C(5E;P3S^PToFh!{ql;I8v zIic72hl%S;{fM9*HXF%IZ-)~my%>`|YgQj`|n;`VE1!}=z zO99;~3AC?Idu^?hwh>C(Dy4or?WLk6Z2)cG*iI;KuatFA*g-OJrP{u+BkFD6*h$cL zcF}i9K_@5LWGw4#-x!AszB(f)&eLAwr68?KkSQtc#xz_%PCyo)h!<2{u913jC)fiu zu+W}@vX_HG+F>WCllr}bdbr#^%=E7lWP#G}PGB3kFOY2~*bl$)iFitYPC&Bk1P4ey zZZ8T?HBDq1?F0v+5DKVAf=|TbZaV>a^x6q>f;P!PQ@y#JpaHeu&?un!G*Efkt4Tp8 z3ur+>-KV{jcu#Iz6x5QUsv93HnYdc48#klgy73f2Z*kFEQ_#tYT5V&!b>lKJ_->4# zBt7lbE;VWXOztGv!BmI%@H2*{6Q$7OR3x66hP$;CnMS-j7=flM(hNa5#6co22~K4& z8-!d^{($UEC3C2d@svzopY~EtNk;2A_+(E!4ilz_D^oS;5t50U)Gl|9WW8PP93}Wi zyZFbX;FA>%a4gfxr@f9t5ww3i63=wuZnaPHs{P8f&MbjEA%H{&Jy9}ou`Sz^P;Wi) zWI;d0ML#tKot!B3X-vCyRtVod37_<8YBl(LA^uLK{IyqeI>6DQGmzkWGq|HgeMQDz zg#v23dw-JaEa7ps@=z0=Bbm4^tO?I$y*1%^f`7h?e?ba9Sy34mGL1jUbrFiu=!=nf z<`Uek8Ob8ajF$@JWdS72c)4WaqFdHipx&DCNks(tnQH~Z zUvgf@OmFi}@Pt*rryB}PDXwSgKFRe*6hLz~Ai)RVai_ZkeBcn2RW;bhC%HAvnJ zA$hY;lH<|%){gw>s_ks*FV=SUYyn!i$A@*}z)?iU#(Dow*ILX#4F*@Fg4akT0O(D>V3xHdlnn?-Z!J z9H<}wtzq)JrK(ai=MQAw!)gtaZvkE4+^4bF&{3S4uV>`HzYnDy#Ax}wAekI3zYjI| z+r%P~u9X5|gJ}5!B2X+^9#L-WZ(}|PG!2yVmm4VmlMwU+cOpYCcC=iKzJ_EI+94QS(Ou4+ne< z3BH_Y0>AI-C9e_KO1Yk^@pHj18r~ED-6! zyux}LO8<)xeN~BOxmTXj$)V-7L?Uxa6oTW)>rA_S1oKzq(1>m%o_PazJ7SQ$j*^w3 z^EU2m-&fj@n2Q#oMSp3&ba^kPn-^MGvf6gn?z5WFT^e^n3& z9896}i%|WZLKgsP{nTmO(Yzy(|(0 z;DweB#FPr1K0K^mUO-lGKq>{YGwg~2kuK0mthY1l%0hG%CF;zut0oeeQ=$+YzcNgN z8Fn?~(1_KMASjQ!?R_Ng&L)=angY3&LRL(boY&Tt@@NY}=Ifx|A3Os;tVS6`s6pbH zb%lWHk*tzLSWh5_Dx`d4Ea-fcVVG2;%TSAY$iT>YfMW=);u$4gb}G`}0Gb(g#m`a^qeN?UWjy}F;zl5N7NeF8`&Pwl&-#xr|}BD10&?$ll<1pTRfZ)9-Rz#_~OYgbG{w#}2<5@&7-kC~f)_F}Hg z+`f2*L#;Dg?<;M=Y`q`LH|hIqy+7dL!v`So%tYKPXX^ufaxz;lo}?&K50IW_=z~xn z%+NVxJTr+!&^*?h*2mCkX%)=Me#`8v+#s;2zHb_drBP+8n>>oprY0nK4qx!q&&VD9 zGMtGE0#bB9Duu8!aY-Q3g*ce?c1mm(qEnQp%*2!1I1#lZ5}8w?5FBD!nd(eDxy`g8 zheni<;Oql;JGhX%JK$Tk?E=}MkV$h0W$2XZXhT97rlLM&2AYN{2s9lD9@!TNmj*WKL$i4bPt%h(NPTzQ$-G9SQw6s?HIpa}^4QNmi-u^Hk?aZLCqj^Hk@f-kvXBAoMN_ z=)u=7N<^PiB5OMM#jLl7Q{cC{v^^B&E1N1k6_)aSTYGk0DV~zneuy!iV^)Y&B5UhCKLT%_!GXtaG#LB zU&+%;3l9|@DLh(utnfHJL0>|`EfNp^JzJf*d2Z9Od1Uxpa7@e6-4K=QMNdJkkX%Go?Zl5
  • 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%0DLeCN9!}{&^{}(VpK0| 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.plotting.doctree b/doc/_build/doctrees/GPy.plotting.doctree new file mode 100644 index 0000000000000000000000000000000000000000..094aa9b731a017cfc433c257e1cc8395460db3f3 GIT binary patch literal 3691 zcmZ`+2YVb>6_sU6TCLS=%fZAYB8l-Dkk%>SUcitOI z0tR9rL8ABGd+5FQ-h1!;Z@_sov#ZtSvp%)meed3L&po%youjT7yP5U_wG_pkP<8V% z6p^m;j^pQfH0PZSnv9%K==DS>-j(xMV`YA1WTcy{FC{^&wI6jC630F3bOn#MR(9hv zm9?vP6i>8PX7N@Sds!eB+&I#(uDI69Xb;XQ?Q8gtBij=l#gjSLX(n+}CG1cr1*3|0 zTRcTGZkDFFYO6R)UBS~Ws(ZqXQ^(xqnHKGJG97o~SVyrIw$e_jd3JdRO&IvTr+6;s zJq3qO^BL7#=?5OL@P3Og8YWN)*8r;XeZb#= zobL<%QfIY7eKC#DIKo39d{B1ZmQ#!*)`Z@78AiOiV4 zebSdwrTH*TXs2rebuVKgL8fez)0hBF>5jSt9c_96`cJ~Q-_1{TXuJaPv`w0-V0HWe7A%XO zE^l|J7CLJo3n(AqQTxY)L?xmkXJ!6~ON^pIPXCXM#r-#i15M7va1UJ%{ z?3SV%PQM>{Vy(_GlAq*^eoX0onj99_9|vg!Fs_d2jD z+FY+MH*MRGd~MrH$@(d@8?-_*Y2wbpHi}ZyG79gkjIea0l*7IAZ*kT@zlD)N@VS-! zLpoS!lo>dFp={8I=G7t%JE}BfZR8r?j)|6b>(q%Xm5`S z+e{?@KdbmPfUyszvrzOh9!MrVnQ7HPI1#cx6)(YXfTyqU&K zM_K2$&~)HL-3&Vl&U=F2N~369Z=*@i!Q9nOnDE;T#DZKq5a&d|@4)n&LKxV4qH=S2 zCl(p$1iCu#uH`YBu0T{n`rR#gqD6;9n#QROq_GDP+vQ8?L|%Zzy@%#ZR0>xl90rJz z-%DejXlGr1UyJ4hnypFfIvSZ2Li77K>2RFsB-0nN`2my**l;!914zg%I<~!L6wV(+ zPG-FN|eYv#1RJkSwr7i5<_J^bel#_ zp!jpBC&LLg#$xbP5r2LYOJuR3+D5(n1;8{K9Z=a9;bMq*{t}I4y0dr0&(*~6lFJEubBq}(8Lw}9GfyOkcowmK|dl*;WT&~f~ zb{+AzXpGLBhU;(BL~ptNjyz1WsA7$c%G3fV()`^Gn(T^5VB-ea-vhKl09%xNA7WP_ z)^3|Ktl)}&fB|Y!-7nA|(n7C5S65fj+07g%3e*$lnmDSO{3FvABkio&((lRuKbn7x z-4ly2|AY>0r(>uJek$*w8Pl=sEed`{qrS&K2U;vQW+|;Q^@~k9Sk{>cL{aP@NlUx8 z8vhb%u1GDks`ytHT~w&nkCaG@hZYeT?mhnX2JOa{k4h?E|Hib=f}VZ@{B0|1)BfQW zUOuM$4jWLhdjCG>KQ!cCY{UDoF3w|ud&3J}*U(7iC zYcce((Em+(W|zaPRG4!cW~naM>8)XwLC}K_WaXgxd(QumM=(%e?Vpu3W2ky^!OmWq bqRC$CR{SrE|4rjYfq0tuPtO0%+DrcjJ*7(z literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.plotting.matplot_dep.doctree b/doc/_build/doctrees/GPy.plotting.matplot_dep.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d12ce4422d89abe0f6b5bef8be9ab15335061935 GIT binary patch literal 324363 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ȂZXs-yG(#Gj$<>^xq`^*tjr)9@S8*hIu9MNtQ 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%0D$ej5bw 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 F|36O>L8t%# literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.plotting.matplot_dep.latent_space_visualizations.doctree b/doc/_build/doctrees/GPy.plotting.matplot_dep.latent_space_visualizations.doctree new file mode 100644 index 0000000000000000000000000000000000000000..5c9e38c7e8c9ffb1ed2585df8e8a75914c864415 GIT binary patch literal 4171 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%0Dx%akQ_8OyrM`t#iPKbLl$w)4qtsQG+grg#zh3?e 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
    ;=T8%{$4Xcv>}OIi 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 N0iI>Swr#?o{{wrWeU|_L literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/GPy.util.doctree b/doc/_build/doctrees/GPy.util.doctree new file mode 100644 index 0000000000000000000000000000000000000000..5c1e9efae92301ef04dc915f26c78348b60deab4 GIT binary patch literal 701457 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

    B@H*gvu#WC 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 e{RAkRU%KitI^XV}F literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/environment.pickle b/doc/_build/doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..14100e4a388250fbea7d2cd9f5df7bbf91b2955c GIT binary patch literal 1879784 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 z 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

    !g~bXQ$2`-JhU2RlCYY$?UrK0z*;*g^#=` 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%0Dcc`VP<8-BV4AQc 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 bK8vPB`W&9-JRet*==1nU=nHtp<>CJa%Oxs& literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/installation.doctree b/doc/_build/doctrees/installation.doctree new file mode 100644 index 0000000000000000000000000000000000000000..195db464b8ab5c11ce5e21bd09dc3a3f2d4c7a5d GIT binary patch literal 10172 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/tuto_GP_regression.doctree b/doc/_build/doctrees/tuto_GP_regression.doctree new file mode 100644 index 0000000000000000000000000000000000000000..0865f87ef2a81a4828e73bfa30b056de341ab4d3 GIT binary patch literal 24548 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/tuto_creating_new_kernels.doctree b/doc/_build/doctrees/tuto_creating_new_kernels.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e763c1092a4db32c5fe1f66cce01e513434dadd9 GIT binary patch literal 39580 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Լ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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/tuto_creating_new_models.doctree b/doc/_build/doctrees/tuto_creating_new_models.doctree new file mode 100644 index 0000000000000000000000000000000000000000..0178e75cad0ec4b2f2f9745b2ea7ca1f0800ca93 GIT binary patch literal 21287 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 E9}1F1ga7~l literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/tuto_interacting_with_models.doctree b/doc/_build/doctrees/tuto_interacting_with_models.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a28bb06ced18158f6df1bc603cef7baf940417cb GIT binary patch literal 63473 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/tuto_kernel_overview.doctree b/doc/_build/doctrees/tuto_kernel_overview.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e3c0c34eefb84990a9c59847579accd163a3f449 GIT binary patch literal 38768 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/tuto_parameterized.doctree b/doc/_build/doctrees/tuto_parameterized.doctree new file mode 100644 index 0000000000000000000000000000000000000000..c0417a75cf52d23e444b6f6f314a167158e7caaa GIT binary patch literal 11754 zcmeHN378y5b(U7zYouLCYso^E1Z~+uBO%TD#Ad-ZGRC%8dn|0Vy&TJ^ccx~lS3TWR zuex`43~gHm8?8CbZNOj-gE2SG!IhAkgq$QHCpk$%PRKN|B2HXA~#wXqt^ z&um(?YE{D_ZWUxn$FF$!HdLG$%s!~$;>=j~!oA#EMMaIAnAz6d=!9!uDxJ?oTH;}Bv)tTsXj zau#(EQCX->_9}Y_)F7ssSV2LQdE%Tp14B2*YD-?CznqW*_E0+h%$Z9d#iR`C!aQiQ z4BbuYkOIFZC$Bl&oP-)DAwf`TsfiU(ARVf$_BOH9z$_&aRRJc-qEeb`mRQN^NwL}{ zM|yb*9jXbKR;x&^D}#p-;yM{d`0 z->kY|h2y~CJdsluLcSER~yXxW0%iUXhT=nTt^=4Kz1Q|4=)g>&(rCnlx#};oq z@iTf&dqgb3uu~_Q?3s5RSI>&oWnfG4#1}<#PBhm`i`7*lry+Cda>#K-te(ws+_t)p z9IkJ{Pc2tlmB1HPC@F|)($axdc05m1td{Px_%2vSq*&Q(A&#;xRv5H9Xe+2%j#Wo! zc;=_yw2rxcrC=RwcS=WMQs0^rRyptyMGhROvfrw@OZJW_+g3`00;sxPhgYz|nxMoA+|L@FYg!8qxz3y?3?~J3u)|qKTV_&Mvco*5pTi8Z zGqb~7C8wS+;P>8u&qV-U9jj|N0NI#Vm;jW#MqC@KLufW@L<$Jf0NV4q46CN?O)d9H zfDE8|ox>=0y&Q5FCUTk8i+RaNbVIBTa|H8xdpJX)EZEfZ!N;`;0!afsH+D^!LQjk4 zP4J}tgpNQsJ61Qda7^@uL^#HfTVgfC9E=RCTGc0P+bH5>k&MXch?D)6qfL-;L|Qtk zVdV}vdOJet)MLLM0BiC$31NvstzaEp3 z!ku4|yrqMYiVN`J<&kp|#+n4XqDIBRipi3QYSk^f$Quywcx?n)yNL20G|DVwY02Q| zWQbB15TI%4hEryAGQb2*=OciQV^uvTwEU>v0BItpx!=+u1H13rr&39F3L3(%V1+3y zLHL|n0tPi>bt^cOOj@U<(fZDA>ZOcAFU#A*7{eP1X2ZY;Vwx5m@>RTyS{6q1JC=L?xw|q-31K zaQP~H9g#`%R+2(hh7wL2_6;+H1S&*j=0(Vfr0_YP0V_cxbWvU=e4`2uQGHqg;S=gV z2tiho02b66J3_`}K5yz5G80+cz8O|}Lc6D|-M7Gf-x{m8ad5Dv?=|iUyft8ZU##Aq zId&JgzN5YetW@hEk_sjS{5hfQU*B{Ryq6EJ-sR_|f&zW`D67{D|E(WC0U;P1Xp z@O)nv7b$|bCVjtTcziHcA7J5l@B`^!1Bf5&2Z%CWmbcC927f03zl5hgVE52>1Uq?$ zJTC7n$^^JJGpu|_GC(~Xs}Cn^0-!#U0n|tH@*eq6H#B{$8=4+u8Xt$#^DgjVh70ux z*z}XJ`c!7QhYcjjZX|jnRzJkH_$G!O0cZdxxX$s!Lb7qxLI~bl!QM{0L`q9NGnZxH z5;2X41#npif2$h#W;53T1SXp~oudtaF&JsL-atWz{U^W@cA2o7R0a4kNSN}iXGYPD zT50*(yQ`$R;N?9ekn3WarNB0rz~)v#{cwjP8A$n&evY&?^WGnYc7G7n^lA9fXJYkP z_DfdTBN;X@JS2OtT{fGe4e#w4;ojR9!TRM-NwhxEjF96>YEMg={5FR&PeRx zTMph>JXE|!{aDw=?T_cps`-Uj{Y2u-p#GC9Z8afH3h+~~6K@|M;az1bSP;aU;@ETu zuqO~uSWrI=iGC(lKbu9y7m~=ha%H)fF5jg&FDM_&sh>lLelb=*&k=JFQ|w#$FJ}TG zIdw^vwQS!!x3cp-*3&QGd}OKaO_{9;^(ACESXBir2=$AJ(potZ=XOTKUxJ9IWq$R` zP{psr>Q^&We9@@F9_tcZ{aTWE^MTHnWA*D<=WGManEN+Q-Q2mv+|pRNwMX`wiIu++ ztKUi{fNp-fpOwGNSob?n!C5UUM~LYaX8v8s_It7V{fynOw9G8okYA0}AK=rB1u8A0 zW!p!&%ewxto&GQ{za;ya#PIV+;OA5*sXqo+e-f)d&A9q%!c~WgzZR=MYiZ!mPhG7W z+iHb^{vuK5*JJgUEn_S!?mt8bun=*x>-w$niCc`%AY8pDs6#_`O| zP8-Zi#|dpxkj^uothSB(cWUN5gx*yVSJqs#abm?awv|-#<}_@|+SSVFxZ2!RpiLMH z%}n4=OlRPky2m{8(eeu~|>IQ9`X$;UIcxa&cA*ah`M*y{=YSG~Jr{ps+HIyz+?+*gyLlVGh>PTy_O!dUYAfUF zdGq0M7&kwiRbaH&&|o9)Gm|~7H5v4?Kb@f0$jlcT`2hbtsgVol1-U2jC#Li8%#6%4 zb{qM8)8~Su&uP#(8~H**t-p~oK`ug{(_`d|K?%Y>9e-lF#7vzSnMG?G89AFhUXF-Q ztV+r48M+ibigvCduxV+sQ+kGJnQ(AlrWypHAB3WWO&ykCysR>!C;L~NRz2};*SM%4+Jwy4#M$ z!?oOD6u@W{py`lleIA}%>DlWum2uTT(`YW*6D?V?+fACTGsCXuVGN8#{D|oWJX@%J z*u1o3CtW5UWqDYg0ONeJFhHNrXVM%sHyYA6b&@`klJ1Qf=7Mcu^WUkN3jtx*qOjuB z_*k|M^sE3}62s~iG?ZS5D$vas4iCEpe`1=!GYcnXr4>#%h~hNJVe2(eSi#OO!1tm( z;#N{0dLiDY2kfy#z|aiOS+YhWQZ$8$IHR-?`lpU(tT#xtf0_q8W7e=704E7puAfiLj&GcaF3 z6Wa@#Pl;tEOY7bu0{c%8W;k2@c{rHL1?O z$2{!UM!1iMfhd1`ZW|Cj1^i>woSTPEy+IAUvjE0OB~y=+LK_UT9-`vDpPyg>nT|Q> zcwyR2bGJczEafk`jYc8&lb00j9WZ%7B`7K|#}UbEa==U!p_{#t1<)8MF~0|8&;mCP zR>WLXqeZ41AjK8sW6T^{YYJIZir{^En6~t$?m@>ckhgiuM*ZTh;Z9 z^-H+r2vOkgx8oz~b?$Ikv^G2M$V9UOgZSre6VcI8Hd$<6aoGm9RTsAb$uyf8FD~FU9ac& z4JBL<;Y(fcb)&?4&Dc>O4Yo^gTaDhp-8kZ$xzeIr!KJ!4qGfu-9`ANidJ}gXw2xd3 zmfp<2hqKl3EqKHA%?-Hk8RBXn$0M$bg!ERlpRh-30tHiuSnitF{*JGp*}2 zj$*=+im;MudOO;dZ5+fk+TigHwAoe$9*c{Mg+>$SF}?whiddLLZ#_xx^m zG%nlQleib2Ft`N0hO%V#dLi2T&;?PH8pK40ruU<9mL6o1XPS6%ee7kK+r+|W`&H-z z_;>=RfX*TUJ8AkLnh>aCMxiZee+aF`XwKf!yO<~W$%lB*DszjL9>(vOK8$Bx7H|N3 zKeE{Ca6xMiek(a2*%MtCo0C-IBWBP?@x(&5m-D!f83L%Yl9S4w&C19g&6W;LA4k_& e`UIZl + + + + + + + GPy.core package — GPy documentation + + + + + + + + + + + + + + +

    + +
    +
    +
    +
    + +
    +

    GPy.core package

    + +
    +

    Submodules

    +
    +
    +

    GPy.core.gp module

    +
    +
    +class GPy.core.gp.GP(X, Y, kernel, likelihood, inference_method=None, name='gp', Y_metadata=None, normalizer=False)[source]
    +

    Bases: GPy.core.model.Model

    +

    General purpose Gaussian process model

    + +++ + + + + + +
    Parameters:
      +
    • X – input observations
    • +
    • Y – output observations
    • +
    • kernel – a GPy kernel, defaults to rbf+white
    • +
    • likelihood – a GPy likelihood
    • +
    • inference_method – The LatentFunctionInference inference method to use for this GP
    • +
    • normalizer (Norm) – normalize the outputs Y. +Prediction will be un-normalized using this normalizer. +If normalizer is None, we will normalize using MeanNorm. +If normalizer is False, no normalization will be done.
    • +
    +
    Return type:

    model object

    +
    +
    +

    Note

    +

    Multiple independent outputs are allowed using columns of Y

    +
    +
    +
    +infer_newX(Y_new, optimize=True)[source]
    +

    Infer the distribution of X for the new observed data Y_new.

    + +++ + + + + + + + +
    Parameters:
      +
    • Y_new (numpy.ndarray) – the new observed data for inference
    • +
    • optimize (boolean) – whether to optimize the location of new X (True by default)
    • +
    +
    Returns:

    a tuple containing the posterior estimation of X and the model that optimize X

    +
    Return type:

    (VariationalPosterior or numpy.ndarray, Model)

    +
    +
    + +
    +
    +input_sensitivity(summarize=True)[source]
    +

    Returns the sensitivity for each dimension of this model

    +
    + +
    +
    +log_likelihood()[source]
    +

    The log marginal likelihood of the model, p(\mathbf{y}), this is the objective function of the model being optimised

    +
    + +
    +
    +optimize(optimizer=None, start=None, **kwargs)[source]
    +

    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:

    + +++ + + + + + +
    Parameters:
      +
    • max_f_eval (int) – maximum number of function evaluations
    • +
    • optimizer (string) – which optimizer to use (defaults to self.preferred optimizer), a range of optimisers can be found in :module:`~GPy.inference.optimization`, they include ‘scg’, ‘lbfgs’, ‘tnc’.
    • +
    +
    Messages:

    whether to display during optimisation

    +
    +
    + +
    +
    +parameters_changed()[source]
    +

    Method that is called upon any changes to Param variables within the model. +In particular in the GP class this method reperforms inference, recalculating the posterior and log marginal likelihood and gradients of the model

    +
    +

    Warning

    +

    This method is not designed to be called manually, the framework is set up to automatically call this method upon changes to parameters, if you call +this method yourself, there may be unexpected consequences.

    +
    +
    + +
    +
    +plot(plot_limits=None, which_data_rows='all', which_data_ycols='all', fixed_inputs=[], levels=20, samples=0, fignum=None, ax=None, resolution=None, plot_raw=False, linecol=None, fillcol=None, Y_metadata=None, data_symbol='kx')[source]
    +
    +
    Plot the posterior of the GP.
    +
      +
    • In one dimension, the function is plotted with a shaded region identifying two standard deviations.
    • +
    • In two dimsensions, a contour-plot shows the mean predicted function
    • +
    • In higher dimensions, use fixed_inputs to plot the GP with some of the inputs fixed.
    • +
    +
    +
    +

    Can plot only part of the data and part of the posterior functions +using which_data_rowsm which_data_ycols.

    + +++ + + + +
    Parameters:
      +
    • plot_limits (np.array) – The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits
    • +
    • which_data_rows (‘all’ or a slice object to slice model.X, model.Y) – which of the training data to plot (default all)
    • +
    • which_data_ycols (‘all’ or a list of integers) – when the data has several columns (independant outputs), only plot these
    • +
    • fixed_inputs (a list of tuples) – a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v.
    • +
    • resolution (int) – the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D
    • +
    • levels (int) – number of levels to plot in a contour plot.
    • +
    • levels – for 2D plotting, the number of contour levels to use is ax is None, create a new figure
    • +
    • samples (int) – the number of a posteriori samples to plot
    • +
    • fignum (figure number) – figure to plot on.
    • +
    • ax (axes handle) – axes to plot on.
    • +
    • linecol (color either as Tango.colorsHex object or character (‘r’ is red, ‘g’ is green) as is standard in matplotlib) – color of line to plot [Tango.colorsHex[‘darkBlue’]]
    • +
    • fillcol (color either as Tango.colorsHex object or character (‘r’ is red, ‘g’ is green) as is standard in matplotlib) – color of fill [Tango.colorsHex[‘lightBlue’]]
    • +
    • Y_metadata (dict) – additional data associated with Y which may be needed
    • +
    • data_symbol (color either as Tango.colorsHex object or character (‘r’ is red, ‘g’ is green) alongside marker type, as is standard in matplotlib.) – symbol as used matplotlib, by default this is a black cross (‘kx’)
    • +
    +
    +
    + +
    +
    +plot_f(plot_limits=None, which_data_rows='all', which_data_ycols='all', fixed_inputs=[], levels=20, samples=0, fignum=None, ax=None, resolution=None, plot_raw=True, linecol=None, fillcol=None, Y_metadata=None, data_symbol='kx')[source]
    +

    Plot the GP’s view of the world, where the data is normalized and before applying a likelihood. +This is a call to plot with plot_raw=True. +Data will not be plotted in this, as the GP’s view of the world +may live in another space, or units then the data.

    +

    Can plot only part of the data and part of the posterior functions +using which_data_rowsm which_data_ycols.

    + +++ + + + +
    Parameters:
      +
    • plot_limits (np.array) – The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits
    • +
    • which_data_rows (‘all’ or a slice object to slice model.X, model.Y) – which of the training data to plot (default all)
    • +
    • which_data_ycols (‘all’ or a list of integers) – when the data has several columns (independant outputs), only plot these
    • +
    • fixed_inputs (a list of tuples) – a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v.
    • +
    • resolution (int) – the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D
    • +
    • levels (int) – number of levels to plot in a contour plot.
    • +
    • levels – for 2D plotting, the number of contour levels to use is ax is None, create a new figure
    • +
    • samples (int) – the number of a posteriori samples to plot
    • +
    • fignum (figure number) – figure to plot on.
    • +
    • ax (axes handle) – axes to plot on.
    • +
    • linecol (color either as Tango.colorsHex object or character (‘r’ is red, ‘g’ is green) as is standard in matplotlib) – color of line to plot [Tango.colorsHex[‘darkBlue’]]
    • +
    • fillcol (color either as Tango.colorsHex object or character (‘r’ is red, ‘g’ is green) as is standard in matplotlib) – color of fill [Tango.colorsHex[‘lightBlue’]]
    • +
    • Y_metadata (dict) – additional data associated with Y which may be needed
    • +
    • data_symbol (color either as Tango.colorsHex object or character (‘r’ is red, ‘g’ is green) alongside marker type, as is standard in matplotlib.) – symbol as used matplotlib, by default this is a black cross (‘kx’)
    • +
    +
    +
    + +
    +
    +posterior_samples(X, size=10, full_cov=False, Y_metadata=None)[source]
    +

    Samples the posterior GP at the points X.

    + +++ + + + + + +
    Parameters:
      +
    • X (np.ndarray (Nnew x self.input_dim.)) – the points at which to take the samples.
    • +
    • size (int.) – the number of a posteriori samples.
    • +
    • full_cov (bool.) – whether to return the full covariance matrix, or just the diagonal.
    • +
    • noise_model (integer.) – for mixed noise likelihood, the noise model to use in the samples.
    • +
    +
    Returns:

    Ysim: set of simulations, a Numpy array (N x samples).

    +
    +
    + +
    +
    +posterior_samples_f(X, size=10, full_cov=True)[source]
    +

    Samples the posterior GP at the points X.

    + +++ + + + + + + + +
    Parameters:
      +
    • X (np.ndarray (Nnew x self.input_dim)) – The points at which to take the samples.
    • +
    • size (int.) – the number of a posteriori samples.
    • +
    • full_cov (bool.) – whether to return the full covariance matrix, or just the diagonal.
    • +
    +
    Returns:

    Ysim: set of simulations

    +
    Return type:

    np.ndarray (N x samples)

    +
    +
    + +
    +
    +predict(Xnew, full_cov=False, Y_metadata=None, kern=None)[source]
    +

    Predict the function(s) at the new point(s) Xnew.

    + +++ + + + + + +
    Parameters:
      +
    • Xnew (np.ndarray (Nnew x self.input_dim)) – The points at which to make a prediction
    • +
    • full_cov (bool) – whether to return the full covariance matrix, or just +the diagonal
    • +
    • Y_metadata – metadata about the predicting point to pass to the likelihood
    • +
    • kern – The kernel to use for prediction (defaults to the model +kern). this is useful for examining e.g. subprocesses.
    • +
    +
    Returns:

    +
    (mean, var, lower_upper):
    +

    mean: posterior mean, a Numpy array, Nnew x self.input_dim +var: posterior variance, a Numpy array, Nnew x 1 if full_cov=False, Nnew x Nnew otherwise +lower_upper: lower and upper boundaries of the 95% confidence intervals, Numpy arrays, Nnew x self.input_dim

    +
    +
    +

    If full_cov and self.input_dim > 1, the return shape of var is Nnew x Nnew x self.input_dim. If self.input_dim == 1, the return shape is Nnew x Nnew. +This is to allow for different normalizations of the output dimensions.

    +

    +
    +
    + +
    +
    +predict_quantiles(X, quantiles=(2.5, 97.5), Y_metadata=None)[source]
    +

    Get the predictive quantiles around the prediction at X

    + +++ + + + + + + + +
    Parameters:
      +
    • X (np.ndarray (Xnew x self.input_dim)) – The points at which to make a prediction
    • +
    • quantiles (tuple) – tuple of quantiles, default is (2.5, 97.5) which is the 95% interval
    • +
    +
    Returns:

    list of quantiles for each X and predictive quantiles for interval combination

    +
    Return type:

    [np.ndarray (Xnew x self.input_dim), np.ndarray (Xnew x self.input_dim)]

    +
    +
    + +
    +
    +predictive_gradients(Xnew)[source]
    +

    Compute the derivatives of the latent function with respect to X*

    +

    Given a set of points at which to predict X* (size [N*,Q]), compute the +derivatives of the mean and variance. Resulting arrays are sized:

    +
    +

    dmu_dX* – [N*, Q ,D], where D is the number of output in this GP (usually one).

    +

    dv_dX* – [N*, Q], (since all outputs have the same variance)

    +
    + +++ + + + + + + + +
    Parameters:X (np.ndarray (Xnew x self.input_dim)) – The points at which to get the predictive gradients
    Returns:dmu_dX, dv_dX
    Return type:[np.ndarray (N*, Q ,D), np.ndarray (N*,Q) ]
    +
    + +
    +
    +set_X(X)[source]
    +

    Set the input data of the model

    + +++ + + + +
    Parameters:X (np.ndarray) – input observations
    +
    + +
    +
    +set_XY(X=None, Y=None)[source]
    +

    Set the input / output data of the model +This is useful if we wish to change our existing data but maintain the same model

    + +++ + + + +
    Parameters:
      +
    • X (np.ndarray) – input observations
    • +
    • Y (np.ndarray) – output observations
    • +
    +
    +
    + +
    +
    +set_Y(Y)[source]
    +

    Set the output data of the model

    + +++ + + + +
    Parameters:X (np.ndarray) – output observations
    +
    + +
    + +
    +
    +

    GPy.core.mapping module

    +
    +
    +class GPy.core.mapping.Bijective_mapping(input_dim, output_dim, name='bijective_mapping')[source]
    +

    Bases: GPy.core.mapping.Mapping

    +

    This is a mapping that is bijective, i.e. you can go from X to f and +also back from f to X. The inverse mapping is called g().

    +
    +
    +g(f)[source]
    +

    Inverse mapping from output domain of the function to the inputs.

    +
    + +
    + +
    +
    +class GPy.core.mapping.Mapping(input_dim, output_dim, name='mapping')[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +

    Base model for shared behavior between models that can act like a mapping.

    +
    +
    +df_dX(dL_df, X)[source]
    +

    Evaluate derivatives of mapping outputs with respect to inputs.

    + +++ + + + + + +
    Parameters:
      +
    • dL_df (ndarray (num_data x output_dim)) – gradient of the objective with respect to the function.
    • +
    • X (ndarray (num_data x input_dim)) – the input locations where derivatives are to be evaluated.
    • +
    +
    Returns:

    matrix containing gradients of the function with respect to the inputs.

    +
    +
    + +
    +
    +df_dtheta(dL_df, X)[source]
    +

    The gradient of the outputs of the mapping with respect to each of the parameters.

    + +++ + + + + + + + +
    Parameters:
      +
    • dL_df (ndarray (num_data x output_dim)) – gradient of the objective with respect to the function.
    • +
    • X (ndarray (num_data x input_dim)) – input locations where the function is evaluated.
    • +
    +
    Returns:

    Matrix containing gradients with respect to parameters of each output for each input data.

    +
    Return type:

    ndarray (num_params length)

    +
    +
    + +
    +
    +f(X)[source]
    +
    + +
    +
    +plot(*args)[source]
    +
    +
    Plots the mapping associated with the model.
    +
      +
    • In one dimension, the function is plotted.
    • +
    • In two dimensions, a contour-plot shows the function
    • +
    • In higher dimensions, we’ve not implemented this yet !TODO!
    • +
    +
    +
    +

    Can plot only part of the data and part of the posterior functions +using which_data and which_functions

    +

    This is a convenience function: arguments are passed to +GPy.plotting.matplot_dep.models_plots.plot_mapping

    +
    + +
    + +
    +
    +class GPy.core.mapping.Mapping_check_df_dX(mapping=None, dL_df=None, X=None)[source]
    +

    Bases: GPy.core.mapping.Mapping_check_model

    +

    This class allows gradient checks for the gradient of a mapping with respect to X.

    +
    + +
    +
    +class GPy.core.mapping.Mapping_check_df_dtheta(mapping=None, dL_df=None, X=None)[source]
    +

    Bases: GPy.core.mapping.Mapping_check_model

    +

    This class allows gradient checks for the gradient of a mapping with respect to parameters.

    +
    + +
    +
    +class GPy.core.mapping.Mapping_check_model(mapping=None, dL_df=None, X=None)[source]
    +

    Bases: GPy.core.model.Model

    +

    This is a dummy model class used as a base class for checking that the +gradients of a given mapping are implemented correctly. It enables +checkgradient() to be called independently on each mapping.

    +
    +
    +log_likelihood()[source]
    +
    + +
    + +
    +
    +

    GPy.core.model module

    +
    +
    +class GPy.core.model.Model(name)[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +
    +
    +ensure_default_constraints(warning=True)[source]
    +

    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.

    +
    + +
    +
    +log_likelihood()[source]
    +
    + +
    +
    +objective_function()[source]
    +

    The objective function for the given algorithm.

    +

    This function is the true objective, which wants to be minimized. +Note that all parameters are already set and in place, so you just need +to return the objective function here.

    +

    For probabilistic models this is the negative log_likelihood +(including the MAP prior), so we return it here. If your model is not +probabilistic, just return your objective to minimize here!

    +
    + +
    +
    +objective_function_gradients()[source]
    +

    The gradients for the objective function for the given algorithm. +The gradients are w.r.t. the negative objective function, as +this framework works with negative log-likelihoods as a default.

    +

    You can find the gradient for the parameters in self.gradient at all times. +This is the place, where gradients get stored for parameters.

    +

    This function is the true objective, which wants to be minimized. +Note that all parameters are already set and in place, so you just need +to return the gradient here.

    +

    For probabilistic models this is the gradient of the negative log_likelihood +(including the MAP prior), so we return it here. If your model is not +probabilistic, just return your negative gradient here!

    +
    + +
    +
    +optimize(optimizer=None, start=None, **kwargs)[source]
    +

    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:

    + +++ + + + + + +
    Parameters:
      +
    • max_f_eval (int) – maximum number of function evaluations
    • +
    • optimizer (string) – which optimizer to use (defaults to self.preferred optimizer)
    • +
    +
    Messages:

    whether to display during optimisation

    +
    +
    +
    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!

      +
    • +
    +
    +
    +
    + +
    +
    +optimize_SGD(momentum=0.1, learning_rate=0.01, iterations=20, **kwargs)[source]
    +
    + +
    +
    +optimize_restarts(num_restarts=10, robust=False, verbose=True, parallel=False, num_processes=None, **kwargs)[source]
    +

    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

    + +++ + + + +
    Parameters:
      +
    • num_restarts (int) – number of restarts to use (default 10)
    • +
    • robust (bool) – whether to handle exceptions silently or not (default False)
    • +
    • parallel (bool) – whether to run each restart as a separate process. It relies on the multiprocessing module.
    • +
    • num_processes – number of workers in the multiprocessing pool
    • +
    +
    +

    **kwargs are passed to the optimizer. They can be:

    + +++ + + + +
    Parameters:
      +
    • max_f_eval (int) – maximum number of function evaluations
    • +
    • max_iters (int) – maximum number of iterations
    • +
    • messages (bool) – whether to display during optimisation
    • +
    +
    +
    +

    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.

    +
    + +
    + +
    +
    +

    GPy.core.sparse_gp module

    +
    +
    +class GPy.core.sparse_gp.SparseGP(X, Y, Z, kernel, likelihood, inference_method=None, name='sparse gp', Y_metadata=None, normalizer=False)[source]
    +

    Bases: GPy.core.gp.GP

    +

    A general purpose Sparse GP model

    +

    This model allows (approximate) inference using variational DTC or FITC +(Gaussian likelihoods) as well as non-conjugate sparse methods based on +these.

    + +++ + + + +
    Parameters:
      +
    • X (np.ndarray (num_data x input_dim)) – inputs
    • +
    • likelihood (GPy.likelihood.(Gaussian | EP | Laplace)) – a likelihood instance, containing the observed data
    • +
    • kernel (a GPy.kern.kern instance) – the kernel (covariance function). See link kernels
    • +
    • X_variance (np.ndarray (num_data x input_dim) | None) – The uncertainty in the measurements of X (Gaussian variance)
    • +
    • Z (np.ndarray (num_inducing x input_dim)) – inducing inputs
    • +
    • num_inducing (int) – Number of inducing points (optional, default 10. Ignored if Z is not None)
    • +
    +
    +
    +
    +has_uncertain_inputs()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +

    GPy.core.sparse_gp_mpi module

    +
    +
    +class GPy.core.sparse_gp_mpi.SparseGP_MPI(X, Y, Z, kernel, likelihood, variational_prior=None, inference_method=None, name='sparse gp mpi', Y_metadata=None, mpi_comm=None, normalizer=False)[source]
    +

    Bases: GPy.core.sparse_gp.SparseGP

    +

    A general purpose Sparse GP model with MPI parallelization support

    +

    This model allows (approximate) inference using variational DTC or FITC +(Gaussian likelihoods) as well as non-conjugate sparse methods based on +these.

    + +++ + + + +
    Parameters:
      +
    • X (np.ndarray (num_data x input_dim)) – inputs
    • +
    • likelihood (GPy.likelihood.(Gaussian | EP | Laplace)) – a likelihood instance, containing the observed data
    • +
    • kernel (a GPy.kern.kern instance) – the kernel (covariance function). See link kernels
    • +
    • X_variance (np.ndarray (num_data x input_dim) | None) – The uncertainty in the measurements of X (Gaussian variance)
    • +
    • Z (np.ndarray (num_inducing x input_dim)) – inducing inputs
    • +
    • num_inducing (int) – Number of inducing points (optional, default 10. Ignored if Z is not None)
    • +
    • mpi_comm (mpi4py.MPI.Intracomm) – The communication group of MPI, e.g. mpi4py.MPI.COMM_WORLD
    • +
    +
    +
    +
    +optimize(optimizer=None, start=None, **kwargs)[source]
    +
    + +
    +
    +optimizer_array
    +

    Array for the optimizer to work on. +This array always lives in the space for the optimizer. +Thus, it is untransformed, going from Transformations.

    +

    Setting this array, will make sure the transformed parameters for this model +will be set accordingly. It has to be set with an array, retrieved from +this method, as e.g. fixing will resize the array.

    +

    The optimizer should only interfere with this array, such that transformations +are secured.

    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +

    GPy.core.svigp module

    +
    +
    +

    GPy.core.symbolic module

    +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.core.parameterization.html b/doc/_build/html/GPy.core.parameterization.html new file mode 100644 index 00000000..0a2a6db3 --- /dev/null +++ b/doc/_build/html/GPy.core.parameterization.html @@ -0,0 +1,2528 @@ + + + + + + + + GPy.core.parameterization package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.core.parameterization package

    +
    +

    Submodules

    +
    +
    +

    GPy.core.parameterization.domains module

    +

    (Hyper-)Parameter domains defined for priors and kern. +These domains specify the legitimate realm of the parameters to live in.

    +
    +
    _REAL :
    +
    real domain, all values in the real numbers are allowed
    +
    _POSITIVE:
    +
    positive domain, only positive real values are allowed
    +
    _NEGATIVE:
    +
    same as _POSITIVE, but only negative values are allowed
    +
    _BOUNDED:
    +
    only values within the bounded range are allowed, +the bounds are specified withing the object with the bounded range
    +
    +
    +
    +

    GPy.core.parameterization.index_operations module

    +
    +
    +class GPy.core.parameterization.index_operations.ParameterIndexOperations(constraints=None)[source]
    +

    Bases: 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

    +
    +
    +add(prop, indices)[source]
    +
    + +
    +
    +clear()[source]
    +
    + +
    +
    +copy()[source]
    +
    + +
    +
    +indices()[source]
    +
    + +
    +
    +items()[source]
    +
    + +
    +
    +iterindices()[source]
    +
    + +
    +
    +iteritems()[source]
    +
    + +
    +
    +iterproperties()[source]
    +
    + +
    +
    +properties()[source]
    +
    + +
    +
    +properties_for(index)[source]
    +

    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']]
    +
    +
    +
    + +
    +
    +properties_to_index_dict(index)[source]
    +

    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]}
    +
    +
    +
    + +
    +
    +remove(prop, indices)[source]
    +
    + +
    +
    +shift_left(start, size)[source]
    +
    + +
    +
    +shift_right(start, size)[source]
    +
    + +
    +
    +size
    +
    + +
    +
    +update(parameter_index_view, offset=0)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.index_operations.ParameterIndexOperationsView(param_index_operations, offset, size)[source]
    +

    Bases: object

    +
    +
    +add(prop, indices)[source]
    +
    + +
    +
    +clear()[source]
    +
    + +
    +
    +copy()[source]
    +
    + +
    +
    +indices()[source]
    +
    + +
    +
    +items()[source]
    +
    + +
    +
    +iterindices()[source]
    +
    + +
    +
    +iteritems()[source]
    +
    + +
    +
    +iterproperties()[source]
    +
    + +
    +
    +properties()[source]
    +
    + +
    +
    +properties_for(index)[source]
    +

    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']]
    +
    +
    +
    + +
    +
    +properties_to_index_dict(index)[source]
    +

    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]}
    +
    +
    +
    + +
    +
    +remove(prop, indices)[source]
    +
    + +
    +
    +shift_left(start, size)[source]
    +
    + +
    +
    +shift_right(start, size)[source]
    +
    + +
    +
    +size
    +
    + +
    +
    +update(parameter_index_view, offset=0)[source]
    +
    + +
    + +
    +
    +GPy.core.parameterization.index_operations.combine_indices(arr1, arr2)[source]
    +
    + +
    +
    +GPy.core.parameterization.index_operations.extract_properties_to_index(index, props)[source]
    +
    + +
    +
    +GPy.core.parameterization.index_operations.index_empty(index)[source]
    +
    + +
    +
    +GPy.core.parameterization.index_operations.remove_indices(arr, to_remove)[source]
    +
    + +
    +
    +

    GPy.core.parameterization.lists_and_dicts module

    +
    +
    +class GPy.core.parameterization.lists_and_dicts.ArrayList[source]
    +

    Bases: list

    +

    List to store ndarray-likes in. +It will look for ‘is’ instead of calling __eq__ on each element.

    +
    +
    +index(item)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.lists_and_dicts.IntArrayDict(default_factory=None)[source]
    +

    Bases: collections.defaultdict

    +
    + +
    +
    +class GPy.core.parameterization.lists_and_dicts.ObserverList[source]
    +

    Bases: object

    +

    A list which containts the observables. +It only holds weak references to observers, such that unbound +observers dont dangle in memory.

    +
    +
    +add(priority, observer, callble)[source]
    +

    Add an observer with priority and callble

    +
    + +
    +
    +flush()[source]
    +

    Make sure all weak references, which point to nothing are flushed (deleted)

    +
    + +
    +
    +remove(priority, observer, callble)[source]
    +

    Remove one observer, which had priority and callble.

    +
    + +
    + +
    +
    +GPy.core.parameterization.lists_and_dicts.intarray_default_factory()[source]
    +
    + +
    +
    +

    GPy.core.parameterization.observable_array module

    +
    +
    +class GPy.core.parameterization.observable_array.ObsAr(*a, **kw)[source]
    +

    Bases: numpy.ndarray, GPy.core.parameterization.parameter_core.Pickleable, GPy.core.parameterization.observable.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.

    +
    +
    +copy()[source]
    +
    + +
    +
    +values
    +
    + +
    + +
    +
    +

    GPy.core.parameterization.param module

    +
    +
    +class GPy.core.parameterization.param.Param(name, input_array, default_constraint=None, *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.Parameterizable, GPy.core.parameterization.observable_array.ObsAr

    +

    Parameter object for GPy models.

    + +++ + + + +
    Parameters:
      +
    • name (str) – name of the parameter to be printed
    • +
    • input_array (numpy.ndarray) – array which this parameter handles
    • +
    • default_constraint – The default constraint for this parameter
    • +
    +
    +

    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!

    +

    See GPy.core.parameterized.Parameterized for more details on constraining etc.

    +
    +
    +build_pydot(G)[source]
    +
    + +
    +
    +copy()[source]
    +
    + +
    +
    +flattened_parameters
    +
    + +
    +
    +gradient
    +

    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

    +
    + +
    +
    +is_fixed
    +
    + +
    +
    +num_params
    +
    + +
    +
    +param_array
    +

    As we are a leaf, this just returns self

    +
    + +
    +
    +parameter_names(add_self=False, adjust_for_printing=False, recursive=True)[source]
    +
    + +
    +
    +parameter_shapes
    +
    + +
    +
    +parameters = []
    +
    + +
    +
    +values
    +

    Return self as numpy array view

    +
    + +
    + +
    +
    +class GPy.core.parameterization.param.ParamConcatenation(params)[source]
    +

    Bases: object

    +
    +
    +checkgrad(verbose=0, step=1e-06, tolerance=0.001)[source]
    +
    + +
    +
    +constrain(constraint, warning=True)[source]
    +
    +++ + + + +
    Parameters:
      +
    • transform – the GPy.core.transformations.Transformation +to constrain the this parameter to.
    • +
    • warning – print a warning if re-constraining parameters.
    • +
    +
    +

    Constrain the parameter to the given +GPy.core.transformations.Transformation.

    +
    + +
    +
    +constrain_bounded(lower, upper, warning=True)[source]
    +
    +++ + + + +
    Parameters:
      +
    • upper (lower,) – the limits to bound this parameter to
    • +
    • warning – print a warning if re-constraining parameters.
    • +
    +
    +

    Constrain this parameter to lie within the given range.

    +
    + +
    +
    +constrain_fixed(value=None, warning=True, trigger_parent=True)[source]
    +

    Constrain this parameter to be fixed to the current value it carries.

    + +++ + + + +
    Parameters:warning – print a warning for overwriting constraints.
    +
    + +
    +
    +constrain_negative(warning=True)[source]
    +
    +++ + + + +
    Parameters:warning – print a warning if re-constraining parameters.
    +

    Constrain this parameter to the default negative constraint.

    +
    + +
    +
    +constrain_positive(warning=True)[source]
    +
    +++ + + + +
    Parameters:warning – print a warning if re-constraining parameters.
    +

    Constrain this parameter to the default positive constraint.

    +
    + +
    +
    +fix(value=None, warning=True, trigger_parent=True)
    +

    Constrain this parameter to be fixed to the current value it carries.

    + +++ + + + +
    Parameters:warning – print a warning for overwriting constraints.
    +
    + +
    +
    +unconstrain(*constraints)[source]
    +
    +++ + + + +
    Parameters:transforms – The transformations to unconstrain from.
    +

    remove all GPy.core.transformations.Transformation +transformats of this parameter object.

    +
    + +
    +
    +unconstrain_bounded(lower, upper)[source]
    +
    +++ + + + +
    Parameters:upper (lower,) – the limits to unbound this parameter from
    +

    Remove (lower, upper) bounded constrain from this parameter/

    +
    + +
    +
    +unconstrain_fixed()[source]
    +

    This parameter will no longer be fixed.

    +
    + +
    +
    +unconstrain_negative()[source]
    +

    Remove negative constraint of this parameter.

    +
    + +
    +
    +unconstrain_positive()[source]
    +

    Remove positive constraint of this parameter.

    +
    + +
    +
    +unfix()
    +

    This parameter will no longer be fixed.

    +
    + +
    +
    +untie(*ties)[source]
    +
    + +
    +
    +update_all_params()[source]
    +
    + +
    +
    +values()[source]
    +
    + +
    + +
    +
    +

    GPy.core.parameterization.parameter_core module

    +

    Core module for parameterization. +This module implements all parameterization techniques, split up in modular bits.

    +

    HierarchyError: +raised when an error with the hierarchy occurs (circles etc.)

    +

    Observable: +Observable Pattern for patameterization

    +
    +
    +class GPy.core.parameterization.parameter_core.Gradcheckable(*a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.Pickleable, GPy.core.parameterization.parameter_core.Parentable

    +

    Adds the functionality for an object to be gradcheckable. +It is just a thin wrapper of a call to the highest parent for now. +TODO: Can be done better, by only changing parameters of the current parameter handle, +such that object hierarchy only has to change for those.

    +
    +
    +checkgrad(verbose=0, step=1e-06, tolerance=0.001, df_tolerance=1e-12)[source]
    +

    Check the gradient of this parameter with respect to the highest parent’s +objective function. +This is a three point estimate of the gradient, wiggling at the parameters +with a stepsize step. +The check passes if either the ratio or the difference between numerical and +analytical gradient is smaller then tolerance.

    + +++ + + + +
    Parameters:
      +
    • verbose (bool) – whether each parameter shall be checked individually.
    • +
    • step (float) – the stepsize for the numerical three point gradient estimate.
    • +
    • tolerance (float) – the tolerance for the gradient ratio or difference.
    • +
    • df_tolerance (float) – the tolerance for df_tolerance
    • +
    +
    +
    +
    Note:-
    +
    The dF_ratio indicates the limit of 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).
    +
    +
    + +
    + +
    +
    +exception GPy.core.parameterization.parameter_core.HierarchyError[source]
    +

    Bases: exceptions.Exception

    +

    Gets thrown when something is wrong with the parameter hierarchy.

    +
    + +
    +
    +class GPy.core.parameterization.parameter_core.Indexable(name, default_constraint=None, *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.Nameable, GPy.core.parameterization.updateable.Updateable

    +

    Make an object constrainable with Priors and Transformations. +TODO: Mappings!! +Adding a constraint to a Parameter means to tell the highest parent that +the constraint was added and making sure that all parameters covered +by this object are indeed conforming to the constraint.

    +

    constrain() and unconstrain() are main methods here

    +
    +
    +constrain(transform, warning=True, trigger_parent=True)[source]
    +
    +++ + + + +
    Parameters:
      +
    • transform – the GPy.core.transformations.Transformation +to constrain the this parameter to.
    • +
    • warning – print a warning if re-constraining parameters.
    • +
    +
    +

    Constrain the parameter to the given +GPy.core.transformations.Transformation.

    +
    + +
    +
    +constrain_bounded(lower, upper, warning=True, trigger_parent=True)[source]
    +
    +++ + + + +
    Parameters:
      +
    • upper (lower,) – the limits to bound this parameter to
    • +
    • warning – print a warning if re-constraining parameters.
    • +
    +
    +

    Constrain this parameter to lie within the given range.

    +
    + +
    +
    +constrain_fixed(value=None, warning=True, trigger_parent=True)[source]
    +

    Constrain this parameter to be fixed to the current value it carries.

    + +++ + + + +
    Parameters:warning – print a warning for overwriting constraints.
    +
    + +
    +
    +constrain_negative(warning=True, trigger_parent=True)[source]
    +
    +++ + + + +
    Parameters:warning – print a warning if re-constraining parameters.
    +

    Constrain this parameter to the default negative constraint.

    +
    + +
    +
    +constrain_positive(warning=True, trigger_parent=True)[source]
    +
    +++ + + + +
    Parameters:warning – print a warning if re-constraining parameters.
    +

    Constrain this parameter to the default positive constraint.

    +
    + +
    +
    +fix(value=None, warning=True, trigger_parent=True)
    +

    Constrain this parameter to be fixed to the current value it carries.

    + +++ + + + +
    Parameters:warning – print a warning for overwriting constraints.
    +
    + +
    +
    +is_fixed
    +
    + +
    +
    +log_prior()[source]
    +

    evaluate the prior

    +
    + +
    +
    +set_prior(prior, warning=True)[source]
    +

    Set the prior for this object to prior. +:param Prior prior: a prior to set for this parameter +:param bool warning: whether to warn if another prior was set for this parameter

    +
    + +
    +
    +tie_together()[source]
    +
    + +
    +
    +unconstrain(*transforms)[source]
    +
    +++ + + + +
    Parameters:transforms – The transformations to unconstrain from.
    +

    remove all GPy.core.transformations.Transformation +transformats of this parameter object.

    +
    + +
    +
    +unconstrain_bounded(lower, upper)[source]
    +
    +++ + + + +
    Parameters:upper (lower,) – the limits to unbound this parameter from
    +

    Remove (lower, upper) bounded constrain from this parameter/

    +
    + +
    +
    +unconstrain_fixed()[source]
    +

    This parameter will no longer be fixed.

    +
    + +
    +
    +unconstrain_negative()[source]
    +

    Remove negative constraint of this parameter.

    +
    + +
    +
    +unconstrain_positive()[source]
    +

    Remove positive constraint of this parameter.

    +
    + +
    +
    +unfix()
    +

    This parameter will no longer be fixed.

    +
    + +
    +
    +unset_priors(*priors)[source]
    +

    Un-set all priors given (in *priors) from this parameter handle.

    +
    + +
    + +
    +
    +class GPy.core.parameterization.parameter_core.Nameable(name, *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.Gradcheckable

    +

    Make an object nameable inside the hierarchy.

    +
    +
    +hierarchy_name(adjust_for_printing=True)[source]
    +

    return the name for this object with the parents names attached by dots.

    + +++ + + + +
    Parameters:adjust_for_printing (bool) – whether to call adjust_for_printing()
    +

    on the names, recursively

    +
    + +
    +
    +name
    +

    The name of this object

    +
    + +
    + +
    +
    +class GPy.core.parameterization.parameter_core.OptimizationHandlable(name, default_constraint=None, *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.Indexable

    +

    This enables optimization handles on an Object as done in GPy 0.4.

    +

    ..._optimizer_copy_transformed: make sure the transformations and constraints etc are handled

    +
    +
    +gradient_full
    +

    Note to users: +This does not return the gradient in the right shape! Use self.gradient +for the right gradient array.

    +

    To work on the gradient array, use this as the gradient handle. +This method exists for in memory use of parameters. +When trying to access the true gradient array, use this.

    +
    + +
    +
    +num_params
    +

    Return the number of parameters of this parameter_handle. +Param objects will always return 0.

    +
    + +
    +
    +optimizer_array
    +

    Array for the optimizer to work on. +This array always lives in the space for the optimizer. +Thus, it is untransformed, going from Transformations.

    +

    Setting this array, will make sure the transformed parameters for this model +will be set accordingly. It has to be set with an array, retrieved from +this method, as e.g. fixing will resize the array.

    +

    The optimizer should only interfere with this array, such that transformations +are secured.

    +
    + +
    +
    +parameter_names(add_self=False, adjust_for_printing=False, recursive=True)[source]
    +

    Get the names of all parameters of this model.

    + +++ + + + +
    Parameters:
      +
    • add_self (bool) – whether to add the own name in front of names
    • +
    • adjust_for_printing (bool) – whether to call adjust_name_for_printing on names
    • +
    • recursive (bool) – whether to traverse through hierarchy and append leaf node names
    • +
    +
    +
    + +
    +
    +randomize(rand_gen=None, *args, **kwargs)[source]
    +

    Randomize the model. +Make this draw from the prior if one exists, else draw from given random generator

    + +++ + + + +
    Parameters:
      +
    • rand_gen – np random number generator which takes args and kwargs
    • +
    • loc (flaot) – loc parameter for random number generator
    • +
    • scale (float) – scale parameter for random number generator
    • +
    • kwargs (args,) – will be passed through to random number generator
    • +
    +
    +
    + +
    + +
    +
    +class GPy.core.parameterization.parameter_core.Parameterizable(*args, **kwargs)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.OptimizationHandlable

    +

    A parameterisable class.

    +

    This class provides the parameters list (ArrayList) and standard parameter handling, +such as {add|remove}_parameter(), traverse hierarchy and param_array, gradient_array +and the empty parameters_changed().

    +

    This class is abstract and should not be instantiated. +Use GPy.core.Parameterized() as node (or leaf) in the parameterized hierarchy. +Use GPy.core.Param() for a leaf in the parameterized hierarchy.

    +
    +
    +gradient
    +
    + +
    +
    +num_params
    +
    + +
    +
    +param_array
    +

    Array representing the parameters of this class. +There is only one copy of all parameters in memory, two during optimization.

    +

    !WARNING!: setting the parameter array MUST always be done in memory: +m.param_array[:] = m_copy.param_array

    +
    + +
    +
    +parameters_changed()[source]
    +

    This method gets called when parameters have changed. +Another way of listening to param changes is to +add self as a listener to the param, such that +updates get passed through. See :py:function:GPy.core.param.Observable.add_observer

    +
    + +
    +
    +save(filename, ftype='HDF5')[source]
    +

    Save all the model parameters into a file (HDF5 by default).

    +
    + +
    +
    +traverse(visit, *args, **kwargs)[source]
    +

    Traverse the hierarchy performing visit(self, *args, **kwargs) +at every node passed by downwards. This function includes self!

    +

    See “visitor pattern” in literature. This is implemented in pre-order fashion.

    +

    Example: +Collect all children:

    +

    children = [] +self.traverse(children.append) +print children

    +
    + +
    +
    +traverse_parents(visit, *args, **kwargs)[source]
    +

    Traverse the hierarchy upwards, visiting all parents and their children except self. +See “visitor pattern” in literature. This is implemented in pre-order fashion.

    +

    Example:

    +

    parents = [] +self.traverse_parents(parents.append) +print parents

    +
    + +
    +
    +unfixed_param_array
    +

    Array representing the parameters of this class. +There is only one copy of all parameters in memory, two during optimization.

    +

    !WARNING!: setting the parameter array MUST always be done in memory: +m.param_array[:] = m_copy.param_array

    +
    + +
    + +
    +
    +class GPy.core.parameterization.parameter_core.Parentable(*args, **kwargs)[source]
    +

    Bases: object

    +

    Enable an Object to have a parent.

    +

    Additionally this adds the parent_index, which is the index for the parent +to look for in its parameter list.

    +
    +
    +has_parent()[source]
    +

    Return whether this parentable object currently has a parent.

    +
    + +
    + +
    +
    +class GPy.core.parameterization.parameter_core.Pickleable(*a, **kw)[source]
    +

    Bases: object

    +

    Make an object pickleable (See python doc ‘pickling’).

    +

    This class allows for pickling support by Memento pattern. +_getstate returns a memento of the class, which gets pickled. +_setstate(<memento>) (re-)sets the state of the class to the memento

    +
    +
    +copy(memo=None, which=None)[source]
    +

    Returns a (deep) copy of the current parameter handle.

    +

    All connections to parents of the copy will be cut.

    + +++ + + + +
    Parameters:
      +
    • memo (dict) – memo for deepcopy
    • +
    • which (Parameterized) – parameterized object which started the copy process [default: self]
    • +
    +
    +
    + +
    +
    +pickle(f, protocol=-1)[source]
    +
    +++ + + + +
    Parameters:
      +
    • f – either filename or open file object to write to. +if it is an open buffer, you have to make sure to close +it properly.
    • +
    • protocol – pickling protocol to use, python-pickle for details.
    • +
    +
    +
    + +
    + +
    +
    +GPy.core.parameterization.parameter_core.adjust_name_for_printing(name)[source]
    +

    Make sure a name can be printed, alongside used as a variable name.

    +
    + +
    +
    +

    GPy.core.parameterization.parameterized module

    +
    +
    +class GPy.core.parameterization.parameterized.Parameterized(name=None, parameters=[], *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.Parameterizable

    +

    Parameterized class

    +

    Say m is a handle to a parameterized class.

    +

    Printing parameters:

    +
    +
      +
    • print m: prints a nice summary over all parameters

      +
    • +
    • print m.name: prints details for param with name ‘name’

      +
    • +
    • +
      print m[regexp]: prints details for all the parameters
      +

      which match (!) regexp

      +
      +
      +
    • +
    • print m[‘’]: prints details for all parameters

      +
    • +
    +

    Fields:

    +
    +

    Name: The name of the param, can be renamed! +Value: Shape or value, if one-valued +Constrain: constraint of the param, curly “{c}” brackets indicate

    +
    +
    some parameters are constrained by c. See detailed print +to get exact constraints.
    +

    Tied_to: which paramter it is tied to.

    +
    +
    +

    Getting and setting parameters:

    +
    +

    Set all values in param to one:

    +
    +
    m.name.to.param = 1
    +
    +

    Handling of constraining, fixing and tieing parameters:

    +
    +

    You can constrain parameters by calling the constrain on the param itself, e.g:

    +
    +
      +
    • m.name[:,1].constrain_positive()
    • +
    • m.name[0].tie_to(m.name[1])
    • +
    +
    +

    Fixing parameters will fix them to the value they are right now. If you change +the parameters value, the param will be fixed to the new value!

    +

    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.

    +
    +
    +
    +add_parameter(*args, **kwargs)[source]
    +
    + +
    +
    +build_pydot(G=None)[source]
    +
    + +
    +
    +copy(memo=None)[source]
    +
    + +
    +
    +flattened_parameters
    +
    + +
    +
    +grep_param_names(regexp)[source]
    +

    create a list of parameters, matching regular expression regexp

    +
    + +
    + +
    +++ + + + +
    Parameters:
      +
    • parameters (list of or one GPy.core.param.Param) – the parameters to add
    • +
    • [index] – index of where to put parameters
    • +
    • _ignore_added_names (bool) – 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 list.insert() syntax

    +
    + +
    + +

    convenience method for adding several +parameters without gradient specification

    +
    + +
    +
    +parameter_shapes
    +
    + +
    +
    +remove_parameter(*args, **kwargs)[source]
    +
    + +
    + +
    +++ + + + +
    Parameters:param – param object to remove from being a parameter of this parameterized object.
    +
    + +
    + +
    +
    +class GPy.core.parameterization.parameterized.ParametersChangedMeta[source]
    +

    Bases: type

    +
    + +
    +
    +

    GPy.core.parameterization.priors module

    +
    +
    +class GPy.core.parameterization.priors.DGPLVM(sigma2, lbl, x_shape)[source]
    +

    Bases: GPy.core.parameterization.priors.Prior

    +

    Implementation of the Discriminative Gaussian Process Latent Variable model paper, by Raquel.

    + +++ + + + +
    Parameters:sigma2 – constant
    +
    +

    Note

    +

    DGPLVM for Classification paper implementation

    +
    +
    +
    +compute_Mi(cls)[source]
    +
    + +
    +
    +compute_Sb(cls, M_i, M_0)[source]
    +
    + +
    +
    +compute_Sw(cls, M_i)[source]
    +
    + +
    +
    +compute_cls(x)[source]
    +
    + +
    +
    +compute_indices(x)[source]
    +
    + +
    +
    +compute_listIndices(data_idx)[source]
    +
    + +
    +
    +compute_sig_alpha_W(data_idx, lst_idx_all, W_i)[source]
    +
    + +
    +
    +compute_sig_beta_Bi(data_idx, M_i, M_0, lst_idx_all)[source]
    +
    + +
    +
    +compute_wj(data_idx, M_i)[source]
    +
    + +
    +
    +domain = 'real'
    +
    + +
    +
    +get_class_label(y)[source]
    +
    + +
    +
    +lnpdf(x)[source]
    +
    + +
    +
    +lnpdf_grad(x)[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.DGPLVM_KFDA(lambdaa, sigma2, lbl, kern, x_shape)[source]
    +

    Bases: GPy.core.parameterization.priors.Prior

    +

    Implementation of the Discriminative Gaussian Process Latent Variable function using +Kernel Fisher Discriminant Analysis by Seung-Jean Kim for implementing Face paper +by Chaochao Lu.

    + +++ + + + +
    Parameters:
      +
    • lambdaa – constant
    • +
    • sigma2 – constant
    • +
    +
    +
    +

    Note

    +

    Surpassing Human-Level Face paper dgplvm implementation

    +
    +
    +
    +compute_A(lst_ni)[source]
    +
    + +
    +
    +compute_a(lst_ni)[source]
    +
    + +
    +
    +compute_cls(x)[source]
    +
    + +
    +
    +compute_lst_ni()[source]
    +
    + +
    +
    +domain = 'real'
    +
    + +
    +
    +get_class_label(y)[source]
    +
    + +
    +
    +lnpdf(x)[source]
    +
    + +
    +
    +lnpdf_grad(x)[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    +
    +x_reduced(cls)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.Gamma(a, b)[source]
    +

    Bases: GPy.core.parameterization.priors.Prior

    +

    Implementation of the Gamma probability function, coupled with random variables.

    + +++ + + + +
    Parameters:
      +
    • a – shape parameter
    • +
    • b – rate parameter (warning: it’s the inverse of the scale)
    • +
    +
    +
    +

    Note

    +

    Bishop 2006 notation is used throughout the code

    +
    +
    +
    +domain = 'positive'
    +
    + +
    +
    +static from_EV(E, V)[source]
    +

    Creates an instance of a Gamma Prior by specifying the Expected value(s) +and Variance(s) of the distribution.

    + +++ + + + +
    Parameters:
      +
    • E – expected value
    • +
    • V – variance
    • +
    +
    +
    + +
    +
    +lnpdf(x)[source]
    +
    + +
    +
    +lnpdf_grad(x)[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    +
    +summary()[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.Gaussian(mu, sigma)[source]
    +

    Bases: GPy.core.parameterization.priors.Prior

    +

    Implementation of the univariate Gaussian probability function, coupled with random variables.

    + +++ + + + +
    Parameters:
      +
    • mu – mean
    • +
    • sigma – standard deviation
    • +
    +
    +
    +

    Note

    +

    Bishop 2006 notation is used throughout the code

    +
    +
    +
    +domain = 'real'
    +
    + +
    +
    +lnpdf(x)[source]
    +
    + +
    +
    +lnpdf_grad(x)[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.HalfT(A, nu)[source]
    +

    Bases: GPy.core.parameterization.priors.Prior

    +

    Implementation of the half student t probability function, coupled with random variables.

    + +++ + + + +
    Parameters:
      +
    • A – scale parameter
    • +
    • nu – degrees of freedom
    • +
    +
    +
    +
    +domain = 'positive'
    +
    + +
    +
    +lnpdf(theta)[source]
    +
    + +
    +
    +lnpdf_grad(theta)[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.InverseGamma(a, b)[source]
    +

    Bases: GPy.core.parameterization.priors.Gamma

    +

    Implementation of the inverse-Gamma probability function, coupled with random variables.

    + +++ + + + +
    Parameters:
      +
    • a – shape parameter
    • +
    • b – rate parameter (warning: it’s the inverse of the scale)
    • +
    +
    +
    +

    Note

    +

    Bishop 2006 notation is used throughout the code

    +
    +
    +
    +domain = 'positive'
    +
    + +
    +
    +lnpdf(x)[source]
    +
    + +
    +
    +lnpdf_grad(x)[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.LogGaussian(mu, sigma)[source]
    +

    Bases: GPy.core.parameterization.priors.Gaussian

    +

    Implementation of the univariate log-Gaussian probability function, coupled with random variables.

    + +++ + + + +
    Parameters:
      +
    • mu – mean
    • +
    • sigma – standard deviation
    • +
    +
    +
    +

    Note

    +

    Bishop 2006 notation is used throughout the code

    +
    +
    +
    +domain = 'positive'
    +
    + +
    +
    +lnpdf(x)[source]
    +
    + +
    +
    +lnpdf_grad(x)[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.MultivariateGaussian(mu, var)[source]
    +

    Bases: GPy.core.parameterization.priors.Prior

    +

    Implementation of the multivariate Gaussian probability function, coupled with random variables.

    + +++ + + + +
    Parameters:
      +
    • mu – mean (N-dimensional array)
    • +
    • var – covariance matrix (NxN)
    • +
    +
    +
    +

    Note

    +

    Bishop 2006 notation is used throughout the code

    +
    +
    +
    +domain = 'real'
    +
    + +
    +
    +lnpdf(x)[source]
    +
    + +
    +
    +lnpdf_grad(x)[source]
    +
    + +
    +
    +pdf(x)[source]
    +
    + +
    +
    +plot()[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    +
    +summary()[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.Prior[source]
    +

    Bases: object

    +
    +
    +domain = None
    +
    + +
    +
    +pdf(x)[source]
    +
    + +
    +
    +plot()[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.priors.Uniform(lower, upper)[source]
    +

    Bases: GPy.core.parameterization.priors.Prior

    +
    +
    +domain = 'real'
    +
    + +
    +
    +lnpdf(x)[source]
    +
    + +
    +
    +lnpdf_grad(x)[source]
    +
    + +
    +
    +rvs(n)[source]
    +
    + +
    + +
    +
    +GPy.core.parameterization.priors.gamma_from_EV(E, V)[source]
    +
    + +
    +
    +

    GPy.core.parameterization.ties_and_remappings module

    +
    +
    +class GPy.core.parameterization.ties_and_remappings.Fix(name=None, parameters=[], *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.ties_and_remappings.Remapping

    +
    + +
    +
    +class GPy.core.parameterization.ties_and_remappings.Remapping(name=None, parameters=[], *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +
    +
    +callback()[source]
    +
    + +
    +
    +mapping()[source]
    +

    The return value of this function gives the values which the re-mapped +parameters should take. Implement in sub-classes.

    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.ties_and_remappings.Tie(name='tie')[source]
    +

    Bases: GPy.core.parameterization.parameterized.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

    +
    +
    +add_tied_parameter(p, p2=None)[source]
    +

    Tie the list of parameters p together (p2==None) or +Tie the list of parameters p with the list of parameters p2 (p2!=None)

    +
    + +
    +
    +collate_gradient()[source]
    +
    + +
    +
    +getTieFlag(p=None)[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +propagate_val()[source]
    +
    + +
    + +
    +
    +

    GPy.core.parameterization.transformations module

    +
    +
    +class GPy.core.parameterization.transformations.Exponent[source]
    +

    Bases: GPy.core.parameterization.transformations.Transformation

    +
    +
    +domain = 'positive'
    +
    + +
    +
    +f(x)[source]
    +
    + +
    +
    +finv(x)[source]
    +
    + +
    +
    +gradfactor(f, df)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.Logexp[source]
    +

    Bases: GPy.core.parameterization.transformations.Transformation

    +
    +
    +domain = 'positive'
    +
    + +
    +
    +f(x)[source]
    +
    + +
    +
    +finv(f)[source]
    +
    + +
    +
    +gradfactor(f, df)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.LogexpClipped(lower=1e-06)[source]
    +

    Bases: GPy.core.parameterization.transformations.Logexp

    +
    +
    +domain = 'positive'
    +
    + +
    +
    +f(x)[source]
    +
    + +
    +
    +finv(f)[source]
    +
    + +
    +
    +gradfactor(f, df)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    +
    +log_max_bound = 230.25850929940458
    +
    + +
    +
    +log_min_bound = -23.025850929940457
    +
    + +
    +
    +max_bound = 1e+100
    +
    + +
    +
    +min_bound = 1e-10
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.LogexpNeg[source]
    +

    Bases: GPy.core.parameterization.transformations.Transformation

    +
    +
    +domain = 'positive'
    +
    + +
    +
    +f(x)[source]
    +
    + +
    +
    +finv(f)[source]
    +
    + +
    +
    +gradfactor(f, df)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.Logistic(lower, upper)[source]
    +

    Bases: GPy.core.parameterization.transformations.Transformation

    +
    +
    +domain = 'bounded'
    +
    + +
    +
    +f(x)[source]
    +
    + +
    +
    +finv(f)[source]
    +
    + +
    +
    +gradfactor(f, df)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.NegativeExponent[source]
    +

    Bases: GPy.core.parameterization.transformations.Exponent

    +
    +
    +domain = 'negative'
    +
    + +
    +
    +f(x)[source]
    +
    + +
    +
    +finv(f)[source]
    +
    + +
    +
    +gradfactor(f, df)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.NegativeLogexp[source]
    +

    Bases: GPy.core.parameterization.transformations.Transformation

    +
    +
    +domain = 'negative'
    +
    + +
    +
    +f(x)[source]
    +
    + +
    +
    +finv(f)[source]
    +
    + +
    +
    +gradfactor(f, df)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    +
    +logexp = Logexp
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.NormalEta(mu_indices, var_indices)[source]
    +

    Bases: GPy.core.parameterization.transformations.Transformation

    +
    +
    +f(theta)[source]
    +
    + +
    +
    +finv(muvar)[source]
    +
    + +
    +
    +gradfactor(muvar, dmuvar)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.NormalNaturalAntti(mu_indices, var_indices)[source]
    +

    Bases: GPy.core.parameterization.transformations.NormalTheta

    +
    +
    +gradfactor(muvar, dmuvar)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.NormalNaturalThroughEta(mu_indices, var_indices)[source]
    +

    Bases: GPy.core.parameterization.transformations.NormalEta

    +
    +
    +gradfactor(muvar, dmuvar)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.NormalNaturalThroughTheta(mu_indices, var_indices)[source]
    +

    Bases: GPy.core.parameterization.transformations.NormalTheta

    +
    +
    +gradfactor(muvar, dmuvar)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.NormalTheta(mu_indices, var_indices)[source]
    +

    Bases: GPy.core.parameterization.transformations.Transformation

    +
    +
    +f(theta)[source]
    +
    + +
    +
    +finv(muvar)[source]
    +
    + +
    +
    +gradfactor(muvar, dmuvar)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.Square[source]
    +

    Bases: GPy.core.parameterization.transformations.Transformation

    +
    +
    +domain = 'positive'
    +
    + +
    +
    +f(x)[source]
    +
    + +
    +
    +finv(x)[source]
    +
    + +
    +
    +gradfactor(f, df)[source]
    +
    + +
    +
    +initialize(f)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.transformations.Transformation[source]
    +

    Bases: object

    +
    +
    +domain = None
    +
    + +
    +
    +f(opt_param)[source]
    +
    + +
    +
    +finv(model_param)[source]
    +
    + +
    +
    +gradfactor(model_param, dL_dmodel_param)[source]
    +

    df(opt_param)_dopt_param evaluated at self.f(opt_param)=model_param, times the gradient dL_dmodel_param,

    +
    +

    i.e.: +define

    +
    +

    +
    +

    rac{ +rac{partial L}{partial f}left(left.partial f(x)}{partial x} +ight|_{x=f^{-1}(f) +ight)}

    +
    + +
    +
    +initialize(f)[source]
    +

    produce a sensible initial value for f(x)

    +
    + +
    +
    +plot(xlabel='transformed $\\theta$', ylabel='$\\theta$', axes=None, *args, **kw)[source]
    +
    + +
    + +
    +
    +

    GPy.core.parameterization.variational module

    +

    Created on 6 Nov 2013

    +

    @author: maxz

    +
    +
    +class GPy.core.parameterization.variational.NormalPosterior(means=None, variances=None, name='latent space', *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.variational.VariationalPosterior

    +

    NormalPosterior distribution for variational approximations.

    +

    holds the means and variances for a factorizing multivariate normal distribution

    +
    +
    +plot(*args)[source]
    +

    Plot latent space X in 1D:

    +

    See GPy.plotting.matplot_dep.variational_plots

    +
    + +
    + +
    +
    +class GPy.core.parameterization.variational.NormalPrior(name='latent space', **kw)[source]
    +

    Bases: GPy.core.parameterization.variational.VariationalPrior

    +
    +
    +KL_divergence(variational_posterior)[source]
    +
    + +
    +
    +update_gradients_KL(variational_posterior)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.variational.SpikeAndSlabPosterior(means, variances, binary_prob, name='latent space')[source]
    +

    Bases: GPy.core.parameterization.variational.VariationalPosterior

    +

    The SpikeAndSlab distribution for variational approximations.

    +
    +
    +gamma_log_prob = <functools.partial object>
    +
    + +
    +
    +gamma_probabilities = <functools.partial object>
    +
    + +
    +
    +plot(*args, **kwargs)[source]
    +

    Plot latent space X in 1D:

    +

    See GPy.plotting.matplot_dep.variational_plots

    +
    + +
    +
    +set_gradients(grad)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.variational.SpikeAndSlabPrior(pi=None, learnPi=False, variance=1.0, name='SpikeAndSlabPrior', **kw)[source]
    +

    Bases: GPy.core.parameterization.variational.VariationalPrior

    +
    +
    +KL_divergence(variational_posterior)[source]
    +
    + +
    +
    +update_gradients_KL(variational_posterior)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.variational.VariationalPosterior(means=None, variances=None, name='latent space', *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +
    +
    +has_uncertain_inputs()[source]
    +
    + +
    +
    +set_gradients(grad)[source]
    +
    + +
    + +
    +
    +class GPy.core.parameterization.variational.VariationalPrior(name='latent space', **kw)[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +
    +
    +KL_divergence(variational_posterior)[source]
    +
    + +
    +
    +update_gradients_KL(variational_posterior)[source]
    +

    updates the gradients for mean and variance in place

    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.examples.html b/doc/_build/html/GPy.examples.html new file mode 100644 index 00000000..029a1be4 --- /dev/null +++ b/doc/_build/html/GPy.examples.html @@ -0,0 +1,464 @@ + + + + + + + + GPy.examples package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.examples package

    +
    +

    Submodules

    +
    +
    +

    GPy.examples.classification module

    +

    Gaussian Processes classification examples

    +
    +
    +GPy.examples.classification.crescent_data(model_type='Full', num_inducing=10, seed=10000, kernel=None, optimize=True, plot=True)[source]
    +

    Run a Gaussian process classification on the crescent data. The demonstration calls the basic GP classification model and uses EP to approximate the likelihood.

    + +++ + + + +
    Parameters:
      +
    • model_type – type of model to fit [‘Full’, ‘FITC’, ‘DTC’].
    • +
    • inducing (int) – number of inducing variables (only used for ‘FITC’ or ‘DTC’).
    • +
    • seed (int) – seed value for data generation.
    • +
    • kernel (a GPy kernel) – kernel to use in the model
    • +
    +
    +
    + +
    +
    +GPy.examples.classification.oil(num_inducing=50, max_iters=100, kernel=None, optimize=True, plot=True)[source]
    +

    Run a Gaussian process classification on the three phase oil data. The demonstration calls the basic GP classification model and uses EP to approximate the likelihood.

    +
    + +
    +
    +GPy.examples.classification.sparse_toy_linear_1d_classification(num_inducing=10, seed=10000, optimize=True, plot=True)[source]
    +

    Sparse 1D classification example

    + +++ + + + +
    Parameters:seed (int) – seed value for data generation (default is 4).
    +
    + +
    +
    +GPy.examples.classification.toy_heaviside(seed=10000, max_iters=100, optimize=True, plot=True)[source]
    +

    Simple 1D classification example using a heavy side gp transformation

    + +++ + + + +
    Parameters:seed (int) – seed value for data generation (default is 4).
    +
    + +
    +
    +GPy.examples.classification.toy_linear_1d_classification(seed=10000, optimize=True, plot=True)[source]
    +

    Simple 1D classification example using EP approximation

    + +++ + + + +
    Parameters:seed (int) – seed value for data generation (default is 4).
    +
    + +
    +
    +GPy.examples.classification.toy_linear_1d_classification_laplace(seed=10000, optimize=True, plot=True)[source]
    +

    Simple 1D classification example using Laplace approximation

    + +++ + + + +
    Parameters:seed (int) – seed value for data generation (default is 4).
    +
    + +
    +
    +

    GPy.examples.coreg_example module

    +
    +
    +

    GPy.examples.dimensionality_reduction module

    +
    +
    +GPy.examples.dimensionality_reduction.bcgplvm_linear_stick(kernel=None, optimize=True, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.bcgplvm_stick(kernel=None, optimize=True, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.bgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, max_iters=1000, **k)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.bgplvm_simulation(optimize=True, verbose=1, plot=True, plot_sim=False, max_iters=20000.0)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.bgplvm_simulation_missing_data(optimize=True, verbose=1, plot=True, plot_sim=False, max_iters=20000.0, percent_missing=0.1)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.bgplvm_test_model(optimize=False, verbose=1, plot=False, output_dim=200, nan=False)[source]
    +

    model for testing purposes. Samples from a GP with rbf kernel and learns +the samples with a new kernel. Normally not for optimization, just model cheking

    +
    + +
    +
    +GPy.examples.dimensionality_reduction.brendan_faces(optimize=True, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.cmu_mocap(subject='35', motion=['01'], in_place=True, optimize=True, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.gplvm_oil_100(optimize=True, verbose=1, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.mrd_simulation(optimize=True, verbose=True, plot=True, plot_sim=True, **kw)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.mrd_simulation_missing_data(optimize=True, verbose=True, plot=True, plot_sim=True, **kw)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.olivetti_faces(optimize=True, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.robot_wireless(optimize=True, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.sparse_gplvm_oil(optimize=True, verbose=0, plot=True, N=100, Q=6, num_inducing=15, max_iters=50)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.ssgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, max_iters=1000, **k)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.ssgplvm_simulation(optimize=True, verbose=1, plot=True, plot_sim=False, max_iters=20000.0, useGPU=False)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.ssgplvm_simulation_linear()[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.stick(kernel=None, optimize=True, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.stick_bgplvm(model=None, optimize=True, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.stick_play(range=None, frame_rate=15, optimize=False, verbose=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.dimensionality_reduction.swiss_roll(optimize=True, verbose=1, plot=True, N=1000, num_inducing=25, Q=4, sigma=0.2)[source]
    +
    + +
    +
    +

    GPy.examples.non_gaussian module

    +
    +
    +GPy.examples.non_gaussian.boston_example(optimize=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.non_gaussian.student_t_approx(optimize=True, plot=True)[source]
    +

    Example of regressing with a student t likelihood using Laplace

    +
    + +
    +
    +

    GPy.examples.regression module

    +

    Gaussian Processes regression examples

    +
    +
    +GPy.examples.regression.coregionalization_sparse(optimize=True, plot=True)[source]
    +

    A simple demonstration of coregionalization on two sinusoidal functions using sparse approximations.

    +
    + +
    +
    +GPy.examples.regression.coregionalization_toy(optimize=True, plot=True)[source]
    +

    A simple demonstration of coregionalization on two sinusoidal functions.

    +
    + +
    +
    +GPy.examples.regression.epomeo_gpx(max_iters=200, optimize=True, plot=True)[source]
    +

    Perform Gaussian process regression on the latitude and longitude data +from the Mount Epomeo runs. Requires gpxpy to be installed on your system +to load in the data.

    +
    + +
    +
    +GPy.examples.regression.multiple_optima(gene_number=937, resolution=80, model_restarts=10, seed=10000, max_iters=300, optimize=True, plot=True)[source]
    +

    Show an example of a multimodal error surface for Gaussian process +regression. Gene 939 has bimodal behaviour where the noisy mode is +higher.

    +
    + +
    +
    +GPy.examples.regression.olympic_100m_men(optimize=True, plot=True)[source]
    +

    Run a standard Gaussian process regression on the Rogers and Girolami olympics data.

    +
    + +
    +
    +GPy.examples.regression.olympic_marathon_men(optimize=True, plot=True)[source]
    +

    Run a standard Gaussian process regression on the Olympic marathon data.

    +
    + +
    +
    +GPy.examples.regression.robot_wireless(max_iters=100, kernel=None, optimize=True, plot=True)[source]
    +

    Predict the location of a robot given wirelss signal strength readings.

    +
    + +
    +
    +GPy.examples.regression.silhouette(max_iters=100, optimize=True, plot=True)[source]
    +

    Predict the pose of a figure given a silhouette. This is a task from Agarwal and Triggs 2004 ICML paper.

    +
    + +
    +
    +GPy.examples.regression.sparse_GP_regression_1D(num_samples=400, num_inducing=5, max_iters=100, optimize=True, plot=True, checkgrad=False)[source]
    +

    Run a 1D example of a sparse GP regression.

    +
    + +
    +
    +GPy.examples.regression.sparse_GP_regression_2D(num_samples=400, num_inducing=50, max_iters=100, optimize=True, plot=True, nan=False)[source]
    +

    Run a 2D example of a sparse GP regression.

    +
    + +
    +
    +GPy.examples.regression.toy_ARD(max_iters=1000, kernel_type='linear', num_samples=300, D=4, optimize=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.regression.toy_ARD_sparse(max_iters=1000, kernel_type='linear', num_samples=300, D=4, optimize=True, plot=True)[source]
    +
    + +
    +
    +GPy.examples.regression.toy_poisson_rbf_1d_laplace(optimize=True, plot=True)[source]
    +

    Run a simple demonstration of a standard Gaussian process fitting it to data sampled from an RBF covariance.

    +
    + +
    +
    +GPy.examples.regression.toy_rbf_1d(optimize=True, plot=True)[source]
    +

    Run a simple demonstration of a standard Gaussian process fitting it to data sampled from an RBF covariance.

    +
    + +
    +
    +GPy.examples.regression.toy_rbf_1d_50(optimize=True, plot=True)[source]
    +

    Run a simple demonstration of a standard Gaussian process fitting it to data sampled from an RBF covariance.

    +
    + +
    +
    +GPy.examples.regression.uncertain_inputs_sparse_regression(max_iters=200, optimize=True, plot=True)[source]
    +

    Run a 1D example of a sparse GP regression with uncertain inputs.

    +
    + +
    +
    +

    GPy.examples.stochastic module

    +
    +
    +

    GPy.examples.tutorials module

    +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.html b/doc/_build/html/GPy.html new file mode 100644 index 00000000..461c452b --- /dev/null +++ b/doc/_build/html/GPy.html @@ -0,0 +1,439 @@ + + + + + + + + GPy package — GPy documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy package

    +
    +

    Subpackages

    +
    + +
    +
    +
    +

    Module contents

    +
    +
    +GPy.load(file_path)[source]
    +

    Load a previously pickled model, using `m.pickle(‘path/to/file.pickle)’

    + +++ + + + +
    Parameters:file_name – path/to/file.pickle
    +
    + +
    +
    +GPy.tests()[source]
    +
    + +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.inference.html b/doc/_build/html/GPy.inference.html new file mode 100644 index 00000000..31725358 --- /dev/null +++ b/doc/_build/html/GPy.inference.html @@ -0,0 +1,174 @@ + + + + + + + + GPy.inference package — GPy documentation + + + + + + + + + + + + + + + + +
    + + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.inference.latent_function_inference.html b/doc/_build/html/GPy.inference.latent_function_inference.html new file mode 100644 index 00000000..f57ab578 --- /dev/null +++ b/doc/_build/html/GPy.inference.latent_function_inference.html @@ -0,0 +1,651 @@ + + + + + + + + GPy.inference.latent_function_inference package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.inference.latent_function_inference package

    +
    +

    Submodules

    +
    +
    +

    GPy.inference.latent_function_inference.dtc module

    +
    +
    +class GPy.inference.latent_function_inference.dtc.DTC[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference

    +

    An object for inference when the likelihood is Gaussian, but we want to do sparse inference.

    +

    The function self.inference returns a Posterior object, which summarizes +the posterior.

    +

    NB. It’s not recommended to use this function! It’s here for historical purposes.

    +
    +
    +inference(kern, X, Z, likelihood, Y, Y_metadata=None)[source]
    +
    + +
    + +
    +
    +class GPy.inference.latent_function_inference.dtc.vDTC[source]
    +

    Bases: object

    +
    +
    +inference(kern, X, X_variance, Z, likelihood, Y, Y_metadata)[source]
    +
    + +
    + +
    +
    +

    GPy.inference.latent_function_inference.exact_gaussian_inference module

    +
    +
    +class GPy.inference.latent_function_inference.exact_gaussian_inference.ExactGaussianInference[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference

    +

    An object for inference when the likelihood is Gaussian.

    +

    The function self.inference returns a Posterior object, which summarizes +the posterior.

    +

    For efficiency, we sometimes work with the cholesky of Y*Y.T. To save repeatedly recomputing this, we cache it.

    +
    +
    +get_YYTfactor(Y)[source]
    +

    find a matrix L which satisfies LL^T = YY^T.

    +

    Note that L may have fewer columns than Y, else L=Y.

    +
    + +
    +
    +inference(kern, X, likelihood, Y, Y_metadata=None)[source]
    +

    Returns a Posterior class containing essential quantities of the posterior

    +
    + +
    + +
    +
    +

    GPy.inference.latent_function_inference.expectation_propagation module

    +
    +
    +class GPy.inference.latent_function_inference.expectation_propagation.EP(epsilon=1e-06, eta=1.0, delta=1.0)[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference

    +
    +
    +expectation_propagation(K, Y, likelihood, Y_metadata)[source]
    +
    + +
    +
    +inference(kern, X, likelihood, Y, Y_metadata=None, Z=None)[source]
    +
    + +
    +
    +on_optimization_end()[source]
    +
    + +
    +
    +on_optimization_start()[source]
    +
    + +
    +
    +reset()[source]
    +
    + +
    + +
    +
    +

    GPy.inference.latent_function_inference.expectation_propagation_dtc module

    +
    +
    +class GPy.inference.latent_function_inference.expectation_propagation_dtc.EPDTC(epsilon=1e-06, eta=1.0, delta=1.0, limit=1)[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference

    +
    +
    +const_jitter = 1e-06
    +
    + +
    +
    +expectation_propagation(Kmm, Kmn, Y, likelihood, Y_metadata)[source]
    +
    + +
    +
    +get_VVTfactor(Y, prec)[source]
    +
    + +
    +
    +inference(kern, X, Z, likelihood, Y, Y_metadata=None)[source]
    +
    + +
    +
    +on_optimization_end()[source]
    +
    + +
    +
    +on_optimization_start()[source]
    +
    + +
    +
    +reset()[source]
    +
    + +
    +
    +set_limit(limit)[source]
    +
    + +
    + +
    +
    +

    GPy.inference.latent_function_inference.fitc module

    +
    +
    +class GPy.inference.latent_function_inference.fitc.FITC[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference

    +

    An object for inference when the likelihood is Gaussian, but we want to do sparse inference.

    +

    The function self.inference returns a Posterior object, which summarizes +the posterior.

    +
    +
    +const_jitter = 1e-06
    +
    + +
    +
    +inference(kern, X, Z, likelihood, Y, Y_metadata=None)[source]
    +
    + +
    + +
    +
    +

    GPy.inference.latent_function_inference.inferenceX module

    +
    +
    +class GPy.inference.latent_function_inference.inferenceX.InferenceX(model, Y, name='inferenceX', init='L2')[source]
    +

    Bases: GPy.core.model.Model

    +

    The class for inference of new X with given new Y. (do_test_latent)

    + +++ + + + +
    Parameters:
      +
    • model (GPy.core.Model) – the GPy model used in inference
    • +
    • Y (numpy.ndarray) – the new observed data for inference
    • +
    +
    +
    +
    +compute_dL()[source]
    +
    + +
    +
    +log_likelihood()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +GPy.inference.latent_function_inference.inferenceX.infer_newX(model, Y_new, optimize=True, init='L2')[source]
    +

    Infer the distribution of X for the new observed data Y_new.

    + +++ + + + + + + + +
    Parameters:
      +
    • model (GPy.core.Model) – the GPy model used in inference
    • +
    • Y_new (numpy.ndarray) – the new observed data for inference
    • +
    • optimize (boolean) – whether to optimize the location of new X (True by default)
    • +
    +
    Returns:

    a tuple containing the estimated posterior distribution of X and the model that optimize X

    +
    Return type:

    (GPy.core.parameterization.variational.VariationalPosterior, GPy.core.Model)

    +
    +
    + +
    +
    +

    GPy.inference.latent_function_inference.laplace module

    +
    +
    +class GPy.inference.latent_function_inference.laplace.Laplace[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference

    +
    +
    +inference(kern, X, likelihood, Y, Y_metadata=None)[source]
    +

    Returns a Posterior class containing essential quantities of the posterior

    +
    + +
    +
    +mode_computations(f_hat, Ki_f, K, Y, likelihood, kern, Y_metadata)[source]
    +

    At the mode, compute the hessian and effective covariance matrix.

    +
    +
    returns: logZ : approximation to the marginal likelihood
    +
    woodbury_inv : variable required for calculating the approximation to the covariance matrix +dL_dthetaL : array of derivatives (1 x num_kernel_params) +dL_dthetaL : array of derivatives (1 x num_likelihood_params)
    +
    +
    + +
    +
    +rasm_mode(K, Y, likelihood, Ki_f_init, Y_metadata=None)[source]
    +

    Rasmussen’s numerically stable mode finding +For nomenclature see Rasmussen & Williams 2006 +Influenced by GPML (BSD) code, all errors are our own

    + +++ + + + + + + + +
    Parameters:
      +
    • K (NxD matrix) – Covariance matrix evaluated at locations X
    • +
    • Y (np.ndarray) – The data
    • +
    • likelihood (a GPy.likelihood object) – the likelihood of the latent function value for the given data
    • +
    • Ki_f_init (np.ndarray) – the initial guess at the mode
    • +
    • Y_metadata (np.ndarray | None) – information about the data, e.g. which likelihood to take from a multi-likelihood object
    • +
    +
    Returns:

    f_hat, mode on which to make laplace approxmiation

    +
    Return type:

    np.ndarray

    +
    +
    + +
    + +
    +
    +GPy.inference.latent_function_inference.laplace.warning_on_one_line(message, category, filename, lineno, file=None, line=None)[source]
    +
    + +
    +
    +

    GPy.inference.latent_function_inference.posterior module

    +
    +
    +class GPy.inference.latent_function_inference.posterior.Posterior(woodbury_chol=None, woodbury_vector=None, K=None, mean=None, cov=None, K_chol=None, woodbury_inv=None)[source]
    +

    Bases: object

    +

    An object to represent a Gaussian posterior over latent function values, p(f|D). +This may be computed exactly for Gaussian likelihoods, or approximated for +non-Gaussian likelihoods.

    +

    The purpose of this class is to serve as an interface between the inference +schemes and the model classes. the model class can make predictions for +the function at any new point x_* by integrating over this posterior.

    +
    +
    +K_chol
    +

    Cholesky of the prior covariance K

    +
    + +
    +
    +covariance
    +

    Posterior covariance +$$ +K_{xx} - K_{xx}W_{xx}^{-1}K_{xx} +W_{xx} := exttt{Woodbury inv} +$$

    +
    + +
    +
    +mean
    +

    Posterior mean +$$ +K_{xx}v +v := exttt{Woodbury vector} +$$

    +
    + +
    +
    +precision
    +

    Inverse of posterior covariance

    +
    + +
    +
    +woodbury_chol
    +

    return $L_{W}$ where L is the lower triangular Cholesky decomposition of the Woodbury matrix +$$ +L_{W}L_{W}^{ op} = W^{-1} +W^{-1} := exttt{Woodbury inv} +$$

    +
    + +
    +
    +woodbury_inv
    +

    The inverse of the woodbury matrix, in the gaussian likelihood case it is defined as +$$ +(K_{xx} + Sigma_{xx})^{-1} +Sigma_{xx} := exttt{Likelihood.variance / Approximate likelihood covariance} +$$

    +
    + +
    +
    +woodbury_vector
    +

    Woodbury vector in the gaussian likelihood case only is defined as +$$ +(K_{xx} + Sigma)^{-1}Y +Sigma := exttt{Likelihood.variance / Approximate likelihood covariance} +$$

    +
    + +
    + +
    +
    +

    GPy.inference.latent_function_inference.var_dtc module

    +
    +
    +class GPy.inference.latent_function_inference.var_dtc.VarDTC(limit=1)[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference

    +

    An object for inference when the likelihood is Gaussian, but we want to do sparse inference.

    +

    The function self.inference returns a Posterior object, which summarizes +the posterior.

    +

    For efficiency, we sometimes work with the cholesky of Y*Y.T. To save repeatedly recomputing this, we cache it.

    +
    +
    +const_jitter = 1e-06
    +
    + +
    +
    +get_VVTfactor(Y, prec)[source]
    +
    + +
    +
    +inference(kern, X, Z, likelihood, Y, Y_metadata=None, Lm=None, dL_dKmm=None)[source]
    +
    + +
    +
    +set_limit(limit)[source]
    +
    + +
    + +
    +
    +

    GPy.inference.latent_function_inference.var_dtc_gpu module

    +
    +
    +

    GPy.inference.latent_function_inference.var_dtc_parallel module

    +
    +
    +class GPy.inference.latent_function_inference.var_dtc_parallel.VarDTC_minibatch(batchsize=None, limit=1, mpi_comm=None)[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference

    +

    An object for inference when the likelihood is Gaussian, but we want to do sparse inference.

    +

    The function self.inference returns a Posterior object, which summarizes +the posterior.

    +

    For efficiency, we sometimes work with the cholesky of Y*Y.T. To save repeatedly recomputing this, we cache it.

    +
    +
    +const_jitter = 1e-06
    +
    + +
    +
    +gatherPsiStat(kern, X, Z, Y, beta, uncertain_inputs)[source]
    +
    + +
    +
    +inference_likelihood(kern, X, Z, likelihood, Y)[source]
    +

    The first phase of inference: +Compute: log-likelihood, dL_dKmm

    +

    Cached intermediate results: Kmm, KmmInv,

    +
    + +
    +
    +inference_minibatch(kern, X, Z, likelihood, Y)[source]
    +

    The second phase of inference: Computing the derivatives over a minibatch of Y +Compute: dL_dpsi0, dL_dpsi1, dL_dpsi2, dL_dthetaL +return a flag showing whether it reached the end of Y (isEnd)

    +
    + +
    +
    +set_limit(limit)[source]
    +
    + +
    + +
    +
    +GPy.inference.latent_function_inference.var_dtc_parallel.update_gradients(model, mpi_comm=None)[source]
    +
    + +
    +
    +GPy.inference.latent_function_inference.var_dtc_parallel.update_gradients_sparsegp(model, mpi_comm=None)[source]
    +
    + +
    +
    +

    Module contents

    +

    Inference over Gaussian process latent functions

    +

    In all our GP models, the consistency propery means that we have a Gaussian +prior over a finite set of points f. This prior is

    +
    +
    math:: N(f | 0, K)
    +

    where K is the kernel matrix.

    +

    We also have a likelihood (see GPy.likelihoods) which defines how the data are +related to the latent function: p(y | f). If the likelihood is also a Gaussian, +the inference over f is tractable (see exact_gaussian_inference.py).

    +

    If the likelihood object is something other than Gaussian, then exact inference +is not tractable. We then resort to a Laplace approximation (laplace.py) or +expectation propagation (ep.py).

    +

    The inference methods return a +Posterior +instance, which is a simple +structure which contains a summary of the posterior. The model classes can then +use this posterior object for making predictions, optimizing hyper-parameters, +etc.

    +
    +
    +class GPy.inference.latent_function_inference.InferenceMethodList[source]
    +

    Bases: GPy.inference.latent_function_inference.LatentFunctionInference, list

    +
    +
    +on_optimization_end()[source]
    +
    + +
    +
    +on_optimization_start()[source]
    +
    + +
    + +
    +
    +class GPy.inference.latent_function_inference.LatentFunctionInference[source]
    +

    Bases: object

    +
    +
    +on_optimization_end()[source]
    +

    This function gets called, just after the optimization loop ended.

    +
    + +
    +
    +on_optimization_start()[source]
    +

    This function gets called, just before the optimization loop to start.

    +
    + +
    + +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.inference.mcmc.html b/doc/_build/html/GPy.inference.mcmc.html new file mode 100644 index 00000000..d3c4fc00 --- /dev/null +++ b/doc/_build/html/GPy.inference.mcmc.html @@ -0,0 +1,221 @@ + + + + + + + + GPy.inference.mcmc package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.inference.mcmc package

    +
    +

    Submodules

    +
    +
    +

    GPy.inference.mcmc.hmc module

    +
    +
    +class GPy.inference.mcmc.hmc.HMC(model, M=None, stepsize=0.1)[source]
    +

    An implementation of Hybrid Monte Carlo (HMC) for GPy models

    +

    Initialize an object for HMC sampling. Note that the status of the model (model parameters) will be changed during sampling.

    + +++ + + + +
    Parameters:
      +
    • model (GPy.core.Model) – the GPy model that will be sampled
    • +
    • M (numpy.ndarray) – the mass matrix (an identity matrix by default)
    • +
    • stepsize (float) – the step size for HMC sampling
    • +
    +
    +
    +
    +sample(num_samples=1000, hmc_iters=20)[source]
    +

    Sample the (unfixed) model parameters.

    + +++ + + + + + + + +
    Parameters:
      +
    • num_samples (int) – the number of samples to draw (1000 by default)
    • +
    • hmc_iters (int) – the number of leap-frog iterations (20 by default)
    • +
    +
    Returns:

    the list of parameters samples with the size N x P (N - the number of samples, P - the number of parameters to sample)

    +
    Return type:

    numpy.ndarray

    +
    +
    + +
    + +
    +
    +class GPy.inference.mcmc.hmc.HMC_shortcut(model, M=None, stepsize_range=[1e-06, 0.1], groupsize=5, Hstd_th=[1e-05, 3.0])[source]
    +
    +
    +sample(m_iters=1000, hmc_iters=20)[source]
    +
    + +
    + +
    +
    +

    GPy.inference.mcmc.samplers module

    +
    +
    +class GPy.inference.mcmc.samplers.Metropolis_Hastings(model, cov=None)[source]
    +
    +
    +new_chain(start=None)[source]
    +
    + +
    +
    +predict(function, args)[source]
    +

    Make a prediction for the function, to which we will pass the additional arguments

    +
    + +
    +
    +sample(Ntotal, Nburn, Nthin, tune=True, tune_throughout=False, tune_interval=400)[source]
    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.inference.optimization.html b/doc/_build/html/GPy.inference.optimization.html new file mode 100644 index 00000000..7e8e951e --- /dev/null +++ b/doc/_build/html/GPy.inference.optimization.html @@ -0,0 +1,456 @@ + + + + + + + + GPy.inference.optimization package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.inference.optimization package

    +
    +

    Submodules

    +
    +
    +

    GPy.inference.optimization.conjugate_gradient_descent module

    +
    +
    +class GPy.inference.optimization.conjugate_gradient_descent.Async_Optimize[source]
    +

    Bases: object

    +
    +
    +SENTINEL = 'SENTINEL'
    +
    + +
    +
    +async_callback_collect(q)[source]
    +
    + +
    +
    +callback(*x)
    +
    + +
    +
    +opt(f, df, x0, callback=None, update_rule=<class GPy.inference.optimization.gradient_descent_update_rules.FletcherReeves>, messages=0, maxiter=5000.0, max_f_eval=15000.0, gtol=1e-06, report_every=10, *args, **kwargs)[source]
    +
    + +
    +
    +opt_async(f, df, x0, callback, update_rule=<class GPy.inference.optimization.gradient_descent_update_rules.PolakRibiere>, messages=0, maxiter=5000.0, max_f_eval=15000.0, gtol=1e-06, report_every=10, *args, **kwargs)[source]
    +
    + +
    +
    +runsignal = <multiprocessing.synchronize.Event object>
    +
    + +
    + +
    +
    +class GPy.inference.optimization.conjugate_gradient_descent.CGD[source]
    +

    Bases: GPy.inference.optimization.conjugate_gradient_descent.Async_Optimize

    +

    Conjugate gradient descent algorithm to minimize +function f with gradients df, starting at x0 +with update rule update_rule

    +

    if df returns tuple (grad, natgrad) it will optimize according +to natural gradient rules

    +
    +
    +opt(*a, **kw)[source]
    +
    +
    opt(self, f, df, x0, callback=None, update_rule=FletcherReeves,
    +
    messages=0, maxiter=5e3, max_f_eval=15e3, gtol=1e-6, +report_every=10, *args, **kwargs)
    +
    +

    Minimize f, calling callback every report_every iterations with following syntax:

    +
    +
    callback(xi, fi, gi, iteration, function_calls, gradient_calls, status_message)
    +

    if df returns tuple (grad, natgrad) it will optimize according +to natural gradient rules

    +

    f, and df will be called with

    +
    +
    f(xi, *args, **kwargs) +df(xi, *args, **kwargs)
    +

    returns

    +
    +
    x_opt, f_opt, g_opt, iteration, function_calls, gradient_calls, status_message
    +

    at end of optimization

    +
    + +
    +
    +opt_async(*a, **kw)[source]
    +
    +
    opt_async(self, f, df, x0, callback, update_rule=FletcherReeves,
    +
    messages=0, maxiter=5e3, max_f_eval=15e3, gtol=1e-6, +report_every=10, *args, **kwargs)
    +
    +

    callback gets called every report_every iterations

    +
    +
    callback(xi, fi, gi, iteration, function_calls, gradient_calls, status_message)
    +

    if df returns tuple (grad, natgrad) it will optimize according +to natural gradient rules

    +

    f, and df will be called with

    +
    +
    f(xi, *args, **kwargs) +df(xi, *args, **kwargs)
    +

    Returns:

    +
    +
    Started Process object, optimizing asynchronously
    +

    Calls:

    +
    +
    callback(x_opt, f_opt, g_opt, iteration, function_calls, gradient_calls, status_message)
    +

    at end of optimization!

    +
    + +
    +
    +opt_name = 'Conjugate Gradient Descent'
    +
    + +
    + +
    +
    +

    GPy.inference.optimization.gradient_descent_update_rules module

    +
    +
    +class GPy.inference.optimization.gradient_descent_update_rules.FletcherReeves(initgrad, initgradnat=None)[source]
    +

    Bases: GPy.inference.optimization.gradient_descent_update_rules.GDUpdateRule

    +

    Fletcher Reeves update rule for gamma

    +
    + +
    +
    +class GPy.inference.optimization.gradient_descent_update_rules.GDUpdateRule(initgrad, initgradnat=None)[source]
    +
    + +
    +
    +class GPy.inference.optimization.gradient_descent_update_rules.PolakRibiere(initgrad, initgradnat=None)[source]
    +

    Bases: GPy.inference.optimization.gradient_descent_update_rules.GDUpdateRule

    +

    Fletcher Reeves update rule for gamma

    +
    + +
    +
    +

    GPy.inference.optimization.optimization module

    +
    +
    +class GPy.inference.optimization.optimization.Optimizer(x_init, messages=False, model=None, max_f_eval=10000.0, max_iters=1000.0, ftol=None, gtol=None, xtol=None, bfgs_factor=None)[source]
    +

    Superclass for all the optimizers.

    + +++ + + + + + +
    Parameters:
      +
    • x_init – initial set of parameters
    • +
    • f_fp – function that returns the function AND the gradients at the same time
    • +
    • f – function to optimize
    • +
    • fp – gradients
    • +
    • messages ((True | False)) – print messages from the optimizer?
    • +
    • max_f_eval – maximum number of function evaluations
    • +
    +
    Return type:

    optimizer object.

    +
    +
    +
    +opt(f_fp=None, f=None, fp=None)[source]
    +
    + +
    +
    +plot()[source]
    +

    See GPy.plotting.matplot_dep.inference_plots

    +
    + +
    +
    +run(**kwargs)[source]
    +
    + +
    + +
    +
    +GPy.inference.optimization.optimization.get_optimizer(f_min)[source]
    +
    + +
    +
    +class GPy.inference.optimization.optimization.opt_SCG(*args, **kwargs)[source]
    +

    Bases: GPy.inference.optimization.optimization.Optimizer

    +
    +
    +opt(f_fp=None, f=None, fp=None)[source]
    +
    + +
    + +
    +
    +class GPy.inference.optimization.optimization.opt_lbfgsb(*args, **kwargs)[source]
    +

    Bases: GPy.inference.optimization.optimization.Optimizer

    +
    +
    +opt(f_fp=None, f=None, fp=None)[source]
    +

    Run the optimizer

    +
    + +
    + +
    +
    +class GPy.inference.optimization.optimization.opt_rasm(*args, **kwargs)[source]
    +

    Bases: GPy.inference.optimization.optimization.Optimizer

    +
    +
    +opt(f_fp=None, f=None, fp=None)[source]
    +

    Run Rasmussen’s Conjugate Gradient optimizer

    +
    + +
    + +
    +
    +class GPy.inference.optimization.optimization.opt_simplex(*args, **kwargs)[source]
    +

    Bases: GPy.inference.optimization.optimization.Optimizer

    +
    +
    +opt(f_fp=None, f=None, fp=None)[source]
    +

    The simplex optimizer does not require gradients.

    +
    + +
    + +
    +
    +class GPy.inference.optimization.optimization.opt_tnc(*args, **kwargs)[source]
    +

    Bases: GPy.inference.optimization.optimization.Optimizer

    +
    +
    +opt(f_fp=None, f=None, fp=None)[source]
    +

    Run the TNC optimizer

    +
    + +
    + +
    +
    +

    GPy.inference.optimization.scg module

    +
    +
    +GPy.inference.optimization.scg.SCG(f, gradf, x, optargs=(), maxiters=500, max_f_eval=inf, display=True, xtol=None, ftol=None, gtol=None)[source]
    +

    Optimisation through Scaled Conjugate Gradients (SCG)

    +

    f: the objective function +gradf : the gradient function (should return a 1D np.ndarray) +x : the initial condition

    +

    Returns +x the optimal value for x +flog : a list of all the objective values +function_eval number of fn evaluations +status: string describing convergence status

    +
    + +
    +
    +GPy.inference.optimization.scg.exponents(fnow, current_grad)[source]
    +
    + +
    +
    +GPy.inference.optimization.scg.print_out(len_maxiters, fnow, current_grad, beta, iteration)[source]
    +
    + +
    +
    +

    GPy.inference.optimization.sgd module

    +
    +
    +

    GPy.inference.optimization.stochastics module

    +
    +
    +class GPy.inference.optimization.stochastics.SparseGPMissing(model, batchsize=1)[source]
    +

    Bases: GPy.inference.optimization.stochastics.StochasticStorage

    +
    + +
    +
    +class GPy.inference.optimization.stochastics.SparseGPStochastics(model, batchsize=1)[source]
    +

    Bases: GPy.inference.optimization.stochastics.StochasticStorage

    +

    For the sparse gp we need to store the dimension we are in, +and the indices corresponding to those

    +
    +
    +do_stochastics()[source]
    +
    + +
    +
    +reset()[source]
    +
    + +
    + +
    +
    +class GPy.inference.optimization.stochastics.StochasticStorage(model)[source]
    +

    Bases: object

    +

    This is a container for holding the stochastic parameters, +such as subset indices or step length and so on.

    +
    +
    +do_stochastics()[source]
    +

    Update the internal state to the next batch of the stochastic +descent algorithm.

    +
    + +
    +
    +reset()[source]
    +

    Reset the state of this stochastics generator.

    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.kern._src.html b/doc/_build/html/GPy.kern._src.html new file mode 100644 index 00000000..677b85f1 --- /dev/null +++ b/doc/_build/html/GPy.kern._src.html @@ -0,0 +1,2052 @@ + + + + + + + + GPy.kern._src package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.kern._src package

    + +
    +

    Submodules

    +
    +
    +

    GPy.kern._src.ODE_UY module

    +
    +
    +class GPy.kern._src.ODE_UY.ODE_UY(input_dim, variance_U=3.0, variance_Y=1.0, lengthscale_U=1.0, lengthscale_Y=1.0, active_dims=None, name='ode_uy')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +

    Compute the diagonal of the covariance matrix associated to X.

    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    derivative of the covariance matrix with respect to the parameters.

    +
    + +
    + +
    +
    +

    GPy.kern._src.ODE_UYC module

    +
    +
    +class GPy.kern._src.ODE_UYC.ODE_UYC(input_dim, variance_U=3.0, variance_Y=1.0, lengthscale_U=1.0, lengthscale_Y=1.0, ubias=1.0, active_dims=None, name='ode_uyc')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +

    Compute the diagonal of the covariance matrix associated to X.

    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    derivative of the covariance matrix with respect to the parameters.

    +
    + +
    + +
    +
    +

    GPy.kern._src.ODE_st module

    +
    +
    +class GPy.kern._src.ODE_st.ODE_st(input_dim, a=1.0, b=1.0, c=1.0, variance_Yx=3.0, variance_Yt=1.5, lengthscale_Yx=1.5, lengthscale_Yt=1.5, active_dims=None, name='ode_st')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    kernel resultiong from a first order ODE with OU driving GP

    + +++ + + + + + +
    Parameters:
      +
    • input_dim (int) – the number of input dimension, has to be equal to one
    • +
    • varianceU (float) – variance of the driving GP
    • +
    • lengthscaleU (float) – lengthscale of the driving GP (sqrt(3)/lengthscaleU)
    • +
    • varianceY (float) – ‘variance’ of the transfer function
    • +
    • lengthscaleY (float) – ‘lengthscale’ of the transfer function (1/lengthscaleY)
    • +
    +
    Return type:

    kernel object

    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +

    Compute the covariance matrix between X and X2.

    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +

    Compute the diagonal of the covariance matrix associated to X.

    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    derivative of the covariance matrix with respect to the parameters.

    +
    + +
    + +
    +
    +

    GPy.kern._src.ODE_t module

    +
    +
    +class GPy.kern._src.ODE_t.ODE_t(input_dim, a=1.0, c=1.0, variance_Yt=3.0, lengthscale_Yt=1.5, ubias=1.0, active_dims=None, name='ode_st')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +

    Compute the covariance matrix between X and X2.

    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    derivative of the covariance matrix with respect to the parameters.

    +
    + +
    + +
    +
    +

    GPy.kern._src.add module

    +
    +
    +class GPy.kern._src.add.Add(subkerns, name='add')[source]
    +

    Bases: GPy.kern._src.kern.CombinationKernel

    +

    Add given list of kernels together. +propagates gradients through.

    +

    This kernel will take over the active dims of it’s subkernels passed in.

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +

    Add all kernels together. +If a list of parts (of this kernel!) which_parts is given, only +the parts of the list are taken to compute the covariance.

    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +add(other)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +

    Compute the gradient of the objective function with respect to X.

    + +++ + + + +
    Parameters:
      +
    • dL_dK (np.ndarray (num_samples x num_inducing)) – An array of gradients of the objective function with respect to the covariance function.
    • +
    • X (np.ndarray (num_samples x input_dim)) – Observed data inputs
    • +
    • X2 (np.ndarray (num_inducing x input_dim)) – Observed data inputs (optional, defaults to X)
    • +
    +
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +gradients_Z_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +gradients_qX_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +input_sensitivity(summarize=True)[source]
    +
    + +
    +
    +psi0(Z, variational_posterior)[source]
    +
    + +
    +
    +psi1(Z, variational_posterior)[source]
    +
    + +
    +
    +psi2(Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.brownian module

    +
    +
    +class GPy.kern._src.brownian.Brownian(input_dim=1, variance=1.0, active_dims=None, name='Brownian')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    Brownian motion in 1D only.

    +

    Negative times are treated as a separate (backwards!) Brownian motion.

    + +++ + + + +
    Parameters:
      +
    • input_dim (int) – the number of input dimensions
    • +
    • variance (float) –
    • +
    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.coregionalize module

    +
    +
    +class GPy.kern._src.coregionalize.Coregionalize(input_dim, output_dim, rank=1, W=None, kappa=None, active_dims=None, name='coregion')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    Covariance function for intrinsic/linear coregionalization models

    +

    This covariance has the form: +.. math:

    +
    \mathbf{B} = \mathbf{W}\mathbf{W}^       op +    ext{diag}(kappa)
    +
    +
    +

    An intrinsic/linear coregionalization covariance function of the form: +.. math:

    +
    k_2(x, y)=\mathbf{B} k(x, y)
    +
    +
    +

    it is obtained as the tensor product between a covariance function +k(x, y) and B.

    + +++ + + + +
    Parameters:
      +
    • output_dim (int) – number of outputs to coregionalize
    • +
    • rank (int) – number of columns of the W matrix (this parameter is ignored if parameter W is not None)
    • +
    • W (numpy array of dimensionality (num_outpus, W_columns)) – a low rank matrix that determines the correlations between the different outputs, together with kappa it forms the coregionalization matrix B
    • +
    • kappa (numpy array of dimensionality (output_dim, )) – a vector which allows the outputs to behave independently
    • +
    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.hierarchical module

    +
    +
    +

    GPy.kern._src.independent_outputs module

    +
    +
    +class GPy.kern._src.independent_outputs.Hierarchical(kernels, name='hierarchy')[source]
    +

    Bases: GPy.kern._src.kern.CombinationKernel

    +

    A kernel which can represent a simple hierarchical model.

    +

    See Hensman et al 2013, “Hierarchical Bayesian modelling of gene expression time +series across irregularly sampled replicates and clusters” +http://www.biomedcentral.com/1471-2105/14/252

    +

    To construct this kernel, you must pass a list of kernels. the first kernel +will be assumed to be the ‘base’ kernel, and will be computed everywhere. +For every additional kernel, we assume another layer in the hierachy, with +a corresponding column of the input matrix which indexes which function the +data are in at that level.

    +

    For more, see the ipython notebook documentation on Hierarchical +covariances.

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.independent_outputs.IndependentOutputs(kernels, index_dim=-1, name='independ')[source]
    +

    Bases: GPy.kern._src.kern.CombinationKernel

    +

    A kernel which can represent several independent functions. this kernel +‘switches off’ parts of the matrix where the output indexes are different.

    +

    The index of the functions is given by the last column in the input X the +rest of the columns of X are passed to the underlying kernel for +computation (in blocks).

    + +++ + + + +
    Parameters:kernels – either a kernel, or list of kernels to work with. If it is
    +

    a list of kernels the indices in the index_dim, index the kernels you gave!

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +GPy.kern._src.independent_outputs.index_to_slices(index)[source]
    +

    take a numpy array of integers (index) and return a nested list of slices such that the slices describe the start, stop points for each integer in the index.

    +

    e.g. +>>> index = np.asarray([0,0,0,1,1,1,2,2,2]) +returns +>>> [[slice(0,3,None)],[slice(3,6,None)],[slice(6,9,None)]]

    +

    or, a more complicated example +>>> index = np.asarray([0,0,1,1,0,2,2,2,1,1]) +returns +>>> [[slice(0,2,None),slice(4,5,None)],[slice(2,4,None),slice(8,10,None)],[slice(5,8,None)]]

    +
    + +
    +
    +

    GPy.kern._src.kern module

    +
    +
    +class GPy.kern._src.kern.CombinationKernel(kernels, name, extra_dims=[])[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    Abstract super class for combination kernels. +A combination kernel combines (a list of) kernels and works on those. +Examples are the HierarchicalKernel or Add and Prod kernels.

    +
    +
    +get_input_dim_active_dims(kernels, extra_dims=None)[source]
    +
    + +
    +
    +input_sensitivity(summarize=True)[source]
    +

    If summize is true, we want to get the summerized view of the sensitivities, +otherwise put everything into an array with shape (#kernels, input_dim) +in the order of appearance of the kernels in the parameterized object.

    +
    + +
    +
    +parts
    +
    + +
    + +
    +
    +class GPy.kern._src.kern.Kern(input_dim, active_dims, name, useGPU=False, *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +

    Compute the kernel function.

    + +++ + + + +
    Parameters:
      +
    • X – the first set of inputs to the kernel
    • +
    • X2 – (optional) the second set of arguments to the kernel. If X2 +is None, this is passed throgh to the ‘part’ object, which +handLes this as X2 == X.
    • +
    +
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +add(other, name='add')[source]
    +

    Add another kernel to this one.

    + +++ + + + +
    Parameters:other (GPy.kern) – the other kernel to be added
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +gradients_Z_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +

    Returns the derivative of the objective wrt Z, using the chain rule +through the expectation variables.

    +
    + +
    +
    +gradients_qX_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +

    Compute the gradients wrt the parameters of the variational +distruibution q(X), chain-ruling via the expectations of the kernel

    +
    + +
    +
    +input_sensitivity(summarize=True)[source]
    +

    Returns the sensitivity for each dimension of this kernel.

    +
    + +
    +
    +plot(x=None, fignum=None, ax=None, title=None, plot_limits=None, resolution=None, **mpl_kwargs)[source]
    +

    plot this kernel. +:param x: the value to use for the other kernel argument (kernels are a function of two variables!) +:param fignum: figure number of the plot +:param ax: matplotlib axis to plot on +:param title: the matplotlib title +:param plot_limits: the range over which to plot the kernel +:resolution: the resolution of the lines used in plotting +:mpl_kwargs avalid keyword arguments to pass through to matplotlib (e.g. lw=7)

    +
    + +
    +
    +plot_ARD(*args, **kw)[source]
    +

    See kernel_plots

    +
    + +
    +
    +prod(other, name='mul')[source]
    +

    Multiply two kernels (either on the same space, or on the tensor +product of the input space).

    + +++ + + + +
    Parameters:
      +
    • other (GPy.kern) – the other kernel to be added
    • +
    • tensor (bool) – whether or not to use the tensor space (default is false).
    • +
    +
    +
    + +
    +
    +psi0(Z, variational_posterior)[source]
    +
    + +
    +
    +psi1(Z, variational_posterior)[source]
    +
    + +
    +
    +psi2(Z, variational_posterior)[source]
    +
    + +
    +
    +return_psi2_n
    +

    Flag whether to pass back psi2 as NxMxM or MxM, by summing out N.

    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +

    update the gradients of all parameters when using only the diagonal elements of the covariance matrix

    +
    + +
    +
    +update_gradients_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +

    Set the gradients of all parameters when doing inference with +uncertain inputs, using expectations of the kernel.

    +

    The esential maths is

    +
    +
    dL_d{theta_i} = dL_dpsi0 * dpsi0_d{theta_i} +
    +
    dL_dpsi1 * dpsi1_d{theta_i} + +dL_dpsi2 * dpsi2_d{theta_i}
    +
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    Set the gradients of all parameters when doing full (N) inference.

    +
    + +
    + +
    +
    +

    GPy.kern._src.kernel_slice_operations module

    +

    Created on 11 Mar 2014

    +

    @author: maxz

    +
    +
    +class GPy.kern._src.kernel_slice_operations.KernCallsViaSlicerMeta[source]
    +

    Bases: GPy.core.parameterization.parameterized.ParametersChangedMeta

    +
    + +
    +
    +GPy.kern._src.kernel_slice_operations.put_clean(dct, name, func)[source]
    +
    + +
    +
    +

    GPy.kern._src.linear module

    +
    +
    +class GPy.kern._src.linear.Linear(input_dim, variances=None, ARD=False, active_dims=None, name='linear')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    Linear kernel

    +
    +

    k(x,y) = \sum_{i=1}^input_dim \sigma^2_i x_iy_i

    +
    +++ + + + + + +
    Parameters:
      +
    • input_dim (int) – the number of input dimensions
    • +
    • variances (array or list of the appropriate size (or float if there +is only one variance parameter)) – the vector of variances \sigma^2_i
    • +
    • ARD (Boolean) – Auto Relevance Determination. If False, the kernel has only one +variance parameter sigma^2, otherwise there is one variance +parameter per dimension.
    • +
    +
    Return type:

    kernel object

    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +gradients_Z_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +gradients_qX_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +input_sensitivity(summarize=True)[source]
    +
    + +
    +
    +psi0(Z, variational_posterior)[source]
    +
    + +
    +
    +psi1(Z, variational_posterior)[source]
    +
    + +
    +
    +psi2(Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.linear.LinearFull(input_dim, rank, W=None, kappa=None, active_dims=None, name='linear_full')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.mlp module

    +
    +
    +class GPy.kern._src.mlp.MLP(input_dim, variance=1.0, weight_variance=1.0, bias_variance=100.0, active_dims=None, name='mlp')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    Multi layer perceptron kernel (also known as arc sine kernel or neural network kernel)

    +
    +

    k(x,y) = \sigma^{2}\frac{2}{\pi }  \text{asin} \left ( \frac{ \sigma_w^2 x^\top y+\sigma_b^2}{\sqrt{\sigma_w^2x^\top x + \sigma_b^2 + 1}\sqrt{\sigma_w^2 y^\top y \sigma_b^2 +1}} \right )

    +
    +++ + + + + + +
    Parameters:
      +
    • input_dim (int) – the number of input dimensions
    • +
    • variance (float) – the variance \sigma^2
    • +
    • weight_variance (array or list of the appropriate size (or float if there is only one weight variance parameter)) – the vector of the variances of the prior over input weights in the neural network \sigma^2_w
    • +
    • bias_variance – the variance of the prior over bias parameters \sigma^2_b
    • +
    • ARD (Boolean) – Auto Relevance Determination. If equal to “False”, the kernel is isotropic (ie. one weight variance parameter sigma^2_w), otherwise there is one weight variance parameter per dimension.
    • +
    +
    Return type:

    Kernpart object

    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +

    Compute the diagonal of the covariance matrix for X.

    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +

    Derivative of the covariance matrix with respect to X

    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +

    Gradient of diagonal of covariance with respect to X

    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    Derivative of the covariance with respect to the parameters.

    +
    + +
    + +
    +
    +

    GPy.kern._src.periodic module

    +
    +
    +class GPy.kern._src.periodic.Periodic(input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name)[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.periodic.PeriodicExponential(input_dim=1, variance=1.0, lengthscale=1.0, period=6.283185307179586, n_freq=10, lower=0.0, upper=12.566370614359172, active_dims=None, name='periodic_exponential')[source]
    +

    Bases: GPy.kern._src.periodic.Periodic

    +

    Kernel of the periodic subspace (up to a given frequency) of a exponential +(Matern 1/2) RKHS.

    +

    Only defined for input_dim=1.

    +
    +
    +Gram_matrix()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    derivative of the covariance matrix with respect to the parameters (shape is N x num_inducing x num_params)

    +
    + +
    + +
    +
    +class GPy.kern._src.periodic.PeriodicMatern32(input_dim=1, variance=1.0, lengthscale=1.0, period=6.283185307179586, n_freq=10, lower=0.0, upper=12.566370614359172, active_dims=None, name='periodic_Matern32')[source]
    +

    Bases: GPy.kern._src.periodic.Periodic

    +

    Kernel of the periodic subspace (up to a given frequency) of a Matern 3/2 RKHS. Only defined for input_dim=1.

    + +++ + + + + + +
    Parameters:
      +
    • input_dim (int) – the number of input dimensions
    • +
    • variance (float) – the variance of the Matern kernel
    • +
    • lengthscale (np.ndarray of size (input_dim,)) – the lengthscale of the Matern kernel
    • +
    • period (float) – the period
    • +
    • n_freq (int) – the number of frequencies considered for the periodic subspace
    • +
    +
    Return type:

    kernel object

    +
    +
    +
    +Gram_matrix()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    derivative of the covariance matrix with respect to the parameters (shape is num_data x num_inducing x num_params)

    +
    + +
    + +
    +
    +class GPy.kern._src.periodic.PeriodicMatern52(input_dim=1, variance=1.0, lengthscale=1.0, period=6.283185307179586, n_freq=10, lower=0.0, upper=12.566370614359172, active_dims=None, name='periodic_Matern52')[source]
    +

    Bases: GPy.kern._src.periodic.Periodic

    +

    Kernel of the periodic subspace (up to a given frequency) of a Matern 5/2 RKHS. Only defined for input_dim=1.

    + +++ + + + + + +
    Parameters:
      +
    • input_dim (int) – the number of input dimensions
    • +
    • variance (float) – the variance of the Matern kernel
    • +
    • lengthscale (np.ndarray of size (input_dim,)) – the lengthscale of the Matern kernel
    • +
    • period (float) – the period
    • +
    • n_freq (int) – the number of frequencies considered for the periodic subspace
    • +
    +
    Return type:

    kernel object

    +
    +
    +
    +Gram_matrix()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.poly module

    +
    +
    +class GPy.kern._src.poly.Poly(input_dim, variance=1.0, order=3.0, active_dims=None, name='poly')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    Polynomial kernel

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.prod module

    +
    +
    +class GPy.kern._src.prod.Prod(kernels, name='mul')[source]
    +

    Bases: GPy.kern._src.kern.CombinationKernel

    +

    Computes the product of 2 kernels

    + +++ + + + + + +
    Parameters:
      +
    • k2 (k1,) – the kernels to multiply
    • +
    • tensor (Boolean) – The kernels are either multiply as functions defined on the same input space (default) or on the product of the input spaces
    • +
    +
    Return type:

    kernel object

    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.rbf module

    +
    +
    +class GPy.kern._src.rbf.RBF(input_dim, variance=1.0, lengthscale=None, ARD=False, active_dims=None, name='rbf', useGPU=False)[source]
    +

    Bases: GPy.kern._src.stationary.Stationary

    +

    Radial Basis Function kernel, aka squared-exponential, exponentiated quadratic or Gaussian kernel:

    +
    +

    k(r) = \sigma^2 \exp \bigg(- \frac{1}{2} r^2 \bigg)

    +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    +
    +gradients_Z_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +gradients_qX_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +psi0(Z, variational_posterior)[source]
    +
    + +
    +
    +psi1(Z, variational_posterior)[source]
    +
    + +
    +
    +psi2(Z, variational_posterior)[source]
    +
    + +
    +
    +spectrum(omega)[source]
    +
    + +
    +
    +update_gradients_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.splitKern module

    +

    A new kernel

    +
    +
    +class GPy.kern._src.splitKern.DiffGenomeKern(kernel, idx_p, Xp, index_dim=-1, name='DiffGenomeKern')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.splitKern.SplitKern(kernel, Xp, index_dim=-1, name='SplitKern')[source]
    +

    Bases: GPy.kern._src.kern.CombinationKernel

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.splitKern.SplitKern_cross(kernel, Xp, name='SplitKern_cross')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.static module

    +
    +
    +class GPy.kern._src.static.Bias(input_dim, variance=1.0, active_dims=None, name='bias')[source]
    +

    Bases: GPy.kern._src.static.Static

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +psi2(Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.static.Fixed(input_dim, covariance_matrix, variance=1.0, active_dims=None, name='fixed')[source]
    +

    Bases: GPy.kern._src.static.Static

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +psi2(Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.static.Static(input_dim, variance, active_dims, name)[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +gradients_Z_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +gradients_qX_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +input_sensitivity(summarize=True)[source]
    +
    + +
    +
    +psi0(Z, variational_posterior)[source]
    +
    + +
    +
    +psi1(Z, variational_posterior)[source]
    +
    + +
    +
    +psi2(Z, variational_posterior)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.static.White(input_dim, variance=1.0, active_dims=None, name='white')[source]
    +

    Bases: GPy.kern._src.static.Static

    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +psi2(Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.stationary module

    +
    +
    +class GPy.kern._src.stationary.Cosine(input_dim, variance=1.0, lengthscale=None, ARD=False, active_dims=None, name='Cosine')[source]
    +

    Bases: GPy.kern._src.stationary.Stationary

    +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.stationary.ExpQuad(input_dim, variance=1.0, lengthscale=None, ARD=False, active_dims=None, name='ExpQuad')[source]
    +

    Bases: GPy.kern._src.stationary.Stationary

    +

    The Exponentiated quadratic covariance function.

    +
    +

    k(r) = \sigma^2 (1 + \sqrt{5} r + \frac53 r^2) \exp(- \sqrt{5} r)

    +
    +
    notes::
    +
      +
    • Yes, this is exactly the same as the RBF covariance function, but the +RBF implementation also has some features for doing variational kernels +(the psi-statistics).
    • +
    +
    +
    +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.stationary.Exponential(input_dim, variance=1.0, lengthscale=None, ARD=False, active_dims=None, name='Exponential')[source]
    +

    Bases: GPy.kern._src.stationary.Stationary

    +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.stationary.Matern32(input_dim, variance=1.0, lengthscale=None, ARD=False, active_dims=None, name='Mat32')[source]
    +

    Bases: GPy.kern._src.stationary.Stationary

    +

    Matern 3/2 kernel:

    +
    +

    k(r) = \sigma^2 (1 + \sqrt{3} r) \exp(- \sqrt{3} r) \ \ \ \  \text{ where  } r = \sqrt{\sum_{i=1}^input_dim \frac{(x_i-y_i)^2}{\ell_i^2} }

    +
    +
    +Gram_matrix(F, F1, F2, lower, upper)[source]
    +

    Return the Gram matrix of the vector of functions F with respect to the +RKHS norm. The use of this function is limited to input_dim=1.

    + +++ + + + +
    Parameters:
      +
    • F (np.array) – vector of functions
    • +
    • F1 (np.array) – vector of derivatives of F
    • +
    • F2 (np.array) – vector of second derivatives of F
    • +
    • lower,upper (floats) – boundaries of the input domain
    • +
    +
    +
    + +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.stationary.Matern52(input_dim, variance=1.0, lengthscale=None, ARD=False, active_dims=None, name='Mat52')[source]
    +

    Bases: GPy.kern._src.stationary.Stationary

    +

    Matern 5/2 kernel:

    +
    +

    k(r) = \sigma^2 (1 + \sqrt{5} r + \frac53 r^2) \exp(- \sqrt{5} r)

    +
    +
    +Gram_matrix(F, F1, F2, F3, lower, upper)[source]
    +

    Return the Gram matrix of the vector of functions F with respect to the RKHS norm. The use of this function is limited to input_dim=1.

    + +++ + + + +
    Parameters:
      +
    • F (np.array) – vector of functions
    • +
    • F1 (np.array) – vector of derivatives of F
    • +
    • F2 (np.array) – vector of second derivatives of F
    • +
    • F3 (np.array) – vector of third derivatives of F
    • +
    • lower,upper (floats) – boundaries of the input domain
    • +
    +
    +
    + +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.stationary.OU(input_dim, variance=1.0, lengthscale=None, ARD=False, active_dims=None, name='OU')[source]
    +

    Bases: GPy.kern._src.stationary.Stationary

    +

    OU kernel:

    +
    +

    k(r) = \sigma^2 \exp(- r) \ \ \ \  \text{ where  } r = \sqrt{\sum_{i=1}^input_dim \frac{(x_i-y_i)^2}{\ell_i^2} }

    +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.stationary.RatQuad(input_dim, variance=1.0, lengthscale=None, power=2.0, ARD=False, active_dims=None, name='RatQuad')[source]
    +

    Bases: GPy.kern._src.stationary.Stationary

    +

    Rational Quadratic Kernel

    +
    +

    k(r) = \sigma^2 \bigg( 1 + \frac{r^2}{2} \bigg)^{- \alpha}

    +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.stationary.Stationary(input_dim, variance, lengthscale, ARD, active_dims, name, useGPU=False)[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +
    +

    Stationary kernels (covariance functions).

    +

    Stationary covariance fucntion depend only on r, where r is defined as

    +
    +
    r = sqrt{ sum_{q=1}^Q (x_q - x’_q)^2 }
    +

    The covariance function k(x, x’ can then be written k(r).

    +

    In this implementation, r is scaled by the lengthscales parameter(s):

    +
    +
    r = sqrt{ sum_{q=1}^Q
    +
    +

    rac{(x_q - x’_q)^2}{ell_q^2} }.

    +
    +

    By default, there’s only one lengthscale: seaprate lengthscales for each +dimension can be enables by setting ARD=True.

    +

    To implement a stationary covariance function using this class, one need +only define the covariance function k(r), and it derivative.

    +
    +

    ... +def K_of_r(self, r):

    +
    +
    return foo
    +
    +
    def dK_dr(self, r):
    +
    return bar
    +
    +
    +

    The lengthscale(s) and variance parameters are added to the structure automatically.

    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +

    Kernel function applied on inputs X and X2. +In the stationary case there is an inner function depending on the +distances from X to X2, called r.

    +

    K(X, X2) = K_of_r((X-X2)**2)

    +
    + +
    +
    +K_of_r(r)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +dK_dr(r)[source]
    +
    + +
    +
    +dK_dr_via_X = <functools.partial object>
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +

    Given the derivative of the objective wrt K (dL_dK), compute the derivative wrt X

    +
    + +
    +
    +gradients_X_(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +gradients_X_weave(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +input_sensitivity(summarize=True)[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +

    Given the derivative of the objective with respect to the diagonal of +the covariance matrix, compute the derivative wrt the parameters of +this kernel and stor in the <parameter>.gradient field.

    +

    See also update_gradients_full

    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +

    Given the derivative of the objective wrt the covariance matrix +(dL_dK), compute the gradient wrt the parameters of this kernel, +and store in the parameters object as e.g. self.variance.gradient

    +
    + +
    +
    +weave_lengthscale_grads(tmp, X, X2)[source]
    +

    Use scipy.weave to compute derivatives wrt the lengthscales

    +
    + +
    + +
    +
    +

    GPy.kern._src.symbolic module

    +
    +
    +

    GPy.kern._src.trunclinear module

    +
    +
    +class GPy.kern._src.trunclinear.TruncLinear(input_dim, variances=None, delta=None, ARD=False, active_dims=None, name='linear')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    Truncated Linear kernel

    +
    +

    System Message: WARNING/2 (k(x,y) = \sum_{i=1}^input_dim \sigma^2_i \max(0, x_iy_i - \simga_q))

    +latex exited with error +[stdout] +This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014/Debian) (preloaded format=latex) + restricted \write18 enabled. +entering extended mode +(./math.tex +LaTeX2e <2014/05/01> +Babel <3.9k> and hyphenation patterns for 79 languages loaded. +(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2007/10/19 v1.4h Standard LaTeX document class +(/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo)) +(/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +(/usr/share/texlive/texmf-dist/tex/latex/ucs/utf8x.def)) +(/usr/share/texlive/texmf-dist/tex/latex/ucs/ucs.sty +(/usr/share/texlive/texmf-dist/tex/latex/ucs/data/uni-global.def)) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?’ option. +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty) +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty)) +(/usr/share/texlive/texmf-dist/tex/latex/tools/bm.sty) +No file math.aux. +(/usr/share/texlive/texmf-dist/tex/latex/ucs/ucsencs.def) +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd) +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd) +! Undefined control sequence. +<argument> ...sigma ^2_i \max (0, x_iy_i - \simga + _q)\end {split}\notag +l.14 \end{gather} + +! Undefined control sequence. +<argument> ...sigma ^2_i \max (0, x_iy_i - \simga + _q)\end {split}\notag +l.14 \end{gather} + +[1] (./math.aux) ) +(see the transcript file for additional information) +Output written on math.dvi (1 page, 616 bytes). +Transcript written on math.log. +
    + +++ + + + + + +
    Parameters:
      +
    • input_dim (int) – the number of input dimensions
    • +
    • variances (array or list of the appropriate size (or float if there +is only one variance parameter)) – the vector of variances \sigma^2_i
    • +
    • ARD (Boolean) – Auto Relevance Determination. If False, the kernel has only one +variance parameter sigma^2, otherwise there is one variance +parameter per dimension.
    • +
    +
    Return type:

    kernel object

    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +input_sensitivity()[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +class GPy.kern._src.trunclinear.TruncLinear_inf(input_dim, interval, variances=None, ARD=False, active_dims=None, name='linear')[source]
    +

    Bases: GPy.kern._src.kern.Kern

    +

    Truncated Linear kernel

    +
    +

    System Message: WARNING/2 (k(x,y) = \sum_{i=1}^input_dim \sigma^2_i \max(0, x_iy_i - \simga_q))

    +latex exited with error +[stdout] +This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014/Debian) (preloaded format=latex) + restricted \write18 enabled. +entering extended mode +(./math.tex +LaTeX2e <2014/05/01> +Babel <3.9k> and hyphenation patterns for 79 languages loaded. +(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls +Document Class: article 2007/10/19 v1.4h Standard LaTeX document class +(/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo)) +(/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +(/usr/share/texlive/texmf-dist/tex/latex/ucs/utf8x.def)) +(/usr/share/texlive/texmf-dist/tex/latex/ucs/ucs.sty +(/usr/share/texlive/texmf-dist/tex/latex/ucs/data/uni-global.def)) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?’ option. +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty) +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty)) +(/usr/share/texlive/texmf-dist/tex/latex/tools/bm.sty) (./math.aux) +(/usr/share/texlive/texmf-dist/tex/latex/ucs/ucsencs.def) +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd) +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd) +! Undefined control sequence. +<argument> ...sigma ^2_i \max (0, x_iy_i - \simga + _q)\end {split}\notag +l.14 \end{gather} + +! Undefined control sequence. +<argument> ...sigma ^2_i \max (0, x_iy_i - \simga + _q)\end {split}\notag +l.14 \end{gather} + +[1] (./math.aux) ) +(see the transcript file for additional information) +Output written on math.dvi (1 page, 616 bytes). +Transcript written on math.log. +
    + +++ + + + + + +
    Parameters:
      +
    • input_dim (int) – the number of input dimensions
    • +
    • variances (array or list of the appropriate size (or float if there +is only one variance parameter)) – the vector of variances \sigma^2_i
    • +
    • ARD (Boolean) – Auto Relevance Determination. If False, the kernel has only one +variance parameter sigma^2, otherwise there is one variance +parameter per dimension.
    • +
    +
    Return type:

    kernel object

    +
    +
    +
    +K(X, X2=None, *a, **kw)[source]
    +
    + +
    +
    +Kdiag(X, *a, **kw)[source]
    +
    + +
    +
    +gradients_X(dL_dK, X, X2=None)[source]
    +
    + +
    +
    +gradients_X_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +input_sensitivity()[source]
    +
    + +
    +
    +update_gradients_diag(dL_dKdiag, X)[source]
    +
    + +
    +
    +update_gradients_full(dL_dK, X, X2=None)[source]
    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.kern._src.psi_comp.html b/doc/_build/html/GPy.kern._src.psi_comp.html new file mode 100644 index 00000000..eb47cbec --- /dev/null +++ b/doc/_build/html/GPy.kern._src.psi_comp.html @@ -0,0 +1,305 @@ + + + + + + + + GPy.kern._src.psi_comp package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.kern._src.psi_comp package

    +
    +

    Submodules

    +
    +
    +

    GPy.kern._src.psi_comp.linear_psi_comp module

    +

    The package for the Psi statistics computation of the linear kernel for Bayesian GPLVM

    +
    +
    +GPy.kern._src.psi_comp.linear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior)[source]
    +
    + +
    +
    +GPy.kern._src.psi_comp.linear_psi_comp.psicomputations(variance, Z, variational_posterior)[source]
    +

    Compute psi-statistics for ss-linear kernel

    +
    + +
    +
    +

    GPy.kern._src.psi_comp.rbf_psi_comp module

    +

    The module for psi-statistics for RBF kernel

    +
    +
    +GPy.kern._src.psi_comp.rbf_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior)[source]
    +
    + +
    +
    +GPy.kern._src.psi_comp.rbf_psi_comp.psicomputations(variance, lengthscale, Z, variational_posterior)[source]
    +

    Z - MxQ +mu - NxQ +S - NxQ +gamma - NxQ

    +
    + +
    +
    +

    GPy.kern._src.psi_comp.rbf_psi_gpucomp module

    +

    The module for psi-statistics for RBF kernel

    +
    +
    +class GPy.kern._src.psi_comp.rbf_psi_gpucomp.PSICOMP_RBF_GPU(threadnum=128, blocknum=15, GPU_direct=False)[source]
    +

    Bases: GPy.kern._src.psi_comp.PSICOMP_RBF

    +
    +
    +get_dimensions(Z, variational_posterior)[source]
    +
    + +
    +
    +psiDerivativecomputations = <functools.partial object>
    +
    + +
    +
    +psicomputations = <functools.partial object>
    +
    + +
    +
    +reset_derivative()[source]
    +
    + +
    +
    +sync_params(lengthscale, Z, mu, S)[source]
    +
    + +
    + +
    +
    +

    GPy.kern._src.psi_comp.sslinear_psi_comp module

    +

    The package for the Psi statistics computation of the linear kernel for SSGPLVM

    +
    +
    +GPy.kern._src.psi_comp.sslinear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior)[source]
    +
    + +
    +
    +GPy.kern._src.psi_comp.sslinear_psi_comp.psicomputations(variance, Z, variational_posterior)[source]
    +

    Compute psi-statistics for ss-linear kernel

    +
    + +
    +
    +

    GPy.kern._src.psi_comp.ssrbf_psi_comp module

    +

    The package for the psi statistics computation

    +
    +
    +GPy.kern._src.psi_comp.ssrbf_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior)[source]
    +
    + +
    +
    +

    GPy.kern._src.psi_comp.ssrbf_psi_gpucomp module

    +

    The module for psi-statistics for RBF kernel for Spike-and-Slab GPLVM

    +
    +
    +class GPy.kern._src.psi_comp.ssrbf_psi_gpucomp.PSICOMP_SSRBF_GPU(threadnum=128, blocknum=15, GPU_direct=False)[source]
    +

    Bases: GPy.kern._src.psi_comp.PSICOMP_RBF

    +
    +
    +get_dimensions(Z, variational_posterior)[source]
    +
    + +
    +
    +psiDerivativecomputations = <functools.partial object>
    +
    + +
    +
    +psicomputations = <functools.partial object>
    +
    + +
    +
    +reset_derivative()[source]
    +
    + +
    +
    +sync_params(lengthscale, Z, mu, S, gamma)[source]
    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    +class GPy.kern._src.psi_comp.PSICOMP_Linear(*a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.Pickleable

    +
    +
    +psiDerivativecomputations = <functools.partial object>
    +
    + +
    +
    +psicomputations = <functools.partial object>
    +
    + +
    + +
    +
    +class GPy.kern._src.psi_comp.PSICOMP_RBF(*a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameter_core.Pickleable

    +
    +
    +psiDerivativecomputations = <functools.partial object>
    +
    + +
    +
    +psicomputations = <functools.partial object>
    +
    + +
    + +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.kern.html b/doc/_build/html/GPy.kern.html new file mode 100644 index 00000000..195b8708 --- /dev/null +++ b/doc/_build/html/GPy.kern.html @@ -0,0 +1,181 @@ + + + + + + + + GPy.kern package — GPy documentation + + + + + + + + + + + + + + + + +
    + + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.likelihoods.html b/doc/_build/html/GPy.likelihoods.html new file mode 100644 index 00000000..8b92b4ed --- /dev/null +++ b/doc/_build/html/GPy.likelihoods.html @@ -0,0 +1,2134 @@ + + + + + + + + GPy.likelihoods package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.likelihoods package

    +
    +

    Submodules

    +
    +
    +

    GPy.likelihoods.bernoulli module

    +
    +
    +class GPy.likelihoods.bernoulli.Bernoulli(gp_link=None)[source]
    +

    Bases: GPy.likelihoods.likelihood.Likelihood

    +

    Bernoulli likelihood

    +
    +

    p(y_{i}|\lambda(f_{i})) = \lambda(f_{i})^{y_{i}}(1-f_{i})^{1-y_{i}}

    +
    +

    Note

    +

    Y takes values in either {-1, 1} or {0, 1}. +link function should have the domain [0, 1], e.g. probit (default) or Heaviside

    +
    +
    +
    +d2logpdf_dlink2(inv_link_f, y, Y_metadata=None)[source]
    +

    Hessian at y, given inv_link_f, w.r.t inv_link_f the hessian will be 0 unless i == j +i.e. second derivative logpdf at y given inverse link of f_i and inverse link of f_j w.r.t inverse link of f_i and inverse link of f_j.

    +
    +

    \frac{d^{2}\ln p(y_{i}|\lambda(f_{i}))}{d\lambda(f)^{2}} = \frac{-y_{i}}{\lambda(f)^{2}} - \frac{(1-y_{i})}{(1-\lambda(f))^{2}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables inverse link of f.
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in bernoulli
    • +
    +
    Returns:

    Diagonal of log hessian matrix (second derivative of log likelihood evaluated at points inverse link of f.

    +
    Return type:

    Nx1 array

    +
    +
    +

    Note

    +

    Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases +(the distribution for y_i depends only on inverse link of f_i not on inverse link of f_(j!=i)

    +
    +
    + +
    +
    +d3logpdf_dlink3(inv_link_f, y, Y_metadata=None)[source]
    +

    Third order derivative log-likelihood function at y given inverse link of f w.r.t inverse link of f

    +
    +

    \frac{d^{3} \ln p(y_{i}|\lambda(f_{i}))}{d^{3}\lambda(f)} = \frac{2y_{i}}{\lambda(f)^{3}} - \frac{2(1-y_{i}}{(1-\lambda(f))^{3}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables passed through inverse link of f.
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in bernoulli
    • +
    +
    Returns:

    third derivative of log likelihood evaluated at points inverse_link(f)

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Gradient of the pdf at y, given inverse link of f w.r.t inverse link of f.

    +
    +

    \frac{d\ln p(y_{i}|\lambda(f_{i}))}{d\lambda(f)} = \frac{y_{i}}{\lambda(f_{i})} - \frac{(1 - y_{i})}{(1 - \lambda(f_{i}))}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables inverse link of f.
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in bernoulli
    • +
    +
    Returns:

    gradient of log likelihood evaluated at points inverse link of f.

    +
    Return type:

    Nx1 array

    +
    +
    + +
    +
    +exact_inference_gradients(dL_dKdiag, Y_metadata=None)[source]
    +
    + +
    + +

    Log Likelihood function given inverse link of f.

    +
    +

    \ln p(y_{i}|\lambda(f_{i})) = y_{i}\log\lambda(f_{i}) + (1-y_{i})\log (1-f_{i})

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables inverse link of f.
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in bernoulli
    • +
    +
    Returns:

    log likelihood evaluated at points inverse link of f.

    +
    Return type:

    float

    +
    +
    + +
    +
    +moments_match_ep(Y_i, tau_i, v_i)[source]
    +

    Moments match of the marginal approximation in EP algorithm

    + +++ + + + +
    Parameters:
      +
    • i – number of observation (int)
    • +
    • tau_i – precision of the cavity distribution (float)
    • +
    • v_i – mean/variance of the cavity distribution (float)
    • +
    +
    +
    + +
    + +

    Likelihood function given inverse link of f.

    +
    +

    p(y_{i}|\lambda(f_{i})) = \lambda(f_{i})^{y_{i}}(1-f_{i})^{1-y_{i}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables inverse link of f.
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in bernoulli
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    +
    +predictive_mean(mu, variance, Y_metadata=None)[source]
    +
    + +
    +
    +predictive_variance(mu, variance, pred_mean, Y_metadata=None)[source]
    +
    + +
    +
    +samples(gp, Y_metadata=None)[source]
    +

    Returns a set of samples of observations based on a given value of the latent variable.

    + +++ + + + +
    Parameters:gp – latent variable
    +
    + +
    + +
    +
    +

    GPy.likelihoods.exponential module

    +
    +
    +class GPy.likelihoods.exponential.Exponential(gp_link=None)[source]
    +

    Bases: GPy.likelihoods.likelihood.Likelihood

    +

    Expoential likelihood +Y is expected to take values in {0,1,2,...} +—– +$$ +L(x) = exp(lambda) * lambda**Y_i / Y_i! +$$

    +
    +
    +d2logpdf_dlink2(link_f, y, Y_metadata=None)[source]
    +

    Hessian at y, given link(f), w.r.t link(f) +i.e. second derivative logpdf at y given link(f_i) and link(f_j) w.r.t link(f_i) and link(f_j) +The hessian will be 0 unless i == j

    +
    +

    \frac{d^{2} \ln p(y_{i}|\lambda(f_{i}))}{d^{2}\lambda(f)} = -\frac{1}{\lambda(f_{i})^{2}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in exponential distribution
    • +
    +
    Returns:

    Diagonal of hessian matrix (second derivative of likelihood evaluated at points f)

    +
    Return type:

    Nx1 array

    +
    +
    +

    Note

    +

    Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases +(the distribution for y_i depends only on link(f_i) not on link(f_(j!=i))

    +
    +
    + +
    +
    +d3logpdf_dlink3(link_f, y, Y_metadata=None)[source]
    +

    Third order derivative log-likelihood function at y given link(f) w.r.t link(f)

    +
    +

    \frac{d^{3} \ln p(y_{i}|\lambda(f_{i}))}{d^{3}\lambda(f)} = \frac{2}{\lambda(f_{i})^{3}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in exponential distribution
    • +
    +
    Returns:

    third derivative of likelihood evaluated at points f

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Gradient of the log likelihood function at y, given link(f) w.r.t link(f)

    +
    +

    \frac{d \ln p(y_{i}|\lambda(f_{i}))}{d\lambda(f)} = \frac{1}{\lambda(f)} - y_{i}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables (f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in exponential distribution
    • +
    +
    Returns:

    gradient of likelihood evaluated at points

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Log Likelihood Function given link(f)

    +
    +

    \ln p(y_{i}|\lambda(f_{i})) = \ln \lambda(f_{i}) - y_{i}\lambda(f_{i})

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables (link(f))
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in exponential distribution
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    + +

    Likelihood function given link(f)

    +
    +

    p(y_{i}|\lambda(f_{i})) = \lambda(f_{i})\exp (-y\lambda(f_{i}))

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in exponential distribution
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    +
    +samples(gp)[source]
    +

    Returns a set of samples of observations based on a given value of the latent variable.

    + +++ + + + +
    Parameters:gp – latent variable
    +
    + +
    + +
    +
    +

    GPy.likelihoods.gamma module

    +
    +
    +class GPy.likelihoods.gamma.Gamma(gp_link=None, beta=1.0)[source]
    +

    Bases: GPy.likelihoods.likelihood.Likelihood

    +

    Gamma likelihood

    +
    +

    p(y_{i}|\lambda(f_{i})) = \frac{\beta^{\alpha_{i}}}{\Gamma(\alpha_{i})}y_{i}^{\alpha_{i}-1}e^{-\beta y_{i}}\\
+\alpha_{i} = \beta y_{i}

    +
    +
    +d2logpdf_dlink2(link_f, y, Y_metadata=None)[source]
    +

    Hessian at y, given link(f), w.r.t link(f) +i.e. second derivative logpdf at y given link(f_i) and link(f_j) w.r.t link(f_i) and link(f_j) +The hessian will be 0 unless i == j

    +
    +

    \frac{d^{2} \ln p(y_{i}|\lambda(f_{i}))}{d^{2}\lambda(f)} = -\beta^{2}\frac{d\Psi(\alpha_{i})}{d\alpha_{i}}\\
+\alpha_{i} = \beta y_{i}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in gamma distribution
    • +
    +
    Returns:

    Diagonal of hessian matrix (second derivative of likelihood evaluated at points f)

    +
    Return type:

    Nx1 array

    +
    +
    +

    Note

    +

    Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases +(the distribution for y_i depends only on link(f_i) not on link(f_(j!=i))

    +
    +
    + +
    +
    +d3logpdf_dlink3(link_f, y, Y_metadata=None)[source]
    +

    Third order derivative log-likelihood function at y given link(f) w.r.t link(f)

    +
    +

    \frac{d^{3} \ln p(y_{i}|\lambda(f_{i}))}{d^{3}\lambda(f)} = -\beta^{3}\frac{d^{2}\Psi(\alpha_{i})}{d\alpha_{i}}\\
+\alpha_{i} = \beta y_{i}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in gamma distribution
    • +
    +
    Returns:

    third derivative of likelihood evaluated at points f

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Gradient of the log likelihood function at y, given link(f) w.r.t link(f)

    +
    +

    \frac{d \ln p(y_{i}|\lambda(f_{i}))}{d\lambda(f)} = \beta (\log \beta y_{i}) - \Psi(\alpha_{i})\beta\\
+\alpha_{i} = \beta y_{i}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables (f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in gamma distribution
    • +
    +
    Returns:

    gradient of likelihood evaluated at points

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Log Likelihood Function given link(f)

    +
    +

    \ln p(y_{i}|\lambda(f_{i})) = \alpha_{i}\log \beta - \log \Gamma(\alpha_{i}) + (\alpha_{i} - 1)\log y_{i} - \beta y_{i}\\
+\alpha_{i} = \beta y_{i}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables (link(f))
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in poisson distribution
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    + +

    Likelihood function given link(f)

    +
    +

    p(y_{i}|\lambda(f_{i})) = \frac{\beta^{\alpha_{i}}}{\Gamma(\alpha_{i})}y_{i}^{\alpha_{i}-1}e^{-\beta y_{i}}\\
+\alpha_{i} = \beta y_{i}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in poisson distribution
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    + +
    +
    +

    GPy.likelihoods.gaussian module

    +

    A lot of this code assumes that the link function is the identity.

    +

    I think laplace code is okay, but I’m quite sure that the EP moments will only work if the link is identity.

    +

    Furthermore, exact Guassian inference can only be done for the identity link, so we should be asserting so for all calls which relate to that.

    +

    James 11/12/13

    +
    +
    +class GPy.likelihoods.gaussian.Gaussian(gp_link=None, variance=1.0, name='Gaussian_noise')[source]
    +

    Bases: GPy.likelihoods.likelihood.Likelihood

    +

    Gaussian likelihood

    +
    +

    \ln p(y_{i}|\lambda(f_{i})) = -\frac{N \ln 2\pi}{2} - \frac{\ln |K|}{2} - \frac{(y_{i} - \lambda(f_{i}))^{T}\sigma^{-2}(y_{i} - \lambda(f_{i}))}{2}

    +
    +++ + + + +
    Parameters:
      +
    • variance – variance value of the Gaussian distribution
    • +
    • N (int) – Number of data points
    • +
    +
    +
    +
    +betaY(Y, Y_metadata=None)[source]
    +
    + +
    +
    +d2logpdf_dlink2(link_f, y, Y_metadata=None)[source]
    +

    Hessian at y, given link_f, w.r.t link_f. +i.e. second derivative logpdf at y given link(f_i) link(f_j) w.r.t link(f_i) and link(f_j)

    +

    The hessian will be 0 unless i == j

    +
    +

    \frac{d^{2} \ln p(y_{i}|\lambda(f_{i}))}{d^{2}f} = -\frac{1}{\sigma^{2}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in gaussian
    • +
    +
    Returns:

    Diagonal of log hessian matrix (second derivative of log likelihood evaluated at points link(f))

    +
    Return type:

    Nx1 array

    +
    +
    +

    Note

    +

    Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases +(the distribution for y_i depends only on link(f_i) not on link(f_(j!=i))

    +
    +
    + +
    +
    +d2logpdf_dlink2_dtheta(f, y, Y_metadata=None)[source]
    +
    + +
    +
    +d2logpdf_dlink2_dvar(link_f, y, Y_metadata=None)[source]
    +

    Gradient of the hessian (d2logpdf_dlink2) w.r.t variance parameter (noise_variance)

    +
    +

    \frac{d}{d\sigma^{2}}(\frac{d^{2} \ln p(y_{i}|\lambda(f_{i}))}{d^{2}\lambda(f)}) = \frac{1}{\sigma^{4}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in gaussian
    • +
    +
    Returns:

    derivative of log hessian evaluated at points link(f_i) and link(f_j) w.r.t variance parameter

    +
    Return type:

    Nx1 array

    +
    +
    + +
    +
    +d3logpdf_dlink3(link_f, y, Y_metadata=None)[source]
    +

    Third order derivative log-likelihood function at y given link(f) w.r.t link(f)

    +
    +

    \frac{d^{3} \ln p(y_{i}|\lambda(f_{i}))}{d^{3}\lambda(f)} = 0

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in gaussian
    • +
    +
    Returns:

    third derivative of log likelihood evaluated at points link(f)

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Gradient of the pdf at y, given link(f) w.r.t link(f)

    +
    +

    \frac{d \ln p(y_{i}|\lambda(f_{i}))}{d\lambda(f)} = \frac{1}{\sigma^{2}}(y_{i} - \lambda(f_{i}))

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in gaussian
    • +
    +
    Returns:

    gradient of log likelihood evaluated at points link(f)

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +
    + +
    + +

    Derivative of the dlogpdf_dlink w.r.t variance parameter (noise_variance)

    +
    +

    \frac{d}{d\sigma^{2}}(\frac{d \ln p(y_{i}|\lambda(f_{i}))}{d\lambda(f)}) = \frac{1}{\sigma^{4}}(-y_{i} + \lambda(f_{i}))

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in gaussian
    • +
    +
    Returns:

    derivative of log likelihood evaluated at points link(f) w.r.t variance parameter

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +
    + +
    + +

    Gradient of the log-likelihood function at y given link(f), w.r.t variance parameter (noise_variance)

    +
    +

    \frac{d \ln p(y_{i}|\lambda(f_{i}))}{d\sigma^{2}} = -\frac{N}{2\sigma^{2}} + \frac{(y_{i} - \lambda(f_{i}))^{2}}{2\sigma^{4}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in gaussian
    • +
    +
    Returns:

    derivative of log likelihood evaluated at points link(f) w.r.t variance parameter

    +
    Return type:

    float

    +
    +
    + +
    +
    +exact_inference_gradients(dL_dKdiag, Y_metadata=None)[source]
    +
    + +
    +
    +gaussian_variance(Y_metadata=None)[source]
    +
    + +
    +
    +log_predictive_density(y_test, mu_star, var_star)[source]
    +

    assumes independence

    +
    + +
    + +

    Log likelihood function given link(f)

    +
    +

    \ln p(y_{i}|\lambda(f_{i})) = -\frac{N \ln 2\pi}{2} - \frac{\ln |K|}{2} - \frac{(y_{i} - \lambda(f_{i}))^{T}\sigma^{-2}(y_{i} - \lambda(f_{i}))}{2}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in gaussian
    • +
    +
    Returns:

    log likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    + +

    Likelihood function given link(f)

    +
    +

    \ln p(y_{i}|\lambda(f_{i})) = -\frac{N \ln 2\pi}{2} - \frac{\ln |K|}{2} - \frac{(y_{i} - \lambda(f_{i}))^{T}\sigma^{-2}(y_{i} - \lambda(f_{i}))}{2}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata not used in gaussian
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    +
    +predictive_mean(mu, sigma)[source]
    +
    + +
    +
    +predictive_quantiles(mu, var, quantiles, Y_metadata=None)[source]
    +
    + +
    +
    +predictive_values(mu, var, full_cov=False, Y_metadata=None)[source]
    +
    + +
    +
    +predictive_variance(mu, sigma, predictive_mean=None)[source]
    +
    + +
    +
    +samples(gp, Y_metadata=None)[source]
    +

    Returns a set of samples of observations based on a given value of the latent variable.

    + +++ + + + +
    Parameters:gp – latent variable
    +
    + +
    +
    +update_gradients(grad)[source]
    +
    + +
    + +
    +
    +

    GPy.likelihoods.likelihood module

    +
    +
    +class GPy.likelihoods.likelihood.Likelihood(gp_link, name)[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +

    Likelihood base class, used to defing p(y|f).

    +

    All instances use _inverse_ link functions, which can be swapped out. It is +expected that inheriting classes define a default inverse link function

    +

    To use this class, inherit and define missing functionality.

    +
    +
    Inheriting classes must implement:
    +
    pdf_link : a bound method which turns the output of the link function into the pdf +logpdf_link : the logarithm of the above
    +
    To enable use with EP, inheriting classes must define:
    +
    TODO: a suitable derivative function for any parameters of the class
    +
    It is also desirable to define:
    +
    moments_match_ep : a function to compute the EP moments If this isn’t defined, the moments will be computed using 1D quadrature.
    +
    To enable use with Laplace approximation, inheriting classes must define:
    +
    Some derivative functions AS TODO
    +
    +

    For exact Gaussian inference, define JH TODO

    +
    +
    +conditional_mean(gp)[source]
    +

    The mean of the random variable conditioned on one value of the GP

    +
    + +
    +
    +conditional_variance(gp)[source]
    +

    The variance of the random variable conditioned on one value of the GP

    +
    + +
    +
    +d2logpdf_df2(f, y, Y_metadata=None)[source]
    +

    Evaluates the link function link(f) then computes the second derivative of log likelihood using it +Uses the Faa di Bruno’s formula for the chain rule

    +
    +

    \frac{d^{2}\log p(y|\lambda(f))}{df^{2}} = \frac{d^{2}\log p(y|\lambda(f))}{d^{2}\lambda(f)}\left(\frac{d\lambda(f)}{df}\right)^{2} + \frac{d\log p(y|\lambda(f))}{d\lambda(f)}\frac{d^{2}\lambda(f)}{df^{2}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • f (Nx1 array) – latent variables f
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution - not used
    • +
    +
    Returns:

    second derivative of log likelihood evaluated for this point (diagonal only)

    +
    Return type:

    1xN array

    +
    +
    + +
    +
    +d2logpdf_df2_dtheta(f, y, Y_metadata=None)[source]
    +

    TODO: Doc strings

    +
    + +
    +
    +d2logpdf_dlink2(inv_link_f, y, Y_metadata=None)[source]
    +
    + +
    +
    +d2logpdf_dlink2_dtheta(inv_link_f, y, Y_metadata=None)[source]
    +
    + +
    +
    +d3logpdf_df3(f, y, Y_metadata=None)[source]
    +

    Evaluates the link function link(f) then computes the third derivative of log likelihood using it +Uses the Faa di Bruno’s formula for the chain rule

    +
    +

    \frac{d^{3}\log p(y|\lambda(f))}{df^{3}} = \frac{d^{3}\log p(y|\lambda(f)}{d\lambda(f)^{3}}\left(\frac{d\lambda(f)}{df}\right)^{3} + 3\frac{d^{2}\log p(y|\lambda(f)}{d\lambda(f)^{2}}\frac{d\lambda(f)}{df}\frac{d^{2}\lambda(f)}{df^{2}} + \frac{d\log p(y|\lambda(f)}{d\lambda(f)}\frac{d^{3}\lambda(f)}{df^{3}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • f (Nx1 array) – latent variables f
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution - not used
    • +
    +
    Returns:

    third derivative of log likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    +
    +d3logpdf_dlink3(inv_link_f, y, Y_metadata=None)[source]
    +
    + +
    +
    +dlogpdf_df(f, y, Y_metadata=None)[source]
    +

    Evaluates the link function link(f) then computes the derivative of log likelihood using it +Uses the Faa di Bruno’s formula for the chain rule

    +
    +

    \frac{d\log p(y|\lambda(f))}{df} = \frac{d\log p(y|\lambda(f))}{d\lambda(f)}\frac{d\lambda(f)}{df}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • f (Nx1 array) – latent variables f
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution - not used
    • +
    +
    Returns:

    derivative of log likelihood evaluated for this point

    +
    Return type:

    1xN array

    +
    +
    + +
    +
    +dlogpdf_df_dtheta(f, y, Y_metadata=None)[source]
    +

    TODO: Doc strings

    +
    + +
    + +
    + +
    + +
    + +
    +
    +dlogpdf_dtheta(f, y, Y_metadata=None)[source]
    +

    TODO: Doc strings

    +
    + +
    + +
    + +
    +
    +log_predictive_density(y_test, mu_star, var_star)[source]
    +

    Calculation of the log predictive density

    + +++ + + + +
    Parameters:
      +
    • y_test ((Nx1) array) – test observations (y_{*})
    • +
    • mu_star ((Nx1) array) – predictive mean of gaussian p(f_{*}|mu_{*}, var_{*})
    • +
    • var_star ((Nx1) array) – predictive variance of gaussian p(f_{*}|mu_{*}, var_{*})
    • +
    +
    +
    + +
    +
    +logpdf(f, y, Y_metadata=None)[source]
    +

    Evaluates the link function link(f) then computes the log likelihood (log pdf) using it

    + +++ + + + + + + + +
    Parameters:
      +
    • f (Nx1 array) – latent variables f
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution - not used
    • +
    +
    Returns:

    log likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    + +
    + +
    +
    +pdf(f, y, Y_metadata=None)[source]
    +

    Evaluates the link function link(f) then computes the likelihood (pdf) using it

    + +++ + + + + + + + +
    Parameters:
      +
    • f (Nx1 array) – latent variables f
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution - not used
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    + +
    + +
    +
    +predictive_mean(mu, variance, Y_metadata=None)[source]
    +

    Quadrature calculation of the predictive mean: E(Y_star|Y) = E( E(Y_star|f_star, Y) )

    + +++ + + + +
    Parameters:
      +
    • mu – mean of posterior
    • +
    • sigma – standard deviation of posterior
    • +
    +
    +
    + +
    +
    +predictive_quantiles(mu, var, quantiles, Y_metadata=None)[source]
    +
    + +
    +
    +predictive_values(mu, var, full_cov=False, Y_metadata=None)[source]
    +

    Compute mean, variance of the predictive distibution.

    + +++ + + + +
    Parameters:
      +
    • mu – mean of the latent variable, f, of posterior
    • +
    • var – variance of the latent variable, f, of posterior
    • +
    • full_cov (Boolean) – whether to use the full covariance or just the diagonal
    • +
    +
    +
    + +
    +
    +predictive_variance(mu, variance, predictive_mean=None, Y_metadata=None)[source]
    +

    Approximation to the predictive variance: V(Y_star)

    +

    The following variance decomposition is used: +V(Y_star) = E( V(Y_star|f_star) ) + V( E(Y_star|f_star) )

    + +++ + + + + + + +
    Parameters:
      +
    • mu – mean of posterior
    • +
    • sigma – standard deviation of posterior
    • +
    +
    Predictive_mean:
     

    output’s predictive mean, if None _predictive_mean function will be called.

    +
    +
    + +
    +
    +samples(gp, Y_metadata=None)[source]
    +

    Returns a set of samples of observations based on a given value of the latent variable.

    + +++ + + + +
    Parameters:gp – latent variable
    +
    + +
    +
    +update_gradients(partial)[source]
    +
    + +
    +
    +variational_expectations(Y, m, v, gh_points=None)[source]
    +

    Use Gauss-Hermite Quadrature to compute

    +
    +
    E_p(f) [ log p(y|f) ] +d/dm E_p(f) [ log p(y|f) ] +d/dv E_p(f) [ log p(y|f) ]
    +

    where p(f) is a Gaussian with mean m and variance v. The shapes of Y, m and v should match.

    +

    if no gh_points are passed, we construct them using defualt options

    +
    + +
    + +
    + +
    +

    GPy.likelihoods.mixed_noise module

    +
    +
    +class GPy.likelihoods.mixed_noise.MixedNoise(likelihoods_list, name='mixed_noise')[source]
    +

    Bases: GPy.likelihoods.likelihood.Likelihood

    +
    +
    +betaY(Y, Y_metadata)[source]
    +
    + +
    +
    +exact_inference_gradients(dL_dKdiag, Y_metadata)[source]
    +
    + +
    +
    +gaussian_variance(Y_metadata)[source]
    +
    + +
    +
    +predictive_quantiles(mu, var, quantiles, Y_metadata)[source]
    +
    + +
    +
    +predictive_values(mu, var, full_cov=False, Y_metadata=None)[source]
    +
    + +
    +
    +predictive_variance(mu, sigma, Y_metadata)[source]
    +
    + +
    +
    +samples(gp, Y_metadata)[source]
    +

    Returns a set of samples of observations based on a given value of the latent variable.

    + +++ + + + +
    Parameters:gp – latent variable
    +
    + +
    +
    +update_gradients(gradients)[source]
    +
    + +
    + +
    +
    +

    GPy.likelihoods.poisson module

    +
    +
    +class GPy.likelihoods.poisson.Poisson(gp_link=None)[source]
    +

    Bases: GPy.likelihoods.likelihood.Likelihood

    +

    Poisson likelihood

    +
    +

    p(y_{i}|\lambda(f_{i})) = \frac{\lambda(f_{i})^{y_{i}}}{y_{i}!}e^{-\lambda(f_{i})}

    +
    +

    Note

    +

    Y is expected to take values in {0,1,2,...}

    +
    +
    +
    +conditional_mean(gp)[source]
    +

    The mean of the random variable conditioned on one value of the GP

    +
    + +
    +
    +conditional_variance(gp)[source]
    +

    The variance of the random variable conditioned on one value of the GP

    +
    + +
    +
    +d2logpdf_dlink2(link_f, y, Y_metadata=None)[source]
    +

    Hessian at y, given link(f), w.r.t link(f) +i.e. second derivative logpdf at y given link(f_i) and link(f_j) w.r.t link(f_i) and link(f_j) +The hessian will be 0 unless i == j

    +
    +

    \frac{d^{2} \ln p(y_{i}|\lambda(f_{i}))}{d^{2}\lambda(f)} = \frac{-y_{i}}{\lambda(f_{i})^{2}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in poisson distribution
    • +
    +
    Returns:

    Diagonal of hessian matrix (second derivative of likelihood evaluated at points f)

    +
    Return type:

    Nx1 array

    +
    +
    +

    Note

    +

    Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases +(the distribution for y_i depends only on link(f_i) not on link(f_(j!=i))

    +
    +
    + +
    +
    +d3logpdf_dlink3(link_f, y, Y_metadata=None)[source]
    +

    Third order derivative log-likelihood function at y given link(f) w.r.t link(f)

    +
    +

    \frac{d^{3} \ln p(y_{i}|\lambda(f_{i}))}{d^{3}\lambda(f)} = \frac{2y_{i}}{\lambda(f_{i})^{3}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in poisson distribution
    • +
    +
    Returns:

    third derivative of likelihood evaluated at points f

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Gradient of the log likelihood function at y, given link(f) w.r.t link(f)

    +
    +

    \frac{d \ln p(y_{i}|\lambda(f_{i}))}{d\lambda(f)} = \frac{y_{i}}{\lambda(f_{i})} - 1

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables (f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in poisson distribution
    • +
    +
    Returns:

    gradient of likelihood evaluated at points

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Log Likelihood Function given link(f)

    +
    +

    \ln p(y_{i}|\lambda(f_{i})) = -\lambda(f_{i}) + y_{i}\log \lambda(f_{i}) - \log y_{i}!

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables (link(f))
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in poisson distribution
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    + +

    Likelihood function given link(f)

    +
    +

    p(y_{i}|\lambda(f_{i})) = \frac{\lambda(f_{i})^{y_{i}}}{y_{i}!}e^{-\lambda(f_{i})}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in poisson distribution
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    +
    +samples(gp, Y_metadata=None)[source]
    +

    Returns a set of samples of observations based on a given value of the latent variable.

    + +++ + + + +
    Parameters:gp – latent variable
    +
    + +
    + +
    +
    +

    GPy.likelihoods.student_t module

    +
    +
    +class GPy.likelihoods.student_t.StudentT(gp_link=None, deg_free=5, sigma2=2)[source]
    +

    Bases: GPy.likelihoods.likelihood.Likelihood

    +

    Student T likelihood

    +

    For nomanclature see Bayesian Data Analysis 2003 p576

    +
    +

    p(y_{i}|\lambda(f_{i})) = \frac{\Gamma\left(\frac{v+1}{2}\right)}{\Gamma\left(\frac{v}{2}\right)\sqrt{v\pi\sigma^{2}}}\left(1 + \frac{1}{v}\left(\frac{(y_{i} - f_{i})^{2}}{\sigma^{2}}\right)\right)^{\frac{-v+1}{2}}

    +
    +
    +conditional_mean(gp)[source]
    +
    + +
    +
    +conditional_variance(gp)[source]
    +
    + +
    +
    +d2logpdf_dlink2(inv_link_f, y, Y_metadata=None)[source]
    +

    Hessian at y, given link(f), w.r.t link(f) +i.e. second derivative logpdf at y given link(f_i) and link(f_j) w.r.t link(f_i) and link(f_j) +The hessian will be 0 unless i == j

    +
    +

    \frac{d^{2} \ln p(y_{i}|\lambda(f_{i}))}{d^{2}\lambda(f)} = \frac{(v+1)((y_{i}-\lambda(f_{i}))^{2} - \sigma^{2}v)}{((y_{i}-\lambda(f_{i}))^{2} + \sigma^{2}v)^{2}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables inv_link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution
    • +
    +
    Returns:

    Diagonal of hessian matrix (second derivative of likelihood evaluated at points f)

    +
    Return type:

    Nx1 array

    +
    +
    +

    Note

    +

    Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases +(the distribution for y_i depends only on link(f_i) not on link(f_(j!=i))

    +
    +
    + +
    +
    +d2logpdf_dlink2_dtheta(f, y, Y_metadata=None)[source]
    +
    + +
    +
    +d2logpdf_dlink2_dvar(inv_link_f, y, Y_metadata=None)[source]
    +

    Gradient of the hessian (d2logpdf_dlink2) w.r.t variance parameter (t_noise)

    +
    +

    \frac{d}{d\sigma^{2}}(\frac{d^{2} \ln p(y_{i}|\lambda(f_{i}))}{d^{2}f}) = \frac{v(v+1)(\sigma^{2}v - 3(y_{i} - \lambda(f_{i}))^{2})}{(\sigma^{2}v + (y_{i} - \lambda(f_{i}))^{2})^{3}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution
    • +
    +
    Returns:

    derivative of hessian evaluated at points f and f_j w.r.t variance parameter

    +
    Return type:

    Nx1 array

    +
    +
    + +
    +
    +d3logpdf_dlink3(inv_link_f, y, Y_metadata=None)[source]
    +

    Third order derivative log-likelihood function at y given link(f) w.r.t link(f)

    +
    +

    \frac{d^{3} \ln p(y_{i}|\lambda(f_{i}))}{d^{3}\lambda(f)} = \frac{-2(v+1)((y_{i} - \lambda(f_{i}))^3 - 3(y_{i} - \lambda(f_{i})) \sigma^{2} v))}{((y_{i} - \lambda(f_{i})) + \sigma^{2} v)^3}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution
    • +
    +
    Returns:

    third derivative of likelihood evaluated at points f

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +

    Gradient of the log likelihood function at y, given link(f) w.r.t link(f)

    +
    +

    \frac{d \ln p(y_{i}|\lambda(f_{i}))}{d\lambda(f)} = \frac{(v+1)(y_{i}-\lambda(f_{i}))}{(y_{i}-\lambda(f_{i}))^{2} + \sigma^{2}v}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables (f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution
    • +
    +
    Returns:

    gradient of likelihood evaluated at points

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +
    + +
    + +

    Derivative of the dlogpdf_dlink w.r.t variance parameter (t_noise)

    +
    +

    \frac{d}{d\sigma^{2}}(\frac{d \ln p(y_{i}|\lambda(f_{i}))}{df}) = \frac{-2\sigma v(v + 1)(y_{i}-\lambda(f_{i}))}{(y_{i}-\lambda(f_{i}))^2 + \sigma^2 v)^2}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables inv_link_f
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution
    • +
    +
    Returns:

    derivative of likelihood evaluated at points f w.r.t variance parameter

    +
    Return type:

    Nx1 array

    +
    +
    + +
    + +
    + +
    + +

    Gradient of the log-likelihood function at y given f, w.r.t variance parameter (t_noise)

    +
    +

    \frac{d \ln p(y_{i}|\lambda(f_{i}))}{d\sigma^{2}} = \frac{v((y_{i} - \lambda(f_{i}))^{2} - \sigma^{2})}{2\sigma^{2}(\sigma^{2}v + (y_{i} - \lambda(f_{i}))^{2})}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution
    • +
    +
    Returns:

    derivative of likelihood evaluated at points f w.r.t variance parameter

    +
    Return type:

    float

    +
    +
    + +
    + +

    Log Likelihood Function given link(f)

    +
    +

    \ln p(y_{i}|\lambda(f_{i})) = \ln \Gamma\left(\frac{v+1}{2}\right) - \ln \Gamma\left(\frac{v}{2}\right) - \ln \sqrt{v \pi\sigma^{2}} - \frac{v+1}{2}\ln \left(1 + \frac{1}{v}\left(\frac{(y_{i} - \lambda(f_{i}))^{2}}{\sigma^{2}}\right)\right)

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables (link(f))
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +

    Likelihood function given link(f)

    +
    +

    p(y_{i}|\lambda(f_{i})) = \frac{\Gamma\left(\frac{v+1}{2}\right)}{\Gamma\left(\frac{v}{2}\right)\sqrt{v\pi\sigma^{2}}}\left(1 + \frac{1}{v}\left(\frac{(y_{i} - \lambda(f_{i}))^{2}}{\sigma^{2}}\right)\right)^{\frac{-v+1}{2}}

    +
    +++ + + + + + + + +
    Parameters:
      +
    • inv_link_f (Nx1 array) – latent variables link(f)
    • +
    • y (Nx1 array) – data
    • +
    • Y_metadata – Y_metadata which is not used in student t distribution
    • +
    +
    Returns:

    likelihood evaluated for this point

    +
    Return type:

    float

    +
    +
    + +
    +
    +predictive_mean(mu, sigma, Y_metadata=None)[source]
    +
    + +
    +
    +predictive_variance(mu, variance, predictive_mean=None, Y_metadata=None)[source]
    +
    + +
    +
    +samples(gp, Y_metadata=None)[source]
    +

    Returns a set of samples of observations based on a given value of the latent variable.

    + +++ + + + +
    Parameters:gp – latent variable
    +
    + +
    +
    +update_gradients(grads)[source]
    +

    Pull out the gradients, be careful as the order must match the order +in which the parameters are added

    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.mappings.html b/doc/_build/html/GPy.mappings.html new file mode 100644 index 00000000..a0775a92 --- /dev/null +++ b/doc/_build/html/GPy.mappings.html @@ -0,0 +1,323 @@ + + + + + + + + GPy.mappings package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.mappings package

    +
    +

    Submodules

    +
    +
    +

    GPy.mappings.additive module

    +
    +
    +class GPy.mappings.additive.Additive(mapping1, mapping2, tensor=False)[source]
    +

    Bases: GPy.core.mapping.Mapping

    +

    Mapping based on adding two existing mappings together.

    +
    +

    f(\mathbf{x}*) = f_1(\mathbf{x}*) + f_2(\mathbf(x)*)

    +
    +++ + + + +
    Parameters:
      +
    • mapping1 (GPy.mappings.Mapping) – first mapping to add together.
    • +
    • mapping2 (GPy.mappings.Mapping) – second mapping to add together.
    • +
    • tensor (bool) – whether or not to use the tensor product of input spaces
    • +
    +
    +
    +
    +df_dX(dL_df, X)[source]
    +
    + +
    +
    +df_dtheta(dL_df, X)[source]
    +
    + +
    +
    +f(X)[source]
    +
    + +
    +
    +randomize()[source]
    +
    + +
    + +
    +
    +

    GPy.mappings.kernel module

    +
    +
    +class GPy.mappings.kernel.Kernel(X, output_dim=1, kernel=None)[source]
    +

    Bases: GPy.core.mapping.Mapping

    +

    Mapping based on a kernel/covariance function.

    +
    +

    f(\mathbf{x}*) = \mathbf{A}\mathbf{k}(\mathbf{X}, \mathbf{x}^*) + \mathbf{b}

    +
    +++ + + + +
    Parameters:
      +
    • X (ndarray) – input observations containing \mathbf{X}
    • +
    • output_dim (int) – dimension of output.
    • +
    • kernel (GPy.kern.kern) – a GPy kernel, defaults to GPy.kern.RBF
    • +
    +
    +
    +
    +df_dX(dL_df, X)[source]
    +
    + +
    +
    +df_dtheta(dL_df, X)[source]
    +
    + +
    +
    +f(X)[source]
    +
    + +
    +
    +randomize()[source]
    +
    + +
    + +
    +
    +

    GPy.mappings.linear module

    +
    +
    +class GPy.mappings.linear.Linear(input_dim=1, output_dim=1, name='linear')[source]
    +

    Bases: GPy.core.mapping.Bijective_mapping

    +

    Mapping based on a linear model.

    +
    +

    f(\mathbf{x}*) = \mathbf{W}\mathbf{x}^* + \mathbf{b}

    +
    +++ + + + +
    Parameters:
      +
    • X (ndarray) – input observations
    • +
    • output_dim (int) – dimension of output.
    • +
    +
    +
    +
    +dL_dX(partial, X)[source]
    +

    The gradient of L with respect to the inputs to the mapping, where L is a function that is dependent on the output of the mapping, f.

    +
    + +
    +
    +df_dtheta(dL_df, X)[source]
    +
    + +
    +
    +f(X)[source]
    +
    + +
    +
    +g(f)[source]
    +
    + +
    + +
    +
    +

    GPy.mappings.mlp module

    +
    +
    +class GPy.mappings.mlp.MLP(input_dim=1, output_dim=1, hidden_dim=3)[source]
    +

    Bases: GPy.core.mapping.Mapping

    +

    Mapping based on a multi-layer perceptron neural network model.

    +
    +

    f(\mathbf{x}*) = \mathbf{W}^0\boldsymbol{\phi}(\mathbf{W}^1\mathbf{x}+\mathbf{b}^1)^* + \mathbf{b}^0

    +

    where

    +
    +

    \phi(\cdot) = \text{tanh}(\cdot)

    +
    +++ + + + +
    Parameters:
      +
    • X (ndarray) – input observations
    • +
    • output_dim (int) – dimension of output.
    • +
    • hidden_dim (int or list of ints.) – dimension of hidden layer. If it is an int, there is one hidden layer of the given dimension. If it is a list of ints there are as manny hidden layers as the length of the list, each with the given number of hidden nodes in it.
    • +
    +
    +
    +
    +df_dX(dL_df, X)[source]
    +
    + +
    +
    +df_dtheta(dL_df, X)[source]
    +
    + +
    +
    +f(X)[source]
    +
    + +
    +
    +randomize()[source]
    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.models.html b/doc/_build/html/GPy.models.html new file mode 100644 index 00000000..5a6596b9 --- /dev/null +++ b/doc/_build/html/GPy.models.html @@ -0,0 +1,1048 @@ + + + + + + + + GPy.models package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.models package

    +
    +

    Submodules

    +
    +
    +

    GPy.models.bayesian_gplvm module

    +
    +
    +class GPy.models.bayesian_gplvm.BayesianGPLVM(Y, input_dim, X=None, X_variance=None, init='PCA', num_inducing=10, Z=None, kernel=None, inference_method=None, likelihood=None, name='bayesian gplvm', mpi_comm=None, normalizer=None, missing_data=False, stochastic=False, batchsize=1)[source]
    +

    Bases: GPy.core.sparse_gp_mpi.SparseGP_MPI

    +

    Bayesian Gaussian Process Latent Variable Model

    + +++ + + + +
    Parameters:
      +
    • Y (np.ndarray| GPy.likelihood instance) – observed data (np.ndarray) or GPy.likelihood
    • +
    • input_dim (int) – latent dimensionality
    • +
    • init (‘PCA’|’random’) – initialisation method for the latent space
    • +
    +
    +
    +
    +dmu_dX(Xnew)[source]
    +

    Calculate the gradient of the prediction at Xnew w.r.t Xnew.

    +
    + +
    +
    +dmu_dXnew(Xnew)[source]
    +

    Individual gradient of prediction at Xnew w.r.t. each sample in Xnew

    +
    + +
    +
    +do_test_latents(Y)[source]
    +

    Compute the latent representation for a set of new points Y

    +

    Notes: +This will only work with a univariate Gaussian likelihood (for now)

    +
    + +
    +
    +get_X_gradients(X)[source]
    +

    Get the gradients of the posterior distribution of X in its specific form.

    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +plot_latent(labels=None, which_indices=None, resolution=50, ax=None, marker='o', s=40, fignum=None, plot_inducing=True, legend=True, plot_limits=None, aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={})[source]
    +
    + +
    +
    +plot_steepest_gradient_map(*args, **kwargs)[source]
    +

    See GPy.plotting.matplot_dep.dim_reduction_plots.plot_steepest_gradient_map

    +
    + +
    +
    +set_X_gradients(X, X_grad)[source]
    +

    Set the gradients of the posterior distribution of X in its specific form.

    +
    + +
    + +
    +
    +GPy.models.bayesian_gplvm.latent_cost_and_grad(mu_S, input_dim, kern, Z, dL_dpsi0, dL_dpsi1, dL_dpsi2)[source]
    +

    objective function for fitting the latent variables for test points +(negative log-likelihood: should be minimised!)

    +
    + +
    +
    +

    GPy.models.bayesian_gplvm_minibatch module

    +
    +
    +class GPy.models.bayesian_gplvm_minibatch.BayesianGPLVMMiniBatch(Y, input_dim, X=None, X_variance=None, init='PCA', num_inducing=10, Z=None, kernel=None, inference_method=None, likelihood=None, name='bayesian gplvm', normalizer=None, missing_data=False, stochastic=False, batchsize=1)[source]
    +

    Bases: GPy.models.sparse_gp_minibatch.SparseGPMiniBatch

    +

    Bayesian Gaussian Process Latent Variable Model

    + +++ + + + +
    Parameters:
      +
    • Y (np.ndarray| GPy.likelihood instance) – observed data (np.ndarray) or GPy.likelihood
    • +
    • input_dim (int) – latent dimensionality
    • +
    • init (‘PCA’|’random’) – initialisation method for the latent space
    • +
    +
    +
    +
    +dmu_dX(Xnew)[source]
    +

    Calculate the gradient of the prediction at Xnew w.r.t Xnew.

    +
    + +
    +
    +dmu_dXnew(Xnew)[source]
    +

    Individual gradient of prediction at Xnew w.r.t. each sample in Xnew

    +
    + +
    +
    +do_test_latents(Y)[source]
    +

    Compute the latent representation for a set of new points Y

    +

    Notes: +This will only work with a univariate Gaussian likelihood (for now)

    +
    + +
    +
    +get_X_gradients(X)[source]
    +

    Get the gradients of the posterior distribution of X in its specific form.

    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +plot_latent(labels=None, which_indices=None, resolution=50, ax=None, marker='o', s=40, fignum=None, plot_inducing=True, legend=True, plot_limits=None, aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={})[source]
    +
    + +
    +
    +plot_steepest_gradient_map(*args, **kwargs)[source]
    +

    See GPy.plotting.matplot_dep.dim_reduction_plots.plot_steepest_gradient_map

    +
    + +
    +
    +set_X_gradients(X, X_grad)[source]
    +

    Set the gradients of the posterior distribution of X in its specific form.

    +
    + +
    + +
    +
    +GPy.models.bayesian_gplvm_minibatch.latent_cost_and_grad(mu_S, input_dim, kern, Z, dL_dpsi0, dL_dpsi1, dL_dpsi2)[source]
    +

    objective function for fitting the latent variables for test points +(negative log-likelihood: should be minimised!)

    +
    + +
    +
    +

    GPy.models.bcgplvm module

    +
    +
    +class GPy.models.bcgplvm.BCGPLVM(Y, input_dim, init='PCA', X=None, kernel=None, normalize_Y=False, mapping=None)[source]
    +

    Bases: GPy.models.gplvm.GPLVM

    +

    Back constrained Gaussian Process Latent Variable Model

    + +++ + + + +
    Parameters:
      +
    • Y (np.ndarray) – observed data
    • +
    • input_dim (int) – latent dimensionality
    • +
    • init (‘PCA’|’random’) – initialisation method for the latent space
    • +
    • mapping (GPy.core.Mapping object) – mapping for back constraint
    • +
    +
    +
    + +
    +
    +

    GPy.models.gp_classification module

    +
    +
    +class GPy.models.gp_classification.GPClassification(X, Y, kernel=None, Y_metadata=None)[source]
    +

    Bases: GPy.core.gp.GP

    +

    Gaussian Process classification

    +

    This is a thin wrapper around the models.GP class, with a set of sensible defaults

    + +++ + + + +
    Parameters:
      +
    • X – input observations
    • +
    • Y – observed values, can be None if likelihood is not None
    • +
    • kernel – a GPy kernel, defaults to rbf
    • +
    +
    +
    +

    Note

    +

    Multiple independent outputs are allowed using columns of Y

    +
    +
    + +
    +
    +

    GPy.models.gp_coregionalized_regression module

    +
    +
    +class GPy.models.gp_coregionalized_regression.GPCoregionalizedRegression(X_list, Y_list, kernel=None, likelihoods_list=None, name='GPCR', W_rank=1, kernel_name='coreg')[source]
    +

    Bases: GPy.core.gp.GP

    +

    Gaussian Process model for heteroscedastic multioutput regression

    +

    This is a thin wrapper around the models.GP class, with a set of sensible defaults

    + +++ + + + + + + +
    Parameters:
      +
    • X_list (list of numpy arrays) – list of input observations corresponding to each output
    • +
    • Y_list (list of numpy arrays) – list of observed values related to the different noise models
    • +
    • kernel (None | GPy.kernel defaults) – a GPy kernel, defaults to RBF ** Coregionalized
    • +
    • name (string) – model name
    • +
    • W_rank (integer) – number tuples of the corregionalization parameters ‘W’ (see coregionalize kernel documentation)
    • +
    • kernel_name (string) – name of the kernel
    • +
    +
    Likelihoods_list:
     

    a list of likelihoods, defaults to list of Gaussian likelihoods

    +
    +
    + +
    +
    +

    GPy.models.gp_heteroscedastic_regression module

    +
    +
    +class GPy.models.gp_heteroscedastic_regression.GPHeteroscedasticRegression(X, Y, kernel=None, Y_metadata=None)[source]
    +

    Bases: GPy.core.gp.GP

    +

    Gaussian Process model for heteroscedastic regression

    +

    This is a thin wrapper around the models.GP class, with a set of sensible defaults

    + +++ + + + +
    Parameters:
      +
    • X – input observations
    • +
    • Y – observed values
    • +
    • kernel – a GPy kernel, defaults to rbf
    • +
    +
    +
    +
    +plot(*args)[source]
    +
    + +
    + +
    +
    +

    GPy.models.gp_kronecker_gaussian_regression module

    +
    +
    +class GPy.models.gp_kronecker_gaussian_regression.GPKroneckerGaussianRegression(X1, X2, Y, kern1, kern2, noise_var=1.0, name='KGPR')[source]
    +

    Bases: GPy.core.model.Model

    +

    Kronecker GP regression

    +

    Take two kernels computed on separate spaces K1(X1), K2(X2), and a data +matrix Y which is f size (N1, N2).

    +

    The effective covaraince is np.kron(K2, K1) +The effective data is vec(Y) = Y.flatten(order=’F’)

    +

    The noise must be iid Gaussian.

    +

    See Stegle et al. +@inproceedings{stegle2011efficient,

    +
    +
    title={Efficient inference in matrix-variate gaussian models with $backslash$ iid observation noise}, +author={Stegle, Oliver and Lippert, Christoph and Mooij, Joris M and Lawrence, Neil D and Borgwardt, Karsten M}, +booktitle={Advances in Neural Information Processing Systems}, +pages={630–638}, +year={2011}
    +

    }

    +
    +
    +log_likelihood()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +predict(X1new, X2new)[source]
    +

    Return the predictive mean and variance at a series of new points X1new, X2new +Only returns the diagonal of the predictive variance, for now.

    + +++ + + + +
    Parameters:
      +
    • X1new (np.ndarray, Nnew x self.input_dim1) – The points at which to make a prediction
    • +
    • X2new (np.ndarray, Nnew x self.input_dim2) – The points at which to make a prediction
    • +
    +
    +
    + +
    + +
    +
    +

    GPy.models.gp_multioutput_regression module

    +
    +
    +

    GPy.models.gp_regression module

    +
    +
    +class GPy.models.gp_regression.GPRegression(X, Y, kernel=None, Y_metadata=None, normalizer=None)[source]
    +

    Bases: GPy.core.gp.GP

    +

    Gaussian Process model for regression

    +

    This is a thin wrapper around the models.GP class, with a set of sensible defaults

    + +++ + + + +
    Parameters:
      +
    • X – input observations
    • +
    • Y – observed values
    • +
    • kernel – a GPy kernel, defaults to rbf
    • +
    • normalizer (Norm) –

      [False]

      +

      Normalize Y with the norm given. +If normalizer is False, no normalization will be done +If it is None, we use GaussianNorm(alization)

      +
    • +
    +
    +
    +

    Note

    +

    Multiple independent outputs are allowed using columns of Y

    +
    +
    + +
    +
    +

    GPy.models.gp_var_gauss module

    +
    +
    +class GPy.models.gp_var_gauss.GPVariationalGaussianApproximation(X, Y, kernel=None)[source]
    +

    Bases: GPy.core.model.Model

    +

    The Variational Gaussian Approximation revisited implementation for regression

    +
    +
    @article{Opper:2009,
    +
    title = {The Variational Gaussian Approximation Revisited}, +author = {Opper, Manfred and Archambeau, C{‘e}dric}, +journal = {Neural Comput.}, +year = {2009}, +pages = {786–792},
    +
    +

    }

    +
    +
    +likelihood_quadrature(m, v)[source]
    +

    Perform Gauss-Hermite quadrature over the log of the likelihood, with a fixed weight

    +
    + +
    +
    +log_likelihood()[source]
    +

    Marginal log likelihood evaluation

    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +predict(Xnew)[source]
    +

    Predict the function(s) at the new point(s) Xnew.

    + +++ + + + +
    Parameters:Xnew (np.ndarray, Nnew x self.input_dim) – The points at which to make a prediction
    +
    + +
    + +
    +
    +

    GPy.models.gplvm module

    +
    +
    +class GPy.models.gplvm.GPLVM(Y, input_dim, init='PCA', X=None, kernel=None, name='gplvm')[source]
    +

    Bases: GPy.core.gp.GP

    +

    Gaussian Process Latent Variable Model

    +
    +
    +jacobian(X)[source]
    +
    + +
    +
    +magnification(X)[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +plot()[source]
    +
    + +
    +
    +plot_latent(labels=None, which_indices=None, resolution=50, ax=None, marker='o', s=40, fignum=None, legend=True, plot_limits=None, aspect='auto', updates=False, **kwargs)[source]
    +
    + +
    +
    +plot_magnification(*args, **kwargs)[source]
    +
    + +
    + +
    +
    +

    GPy.models.gradient_checker module

    +
    +
    +class GPy.models.gradient_checker.GradientChecker(f, df, x0, names=None, *args, **kwargs)[source]
    +

    Bases: GPy.core.model.Model

    +
    +
    +log_likelihood()[source]
    +
    + +
    + +
    +
    +GPy.models.gradient_checker.at_least_one_element(x)[source]
    +
    + +
    +
    +GPy.models.gradient_checker.flatten_if_needed(x)[source]
    +
    + +
    +
    +GPy.models.gradient_checker.get_shape(x)[source]
    +
    + +
    +
    +

    GPy.models.mrd module

    +
    +
    +class GPy.models.mrd.MRD(Ylist, input_dim, X=None, X_variance=None, initx='PCA', initz='permute', num_inducing=10, Z=None, kernel=None, inference_method=None, likelihoods=None, name='mrd', Ynames=None, normalizer=False, stochastic=False, batchsize=10)[source]
    +

    Bases: GPy.models.bayesian_gplvm_minibatch.BayesianGPLVMMiniBatch

    +

    !WARNING: This is bleeding edge code and still in development. +Functionality may change fundamentally during development!

    +

    Apply MRD to all given datasets Y in Ylist.

    +

    Y_i in [n x p_i]

    +

    If Ylist is a dictionary, the keys of the dictionary are the names, and the +values are the different datasets to compare.

    +

    The samples n in the datasets need +to match up, whereas the dimensionality p_d can differ.

    + +++ + + + +
    Parameters:
      +
    • Ylist ([array-like]) – List of datasets to apply MRD on
    • +
    • input_dim (int) – latent dimensionality
    • +
    • X (array-like) – mean of starting latent space q in [n x q]
    • +
    • X_variance (array-like) – variance of starting latent space q in [n x q]
    • +
    • initx ([‘concat’|’single’|’random’]) –

      initialisation method for the latent space :

      +
        +
      • ‘concat’ - PCA on concatenation of all datasets
      • +
      • ‘single’ - Concatenation of PCA on datasets, respectively
      • +
      • ‘random’ - Random draw from a Normal(0,1)
      • +
      +
    • +
    • initz (‘permute’|’random’) – initialisation method for inducing inputs
    • +
    • num_inducing – number of inducing inputs to use
    • +
    • Z – initial inducing inputs
    • +
    • kernel ([GPy.kernels.kernels] | GPy.kernels.kernels | None (default)) – list of kernels or kernel to copy for each output
    • +
    +
    +
    +
    :param :class:`~GPy.inference.latent_function_inference inference_method:
    +
    InferenceMethodList of inferences, or one inference method for all
    +
    +

    :param likelihoods likelihoods: the likelihoods to use +:param str name: the name of this model +:param [str] Ynames: the names for the datasets given, must be of equal length as Ylist or None +:param bool|Norm normalizer: How to normalize the data? +:param bool stochastic: Should this model be using stochastic gradient descent over the dimensions? +:param bool|[bool] batchsize: either one batchsize for all, or one batchsize per dataset.

    +
    +
    +log_likelihood()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +plot_latent(labels=None, which_indices=None, resolution=50, ax=None, marker='o', s=40, fignum=None, plot_inducing=True, legend=True, plot_limits=None, aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={})[source]
    +

    see plotting.matplot_dep.dim_reduction_plots.plot_latent +if predict_kwargs is None, will plot latent spaces for 0th dataset (and kernel), otherwise give +predict_kwargs=dict(Yindex=’index’) for plotting only the latent space of dataset with ‘index’.

    +
    + +
    +
    +plot_scales(fignum=None, ax=None, titles=None, sharex=False, sharey=True, *args, **kwargs)[source]
    +

    TODO: Explain other parameters

    + +++ + + + +
    Parameters:titles – titles for axes of datasets
    +
    + +
    +
    +predict(Xnew, full_cov=False, Y_metadata=None, kern=None, Yindex=0)[source]
    +

    Prediction for data set Yindex[default=0]. +This predicts the output mean and variance for the dataset given in Ylist[Yindex]

    +
    + +
    + +
    +
    +

    GPy.models.sparse_gp_classification module

    +
    +
    +class GPy.models.sparse_gp_classification.SparseGPClassification(X, Y=None, likelihood=None, kernel=None, Z=None, num_inducing=10, Y_metadata=None)[source]
    +

    Bases: GPy.core.sparse_gp.SparseGP

    +

    sparse Gaussian Process model for classification

    +

    This is a thin wrapper around the sparse_GP class, with a set of sensible defaults

    + +++ + + + + + +
    Parameters:
      +
    • X – input observations
    • +
    • Y – observed values
    • +
    • likelihood – a GPy likelihood, defaults to Binomial with probit link_function
    • +
    • kernel – a GPy kernel, defaults to rbf+white
    • +
    • normalize_X (False|True) – whether to normalize the input data before computing (predictions will be in original scales)
    • +
    • normalize_Y (False|True) – whether to normalize the input data before computing (predictions will be in original scales)
    • +
    +
    Return type:

    model object

    +
    +
    + +
    +
    +

    GPy.models.sparse_gp_coregionalized_regression module

    +
    +
    +class GPy.models.sparse_gp_coregionalized_regression.SparseGPCoregionalizedRegression(X_list, Y_list, Z_list=[], kernel=None, likelihoods_list=None, num_inducing=10, X_variance=None, name='SGPCR', W_rank=1, kernel_name='coreg')[source]
    +

    Bases: GPy.core.sparse_gp.SparseGP

    +

    Sparse Gaussian Process model for heteroscedastic multioutput regression

    +

    This is a thin wrapper around the SparseGP class, with a set of sensible defaults

    + +++ + + + + + + +
    Parameters:
      +
    • X_list (list of numpy arrays) – list of input observations corresponding to each output
    • +
    • Y_list (list of numpy arrays) – list of observed values related to the different noise models
    • +
    • Z_list (empty list | list of numpy arrays) – list of inducing inputs (optional)
    • +
    • kernel (None | GPy.kernel defaults) – a GPy kernel, defaults to RBF ** Coregionalized
    • +
    • num_inducing (integer | list of integers) – number of inducing inputs, defaults to 10 per output (ignored if Z_list is not empty)
    • +
    • name (string) – model name
    • +
    • W_rank (integer) – number tuples of the corregionalization parameters ‘W’ (see coregionalize kernel documentation)
    • +
    • kernel_name (string) – name of the kernel
    • +
    +
    Likelihoods_list:
     

    a list of likelihoods, defaults to list of Gaussian likelihoods

    +
    +
    + +
    +
    +

    GPy.models.sparse_gp_minibatch module

    +
    +
    +class GPy.models.sparse_gp_minibatch.SparseGPMiniBatch(X, Y, Z, kernel, likelihood, inference_method=None, name='sparse gp', Y_metadata=None, normalizer=False, missing_data=False, stochastic=False, batchsize=1)[source]
    +

    Bases: GPy.core.gp.GP

    +
    +
    A general purpose Sparse GP model
    +

    ‘’’ +Created on 3 Nov 2014

    +

    @author: maxz +‘’‘

    +
    +

    This model allows (approximate) inference using variational DTC or FITC +(Gaussian likelihoods) as well as non-conjugate sparse methods based on +these.

    + +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    param X:inputs
    type X:np.ndarray (num_data x input_dim)
    param likelihood:
     a likelihood instance, containing the observed data
    type likelihood:
     GPy.likelihood.(Gaussian | EP | Laplace)
    param kernel:the kernel (covariance function). See link kernels
    type kernel:a GPy.kern.kern instance
    param X_variance:
     The uncertainty in the measurements of X (Gaussian variance)
    type X_variance:
     np.ndarray (num_data x input_dim) | None
    param Z:inducing inputs
    type Z:np.ndarray (num_inducing x input_dim)
    param num_inducing:
     Number of inducing points (optional, default 10. Ignored if Z is not None)
    type num_inducing:
     int
    +
    +
    +
    +has_uncertain_inputs()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +

    GPy.models.sparse_gp_multioutput_regression module

    +
    +
    +

    GPy.models.sparse_gp_regression module

    +
    +
    +class GPy.models.sparse_gp_regression.SparseGPRegression(X, Y, kernel=None, Z=None, num_inducing=10, X_variance=None, normalizer=None, mpi_comm=None)[source]
    +

    Bases: GPy.core.sparse_gp_mpi.SparseGP_MPI

    +

    Gaussian Process model for regression

    +

    This is a thin wrapper around the SparseGP class, with a set of sensible defalts

    + +++ + + + + + +
    Parameters:
      +
    • X – input observations
    • +
    • Y – observed values
    • +
    • kernel – a GPy kernel, defaults to rbf+white
    • +
    • Z (np.ndarray (num_inducing x input_dim) | None) – inducing inputs (optional, see note)
    • +
    • num_inducing (int) – number of inducing points (ignored if Z is passed, see note)
    • +
    +
    Return type:

    model object

    +
    +
    +

    Note

    +

    If no Z array is passed, num_inducing (default 10) points are selected from the data. Other wise num_inducing is ignored

    +
    +
    +

    Note

    +

    Multiple independent outputs are allowed using columns of Y

    +
    +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +class GPy.models.sparse_gp_regression.SparseGPRegressionUncertainInput(X, X_variance, Y, kernel=None, Z=None, num_inducing=10, normalizer=None)[source]
    +

    Bases: GPy.core.sparse_gp.SparseGP

    +

    Gaussian Process model for regression with Gaussian variance on the inputs (X_variance)

    +

    This is a thin wrapper around the SparseGP class, with a set of sensible defalts

    +
    + +
    +
    +

    GPy.models.sparse_gplvm module

    +
    +
    +class GPy.models.sparse_gplvm.SparseGPLVM(Y, input_dim, X=None, kernel=None, init='PCA', num_inducing=10)[source]
    +

    Bases: GPy.models.sparse_gp_regression.SparseGPRegression

    +

    Sparse Gaussian Process Latent Variable Model

    + +++ + + + +
    Parameters:
      +
    • Y (np.ndarray) – observed data
    • +
    • input_dim (int) – latent dimensionality
    • +
    • init (‘PCA’|’random’) – initialisation method for the latent space
    • +
    +
    +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +plot_latent(labels=None, which_indices=None, resolution=50, ax=None, marker='o', s=40, fignum=None, plot_inducing=True, legend=True, plot_limits=None, aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={})[source]
    +
    + +
    + +
    +
    +

    GPy.models.ss_gplvm module

    +
    +
    +class GPy.models.ss_gplvm.SSGPLVM(Y, input_dim, X=None, X_variance=None, Gamma=None, init='PCA', num_inducing=10, Z=None, kernel=None, inference_method=None, likelihood=None, name='Spike_and_Slab GPLVM', group_spike=False, mpi_comm=None, pi=None, learnPi=True, normalizer=False, **kwargs)[source]
    +

    Bases: GPy.core.sparse_gp_mpi.SparseGP_MPI

    +

    Spike-and-Slab Gaussian Process Latent Variable Model

    + +++ + + + +
    Parameters:
      +
    • Y (np.ndarray| GPy.likelihood instance) – observed data (np.ndarray) or GPy.likelihood
    • +
    • input_dim (int) – latent dimensionality
    • +
    • init (‘PCA’|’random’) – initialisation method for the latent space
    • +
    +
    +
    +
    +get_X_gradients(X)[source]
    +

    Get the gradients of the posterior distribution of X in its specific form.

    +
    + +
    +
    +input_sensitivity()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +plot_latent(plot_inducing=True, *args, **kwargs)[source]
    +
    + +
    +
    +set_X_gradients(X, X_grad)[source]
    +

    Set the gradients of the posterior distribution of X in its specific form.

    +
    + +
    + +
    +
    +

    GPy.models.ss_mrd module

    +

    The Maniforld Relevance Determination model with the spike-and-slab prior

    +
    +
    +class GPy.models.ss_mrd.SSMRD(Ylist, input_dim, X=None, X_variance=None, initx='PCA', initz='permute', num_inducing=10, Z=None, kernel=None, inference_method=None, likelihoods=None, name='ss_mrd', Ynames=None)[source]
    +

    Bases: GPy.core.model.Model

    +
    +
    +log_likelihood()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +

    GPy.models.svigp_regression module

    +
    +
    +

    GPy.models.warped_gp module

    +
    +
    +class GPy.models.warped_gp.WarpedGP(X, Y, kernel=None, warping_function=None, warping_terms=3, normalize_X=False, normalize_Y=False)[source]
    +

    Bases: GPy.core.gp.GP

    +
    +
    +log_likelihood()[source]
    +
    + +
    +
    +plot_warping()[source]
    +
    + +
    +
    +predict(Xnew, which_parts='all', full_cov=False, pred_init=None)[source]
    +
    + +
    +
    +transform_data()[source]
    +
    + +
    +
    +warping_function_gradients(Kiy)[source]
    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.plotting.html b/doc/_build/html/GPy.plotting.html new file mode 100644 index 00000000..d90f0b68 --- /dev/null +++ b/doc/_build/html/GPy.plotting.html @@ -0,0 +1,181 @@ + + + + + + + + GPy.plotting package — GPy documentation + + + + + + + + + + + + + + + + +
    + + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.plotting.matplot_dep.html b/doc/_build/html/GPy.plotting.matplot_dep.html new file mode 100644 index 00000000..cedd4e77 --- /dev/null +++ b/doc/_build/html/GPy.plotting.matplot_dep.html @@ -0,0 +1,1098 @@ + + + + + + + + GPy.plotting.matplot_dep package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.plotting.matplot_dep package

    + +
    +

    Submodules

    +
    +
    +

    GPy.plotting.matplot_dep.Tango module

    +
    +
    +GPy.plotting.matplot_dep.Tango.currentDark()[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.currentLight()[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.currentMedium()[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.fewerXticks(ax=None, divideby=2)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.hex2rgb(hexcolor)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.nextDark()[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.nextLight()[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.nextMedium()[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.removeRightTicks(ax=None)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.removeUpperTicks(ax=None)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.reset()[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.setDarkFigures()[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.Tango.setLightFigures()[source]
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.base_plots module

    +
    +
    +GPy.plotting.matplot_dep.base_plots.align_subplot_array(axes, xlim=None, ylim=None)[source]
    +

    Make all of the axes in the array hae the same limits, turn off unnecessary ticks +use pb.subplots() to get an array of axes

    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.align_subplots(N, M, xlim=None, ylim=None)[source]
    +

    make all of the subplots have the same limits, turn off unnecessary ticks

    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.ax_default(fignum, ax)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.fewerXticks(ax=None, divideby=2)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.gpplot(x, mu, lower, upper, edgecol='#204a87', fillcol='#729fcf', ax=None, fignum=None, **kwargs)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.meanplot(x, mu, color='#204a87', ax=None, fignum=None, linewidth=2, **kw)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.removeRightTicks(ax=None)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.removeUpperTicks(ax=None)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.x_frame1D(X, plot_limits=None, resolution=None)[source]
    +

    Internal helper function for making plots, returns a set of input values to plot as well as lower and upper limits

    +
    + +
    +
    +GPy.plotting.matplot_dep.base_plots.x_frame2D(X, plot_limits=None, resolution=None)[source]
    +

    Internal helper function for making plots, returns a set of input values to plot as well as lower and upper limits

    +
    + +
    +
    +

    GPy.plotting.matplot_dep.dim_reduction_plots module

    +
    +
    +GPy.plotting.matplot_dep.dim_reduction_plots.most_significant_input_dimensions(model, which_indices)[source]
    +

    Determine which dimensions should be plotted

    +
    + +
    +
    +GPy.plotting.matplot_dep.dim_reduction_plots.plot_latent(model, labels=None, which_indices=None, resolution=50, ax=None, marker='o', s=40, fignum=None, plot_inducing=False, legend=True, plot_limits=None, aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={})[source]
    +
    +++ + + + +
    Parameters:
      +
    • labels – a np.array of size model.num_data containing labels for the points (can be number, strings, etc)
    • +
    • resolution – the resolution of the grid on which to evaluate the predictive variance
    • +
    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.dim_reduction_plots.plot_magnification(model, labels=None, which_indices=None, resolution=60, ax=None, marker='o', s=40, fignum=None, plot_inducing=False, legend=True, aspect='auto', updates=False)[source]
    +
    +++ + + + +
    Parameters:
      +
    • labels – a np.array of size model.num_data containing labels for the points (can be number, strings, etc)
    • +
    • resolution – the resolution of the grid on which to evaluate the predictive variance
    • +
    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.dim_reduction_plots.plot_steepest_gradient_map(model, fignum=None, ax=None, which_indices=None, labels=None, data_labels=None, data_marker='o', data_s=40, resolution=20, aspect='auto', updates=False, **kwargs)[source]
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.img_plots module

    +

    The module contains the tools for ploting 2D image visualizations

    +
    +
    +GPy.plotting.matplot_dep.img_plots.plot_2D_images(figure, arr, symmetric=False, pad=None, zoom=None, mode=None, interpolation='nearest')[source]
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.inference_plots module

    +
    +
    +GPy.plotting.matplot_dep.inference_plots.plot_optimizer(optimizer)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.inference_plots.plot_sgd_traces(optimizer)[source]
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.kernel_plots module

    +
    +
    +GPy.plotting.matplot_dep.kernel_plots.add_bar_labels(fig, ax, bars, bottom=0)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.kernel_plots.plot(kernel, x=None, fignum=None, ax=None, title=None, plot_limits=None, resolution=None, **mpl_kwargs)[source]
    +

    plot a kernel. +:param x: the value to use for the other kernel argument (kernels are a function of two variables!) +:param fignum: figure number of the plot +:param ax: matplotlib axis to plot on +:param title: the matplotlib title +:param plot_limits: the range over which to plot the kernel +:resolution: the resolution of the lines used in plotting +:mpl_kwargs avalid keyword arguments to pass through to matplotlib (e.g. lw=7)

    +
    + +
    +
    +GPy.plotting.matplot_dep.kernel_plots.plot_ARD(kernel, fignum=None, ax=None, title='', legend=False, filtering=None)[source]
    +

    If an ARD kernel is present, plot a bar representation using matplotlib

    + +++ + + + +
    Parameters:
      +
    • fignum – figure number of the plot
    • +
    • ax – matplotlib axis to plot on
    • +
    • title – title of the plot, +pass ‘’ to not print a title +pass None for a generic title
    • +
    • filtering (list of names to use for ARD plot) – list of names, which to use for plotting ARD parameters. +Only kernels which match names in the list of names in filtering +will be used for plotting.
    • +
    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.kernel_plots.plot_bars(fig, ax, x, ard_params, color, name, bottom=0)[source]
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.mapping_plots module

    +
    +
    +GPy.plotting.matplot_dep.mapping_plots.plot_mapping(self, plot_limits=None, which_data='all', which_parts='all', resolution=None, levels=20, samples=0, fignum=None, ax=None, fixed_inputs=[], linecol='#204a87')[source]
    +
    +
    Plots the mapping associated with the model.
    +
      +
    • In one dimension, the function is plotted.
    • +
    • In two dimsensions, a contour-plot shows the function
    • +
    • In higher dimensions, we’ve not implemented this yet !TODO!
    • +
    +
    +
    +

    Can plot only part of the data and part of the posterior functions +using which_data and which_functions

    + +++ + + + +
    Parameters:
      +
    • plot_limits (np.array) – The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits
    • +
    • which_data (‘all’ or a slice object to slice self.X, self.Y) – which if the training data to plot (default all)
    • +
    • which_parts (‘all’, or list of bools) – which of the kernel functions to plot (additively)
    • +
    • resolution (int) – the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D
    • +
    • levels (int) – number of levels to plot in a contour plot.
    • +
    • samples (int) – the number of a posteriori samples to plot
    • +
    • fignum (figure number) – figure to plot on.
    • +
    • ax (axes handle) – axes to plot on.
    • +
    • fixed_inputs (a list of tuples) – a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v.
    • +
    • linecol – color of line to plot.
    • +
    • levels – for 2D plotting, the number of contour levels to use is ax is None, create a new figure
    • +
    +
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.maps module

    +
    +
    +GPy.plotting.matplot_dep.maps.apply_bbox(sf, ax)[source]
    +

    Use bbox as xlim and ylim in ax

    +
    + +
    +
    +GPy.plotting.matplot_dep.maps.bbox_match(sf, bbox, inside_only=True)[source]
    +

    Return the geometry and attributes of a shapefile that lie within (or intersect) a bounding box

    + +++ + + + + + +
    Parameters:
      +
    • sf (shapefile object) – shapefile
    • +
    • bbox (list of floats [x_min,y_min,x_max,y_max]) – bounding box
    • +
    +
    Inside_only:

    True if the objects returned are those that lie within the bbox and False if the objects returned are any that intersect the bbox

    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.maps.new_shape_string(sf, name, regex, field=2, type=None)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.maps.plot(shape_records, facecolor='w', edgecolor='k', linewidths=0.5, ax=None, xlims=None, ylims=None)[source]
    +

    Plot the geometry of a shapefile

    + +++ + + + +
    Parameters:
      +
    • shape_records (ShapeRecord object (output of a shapeRecords() method)) – geometry and attributes list
    • +
    • facecolor – color to be used to fill in polygons
    • +
    • edgecolor – color to be used for lines
    • +
    • ax (axes handle) – axes to plot on.
    • +
    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.maps.plot_bbox(sf, bbox, inside_only=True)[source]
    +

    Plot the geometry of a shapefile within a bbox

    + +++ + + + + + +
    Parameters:
      +
    • sf (shapefile object) – shapefile
    • +
    • bbox (list of floats [x_min,y_min,x_max,y_max]) – bounding box
    • +
    +
    Inside_only:

    True if the objects returned are those that lie within the bbox and False if the objects returned are any that intersect the bbox

    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.maps.plot_string_match(sf, regex, field, **kwargs)[source]
    +

    Plot the geometry of a shapefile whose fields match a regular expression given

    + +++ + + + + + + + +
    Parameters:sf (shapefile object) – shapefile
    Regex:regular expression to match
    Field:field number to be matched with the regex
    +
    + +
    +
    +GPy.plotting.matplot_dep.maps.string_match(sf, regex, field=2)[source]
    +

    Return the geometry and attributes of a shapefile whose fields match a regular expression given

    + +++ + + + + + + + +
    Parameters:sf (shapefile object) – shapefile
    Regex:regular expression to match
    Field:field number to be matched with the regex
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.models_plots module

    +
    +
    +GPy.plotting.matplot_dep.models_plots.plot_fit(model, plot_limits=None, which_data_rows='all', which_data_ycols='all', fixed_inputs=[], levels=20, samples=0, fignum=None, ax=None, resolution=None, plot_raw=False, linecol='#204a87', fillcol='#729fcf', Y_metadata=None, data_symbol='kx')[source]
    +
    +
    Plot the posterior of the GP.
    +
      +
    • In one dimension, the function is plotted with a shaded region identifying two standard deviations.
    • +
    • In two dimsensions, a contour-plot shows the mean predicted function
    • +
    • In higher dimensions, use fixed_inputs to plot the GP with some of the inputs fixed.
    • +
    +
    +
    +

    Can plot only part of the data and part of the posterior functions +using which_data_rowsm which_data_ycols.

    + +++ + + + +
    Parameters:
      +
    • plot_limits (np.array) – The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits
    • +
    • which_data_rows (‘all’ or a list of integers) – which of the training data to plot (default all)
    • +
    • which_data_ycols – when the data has several columns (independant outputs), only plot these
    • +
    • fixed_inputs (a list of tuples) – a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v.
    • +
    • resolution (int) – the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D
    • +
    • levels (int) – number of levels to plot in a contour plot.
    • +
    • samples (int) – the number of a posteriori samples to plot
    • +
    • fignum (figure number) – figure to plot on.
    • +
    • ax (axes handle) – axes to plot on.
    • +
    • linecol – color of line to plot.
    • +
    • fillcol – color of fill
    • +
    • levels – for 2D plotting, the number of contour levels to use is ax is None, create a new figure
    • +
    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.models_plots.plot_fit_f(model, *args, **kwargs)[source]
    +

    Plot the GP’s view of the world, where the data is normalized and before applying a likelihood.

    +

    All args and kwargs are passed on to models_plots.plot.

    +
    + +
    +
    +

    GPy.plotting.matplot_dep.netpbmfile module

    +

    Read and write image data from respectively to Netpbm files.

    +

    This implementation follows the Netpbm format specifications at +http://netpbm.sourceforge.net/doc/. No gamma correction is performed.

    +

    The following image formats are supported: PBM (bi-level), PGM (grayscale), +PPM (color), PAM (arbitrary), XV thumbnail (RGB332, read-only).

    + +++ + + + + + + + +
    Author:Christoph Gohlke
    Organization:Laboratory for Fluorescence Dynamics, University of California, Irvine
    Version:2013.01.18
    +
    +

    Requirements

    + +
    +
    +

    Examples

    +
    >>> im1 = numpy.array([[0, 1],[65534, 65535]], dtype=numpy.uint16)
    +>>> imsave('_tmp.pgm', im1)
    +>>> im2 = imread('_tmp.pgm')
    +>>> assert numpy.all(im1 == im2)
    +
    +
    +
    +
    +GPy.plotting.matplot_dep.netpbmfile.imread(filename, *args, **kwargs)[source]
    +

    Return image data from Netpbm file as numpy array.

    +

    args and kwargs are arguments to NetpbmFile.asarray().

    +
    >>> image = imread('_tmp.pgm')
    +
    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.netpbmfile.imsave(filename, data, maxval=None, pam=False)[source]
    +

    Write image data to Netpbm file.

    +
    >>> image = numpy.array([[0, 1],[65534, 65535]], dtype=numpy.uint16)
    +>>> imsave('_tmp.pgm', image)
    +
    +
    +
    + +
    +
    +class GPy.plotting.matplot_dep.netpbmfile.NetpbmFile(arg=None, **kwargs)[source]
    +

    Bases: object

    +

    Read and write Netpbm PAM, PBM, PGM, PPM, files.

    +
    +
    +asarray(copy=True, cache=False, **kwargs)[source]
    +

    Return image data from file as numpy array.

    +
    + +
    +
    +close()[source]
    +

    Close open file. Future asarray calls might fail.

    +
    + +
    +
    +write(arg, **kwargs)[source]
    +

    Write instance to file.

    +
    + +
    + +
    +
    +
    +

    GPy.plotting.matplot_dep.priors_plots module

    +
    +
    +GPy.plotting.matplot_dep.priors_plots.plot(prior)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.priors_plots.univariate_plot(prior)[source]
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.ssgplvm module

    +

    The module plotting results for SSGPLVM

    +
    +
    +class GPy.plotting.matplot_dep.ssgplvm.SSGPLVM_plot(model, imgsize)[source]
    +

    Bases: object

    +
    +
    +plot_inducing()[source]
    +
    + +
    + +
    +
    +

    GPy.plotting.matplot_dep.svig_plots module

    +
    +
    +GPy.plotting.matplot_dep.svig_plots.plot(model, ax=None, fignum=None, Z_height=None, **kwargs)[source]
    +
    + +
    +
    +GPy.plotting.matplot_dep.svig_plots.plot_traces(model)[source]
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.variational_plots module

    +
    +
    +GPy.plotting.matplot_dep.variational_plots.plot(parameterized, fignum=None, ax=None, colors=None)[source]
    +

    Plot latent space X in 1D:

    +
    +
      +
    • if fig is given, create input_dim subplots in fig and plot in these
    • +
    • if ax is given plot input_dim 1D latent space plots of X into each axis
    • +
    • if neither fig nor ax is given create a figure with fignum and plot in there
    • +
    +
    +
    +
    colors:
    +
    colors of different latent space dimensions input_dim
    +
    +
    + +
    +
    +GPy.plotting.matplot_dep.variational_plots.plot_SpikeSlab(parameterized, fignum=None, ax=None, colors=None, side_by_side=True)[source]
    +

    Plot latent space X in 1D:

    +
    +
      +
    • if fig is given, create input_dim subplots in fig and plot in these
    • +
    • if ax is given plot input_dim 1D latent space plots of X into each axis
    • +
    • if neither fig nor ax is given create a figure with fignum and plot in there
    • +
    +
    +
    +
    colors:
    +
    colors of different latent space dimensions input_dim
    +
    +
    + +
    +
    +

    GPy.plotting.matplot_dep.visualize module

    +
    +
    +GPy.plotting.matplot_dep.visualize.data_play(Y, visualizer, frame_rate=30)[source]
    +

    Play a data set using the data_show object given.

    + +++ + + + + + +
    Y:the data set to be visualized.
    Parameters:visualizer (data_show) – the data show objectwhether to display during optimisation
    +

    Example usage:

    +

    This example loads in the CMU mocap database (http://mocap.cs.cmu.edu) subject number 35 motion number 01. It then plays it using the mocap_show visualize object.

    +
    data = GPy.util.datasets.cmu_mocap(subject='35', train_motions=['01'])
    +Y = data['Y']
    +Y[:, 0:3] = 0.   # Make figure walk in place
    +visualize = GPy.util.visualize.skeleton_show(Y[0, :], data['skel'])
    +GPy.util.visualize.data_play(Y, visualize)
    +
    +
    +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.data_show(vals)[source]
    +

    The data_show class is a base class which describes how to visualize a +particular data set. For example, motion capture data can be plotted as a +stick figure, or images are shown using imshow. This class enables latent +to data visualizations for the GP-LVM.

    +
    +
    +close()[source]
    +
    + +
    +
    +modify(vals)[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.image_show(vals, axes=None, dimensions=(16, 16), transpose=False, order='C', invert=False, scale=False, palette=[], preset_mean=0.0, preset_std=1.0, select_image=0, cmap=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.matplotlib_show

    +

    Show a data vector as an image. This visualizer rehapes the output vector and displays it as an image.

    + +++ + + + +
    Parameters:
      +
    • vals (axes handle) – the values of the output to display.
    • +
    • axes – the axes to show the output on.
    • +
    • dimensions (tuple) – the dimensions that the image needs to be transposed to for display.
    • +
    • transpose – whether to transpose the image before display.
    • +
    • order (string) – whether array is in Fortan ordering (‘F’) or Python ordering (‘C’). Default is python (‘C’).
    • +
    • invert (bool) – whether to invert the pixels or not (default False).
    • +
    • palette – a palette to use for the image.
    • +
    • preset_mean (double) – the preset mean of a scaled image.
    • +
    • preset_std (double) – the preset standard deviation of a scaled image.
    • +
    • cmap (matplotlib.cm) – the colormap for image visualization
    • +
    +
    +
    +
    +modify(vals)[source]
    +
    + +
    +
    +set_image(vals)[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.lvm(vals, model, data_visualize, latent_axes=None, sense_axes=None, latent_index=[0, 1], disable_drag=False)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.matplotlib_show

    +
    +
    +modify(vals)[source]
    +

    When latent values are modified update the latent representation and ulso update the output visualization.

    +
    + +
    +
    +on_click(event)[source]
    +
    + +
    +
    +on_enter(event)[source]
    +
    + +
    +
    +on_leave(event)[source]
    +
    + +
    +
    +on_move(event)[source]
    +
    + +
    +
    +show_sensitivities()[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.lvm_dimselect(vals, model, data_visualize, latent_axes=None, sense_axes=None, latent_index=[0, 1], labels=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.lvm

    +

    A visualizer for latent variable models which allows selection of the latent dimensions to use by clicking on a bar chart of their length scales.

    +

    For an example of the visualizer’s use try:

    +

    GPy.examples.dimensionality_reduction.BGPVLM_oil()

    +
    +
    +on_click(event)[source]
    +
    + +
    +
    +on_leave(event)[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.lvm_subplots(vals, Model, data_visualize, latent_axes=None, sense_axes=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.lvm

    +

    latent_axes is a np array of dimension np.ceil(input_dim/2), +one for each pair of the latent dimensions.

    +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.matplotlib_show(vals, axes=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.data_show

    +

    the matplotlib_show class is a base class for all visualization methods that use matplotlib. It is initialized with an axis. If the axis is set to None it creates a figure window.

    +
    +
    +close()[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.mocap_data_show(vals, axes=None, connect=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.matplotlib_show

    +

    Base class for visualizing motion capture data.

    +
    +
    +draw_edges()[source]
    +
    + +
    +
    +draw_vertices()[source]
    +
    + +
    +
    +finalize_axes()[source]
    +
    + +
    +
    +finalize_axes_modify()[source]
    +
    + +
    +
    +initialize_axes(boundary=0.05)[source]
    +

    Set up the axes with the right limits and scaling.

    +
    + +
    +
    +initialize_axes_modify()[source]
    +
    + +
    +
    +modify(vals)[source]
    +
    + +
    +
    +process_values()[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.mocap_data_show_vpython(vals, scene=None, connect=None, radius=0.1)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.vpython_show

    +

    Base class for visualizing motion capture data using visual module.

    +
    +
    +draw_edges()[source]
    +
    + +
    +
    +draw_vertices()[source]
    +
    + +
    +
    +modify(vals)[source]
    +
    + +
    +
    +modify_edges()[source]
    +
    + +
    +
    +modify_vertices()[source]
    +
    + +
    +
    +pos_axis(i, j)[source]
    +
    + +
    +
    +process_values()[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.skeleton_show(vals, skel, axes=None, padding=0)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.mocap_data_show

    +

    data_show class for visualizing motion capture data encoded as a skeleton with angles.

    +
    +
    +process_values()[source]
    +

    Takes a set of angles and converts them to the x,y,z coordinates in the internal prepresentation of the class, ready for plotting.

    + +++ + + + +
    Parameters:vals – the values that are being modelled.
    +
    + +
    +
    +wrap_around(lim, connect)[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.stick_show(vals, connect=None, axes=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.mocap_data_show

    +

    Show a three dimensional point cloud as a figure. Connect elements of the figure together using the matrix connect.

    +
    +
    +process_values()[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.vector_show(vals, axes=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.matplotlib_show

    +

    A base visualization class that just shows a data vector as a plot of +vector elements alongside their indices.

    +
    +
    +modify(vals)[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.visualize.vpython_show(vals, scene=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.visualize.data_show

    +

    the vpython_show class is a base class for all visualization methods that use vpython to display. It is initialized with a scene. If the scene is set to None it creates a scene window.

    +
    +
    +close()[source]
    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.html b/doc/_build/html/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.html new file mode 100644 index 00000000..3e12c5a6 --- /dev/null +++ b/doc/_build/html/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.html @@ -0,0 +1,260 @@ + + + + + + + + GPy.plotting.matplot_dep.latent_space_visualizations.controllers package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.plotting.matplot_dep.latent_space_visualizations.controllers package

    +
    +

    Submodules

    +
    +
    +

    GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller module

    +

    Created on 24 Jul 2013

    +

    @author: maxz

    +
    +
    +class GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller.AxisChangedController(ax, update_lim=None)[source]
    +

    Bases: GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller.AxisEventController

    +

    Buffered control of axis limit changes

    +
    +
    +extent(lim)[source]
    +
    + +
    +
    +lim_changed(axlim, savedlim)[source]
    +
    + +
    +
    +update(ax)[source]
    +
    + +
    +
    +xlim_changed(ax)[source]
    +
    + +
    +
    +ylim_changed(ax)[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller.AxisEventController(ax)[source]
    +

    Bases: object

    +
    +
    +activate()[source]
    +
    + +
    +
    +deactivate()[source]
    +
    + +
    +
    +xlim_changed(ax)[source]
    +
    + +
    +
    +ylim_changed(ax)[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller.BufferedAxisChangedController(ax, plot_function, plot_limits, resolution=50, update_lim=None, **kwargs)[source]
    +

    Bases: GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller.AxisChangedController

    +
    +
    +get_grid(buffered=True)[source]
    +
    + +
    +
    +recompute_X(buffered=True)[source]
    +
    + +
    +
    +update(ax)[source]
    +
    + +
    +
    +update_view(view, X, xmin, xmax, ymin, ymax)[source]
    +
    + +
    + +
    +
    +

    GPy.plotting.matplot_dep.latent_space_visualizations.controllers.imshow_controller module

    +

    Created on 24 Jul 2013

    +

    @author: maxz

    +
    +
    +class GPy.plotting.matplot_dep.latent_space_visualizations.controllers.imshow_controller.ImAnnotateController(ax, plot_function, plot_limits, resolution=20, update_lim=0.99, **kwargs)[source]
    +

    Bases: GPy.plotting.matplot_dep.latent_space_visualizations.controllers.imshow_controller.ImshowController

    +
    +
    +update_view(view, X, xmin, xmax, ymin, ymax)[source]
    +
    + +
    + +
    +
    +class GPy.plotting.matplot_dep.latent_space_visualizations.controllers.imshow_controller.ImshowController(ax, plot_function, plot_limits, resolution=50, update_lim=0.8, **kwargs)[source]
    +

    Bases: GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller.BufferedAxisChangedController

    +
    +
    +update_view(view, X, xmin, xmax, ymin, ymax)[source]
    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.plotting.matplot_dep.latent_space_visualizations.html b/doc/_build/html/GPy.plotting.matplot_dep.latent_space_visualizations.html new file mode 100644 index 00000000..44909eaa --- /dev/null +++ b/doc/_build/html/GPy.plotting.matplot_dep.latent_space_visualizations.html @@ -0,0 +1,151 @@ + + + + + + + + GPy.plotting.matplot_dep.latent_space_visualizations package — GPy documentation + + + + + + + + + + + + + + + + +
    + + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.testing.html b/doc/_build/html/GPy.testing.html new file mode 100644 index 00000000..286b4ddb --- /dev/null +++ b/doc/_build/html/GPy.testing.html @@ -0,0 +1,1282 @@ + + + + + + + + GPy.testing package — GPy documentation + + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.testing package

    +
    +

    Submodules

    +
    +
    +

    GPy.testing.examples_tests module

    +
    +
    +class GPy.testing.examples_tests.ExamplesTests(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    + +
    +
    +GPy.testing.examples_tests.flatten_nested(lst)[source]
    +
    + +
    +
    +GPy.testing.examples_tests.model_checkgrads(model)[source]
    +
    + +
    +
    +GPy.testing.examples_tests.model_instance(model)[source]
    +
    + +
    +
    +GPy.testing.examples_tests.test_models()[source]
    +
    + +
    +
    +

    GPy.testing.fitc module

    +
    +
    +class GPy.testing.fitc.FITCtest(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_fitc_1d()[source]
    +
    + +
    +
    +test_fitc_2d()[source]
    +
    + +
    + +
    +
    +

    GPy.testing.index_operations_tests module

    +
    +
    +class GPy.testing.index_operations_tests.Test(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_clear()[source]
    +
    + +
    +
    +test_index_view()[source]
    +
    + +
    +
    +test_indexview_remove()[source]
    +
    + +
    +
    +test_misc()[source]
    +
    + +
    +
    +test_print()[source]
    +
    + +
    +
    +test_remove()[source]
    +
    + +
    +
    +test_shift_left()[source]
    +
    + +
    +
    +test_shift_right()[source]
    +
    + +
    +
    +test_view_of_view()[source]
    +
    + +
    + +
    +
    +

    GPy.testing.inference_tests module

    +

    The test cases for various inference algorithms

    +
    +
    +class GPy.testing.inference_tests.InferenceXTestCase(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +genData()[source]
    +
    + +
    +
    +test_inferenceX_BGPLVM()[source]
    +
    + +
    +
    +test_inferenceX_GPLVM()[source]
    +
    + +
    + +
    +
    +

    GPy.testing.kernel_tests module

    +
    +
    +class GPy.testing.kernel_tests.Coregionalize_weave_test(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +

    Make sure that the coregionalize kernel work with and without weave enabled

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_nonsym()[source]
    +
    + +
    +
    +test_sym()[source]
    +
    + +
    + +
    +
    +class GPy.testing.kernel_tests.Kern_check_dK_dX(kernel=None, dL_dK=None, X=None, X2=None)[source]
    +

    Bases: GPy.testing.kernel_tests.Kern_check_model

    +

    This class allows gradient checks for the gradient of a kernel with respect to X.

    +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +class GPy.testing.kernel_tests.Kern_check_dK_dtheta(kernel=None, dL_dK=None, X=None, X2=None)[source]
    +

    Bases: GPy.testing.kernel_tests.Kern_check_model

    +

    This class allows gradient checks for the gradient of a kernel with +respect to parameters.

    +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +class GPy.testing.kernel_tests.Kern_check_dKdiag_dX(kernel=None, dL_dK=None, X=None, X2=None)[source]
    +

    Bases: GPy.testing.kernel_tests.Kern_check_dK_dX

    +

    This class allows gradient checks for the gradient of a kernel diagonal with respect to X.

    +
    +
    +log_likelihood()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +class GPy.testing.kernel_tests.Kern_check_dKdiag_dtheta(kernel=None, dL_dK=None, X=None)[source]
    +

    Bases: GPy.testing.kernel_tests.Kern_check_model

    +

    This class allows gradient checks of the gradient of the diagonal of a +kernel with respect to the parameters.

    +
    +
    +log_likelihood()[source]
    +
    + +
    +
    +parameters_changed()[source]
    +
    + +
    + +
    +
    +class GPy.testing.kernel_tests.Kern_check_model(kernel=None, dL_dK=None, X=None, X2=None)[source]
    +

    Bases: GPy.core.model.Model

    +

    This is a dummy model class used as a base class for checking that the +gradients of a given kernel are implemented correctly. It enables +checkgrad() to be called independently on a kernel.

    +
    +
    +is_positive_semi_definite()[source]
    +
    + +
    +
    +log_likelihood()[source]
    +
    + +
    + +
    +
    +class GPy.testing.kernel_tests.KernelGradientTestsContinuous(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_Add()[source]
    +
    + +
    +
    +test_Add_dims()[source]
    +
    + +
    +
    +test_Linear()[source]
    +
    + +
    +
    +test_LinearFull()[source]
    +
    + +
    +
    +test_Matern32()[source]
    +
    + +
    +
    +test_Matern52()[source]
    +
    + +
    +
    +test_Prod()[source]
    +
    + +
    +
    +test_Prod2()[source]
    +
    + +
    +
    +test_Prod3()[source]
    +
    + +
    +
    +test_RBF()[source]
    +
    + +
    + +
    +
    +class GPy.testing.kernel_tests.KernelTestsMiscellaneous(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_which_parts()[source]
    +
    + +
    + +
    +
    +class GPy.testing.kernel_tests.KernelTestsNonContinuous(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_Hierarchical()[source]
    +
    + +
    +
    +test_IndependentOutputs()[source]
    +
    + +
    +
    +test_ODE_UY()[source]
    +
    + +
    + +
    +
    +GPy.testing.kernel_tests.check_kernel_gradient_functions(kern, X=None, X2=None, output_ind=None, verbose=False, fixed_X_dims=None)[source]
    +

    This function runs on kernels to check the correctness of their +implementation. It checks that the covariance function is positive definite +for a randomly generated data set.

    + +++ + + + +
    Parameters:
      +
    • kern (GPy.kern.Kernpart) – the kernel to be tested.
    • +
    • X (ndarray) – X input values to test the covariance function.
    • +
    • X2 (ndarray) – X2 input values to test the covariance function.
    • +
    +
    +
    + +
    +
    +

    GPy.testing.likelihood_tests module

    +
    +
    +class GPy.testing.likelihood_tests.LaplaceTests(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +

    Specific likelihood tests, not general enough for the above tests

    +
    +
    +setUp()[source]
    +
    + +
    +
    +tearDown()[source]
    +
    + +
    +
    +test_gaussian_d2logpdf_df2_2()[source]
    +
    + +
    +
    +test_laplace_log_likelihood()[source]
    +
    + +
    + +
    +
    +class GPy.testing.likelihood_tests.TestNoiseModels[source]
    +

    Bases: object

    +

    Generic model checker

    +
    +
    +setUp()[source]
    +
    + +
    +
    +t_d2logpdf2_df2_dparams(model, Y, f, params, params_names, param_constraints)[source]
    +
    + +
    +
    +t_d2logpdf2_dlink2_dparams(model, Y, f, params, param_names, param_constraints)[source]
    +
    + +
    +
    +t_d2logpdf_df2(model, Y, f)[source]
    +
    + +
    +
    +t_d2logpdf_dlink2(model, Y, f, link_f_constraints)[source]
    +
    + +
    +
    +t_d3logpdf_df3(model, Y, f)[source]
    +
    + +
    +
    +t_d3logpdf_dlink3(model, Y, f, link_f_constraints)[source]
    +
    + +
    +
    +t_dlogpdf_df(model, Y, f)[source]
    +
    + +
    +
    +t_dlogpdf_df_dparams(model, Y, f, params, params_names, param_constraints)[source]
    +
    + +
    + +
    + +
    + +
    + +
    +
    +t_dlogpdf_dparams(model, Y, f, params, params_names, param_constraints)[source]
    +
    + +
    + +
    + +
    +
    +t_ep_fit_rbf_white(model, X, Y, f, step, param_vals, param_names, constraints)[source]
    +
    + +
    +
    +t_laplace_fit_rbf_white(model, X, Y, f, step, param_vals, param_names, constraints)[source]
    +
    + +
    +
    +t_logpdf(model, Y, f)[source]
    +
    + +
    +
    +tearDown()[source]
    +
    + +
    +
    +test_scale2_models()[source]
    +
    + +
    + +
    +
    +GPy.testing.likelihood_tests.dparam_checkgrad(func, dfunc, params, params_names, args, constraints=None, randomize=False, verbose=False)[source]
    +

    checkgrad expects a f: R^N -> R^1 and df: R^N -> R^N +However if we are holding other parameters fixed and moving something else +We need to check the gradient of each of the fixed parameters +(f and y for example) seperately, whilst moving another parameter. +Otherwise f: gives back R^N and

    +
    +
    df: gives back R^NxM where M is
    +

    The number of parameters and N is the number of data +Need to take a slice out from f and a slice out of df

    +
    + +
    +
    +GPy.testing.likelihood_tests.dparam_partial(inst_func, *args)[source]
    +

    If we have a instance method that needs to be called but that doesn’t +take the parameter we wish to change to checkgrad, then this function +will change the variable using set params.

    +
    +
    inst_func: should be a instance function of an object that we would like
    +
    to change
    +
    +

    param: the param that will be given to set_params +args: anything else that needs to be given to the function (for example

    +
    +
    the f or Y that are being used in the function whilst we tweak the +param
    +
    + +
    +
    +

    GPy.testing.model_tests module

    +
    +
    +class GPy.testing.model_tests.GradientTests(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +check_model(kern, model_type='GPRegression', dimension=1, uncertain_inputs=False)[source]
    +
    + +
    +
    +setUp()[source]
    +
    + +
    +
    +test_GPLVM_rbf_bias_white_kern_2D()[source]
    +

    Testing GPLVM with rbf + bias kernel

    +
    + +
    +
    +test_GPLVM_rbf_linear_white_kern_2D()[source]
    +

    Testing GPLVM with rbf + bias kernel

    +
    + +
    +
    +test_GPRegression_bias_kern_1D()[source]
    +

    Testing the GP regression with bias kernel on 1d data

    +
    + +
    +
    +test_GPRegression_bias_kern_2D()[source]
    +

    Testing the GP regression with bias kernel on 2d data

    +
    + +
    +
    +test_GPRegression_exponential_1D()[source]
    +

    Testing the GP regression with exponential kernel on 1d data

    +
    + +
    +
    +test_GPRegression_exponential_2D()[source]
    +

    Testing the GP regression with exponential kernel on 2d data

    +
    + +
    +
    +test_GPRegression_exponential_ARD_2D()[source]
    +

    Testing the GP regression with exponential kernel on 2d data

    +
    + +
    +
    +test_GPRegression_linear_kern_1D()[source]
    +

    Testing the GP regression with linear kernel on 1d data

    +
    + +
    +
    +test_GPRegression_linear_kern_1D_ARD()[source]
    +

    Testing the GP regression with linear kernel on 1d data

    +
    + +
    +
    +test_GPRegression_linear_kern_2D()[source]
    +

    Testing the GP regression with linear kernel on 2d data

    +
    + +
    +
    +test_GPRegression_linear_kern_2D_ARD()[source]
    +

    Testing the GP regression with linear kernel on 2d data

    +
    + +
    +
    +test_GPRegression_matern32_1D()[source]
    +

    Testing the GP regression with matern32 kernel on 1d data

    +
    + +
    +
    +test_GPRegression_matern32_2D()[source]
    +

    Testing the GP regression with matern32 kernel on 2d data

    +
    + +
    +
    +test_GPRegression_matern32_ARD_2D()[source]
    +

    Testing the GP regression with matern32 kernel on 2d data

    +
    + +
    +
    +test_GPRegression_matern52_1D()[source]
    +

    Testing the GP regression with matern52 kernel on 1d data

    +
    + +
    +
    +test_GPRegression_matern52_2D()[source]
    +

    Testing the GP regression with matern52 kernel on 2d data

    +
    + +
    +
    +test_GPRegression_matern52_ARD_2D()[source]
    +

    Testing the GP regression with matern52 kernel on 2d data

    +
    + +
    +
    +test_GPRegression_mlp_1d()[source]
    +

    Testing the GP regression with mlp kernel with white kernel on 1d data

    +
    + +
    +
    +test_GPRegression_rbf_1d()[source]
    +

    Testing the GP regression with rbf kernel with white kernel on 1d data

    +
    + +
    +
    +test_GPRegression_rbf_2D()[source]
    +

    Testing the GP regression with rbf kernel on 2d data

    +
    + +
    +
    +test_GPRegression_rbf_ARD_2D()[source]
    +

    Testing the GP regression with rbf kernel on 2d data

    +
    + +
    +
    +test_GP_EP_probit()[source]
    +
    + +
    +
    +test_SparseGPRegression_rbf_linear_white_kern_1D()[source]
    +

    Testing the sparse GP regression with rbf kernel on 2d data

    +
    + +
    +
    +test_SparseGPRegression_rbf_linear_white_kern_1D_uncertain_inputs()[source]
    +

    Testing the sparse GP regression with rbf, linear kernel on 1d data with uncertain inputs

    +
    + +
    +
    +test_SparseGPRegression_rbf_linear_white_kern_2D()[source]
    +

    Testing the sparse GP regression with rbf kernel on 2d data

    +
    + +
    +
    +test_SparseGPRegression_rbf_linear_white_kern_2D_uncertain_inputs()[source]
    +

    Testing the sparse GP regression with rbf, linear kernel on 2d data with uncertain inputs

    +
    + +
    +
    +test_SparseGPRegression_rbf_white_kern_1d()[source]
    +

    Testing the sparse GP regression with rbf kernel with white kernel on 1d data

    +
    + +
    +
    +test_SparseGPRegression_rbf_white_kern_2D()[source]
    +

    Testing the sparse GP regression with rbf kernel on 2d data

    +
    + +
    +
    +test_generalized_FITC(*args, **kwargs)[source]
    +
    + +
    +
    +test_gp_VGPC()[source]
    +
    + +
    +
    +test_gp_heteroscedastic_regression()[source]
    +
    + +
    +
    +test_gp_kronecker_gaussian()[source]
    +
    + +
    +
    +test_multioutput_regression_1D(*args, **kwargs)[source]
    +
    + +
    +
    +test_multioutput_sparse_regression_1D(*args, **kwargs)[source]
    +
    + +
    +
    +test_sparse_EP_DTC_probit()[source]
    +
    + +
    +
    +test_sparse_gp_heteroscedastic_regression()[source]
    +
    + +
    + +
    +
    +class GPy.testing.model_tests.MiscTests(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_big_model()[source]
    +
    + +
    +
    +test_likelihood_replicate()[source]
    +
    + +
    +
    +test_likelihood_replicate_kern()[source]
    +
    + +
    +
    +test_likelihood_set()[source]
    +
    + +
    +
    +test_missing_data()[source]
    +
    + +
    +
    +test_model_optimize()[source]
    +
    + +
    +
    +test_model_set_params()[source]
    +
    + +
    +
    +test_raw_predict()[source]
    +
    + +
    +
    +test_sparse_raw_predict()[source]
    +
    + +
    + +
    +
    +

    GPy.testing.observable_tests module

    +
    +
    +class GPy.testing.observable_tests.ParamTestParent(name=None, parameters=[], *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +parent_changed_count = -1
    +
    + +
    + +
    +
    +class GPy.testing.observable_tests.ParameterizedTest(name=None, parameters=[], *a, **kw)[source]
    +

    Bases: GPy.core.parameterization.parameterized.Parameterized

    +
    +
    +parameters_changed()[source]
    +
    + +
    +
    +params_changed_count = -1
    +
    + +
    + +
    +
    +class GPy.testing.observable_tests.Test(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_observable()[source]
    +
    + +
    +
    +test_priority()[source]
    +
    + +
    +
    +test_priority_notify()[source]
    +
    + +
    +
    +test_set_params()[source]
    +
    + +
    + +
    +
    +

    GPy.testing.parameterized_tests module

    +

    Created on Feb 13, 2014

    +

    @author: maxzwiessele

    +
    +
    +class GPy.testing.parameterized_tests.ArrayCoreTest(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_init()[source]
    +
    + +
    +
    +test_slice()[source]
    +
    + +
    + +
    +
    +class GPy.testing.parameterized_tests.ParameterizedTest(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +setUp()[source]
    +
    + +
    +
    +test_add_parameter()[source]
    +
    + +
    +
    +test_add_parameter_already_in_hirarchy()[source]
    +
    + +
    +
    +test_add_parameter_in_hierarchy()[source]
    +
    + +
    +
    +test_constraints()[source]
    +
    + +
    +
    +test_constraints_in_init()[source]
    +
    + +
    + +
    + +
    +
    +test_constraints_views()[source]
    +
    + +
    +
    +test_default_constraints()[source]
    +
    + +
    +
    +test_fix_unfix()[source]
    +
    + +
    +
    +test_fixes()[source]
    +
    + +
    +
    +test_fixing_optimize()[source]
    +
    + +
    +
    +test_fixing_randomize()[source]
    +
    + +
    +
    +test_fixing_randomize_parameter_handling()[source]
    +
    + +
    +
    +test_parameter_modify_in_init()[source]
    +
    + +
    +
    +test_printing()[source]
    +
    + +
    +
    +test_randomize()[source]
    +
    + +
    +
    +test_regular_expression_misc()[source]
    +
    + +
    +
    +test_remove_parameter()[source]
    +
    + +
    +
    +test_remove_parameter_param_array_grad_array()[source]
    +
    + +
    +
    +test_updates()[source]
    +
    + +
    + +
    +
    +

    GPy.testing.pickle_tests module

    +

    Created on 13 Mar 2014

    +

    @author: maxz

    +
    +
    +class GPy.testing.pickle_tests.ListDictTestCase(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +assertArrayListEquals(l1, l2)[source]
    +
    + +
    +
    +assertListDictEquals(d1, d2, msg=None)[source]
    +
    + +
    + +
    +
    +class GPy.testing.pickle_tests.Test(methodName='runTest')[source]
    +

    Bases: GPy.testing.pickle_tests.ListDictTestCase

    +
    +
    +test_add_observer(test_item)
    +
    + +
    +
    +test_model()[source]
    +
    + +
    +
    +test_model_concat()[source]
    +
    + +
    +
    +test_modelrecreation()[source]
    +
    + +
    +
    +test_observable_array()[source]
    +
    + +
    +
    +test_param()[source]
    +
    + +
    +
    +test_parameter_index_operations()[source]
    +
    + +
    +
    +test_parameterized()[source]
    +
    + +
    +
    +test_posterior()[source]
    +
    + +
    + +
    +
    +GPy.testing.pickle_tests.toy_model()[source]
    +
    + +
    +
    +

    GPy.testing.prior_tests module

    +
    +
    +class GPy.testing.prior_tests.PriorTests(methodName='runTest')[source]
    +

    Bases: unittest.case.TestCase

    +
    +
    +test_Gamma()[source]
    +
    + +
    +
    +test_fixed_domain_check()[source]
    +
    + +
    +
    +test_fixed_domain_check1()[source]
    +
    + +
    +
    +test_incompatibility()[source]
    +
    + +
    +
    +test_lognormal()[source]
    +
    + +
    +
    +test_set_gaussian_for_reals()[source]
    +
    + +
    +
    +test_set_prior()[source]
    +
    + +
    + +
    +
    +

    Module contents

    +

    MaxZ

    +
    +
    +GPy.testing.deepTest(reason)[source]
    +
    + +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/GPy.util.html b/doc/_build/html/GPy.util.html new file mode 100644 index 00000000..d057ac00 --- /dev/null +++ b/doc/_build/html/GPy.util.html @@ -0,0 +1,2085 @@ + + + + + + + + GPy.util package — GPy documentation + + + + + + + + + + + + + + + +
    +
    +
    +
    + +
    +

    GPy.util package

    +
    +

    Submodules

    +
    +
    +

    GPy.util.block_matrices module

    +
    +
    +GPy.util.block_matrices.get_blocks(A, blocksizes)[source]
    +
    + +
    +
    +

    GPy.util.caching module

    +
    +
    +class GPy.util.caching.Cache_this(limit=5, ignore_args=(), force_kwargs=())[source]
    +

    Bases: object

    +

    A decorator which can be applied to bound methods in order to cache them

    +
    + +
    +
    +class GPy.util.caching.Cacher(operation, limit=5, ignore_args=(), force_kwargs=())[source]
    +

    Bases: object

    +
    +
    +add_to_cache(cache_id, inputs, output)[source]
    +

    This adds cache_id to the cache, with inputs and output

    +
    + +
    +
    +combine_inputs(args, kw, ignore_args)[source]
    +

    Combines the args and kw in a unique way, such that ordering of kwargs does not lead to recompute

    +
    + +
    +
    +ensure_cache_length(cache_id)[source]
    +

    Ensures the cache is within its limits and has one place free

    +
    + +
    +
    +id(obj)[source]
    +

    returns the self.id of an object, to be used in caching individual self.ids

    +
    + +
    +
    +on_cache_changed(direct, which=None)[source]
    +

    A callback funtion, which sets local flags when the elements of some cached inputs change

    +

    this function gets ‘hooked up’ to the inputs when we cache them, and upon their elements being changed we update here.

    +
    + +
    +
    +prepare_cache_id(combined_args_kw)[source]
    +

    get the cacheid (conc. string of argument self.ids in order)

    +
    + +
    +
    +reset()[source]
    +

    Totally reset the cache

    +
    + +
    + +
    +
    +class GPy.util.caching.Cacher_wrap(f, limit, ignore_args, force_kwargs)[source]
    +

    Bases: object

    +
    + +
    +
    +

    GPy.util.classification module

    +
    +
    +GPy.util.classification.conf_matrix(p, labels, names=['1', '0'], threshold=0.5, show=True)[source]
    +

    Returns error rate and true/false positives in a binary classification problem +- Actual classes are displayed by column. +- Predicted classes are displayed by row.

    + +++ + + + +
    Parameters:
      +
    • p – array of class ‘1’ probabilities.
    • +
    • labels – array of actual classes.
    • +
    • names – list of class names, defaults to [‘1’,‘0’].
    • +
    • threshold – probability value used to decide the class.
    • +
    • show (False|True) – whether the matrix should be shown or not
    • +
    +
    +
    + +
    +
    +

    GPy.util.config module

    +
    +
    +

    GPy.util.datasets module

    +
    +
    +GPy.util.datasets.authorize_download(dataset_name=None)[source]
    +

    Check with the user that the are happy with terms and conditions for the data set.

    +
    + +
    +
    +GPy.util.datasets.boston_housing(data_set='boston_housing')[source]
    +
    + +
    +
    +GPy.util.datasets.boxjenkins_airline(data_set='boxjenkins_airline', num_train=96)[source]
    +
    + +
    +
    +GPy.util.datasets.brendan_faces(data_set='brendan_faces')[source]
    +
    + +
    +
    +GPy.util.datasets.cifar10_patches(data_set='cifar-10')[source]
    +

    The Candian Institute for Advanced Research 10 image data set. Code for loading in this data is taken from this Boris Babenko’s blog post, original code available here: http://bbabenko.tumblr.com/post/86756017649/learning-low-level-vision-feautres-in-10-lines-of-code

    +
    + +
    +
    +GPy.util.datasets.cmu_mocap(subject, train_motions, test_motions=[], sample_every=4, data_set='cmu_mocap')[source]
    +

    Load a given subject’s training and test motions from the CMU motion capture data.

    +
    + +
    +
    +GPy.util.datasets.cmu_mocap_35_walk_jog(data_set='cmu_mocap')[source]
    +

    Load CMU subject 35’s walking and jogging motions, the same data that was used by Taylor, Roweis and Hinton at NIPS 2007. but without their preprocessing. Also used by Lawrence at AISTATS 2007.

    +
    + +
    +
    +GPy.util.datasets.cmu_mocap_49_balance(data_set='cmu_mocap')[source]
    +

    Load CMU subject 49’s one legged balancing motion that was used by Alvarez, Luengo and Lawrence at AISTATS 2009.

    +
    + +
    +
    +GPy.util.datasets.cmu_urls_files(subj_motions, messages=True)[source]
    +

    Find which resources are missing on the local disk for the requested CMU motion capture motions.

    +
    + +
    +
    +GPy.util.datasets.creep_data(data_set='creep_rupture')[source]
    +

    Brun and Yoshida’s metal creep rupture data.

    +
    + +
    +
    +GPy.util.datasets.crescent_data(num_data=200, seed=10000)[source]
    +

    Data set formed from a mixture of four Gaussians. In each class two of the Gaussians are elongated at right angles to each other and offset to form an approximation to the crescent data that is popular in semi-supervised learning as a toy problem.

    +
    +
    +++ + + + + + + + + + + +
    param num_data_part:
     number of data to be sampled (default is 200).
    type num_data:int
    param seed:random seed to be used for data generation.
    type seed:int
    +
    +
    + +
    +
    +GPy.util.datasets.data_available(dataset_name=None)[source]
    +

    Check if the data set is available on the local machine already.

    +
    + +
    +
    +GPy.util.datasets.data_details_return(data, data_set)[source]
    +

    Update the data component of the data dictionary with details drawn from the data_resources.

    +
    + +
    +
    +GPy.util.datasets.decampos_digits(data_set='decampos_characters', which_digits=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[source]
    +
    + +
    +
    +GPy.util.datasets.della_gatta_TRP63_gene_expression(data_set='della_gatta', gene_number=None)[source]
    +
    + +
    +
    +GPy.util.datasets.download_data(dataset_name=None)[source]
    +

    Check with the user that the are happy with terms and conditions for the data set, then download it.

    +
    + +
    +
    +GPy.util.datasets.download_rogers_girolami_data(data_set='rogers_girolami_data')[source]
    +
    + +
    +
    +GPy.util.datasets.download_url(url, store_directory, save_name=None, messages=True, suffix='')[source]
    +

    Download a file from a url and save it to disk.

    +
    + +
    +
    +GPy.util.datasets.drosophila_knirps(data_set='drosophila_protein')[source]
    +
    + +
    +
    +GPy.util.datasets.drosophila_protein(data_set='drosophila_protein')[source]
    +
    + +
    +
    +GPy.util.datasets.football_data(season='1314', data_set='football_data')[source]
    +

    Football data from English games since 1993. This downloads data from football-data.co.uk for the given season.

    +
    + +
    +
    +GPy.util.datasets.fruitfly_tomancak(data_set='fruitfly_tomancak', gene_number=None)[source]
    +
    + +
    +
    +GPy.util.datasets.global_average_temperature(data_set='global_temperature', num_train=1000, refresh_data=False)[source]
    +
    + +
    + +

    Data downloaded from Google trends for given query terms. Warning, if you use this function multiple times in a row you get blocked due to terms of service violations. The function will cache the result of your query, if you wish to refresh an old query set refresh_data to True. The function is inspired by this notebook: http://nbviewer.ipython.org/github/sahuguet/notebooks/blob/master/GoogleTrends%20meet%20Notebook.ipynb

    +
    + +
    +
    +GPy.util.datasets.hapmap3(data_set='hapmap3')[source]
    +

    The HapMap phase three SNP dataset - 1184 samples out of 11 populations.

    +

    SNP_matrix (A) encoding [see Paschou et all. 2007 (PCA-Correlated SNPs...)]: +Let (B1,B2) be the alphabetically sorted bases, which occur in the j-th SNP, then

    +
    +
    / 1, iff SNPij==(B1,B1)
    +
    +
    Aij = | 0, iff SNPij==(B1,B2)
    +
    -1, iff SNPij==(B2,B2)
    +
    +

    The SNP data and the meta information (such as iid, sex and phenotype) are +stored in the dataframe datadf, index is the Individual ID, +with following columns for metainfo:

    +
    +
      +
    • family_id -> Family ID
    • +
    • paternal_id -> Paternal ID
    • +
    • maternal_id -> Maternal ID
    • +
    • sex -> Sex (1=male; 2=female; other=unknown)
    • +
    • phenotype -> Phenotype (-9, or 0 for unknown)
    • +
    • population -> Population string (e.g. ‘ASW’ - ‘YRI’)
    • +
    • rest are SNP rs (ids)
    • +
    +
    +

    More information is given in infodf:

    +
    +
      +
    • +
      Chromosome:
      +
        +
      • autosomal chromosemes -> 1-22
      • +
      • X X chromosome -> 23
      • +
      • Y Y chromosome -> 24
      • +
      • XY Pseudo-autosomal region of X -> 25
      • +
      • MT Mitochondrial -> 26
      • +
      +
      +
      +
    • +
    • Relative Positon (to Chromosome) [base pairs]

      +
    • +
    +
    +
    + +
    +
    +GPy.util.datasets.isomap_faces(num_samples=698, data_set='isomap_face_data')[source]
    +
    + +
    +
    +GPy.util.datasets.lee_yeast_ChIP(data_set='lee_yeast_ChIP')[source]
    +
    + +
    +
    +GPy.util.datasets.mauna_loa(data_set='mauna_loa', num_train=545, refresh_data=False)[source]
    +
    + +
    +
    +GPy.util.datasets.oil(data_set='three_phase_oil_flow')[source]
    +

    The three phase oil data from Bishop and James (1993).

    +
    + +
    +
    +GPy.util.datasets.oil_100(seed=10000, data_set='three_phase_oil_flow')[source]
    +
    + +
    +
    +GPy.util.datasets.olivetti_faces(data_set='olivetti_faces')[source]
    +
    + +
    +
    +GPy.util.datasets.olivetti_glasses(data_set='olivetti_glasses', num_training=200, seed=10000)[source]
    +
    + +
    +
    +GPy.util.datasets.olympic_100m_men(data_set='rogers_girolami_data')[source]
    +
    + +
    +
    +GPy.util.datasets.olympic_100m_women(data_set='rogers_girolami_data')[source]
    +
    + +
    +
    +GPy.util.datasets.olympic_200m_men(data_set='rogers_girolami_data')[source]
    +
    + +
    +
    +GPy.util.datasets.olympic_200m_women(data_set='rogers_girolami_data')[source]
    +
    + +
    +
    +GPy.util.datasets.olympic_400m_men(data_set='rogers_girolami_data')[source]
    +
    + +
    +
    +GPy.util.datasets.olympic_400m_women(data_set='rogers_girolami_data')[source]
    +
    + +
    +
    +GPy.util.datasets.olympic_marathon_men(data_set='olympic_marathon_men')[source]
    +
    + +
    +
    +GPy.util.datasets.olympic_sprints(data_set='rogers_girolami_data')[source]
    +

    All olympics sprint winning times for multiple output prediction.

    +
    + +
    +
    +GPy.util.datasets.osu_run1(data_set='osu_run1', sample_every=4)[source]
    +
    + +
    +
    +GPy.util.datasets.prompt_user(prompt)[source]
    +

    Ask user for agreeing to data set licenses.

    +
    + +
    +
    +GPy.util.datasets.pumadyn(seed=10000, data_set='pumadyn-32nm')[source]
    +
    + +
    +
    +GPy.util.datasets.reporthook(a, b, c)[source]
    +
    + +
    +
    +GPy.util.datasets.ripley_synth(data_set='ripley_prnn_data')[source]
    +
    + +
    +
    +GPy.util.datasets.robot_wireless(data_set='robot_wireless')[source]
    +
    + +
    +
    +GPy.util.datasets.sample_class(f)[source]
    +
    + +
    +
    +GPy.util.datasets.silhouette(data_set='ankur_pose_data')[source]
    +
    + +
    +
    +GPy.util.datasets.simulation_BGPLVM()[source]
    +
    + +
    +
    +GPy.util.datasets.singlecell(data_set='singlecell')[source]
    +
    + +
    +
    +GPy.util.datasets.singlecell_rna_seq_deng(dataset='singlecell_deng')[source]
    +
    + +
    +
    +GPy.util.datasets.singlecell_rna_seq_islam(dataset='singlecell_islam')[source]
    +
    + +
    +
    +GPy.util.datasets.sod1_mouse(data_set='sod1_mouse')[source]
    +
    + +
    +
    +GPy.util.datasets.spellman_yeast(data_set='spellman_yeast')[source]
    +
    + +
    +
    +GPy.util.datasets.spellman_yeast_cdc15(data_set='spellman_yeast')[source]
    +
    + +
    +
    +GPy.util.datasets.swiss_roll(num_samples=3000, data_set='swiss_roll')[source]
    +
    + +
    +
    +GPy.util.datasets.swiss_roll_1000()[source]
    +
    + +
    +
    +GPy.util.datasets.swiss_roll_generated(num_samples=1000, sigma=0.0)[source]
    +
    + +
    +
    +GPy.util.datasets.toy_linear_1d_classification(seed=10000)[source]
    +
    + +
    +
    +GPy.util.datasets.toy_rbf_1d(seed=10000, num_samples=500)[source]
    +

    Samples values of a function from an RBF covariance with very small noise for inputs uniformly distributed between -1 and 1.

    + +++ + + + +
    Parameters:
      +
    • seed (int) – seed to use for random sampling.
    • +
    • num_samples (int) – number of samples to sample in the function (default 500).
    • +
    +
    +
    + +
    +
    +GPy.util.datasets.toy_rbf_1d_50(seed=10000)[source]
    +
    + +
    +
    +GPy.util.datasets.xw_pen(data_set='xw_pen')[source]
    +
    + +
    +
    +

    GPy.util.debug module

    +

    The module for some general debug tools

    +
    +
    +GPy.util.debug.checkFinite(arr, name=None)[source]
    +
    + +
    +
    +GPy.util.debug.checkFullRank(m, tol=1e-10, name=None, force_check=False)[source]
    +
    + +
    +
    +

    GPy.util.decorators module

    +
    +
    +GPy.util.decorators.silence_errors(f)[source]
    +

    This wraps a function and it silences numpy errors that +happen during the execution. After the function has exited, it restores +the previous state of the warnings.

    +
    + +
    +
    +

    GPy.util.diag module

    +
    +
    +GPy.util.diag.add(A, b, offset=0)[source]
    +

    Add b to the view of A in place (!). +Returns modified A. +Broadcasting is allowed, thus b can be scalar.

    +

    if offset is not zero, make sure b is of right shape!

    + +++ + + + + + +
    Parameters:
      +
    • A (ndarray) – 2 dimensional array
    • +
    • b (ndarray-like) – either one dimensional or scalar
    • +
    • offset (int) – same as in view.
    • +
    +
    Return type:

    view of A, which is adjusted inplace

    +
    +
    + +
    +
    +GPy.util.diag.divide(A, b, offset=0)[source]
    +

    Divide the view of A by b in place (!). +Returns modified A +Broadcasting is allowed, thus b can be scalar.

    +

    if offset is not zero, make sure b is of right shape!

    + +++ + + + + + +
    Parameters:
      +
    • A (ndarray) – 2 dimensional array
    • +
    • b (ndarray-like) – either one dimensional or scalar
    • +
    • offset (int) – same as in view.
    • +
    +
    Return type:

    view of A, which is adjusted inplace

    +
    +
    + +
    +
    +GPy.util.diag.multiply(A, b, offset=0)
    +

    Times the view of A with b in place (!). +Returns modified A +Broadcasting is allowed, thus b can be scalar.

    +

    if offset is not zero, make sure b is of right shape!

    + +++ + + + + + +
    Parameters:
      +
    • A (ndarray) – 2 dimensional array
    • +
    • b (ndarray-like) – either one dimensional or scalar
    • +
    • offset (int) – same as in view.
    • +
    +
    Return type:

    view of A, which is adjusted inplace

    +
    +
    + +
    +
    +GPy.util.diag.offdiag_view(A, offset=0)[source]
    +
    + +
    +
    +GPy.util.diag.subtract(A, b, offset=0)[source]
    +

    Subtract b from the view of A in place (!). +Returns modified A. +Broadcasting is allowed, thus b can be scalar.

    +

    if offset is not zero, make sure b is of right shape!

    + +++ + + + + + +
    Parameters:
      +
    • A (ndarray) – 2 dimensional array
    • +
    • b (ndarray-like) – either one dimensional or scalar
    • +
    • offset (int) – same as in view.
    • +
    +
    Return type:

    view of A, which is adjusted inplace

    +
    +
    + +
    +
    +GPy.util.diag.times(A, b, offset=0)[source]
    +

    Times the view of A with b in place (!). +Returns modified A +Broadcasting is allowed, thus b can be scalar.

    +

    if offset is not zero, make sure b is of right shape!

    + +++ + + + + + +
    Parameters:
      +
    • A (ndarray) – 2 dimensional array
    • +
    • b (ndarray-like) – either one dimensional or scalar
    • +
    • offset (int) – same as in view.
    • +
    +
    Return type:

    view of A, which is adjusted inplace

    +
    +
    + +
    +
    +GPy.util.diag.view(A, offset=0)[source]
    +

    Get a view on the diagonal elements of a 2D array.

    +

    This is actually a view (!) on the diagonal of the array, so you can +in-place adjust the view.

    +

    :param ndarray A: 2 dimensional numpy array +:param int offset: view offset to give back (negative entries allowed) +:rtype: ndarray view of diag(A)

    +
    >>> import numpy as np
    +>>> X = np.arange(9).reshape(3,3)
    +>>> view(X)
    +array([0, 4, 8])
    +>>> d = view(X)
    +>>> d += 2
    +>>> view(X)
    +array([ 2,  6, 10])
    +>>> view(X, offset=-1)
    +array([3, 7])
    +>>> subtract(X, 3, offset=-1)
    +array([[ 2,  1,  2],
    +       [ 0,  6,  5],
    +       [ 6,  4, 10]])
    +
    +
    +
    + +
    +
    +

    GPy.util.erfcx module

    +
    +
    +GPy.util.erfcx.erfcx(arg)[source]
    +
    + +
    +
    +

    GPy.util.functions module

    +
    +
    +GPy.util.functions.clip_exp(x)[source]
    +
    + +
    +
    +GPy.util.functions.differfln(x0, x1)[source]
    +
    + +
    +
    +GPy.util.functions.logistic(x)[source]
    +
    + +
    +
    +GPy.util.functions.logisticln(x)[source]
    +
    + +
    +
    +GPy.util.functions.normcdf(x)[source]
    +
    + +
    +
    +GPy.util.functions.normcdfln(x)[source]
    +
    + +
    +
    +

    GPy.util.gpu_init module

    +

    The package for scikits.cuda initialization

    +

    Global variables: initSuccess +providing CUBLAS handle: cublas_handle

    +
    +
    +GPy.util.gpu_init.closeGPU()[source]
    +
    + +
    +
    +

    GPy.util.initialization module

    +

    Created on 24 Feb 2014

    +

    @author: maxz

    +
    +
    +GPy.util.initialization.initialize_latent(init, input_dim, Y)[source]
    +
    + +
    +
    +

    GPy.util.linalg module

    +
    +
    +GPy.util.linalg.DSYR(*args, **kwargs)[source]
    +
    + +
    +
    +GPy.util.linalg.DSYR_blas(A, x, alpha=1.0)[source]
    +

    Performs a symmetric rank-1 update operation: +A <- A + alpha * np.dot(x,x.T)

    + +++ + + + +
    Parameters:
      +
    • A – Symmetric NxN np.array
    • +
    • x – Nx1 np.array
    • +
    • alpha – scalar
    • +
    +
    +
    + +
    +
    +GPy.util.linalg.DSYR_numpy(A, x, alpha=1.0)[source]
    +

    Performs a symmetric rank-1 update operation: +A <- A + alpha * np.dot(x,x.T)

    + +++ + + + +
    Parameters:
      +
    • A – Symmetric NxN np.array
    • +
    • x – Nx1 np.array
    • +
    • alpha – scalar
    • +
    +
    +
    + +
    +
    +GPy.util.linalg.backsub_both_sides(L, X, transpose='left')[source]
    +

    Return L^-T * X * L^-1, assumuing X is symmetrical and L is lower cholesky

    +
    + +
    +
    +GPy.util.linalg.cholupdate(L, x)[source]
    +

    update the LOWER cholesky factor of a pd matrix IN PLACE

    +

    if L is the lower chol. of K, then this function computes L_ +where L_ is the lower chol of K + x*x^T

    +
    + +
    +
    +GPy.util.linalg.dpotri(A, lower=1)[source]
    +

    Wrapper for lapack dpotri function

    +
    +
    DPOTRI - compute the inverse of a real symmetric positive
    +
    definite matrix A using the Cholesky factorization A = +U**T*U or A = L*L**T computed by DPOTRF
    +
    + +++ + + + + + +
    Parameters:
      +
    • A – Matrix A
    • +
    • lower – is matrix lower (true) or upper (false)
    • +
    +
    Returns:

    A inverse

    +
    +
    + +
    +
    +GPy.util.linalg.dpotrs(A, B, lower=1)[source]
    +

    Wrapper for lapack dpotrs function +:param A: Matrix A +:param B: Matrix B +:param lower: is matrix lower (true) or upper (false) +:returns:

    +
    + +
    +
    +GPy.util.linalg.dtrtri(L)[source]
    +

    Inverts a Cholesky lower triangular matrix

    + +++ + + + + + +
    Parameters:L – lower triangular matrix
    Return type:inverse of L
    +
    + +
    +
    +GPy.util.linalg.dtrtrs(A, B, lower=1, trans=0, unitdiag=0)[source]
    +

    Wrapper for lapack dtrtrs function

    +

    DTRTRS solves a triangular system of the form

    +
    +
    A * X = B or A**T * X = B,
    +

    where A is a triangular matrix of order N, and B is an N-by-NRHS +matrix. A check is made to verify that A is nonsingular.

    + +++ + + + + + +
    Parameters:
      +
    • A – Matrix A(triangular)
    • +
    • B – Matrix B
    • +
    • lower – is matrix lower (true) or upper (false)
    • +
    +
    Returns:

    Solution to A * X = B or A**T * X = B

    +
    +
    + +
    +
    +GPy.util.linalg.force_F_ordered(A)[source]
    +

    return a F ordered version of A, assuming A is triangular

    +
    + +
    +
    +GPy.util.linalg.force_F_ordered_symmetric(A)[source]
    +

    return a F ordered version of A, assuming A is symmetric

    +
    + +
    +
    +GPy.util.linalg.jitchol(A, maxtries=5)[source]
    +
    + +
    +
    +GPy.util.linalg.mdot(*args)[source]
    +

    Multiply all the arguments using matrix product rules. +The output is equivalent to multiplying the arguments one by one +from left to right using dot(). +Precedence can be controlled by creating tuples of arguments, +for instance mdot(a,((b,c),d)) multiplies a (a*((b*c)*d)). +Note that this means the output of dot(a,b) and mdot(a,b) will differ if +a or b is a pure tuple of numbers.

    +
    + +
    +
    +GPy.util.linalg.multiple_pdinv(A)[source]
    +
    +++ + + + + + + + + + + + +
    Parameters:A – A DxDxN numpy array (each A[:,:,i] is pd)
    Rval invs:the inverses of A
    Rtype invs:np.ndarray
    Rval hld:0.5* the log of the determinants of A
    Rtype hld:np.array
    +
    + +
    +
    +GPy.util.linalg.pca(Y, input_dim)[source]
    +

    Principal component analysis: maximum likelihood solution by SVD

    + +++ + + + + + + + +
    Parameters:
      +
    • Y – NxD np.array of data
    • +
    • input_dim – int, dimension of projection
    • +
    +
    Rval X:
      +
    • Nxinput_dim np.array of dimensionality reduced data
    • +
    +
    Rval W:
      +
    • input_dimxD mapping from X to Y
    • +
    +
    +
    + +
    +
    +GPy.util.linalg.pddet(A)[source]
    +

    Determinant of a positive definite matrix, only symmetric matricies though

    +
    + +
    +
    +GPy.util.linalg.pdinv(A, *args)[source]
    +
    +++ + + + + + + + + + + + + + + + + + + + +
    Parameters:A – A DxD pd numpy array
    Rval Ai:the inverse of A
    Rtype Ai:np.ndarray
    Rval L:the Cholesky decomposition of A
    Rtype L:np.ndarray
    Rval Li:the Cholesky decomposition of Ai
    Rtype Li:np.ndarray
    Rval logdet:the log of the determinant of A
    Rtype logdet:float64
    +
    + +
    +
    +GPy.util.linalg.ppca(Y, Q, iterations=100)[source]
    +

    EM implementation for probabilistic pca.

    + +++ + + + +
    Parameters:
      +
    • Y (array-like) – Observed Data
    • +
    • Q (int) – Dimensionality for reduced array
    • +
    • iterations (int) – number of iterations for EM
    • +
    +
    +
    + +
    +
    +GPy.util.linalg.symmetrify(A, upper=False)[source]
    +

    Take the square matrix A and make it symmetrical by copting elements from the lower half to the upper

    +

    works IN PLACE.

    +

    note: tries to use weave, falls back to a slower numpy version

    +
    + +
    +
    +GPy.util.linalg.symmetrify_numpy(A, upper=False)[source]
    +

    Force a matrix to be symmetric

    +
    + +
    +
    +GPy.util.linalg.symmetrify_weave(A, upper=False)[source]
    +

    Take the square matrix A and make it symmetrical by copting elements from the lower half to the upper

    +

    works IN PLACE.

    +
    + +
    +
    +GPy.util.linalg.tdot(*args, **kwargs)[source]
    +
    + +
    +
    +GPy.util.linalg.tdot_blas(mat, out=None)[source]
    +

    returns np.dot(mat, mat.T), but faster for large 2D arrays of doubles.

    +
    + +
    +
    +GPy.util.linalg.tdot_numpy(mat, out=None)[source]
    +
    + +
    +
    +GPy.util.linalg.trace_dot(a, b)[source]
    +

    Efficiently compute the trace of the matrix product of a and b

    +
    + +
    +
    +

    GPy.util.linalg_gpu module

    +
    +
    +

    GPy.util.ln_diff_erfs module

    +
    +
    +GPy.util.ln_diff_erfs.ln_diff_erfs(x1, x2, return_sign=False)[source]
    +

    Function for stably computing the log of difference of two erfs in a numerically stable manner. +:param x1 : argument of the positive erf +:type x1: ndarray +:param x2 : argument of the negative erf +:type x2: ndarray +:return: tuple containing (log(abs(erf(x1) - erf(x2))), sign(erf(x1) - erf(x2)))

    +

    Based on MATLAB code that was written by Antti Honkela and modified by David Luengo and originally derived from code by Neil Lawrence.

    +
    + +
    +
    +

    GPy.util.misc module

    +
    +
    +GPy.util.misc.chain_1(df_dg, dg_dx)[source]
    +

    Generic chaining function for first derivative

    +
    +

    \frac{d(f . g)}{dx} = \frac{df}{dg} \frac{dg}{dx}

    +
    + +
    +
    +GPy.util.misc.chain_2(d2f_dg2, dg_dx, df_dg, d2g_dx2)[source]
    +

    Generic chaining function for second derivative

    +
    +

    \frac{d^{2}(f . g)}{dx^{2}} = \frac{d^{2}f}{dg^{2}}(\frac{dg}{dx})^{2} + \frac{df}{dg}\frac{d^{2}g}{dx^{2}}

    +
    + +
    +
    +GPy.util.misc.chain_3(d3f_dg3, dg_dx, d2f_dg2, d2g_dx2, df_dg, d3g_dx3)[source]
    +

    Generic chaining function for third derivative

    +
    +

    \frac{d^{3}(f . g)}{dx^{3}} = \frac{d^{3}f}{dg^{3}}(\frac{dg}{dx})^{3} + 3\frac{d^{2}f}{dg^{2}}\frac{dg}{dx}\frac{d^{2}g}{dx^{2}} + \frac{df}{dg}\frac{d^{3}g}{dx^{3}}

    +
    + +
    +
    +GPy.util.misc.kmm_init(X, m=10)[source]
    +

    This is the same initialization algorithm that is used +in Kmeans++. It’s quite simple and very useful to initialize +the locations of the inducing points in sparse GPs.

    + +++ + + + +
    Parameters:
      +
    • X – data
    • +
    • m – number of inducing points
    • +
    +
    +
    + +
    +
    +GPy.util.misc.linear_grid(D, n=100, min_max=(-100, 100))[source]
    +

    Creates a D-dimensional grid of n linearly spaced points

    + +++ + + + +
    Parameters:
      +
    • D – dimension of the grid
    • +
    • n – number of points
    • +
    • min_max – (min, max) list
    • +
    +
    +
    + +
    +
    +GPy.util.misc.opt_wrapper(m, **kwargs)[source]
    +

    This function just wraps the optimization procedure of a GPy +object so that optimize() pickleable (necessary for multiprocessing).

    +
    + +
    +
    +GPy.util.misc.param_to_array(*param)[source]
    +

    Convert an arbitrary number of parameters to :class:ndarray class objects. This is for +converting parameter objects to numpy arrays, when using scipy.weave.inline routine. +In scipy.weave.blitz there is no automatic array detection (even when the array inherits +from :class:ndarray)

    +
    + +
    +
    +

    GPy.util.mocap module

    +
    +
    +class GPy.util.mocap.acclaim_skeleton(file_name=None)[source]
    +

    Bases: GPy.util.mocap.skeleton

    +
    +
    +get_child_xyz(ind, channels)[source]
    +
    + +
    +
    +load_channels(file_name)[source]
    +
    + +
    +
    +load_skel(file_name)[source]
    +

    Loads an ASF file into a skeleton structure.

    + +++ + + + +
    Parameters:file_name – The file name to load in.
    +
    + +
    +
    +read_bonedata(fid)[source]
    +

    Read bone data from an acclaim skeleton file stream.

    +
    + +
    +
    +read_channels(fid)[source]
    +

    Read channels from an acclaim file.

    +
    + +
    +
    +read_documentation(fid)[source]
    +

    Read documentation from an acclaim skeleton file stream.

    +
    + +
    +
    +read_hierarchy(fid)[source]
    +

    Read hierarchy information from acclaim skeleton file stream.

    +
    + +
    +
    +read_line(fid)[source]
    +

    Read a line from a file string and check it isn’t either empty or commented before returning.

    +
    + +
    +
    +read_root(fid)[source]
    +

    Read the root node from an acclaim skeleton file stream.

    +
    + +
    +
    +read_skel(fid)[source]
    +

    Loads an acclaim skeleton format from a file stream.

    +
    + +
    +
    +read_units(fid)[source]
    +

    Read units from an acclaim skeleton file stream.

    +
    + +
    +
    +resolve_indices(index, start_val)[source]
    +

    Get indices for the skeleton from the channels when loading in channel data.

    +
    + +
    +
    +set_rotation_matrices()[source]
    +

    Set the meta information at each vertex to contain the correct matrices C and Cinv as prescribed by the rotations and rotation orders.

    +
    + +
    +
    +to_xyz(channels)[source]
    +
    + +
    + +
    +
    +GPy.util.mocap.load_text_data(dataset, directory, centre=True)[source]
    +

    Load in a data set of marker points from the Ohio State University C3D motion capture files (http://accad.osu.edu/research/mocap/mocap_data.htm).

    +
    + +
    +
    +GPy.util.mocap.parse_text(file_name)[source]
    +

    Parse data from Ohio State University text mocap files (http://accad.osu.edu/research/mocap/mocap_data.htm).

    +
    + +
    +
    +GPy.util.mocap.read_connections(file_name, point_names)[source]
    +

    Read a file detailing which markers should be connected to which for motion capture data.

    +
    + +
    +
    +GPy.util.mocap.rotation_matrix(xangle, yangle, zangle, order='zxy', degrees=False)[source]
    +

    Compute the rotation matrix for an angle in each direction. +This is a helper function for computing the rotation matrix for a given set of angles in a given order.

    + +++ + + + +
    Parameters:
      +
    • xangle – rotation for x-axis.
    • +
    • yangle – rotation for y-axis.
    • +
    • zangle – rotation for z-axis.
    • +
    • order – the order for the rotations.
    • +
    +
    +
    + +
    +
    +class GPy.util.mocap.skeleton[source]
    +

    Bases: GPy.util.mocap.tree

    +
    +
    +connection_matrix()[source]
    +
    + +
    +
    +finalize()[source]
    +

    After loading in a skeleton ensure parents are correct, vertex orders are correct and rotation matrices are correct.

    +
    + +
    +
    +smooth_angle_channels(channels)[source]
    +

    Remove discontinuities in angle channels so that they don’t cause artifacts in algorithms that rely on the smoothness of the functions.

    +
    + +
    +
    +to_xyz(channels)[source]
    +
    + +
    + +
    +
    +class GPy.util.mocap.tree[source]
    +
    +
    +branch_str(index, indent='')[source]
    +
    + +
    +
    +find_children()[source]
    +

    Take a tree and set the children according to the parents.

    +

    Takes a tree structure which lists the parents of each vertex +and computes the children for each vertex and places them in.

    +
    + +
    +
    +find_parents()[source]
    +

    Take a tree and set the parents according to the children

    +

    Takes a tree structure which lists the children of each vertex +and computes the parents for each vertex and places them in.

    +
    + +
    +
    +find_root()[source]
    +

    Finds the index of the root node of the tree.

    +
    + +
    +
    +get_index_by_id(id)[source]
    +

    Give the index associated with a given vertex id.

    +
    + +
    +
    +get_index_by_name(name)[source]
    +

    Give the index associated with a given vertex name.

    +
    + +
    +
    +order_vertices()[source]
    +

    Order vertices in the graph such that parents always have a lower index than children.

    +
    + +
    +
    +swap_vertices(i, j)[source]
    +

    Swap two vertices in the tree structure array. +swap_vertex swaps the location of two vertices in a tree structure array.

    + +++ + + + + + +
    Parameters:
      +
    • tree – the tree for which two vertices are to be swapped.
    • +
    • i – the index of the first vertex to be swapped.
    • +
    • j – the index of the second vertex to be swapped.
    • +
    +
    Rval tree:

    the tree structure with the two vertex locations swapped.

    +
    +
    + +
    + +
    +
    +class GPy.util.mocap.vertex(name, id, parents=[], children=[], meta={})[source]
    +
    + +
    +
    +

    GPy.util.mpi module

    +
    +
    +

    GPy.util.multioutput module

    +
    +
    +GPy.util.multioutput.ICM(input_dim, num_outputs, kernel, W_rank=1, W=None, kappa=None, name='ICM')[source]
    +

    Builds a kernel for an Intrinsic Coregionalization Model

    + +++ + + + + + + + +
    Input_dim:

    Input dimensionality (does not include dimension of indices)

    +
    Num_outputs:

    Number of outputs

    +
    Parameters:
      +
    • kernel (a GPy kernel) – kernel that will be multiplied by the coregionalize kernel (matrix B).
    • +
    • W_rank (integer) – number tuples of the corregionalization parameters ‘W’
    • +
    +
    +
    + +
    +
    +GPy.util.multioutput.LCM(input_dim, num_outputs, kernels_list, W_rank=1, name='ICM')[source]
    +

    Builds a kernel for an Linear Coregionalization Model

    + +++ + + + + + + + +
    Input_dim:

    Input dimensionality (does not include dimension of indices)

    +
    Num_outputs:

    Number of outputs

    +
    Parameters:
      +
    • kernel (a GPy kernel) – kernel that will be multiplied by the coregionalize kernel (matrix B).
    • +
    • W_rank (integer) – number tuples of the corregionalization parameters ‘W’
    • +
    +
    +
    + +
    +
    +GPy.util.multioutput.Private(input_dim, num_outputs, kernel, output, kappa=None, name='X')[source]
    +

    Builds a kernel for an Intrinsic Coregionalization Model

    + +++ + + + + + + + +
    Input_dim:

    Input dimensionality

    +
    Num_outputs:

    Number of outputs

    +
    Parameters:
      +
    • kernel (a GPy kernel) – kernel that will be multiplied by the coregionalize kernel (matrix B).
    • +
    • W_rank (integer) – number tuples of the corregionalization parameters ‘W’
    • +
    +
    +
    + +
    +
    +GPy.util.multioutput.build_XY(input_list, output_list=None, index=None)[source]
    +
    + +
    +
    +GPy.util.multioutput.build_likelihood(Y_list, noise_index, likelihoods_list=None)[source]
    +
    + +
    +
    +GPy.util.multioutput.get_slices(input_list)[source]
    +
    + +
    +
    +

    GPy.util.netpbmfile module

    +

    Read and write image data from respectively to Netpbm files.

    +

    This implementation follows the Netpbm format specifications at +http://netpbm.sourceforge.net/doc/. No gamma correction is performed.

    +

    The following image formats are supported: PBM (bi-level), PGM (grayscale), +PPM (color), PAM (arbitrary), XV thumbnail (RGB332, read-only).

    + +++ + + + + + + + +
    Author:Christoph Gohlke
    Organization:Laboratory for Fluorescence Dynamics, University of California, Irvine
    Version:2013.01.18
    +
    +

    Requirements

    + +
    +
    +

    Examples

    +
    >>> im1 = numpy.array([[0, 1],[65534, 65535]], dtype=numpy.uint16)
    +>>> imsave('_tmp.pgm', im1)
    +>>> im2 = imread('_tmp.pgm')
    +>>> assert numpy.all(im1 == im2)
    +
    +
    +
    +
    +GPy.util.netpbmfile.imread(filename, *args, **kwargs)[source]
    +

    Return image data from Netpbm file as numpy array.

    +

    args and kwargs are arguments to NetpbmFile.asarray().

    +
    >>> image = imread('_tmp.pgm')
    +
    +
    +
    + +
    +
    +GPy.util.netpbmfile.imsave(filename, data, maxval=None, pam=False)[source]
    +

    Write image data to Netpbm file.

    +
    >>> image = numpy.array([[0, 1],[65534, 65535]], dtype=numpy.uint16)
    +>>> imsave('_tmp.pgm', image)
    +
    +
    +
    + +
    +
    +class GPy.util.netpbmfile.NetpbmFile(arg=None, **kwargs)[source]
    +

    Bases: object

    +

    Read and write Netpbm PAM, PBM, PGM, PPM, files.

    +
    +
    +asarray(copy=True, cache=False, **kwargs)[source]
    +

    Return image data from file as numpy array.

    +
    + +
    +
    +close()[source]
    +

    Close open file. Future asarray calls might fail.

    +
    + +
    +
    +write(arg, **kwargs)[source]
    +

    Write instance to file.

    +
    + +
    + +
    +
    +
    +

    GPy.util.normalizer module

    +

    Created on Aug 27, 2014

    +

    @author: t-mazwie

    +
    +
    +class GPy.util.normalizer.MeanNorm[source]
    +

    Bases: GPy.util.normalizer.Norm

    +
    +
    +inverse_mean(X)[source]
    +
    + +
    +
    +normalize(Y)[source]
    +
    + +
    +
    +scale_by(Y)[source]
    +
    + +
    +
    +scaled()[source]
    +
    + +
    + +
    +
    +class GPy.util.normalizer.Norm[source]
    +

    Bases: object

    +
    +
    +inverse_mean(X)[source]
    +

    Project the normalized object X into space of Y

    +
    + +
    +
    +inverse_variance(var)[source]
    +
    + +
    +
    +normalize(Y)[source]
    +

    Project Y into normalized space

    +
    + +
    +
    +scale_by(Y)[source]
    +

    Use data matrix Y as normalization space to work in.

    +
    + +
    +
    +scaled()[source]
    +

    Whether this Norm object has been initialized.

    +
    + +
    + +
    +
    +

    GPy.util.parallel module

    +

    The module of tools for parallelization (MPI)

    +
    +
    +GPy.util.parallel.divide_data(datanum, rank, size)[source]
    +
    + +
    +
    +

    GPy.util.pca module

    +

    Created on 10 Sep 2012

    +

    @author: Max Zwiessele +@copyright: Max Zwiessele 2012

    +
    +
    +class GPy.util.pca.PCA(X)[source]
    +

    Bases: object

    +

    PCA module with automatic primal/dual determination.

    +
    +
    +center(X)[source]
    +

    Center X in PCA space.

    +
    + +
    +
    +plot_2d(X, labels=None, s=20, marker='o', dimensions=(0, 1), ax=None, colors=None, fignum=None, cmap=None, **kwargs)[source]
    +

    Plot dimensions dimensions with given labels against each other in +PC space. Labels can be any sequence of labels of dimensions X.shape[0]. +Labels can be drawn with a subsequent call to legend()

    +
    + +
    +
    +plot_fracs(Q=None, ax=None, fignum=None)[source]
    +

    Plot fractions of Eigenvalues sorted in descending order.

    +
    + +
    +
    +project(X, Q=None)[source]
    +

    Project X into PCA space, defined by the Q highest eigenvalues. +Y = X dot V

    +
    + +
    + +
    +
    +

    GPy.util.squashers module

    +
    +
    +GPy.util.squashers.sigmoid(x)[source]
    +
    + +
    +
    +GPy.util.squashers.single_softmax(x)[source]
    +
    + +
    +
    +GPy.util.squashers.softmax(x)[source]
    +
    + +
    +
    +

    GPy.util.subarray_and_sorting module

    +
    +
    +GPy.util.subarray_and_sorting.common_subarrays(X, axis=0)[source]
    +

    Find common subarrays of 2 dimensional X, where axis is the axis to apply the search over. +Common subarrays are returned as a dictionary of <subarray, [index]> pairs, where +the subarray is a tuple representing the subarray and the index is the index +for the subarray in X, where index is the index to the remaining axis.

    +

    :param np.ndarray X: 2d array to check for common subarrays in +:param int axis: axis to apply subarray detection over.

    +
    +
    When the index is 0, compare rows – columns, otherwise.
    +

    In a 2d array: +>>> import numpy as np +>>> X = np.zeros((3,6), dtype=bool) +>>> X[[1,1,1],[0,4,5]] = 1; X[1:,[2,3]] = 1 +>>> X +array([[False, False, False, False, False, False],

    +
    +
    [ True, False, True, True, True, True], +[False, False, True, True, False, False]], dtype=bool)
    +
    >>> d = common_subarrays(X,axis=1)
    +>>> len(d)
    +3
    +>>> X[:, d[tuple(X[:,0])]]
    +array([[False, False, False],
    +       [ True,  True,  True],
    +       [False, False, False]], dtype=bool)
    +>>> d[tuple(X[:,4])] == d[tuple(X[:,0])] == [0, 4, 5]
    +True
    +>>> d[tuple(X[:,1])]
    +[1]
    +
    +
    +
    + +
    +
    +

    GPy.util.univariate_Gaussian module

    +
    +
    +GPy.util.univariate_Gaussian.inv_std_norm_cdf(x)[source]
    +

    Inverse cumulative standard Gaussian distribution +Based on Winitzki, S. (2008)

    +
    + +
    +
    +GPy.util.univariate_Gaussian.std_norm_cdf(x)[source]
    +

    Cumulative standard Gaussian distribution +Based on Abramowitz, M. and Stegun, I. (1970)

    +
    + +
    +
    +GPy.util.univariate_Gaussian.std_norm_cdf_weave(x)[source]
    +

    Cumulative standard Gaussian distribution +Based on Abramowitz, M. and Stegun, I. (1970)

    +

    A weave implementation of std_norm_cdf, which is faster. this is unused, +because of the difficulties of a weave dependency. (see github issue #94)

    +
    + +
    +
    +GPy.util.univariate_Gaussian.std_norm_pdf(x)[source]
    +

    Standard Gaussian density function

    +
    + +
    +
    +

    GPy.util.warping_functions module

    +
    +
    +class GPy.util.warping_functions.TanhWarpingFunction(n_terms=3)[source]
    +

    Bases: GPy.util.warping_functions.WarpingFunction

    +
    +
    +f(y, psi)[source]
    +

    transform y with f using parameter vector psi +psi = [[a,b,c]] +::math::f = sum_{terms} a * tanh(b*(y+c))

    +
    + +
    +
    +f_inv(y, psi, iterations=10)[source]
    +

    calculate the numerical inverse of f

    + +++ + + + +
    Parameters:iterations – number of N.R. iterations
    +
    + +
    +
    +fgrad_y(y, psi, return_precalc=False)[source]
    +

    gradient of f w.r.t to y ([N x 1]) +returns: Nx1 vector of derivatives, unless return_precalc is true, +then it also returns the precomputed stuff

    +
    + +
    +
    +fgrad_y_psi(y, psi, return_covar_chain=False)[source]
    +

    gradient of f w.r.t to y and psi

    +

    returns: NxIx3 tensor of partial derivatives

    +
    + +
    + +
    +
    +class GPy.util.warping_functions.TanhWarpingFunction_d(n_terms=3)[source]
    +

    Bases: GPy.util.warping_functions.WarpingFunction

    +
    +
    +f(y, psi)[source]
    +

    Transform y with f using parameter vector psi +psi = [[a,b,c]]

    +

    f = \sum_{terms} a * tanh(b*(y+c))

    +
    + +
    +
    +f_inv(z, psi, max_iterations=1000, y=None)[source]
    +

    calculate the numerical inverse of f

    + +++ + + + +
    Parameters:max_iterations – maximum number of N.R. iterations
    +
    + +
    +
    +fgrad_y(y, psi, return_precalc=False)[source]
    +

    gradient of f w.r.t to y ([N x 1])

    + +++ + + + +
    Returns:Nx1 vector of derivatives, unless return_precalc is true, then it also returns the precomputed stuff
    +
    + +
    +
    +fgrad_y_psi(y, psi, return_covar_chain=False)[source]
    +

    gradient of f w.r.t to y and psi

    + +++ + + + +
    Returns:NxIx4 tensor of partial derivatives
    +
    + +
    + +
    +
    +class GPy.util.warping_functions.WarpingFunction[source]
    +

    Bases: object

    +

    abstract function for warping +z = f(y)

    +
    +
    +f(y, psi)[source]
    +

    function transformation +y is a list of values (GP training data) of shpape [N,1]

    +
    + +
    +
    +f_inv(z, psi)[source]
    +

    inverse function transformation

    +
    + +
    +
    +fgrad_y(y, psi)[source]
    +

    gradient of f w.r.t to y

    +
    + +
    +
    +fgrad_y_psi(y, psi)[source]
    +

    gradient of f w.r.t to y

    +
    + +
    +
    +plot(psi, xmin, xmax)[source]
    +
    + +
    + +
    +
    +

    Module contents

    +
    +
    + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/doc/_build/html/_images/math/07aad80690e06cd5a29e87d6e696222f9b3a2f39.png b/doc/_build/html/_images/math/07aad80690e06cd5a29e87d6e696222f9b3a2f39.png new file mode 100644 index 0000000000000000000000000000000000000000..6eb978b51731eb89a0108875d20d2d7deb70a709 GIT binary patch literal 534 zcmeAS@N?(olHy`uVBq!ia0vp^AwVq7!VDzSJ4+3KltF+`i0l9V|A9>6f&SeE)j-w! zB|(0{3=((eo=^C_zWb%e{*uo|H~#&*2$bS1@Q5sCVBk9f!i-b3`J@>b7z;gJ978nD zZ@pyiao9oR_{aE5Gmb6Uc65I;2P^wg%^RLtLMytOJqk;-N`xmiG(QU2prFe)cP?K` zUaOyyUYbVA*3}j%1snVL@~(Nm6Y{OrYs&xi>63za4TI0Dmv4D_`nPmU?-CbH`<|ht zDq>(2?NM^btL(xDZ`Nt7%TrHWT`^~+PVZ*Z2gOeeDlfVm>t2Qs-pKQd3{ zoqr(kIdCP5!Md)O?SIx9f4R1M-Oq1v7LUF*eiQy@acr6WxAphgYm!c%QHc6~;(w)s zLi)QHj_$%wZ#|c{oIdHxozOa`rg~F~p(W?%P?qjOt~XCF`>MHr{pPyi*PokL?tP5t zJDK@(y32+bw!T}JwO5-NUpcy!LF}=}4e!XuEhl$Qkz?H;vHZZiH2nf+b2h<4LCvOH o%MVO2n`36DDqg5fs?!m*j94ITnxv*K zy}F?9e#VWxKSK?o&TrnJRm8h!*)uK4&$l$nHYFZg@%Zr1T-_rtT|;!I%s288%v`l| z&h0f#&%T#Q?|!4%Zu;h4Hm|AO@t%z==2s1h*0cGp+h8bsChZ1qaPvkpnTbcux366I z*=b8;@%aRwEqs=TgFV!aq@*llTmInZE~C6zci&By-{qJ!Bfd(r|CowOXT9I%Y~gy% zImsVcXZ(I2Q1$T`qp4Zt!}g7vd*wwB=Jm|laonReNcjGVO8?v`Pq{5RH|ziLYFpuY zFU!o-<_y=(%iX~nWPQcTlCOMFXqn7y%2IRGqUGcjvCJDYUj)^dhs}Jt;F#RChs;?X z9J9oB@>~&^U}SeYXWN{faEtV*k-Uj!=X#%hsM&a{=E?3(;T}n$Qq#oVq{c_T^Pl~3 zR6SP`;++0}{p`d&f$eeOkA*`UqEph#Z5-xaIWjk8S@qYiSsoIT&b+>Lp<+UZ_ukM9 zN$t8#KYd!o&Pga4dZcNIt6j5S>6YDT+GqGmCEEJ!p;cCUSIxYX=)CIeG5c=)-FtGS zZtN{ySC}(X_V0hjZ?n?3uRI#)Y@@sRlSFHRp`Y1bKeK%Eedk@~ObM9%_{i=ZNvWS) zq`O_J=H;+9;WbyAm_)&cuzE(d$;YQVzU|{Tmxwypu@nXV{a#q>hRXPR_UPv=)EliH@XJwP&`G4-h b#}^;vW#($zY~wAK0_A#7S3j3^P60{{R3%e2>Q0000mP)t-s|Ns90 z0000000000000000000000000000000000000000000000000000000FWsPf0000F zbW%=J0G%>O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000H0NklvS zFDlCPNn;WTDHK5?i9cuz>gtPmNf}}b36y3gZl!mun_!tl%>r{?h?})orre;=XLP2bM}WY?np4M@b`Xbtv?S^&R+Nr=uyM-Us}U zu=G2$K*~u>Zy4pzWtD`=xGzT!LB#%t8g!OWD&ohgI>(&*ZNt%->HTStx_=2ctXcY9 z@O7u%#Bn1!!e7OWU|t_%;)6ykC+3*6NK%!UbAQqBEsyUJD(t_bMSbI9UUw6BX-!Ff z`{PDO+Mgrhz$ia0#{(rAl2i>R&izHhGJ%l#C_+b7OF#7cXZ>Qf0w?di^RK5*Qarua z-V6-T>#_JJVmc8k6a+7`1WKAE@QnkzD@`!ve%mlwMam@g+XjdC?XmP%fp{6u^S>4- z^Y$Xa5{e;`R7{!k0|{{MFU5H)tIWI8rvttGFP5ZOI*VAdO-vHw7+8YiHX3=-K>arLG&O}7+FGaR&SuDYG{}^)J9$0j*$MaZ} zKO{l}hSwmz36X3_cPzuJ6#|B*`lWGQ)z0{XMicQv-3FD-ClmAg^9`8qW_* z)WGYz5r-^anz1qGQFZnC^=Y1z1NT6kp$x{OuM@0op6YiQ#;Y6jhG*~v83=bMxFY0K@u;ZCSo>7)qT^hDgm)1_D_Vp zMj!cy@T~aR8|4)SJ2V7)&{{Ej6wne9H#7J{(zVt^EDUzhROcg=z4nB9P8^OL(C9fu zIQ65ZaAJdshGTi-){5g^nA*oX4xFKCD;weW>@0uWy@QFPitUVKjW0UdOVyiHCx*(|jGq4tB7E9qeFh!Dmt10eKd+ z4Ty^RVjI9`QFSM=+W^kJB%ei@9f!IdQrK+(*Cw{fusRO)La_}{JSP!nQC7#HUMRK! zTt`CTgw=7V6C7;-7qODIIu3P$qYY4WwLFV5I}Y`N-3D+#o<*4*hkC(o12`bhqRfs% zU7^goKBmoUOX(Mz4sHXu!kA%p9JUbhEXwLQZ0!=kkR6Br0qa@dnoXBEZ2$lO07*qo IM6N<$f(B;aH~;_u literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/112c6d94605f31bddb3f52529408cf14d2a03456.png b/doc/_build/html/_images/math/112c6d94605f31bddb3f52529408cf14d2a03456.png new file mode 100644 index 0000000000000000000000000000000000000000..0ea5b7aefac424986114e16aed26e40d41e07970 GIT binary patch literal 2324 zcmV+v3G4QWP))U4^XXvyuGqc+000SaNLh0L01m_e01m_fl`9S#000PYNklk$Q!iWb?5bHjFk$&>)nwJ{H0j*RjYgPL)*E;_L29zwTG zpo_zT9r>t4I!!pssi-b$orEu=F*?Rcfo|Ho1+_!>8@?~)*6A|r-S6hXbzw8$&VdqX zM!ao3y6C+zY$Sd2v$*^P9}qM~kXg&@ME3x`A7u6s|J8tQwb{nDi=HrGlsd$2=Q*c| z)P8P=_;Dh@bqao7%ct>dFbs|~*@=#|3v3@2WI4Lf{f+p|Ysz@a1{pdo4MfG$e5r{X zy?p(+mFvJUmIV_(x!l{v(SO*CPCci0Jga{QnzkX3mZ9TPFD`u?I85>OdM*OB>p0h0 z2m2b!Ut~(5nPUdEsEchzr}UehEK=Uno|K{EQiRarP5Dh~Se@nQAV4a^N$YjdZvN^w zDCDM)&FDP2vTP$lw;N>WxD-7m8$+XZl;LaZCTI4hfQc}=29qT^^Ay#qy!2J=_s(RQ z>IE4(k~Z<^(he$H@B!Aij?}wzTBrgpGNKET7C)_3Mlkwak^Fhf!@sjbhK{6dJpA5Z z&hzWJ2>A&V{7zp14>ZtKLv*m&ME>f_!(X6VhK{6c&Hb<+rj#axAK*2DGll<@p!1Mo z+oLi@s+*6gCobcp%94Lx;UC`DIvDw*wzhn1eO!i)q%7?BD+8`zNdS5}iZPLAgg1bR zC?n`?J(-Gx!WLp^z|_-9#I8b{tHUj%>^sVboEB+Uef82-gVcpoq#F26UnC^d5CVf;htHis;%3pLF(oqI}47{<_Md>LRJiD3`Mb zIt6;@p;XXWU}9RkkH}iD<=X1NxOeyJJ%JGkdQM$MbZ$L{_%%f-rrGwems{p*^2bC{ zfUTGgf>}5$u(Pe8h7ci&PU0362h69k$hzJcU4o7|=;$I2G>Ny zz9#?D`tK4-!Hu4<1>j|Y6}!RPoMj@d0xDQMw}#LK%e8$_f-acWddBmvbwuncw2|7m z%~-9HeB3l*lN8-1y+n02$E~VY-)*!_sPs9-{unnK<&1Dujk6Oh!mjCoYczDuULJE{ z z&|yu{r=lGO!_Ev@rn1i)XFU+2pguUit9-z8Mz(k2pfIQ=Lsy@~dbfkU2hzBYi0+xB zFT>&BSNtiU8=_?@Qp;3oW0~#Ix)h85^~qQ^ei+et4zYTdWdwf&uxF4N;R^blbyR`5 z6B_|$V-o4y2}%ahvE!v(tOt-YU=L$-&hTZ-785u~VfvMy98Xn~5q{ZXjV^8-bl>FU zkG)Iw$ya4l1j~)+->O+tGVh`q2q4kRay$u!4U|y z6wqN$@=strjM1I6da`ymV%%G$+=}&r_H*g_<V=eF({5GkMXbV5z|65wkr zRzL|@k4y!7q!rLU?e<`wfexljwIda@??~4#mqOInZ6%t(IjQ5E=nVUOl2$Ogv$Vcz zfll()IYjJ)jopp#+k>ZyeXGg`=>_d{>GG#n@aAAt{+G_d&?*0*g1hlILoTr0kh;DZslGcHN(`^)yAl8{xMHzO<_3oKZ_D-?|<&5hb6uLa!C&^X)(9E7rrCwF4%W``7fS&nrLW z(VpPWe7-|3Xg#8+hCb<%Na^@_oNO%t3g~-lcSZ~F8C&4aFw6a{R6OC1Mn<7cE?$)` z6tv>w;)D8mqSayY%^2Yfi{8E-X zP(se_-n*h@vV$$ozQe!>YY!+LV5El*QI$AmwoJ-Y*tu1<6pf+HgWC8V(a7g0a78n` zWb~w<8FI`ly~ZScO#0AcRV}5B+-{@&=y;?g8cFfRyD-AhIoVM(`gt$BZv3;RsO+I~ zsa2y3j6lRba3yymoJM-ctels)jV+9W+6x~8JlR}AsY6n>6sm?xX?{HpYS8BDG}1+r zs1<6^Nkfo|8(jt2adsdudYwkrX(6jZWLaNV*sCB!(qAXNuFvR`|dD=j~sLGr8%4#*cLX0000W-^ZUC$m%Nl%-`Jh&k_VLIEbxddW?X?_wfUqO7?^cDT^vIq z4!@1KUA9Jnr?sG$R z<_g@XzrOqH>gQHFB=iJ16t@S%jzV8{spm_d;0C{81!(ghamqpUMR}WwPSu*+l#p5ew)f)Ma`@LJzZnrX7 z{%otNU*e>eDOMJH^Y~cwvqPVsx%qd}jGOL7+e0k5k`}#KKYez|q77ebuWr1W+ilMx zS#kE$*2Pb@&&t*J3Y{{y@%r~g=if2^Js|aH)1?kh`LE|))fYaot$%V@UqJoe6Z7u! z$uc|a`12>WU*F^T#BSgIrT-S*so42vZ)2%d=4aV8mpx~Hy1zYgdAUJsyn#heY0{q4 zXJuJ7SKdiJ9%>!7p*r~_WDNokq2kiT<$90 z>9|3Ax%~FZ0IBA~k?OVi;_qvEtOAA4&se8y_ujz5?XFa+FYlk3*4L&T?EG$~D>89G z{QQLegB!Q!IVvQl_ua8&bH7*RxiT{GT*zfvw&N$Gix;n1#J&8^JtK>|Yg_$Rw7mS} s`>*hOTW9%Cg~(5O^A)}CJxzaN9~PqI^m%#4L{QH3boFyt=akR{0E!{IfdBvi literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/153e15220d6bec90ed9f8e0c870c3c808eae75aa.png b/doc/_build/html/_images/math/153e15220d6bec90ed9f8e0c870c3c808eae75aa.png new file mode 100644 index 0000000000000000000000000000000000000000..976b19a724b8611253189b447e0d76bfc9afd8b3 GIT binary patch literal 1035 zcmeAS@N?(olHy`uVBq!ia0vp^-+@?!g&9aLF52b;qznRlLR|m<{|{sm5A^RYs0OO$ zFA4GsW{}uF_ioAO^)C~;e|wxa5^41R1eD?|@Q5sCVBk9f!i-b3`J@>bnA1F6978;g zZ=L3yA?zq|{QvB`zIX20gl$|PSYq4pz%fg{W6^}>CXb6rA00nVlw0$|q4=X?K#xX< z?g^zuL89BPEaHv2wK&Mc>8SHTwl0n&(>R+9Q%yUEE7$VNW|!`sogpeatFq?v*+1W^ z&-gUfM_U|L?U;6H(#!NIG4=nitP0JJI&S}8(|keD)8K>Yb1wZY<0H&sbCy`C$zC$1<_Ss`lK`g;bMhrS<;TJ~3N-!;n{$5x3H9Mqii z?1lY29lx1&5~aC2!%b&v9ymUy*>%Gi%Qr?B^%@@M9l}DV9p*uk>TDOpM`~3r+WrhQ%?yb2>RuccIre z)x|vTuJ6p>#&%Hf1RM9V!sWh?MJ``-{o$(r*u%2IE?sTro_xcde8&ak4l|rEP~vZ> zv2V`_JleGO;KXhF=lNUeoPVxXbg<{A*N(gA=57e!xB1{$WUzF3%akKR4ZEWpct5{Z z>)a-&ReI}#ZcEGBg9?J79u^OppY+fFpvdnu!(&Hr-1gO*g^nFrcEC<n?g$%6@0Q^Y+>+8*Vp87+m~Tk+!7yc6-Qgp&NI4y`}H#a!OQO z>HEu3;$-Hr^irYk5>2L)kIxm$`7L|-Z~5hj({8N(UeR&0>i#V`6~2GftBm+t-;~xa z+*ZrgA9Y4`#>rJutM^|m-di*&TK@VPx5wIn>UKRLIXx*^7nD`Qd>&?6zp8s>G^H=@ z{_}fWGyUP& z#vZ1LQ&!!KpS(u#*5~s7K1(Lw+ubF!s6-&%%-sCFto;A3$RdN&FV8nx>B(iib{G4< x|4eQEwD1pios7 zmjw9*Gf1rOo@?|u;pP7GC3k;&tUFZ;GM2NzBeIx*f$s~OHl!MWakwe#WPEq-WD1Wv*lgE-*>v9h)+QaBF=N@OO0%IR*L`XAl>K_i3 zITurYZ2Z}#&agzC(PNL}#8kw|oaS(h`SBFphKCb`E*Rd?TaXZRv#7CAQbgmWLS??lRj0r0 z2gUpt3YioSvX$^XW>omgI8Q3zz&qPFjH@PGImKVZ!hRvcmd&kff>_xZi~A`lXAiLQ zOgCqj_#)}5*?2TE}kctjR6Fz_7#VaBQ2e9}O{zn(6RAsXkC z6BwA?m^pZtZea9dmyx-{Fv?FKdJV zO9hj|E1`xX(k7}2j&7;K>~R8XuZ0{qaG*PlBf`MPVIPCeLFP@p@@GXhBp5UAcaZ2f z{+q#LLt~A7wy1zkQUm9v`V@_12JMOI4VsQj3XaoQ*nHU{1=jPd;XbQ0LE$n}TV6+t zcns$xR|Us+%xB^i=fxdrIC?q3ajLGk#0KJAy$8bshfng)dfhHaq z2jwpk5;q-B-3VMPsI=nX2IeUe5*58%2ExoP1((HG3nnEQF?LEW(qiOhVyHY}$iTbl SkPa{)7(8A5T-G@yGywo6?|W|m literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/21bfcdadd1abee6b044daaa51d5a195606ee453c.png b/doc/_build/html/_images/math/21bfcdadd1abee6b044daaa51d5a195606ee453c.png new file mode 100644 index 0000000000000000000000000000000000000000..6f44a7e0ce181969095c4d607fce48a19f4c62c3 GIT binary patch literal 467 zcmeAS@N?(olHy`uVBq!ia0vp^{y;3i!VDyr9b81+0|978nD zCnp@>lz7Z-v1x%1D_c#%Yvwjifopc`Yq++}uv(qL{BkEJkF>-MNeM0qiAJv0H~U!( zo?0)w@l&Cp@F){o8?TrR6Hg4&8^(lIo-_BkBuoN)QsM;;2yAF?{ODk8K4E*n6vjmp zKGrilXIc^1KgA@GE8nQVc*9+`PZ7)uxFmno%eP5weaW<`^A69Piw^TL6nqq~*Ozx# z&0{TCU8y8)P++v-KkF*a2SN>6DIeOa=1IPDQx%qFb9>6o<1jad$Klfzf5r(%eytZ^ zEh=bz$auqPhVrlfYzB`zCJCJ}F1FgJvFD7yf59^ooLKm^S2MI(mASJ`)6dA`c`#G1 zVc~?8j3QGM#PS(z(j=zMcM8A$X8y?oQ~pc7`LWC`B1T?=E4o2_=Z5!8)oj`f3_lXR U*seXZ1VtHxr>mdKI;Vst019fHI{*Lx literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/2520c5bbd4ca1928f464fd3873b10a9b0bde8c18.png b/doc/_build/html/_images/math/2520c5bbd4ca1928f464fd3873b10a9b0bde8c18.png new file mode 100644 index 0000000000000000000000000000000000000000..2c01240a77c9ac293767c34045a300e2e08e0be6 GIT binary patch literal 639 zcmeAS@N?(olHy`uVBq!ia0vp^y+AC)!VDy*I5+@F27>^f5ZC|z|AW{>1O2-Ts)366 zOM?7@86@`4y<75m{mX>z-yY|UL>m1+0i`$#JR*x382FBWFymBhK4}I9##^2)jv*GO zr%tigVGfizzJLAOK;0rAA?8jGokvQJJd^a?>XS^aW)z7{USit8Dc;<;aJq*3X@9CcVd+pxEu6{Uu%lCWlYu^{||6W_qAb93jxl4fkjE}z~9KOHU z^}1NheR=k?+w6^j`AK1te0lrUmn=Emwyi)(sC@Okhj%yS^qyz%d>;_;*KY^Q61%!f zwtpqR-<-4jf7r=H|AsVeQ4QM+Ke>zk39B#V8@F-_p0158+F~Ja>hyG}m(GS;7i{TV zwD@t@H{%rt6TP#=79Ciayu`26B;cLLQy!Ux*EdG`WGyI&W6Sr+YWbmK!EU*D!Q)-3 zhq^06ERUwE6n}hB;`;cpg_!kHw<*(qI+X3pEy&&!9%JEdt>~S|wb)eotKc*#`R8*V zpS+;Q!RH;EUm@7ESfX~ldCk1~>^m>c-&>Quo>kq^I&b!WtIU*F5;yGiXN3M!ux(sm ztZ91n>y9~w9Q91jcPh1cybEkTJ3X3ud%~1iQlA&`*0FAUr|c2KwW$7XU{ClKr^lZy zFGnppX0tR$XX*rv+X-9v|2|hg;{S}bKFmbxdCrpawmY_*&ni^BY`I^fzKuO5c)z4*}Q$iB}BHskA literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/26038e5468fa3f743e11b649cd49e30d4bf2d9aa.png b/doc/_build/html/_images/math/26038e5468fa3f743e11b649cd49e30d4bf2d9aa.png new file mode 100644 index 0000000000000000000000000000000000000000..60fd6d1368435ff1b4647df54d495a8f9f3583af GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^f6f&SeE)j-w! zB|(0{3?*|Vy3Z#Vz5IN4|N7q^%ikMc14?lgctjR6Fz_7#VaBQ2e9}O{08bak5RU7~ z2_Z&>z6lJBo2%H5u^DJPPHN0#Wd6;hP|VM~nyL9bi^6Lu=6XhE>j_8yH9Ah>J(HA~ uaN{sb+D8k6J%wzW6&R$oe+M%%%P=rFz7#057B#X4x!lv$&t;ucLK6Vn(L4_T literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/26d17fb3a403d131bb3eef5cfb5c32587282b0d5.png b/doc/_build/html/_images/math/26d17fb3a403d131bb3eef5cfb5c32587282b0d5.png new file mode 100644 index 0000000000000000000000000000000000000000..262e5952da96c0ddbe4c369651e79b9b196e28ef GIT binary patch literal 1107 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 E0Jk;v6aWAK literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/36ad6994800a13c9387535b07ae468a4784b120d.png b/doc/_build/html/_images/math/36ad6994800a13c9387535b07ae468a4784b120d.png new file mode 100644 index 0000000000000000000000000000000000000000..de055027456a59a3db9b3760d91d8c7d4dd74c70 GIT binary patch literal 878 zcmeAS@N?(olHy`uVBq!ia0vp^pMY41g&9arW|}7oqznRlLR|m<{|{sm5A^RYs0OO$ zFA4GsW>_zg@bY)b`TgBSbMJb5ezRKk3{Z-*z$3Dlfr0M`2s2LA=96Y%U^?mP;uzv_ zeC{;g3}Hu+Tanpup;_UZGJChvobPGr*Y3VK^~zz>|H}8%D?g{* zJHys6>z%`n$O%`LC9SALuP!5y$f*?NDsv$7!1% z7tj7#zNc@I(F3WjFRwYjvDoq2owr|R{NR+U&*zWX6OSxExcq1F5$S@b*AM;8{QuJ~ zQR7i$xBiy7Lg}H!qDBndf3Mv<9U*q@yKcp2)&){ZoQIE{T~_^P;+(91Y%_RYGR*jJ z-I6!YR8H>jiGt-{L#`xO&Mr$duHg~*+-`MrUCOOb7gBB=W(_)$t!r2yRg=IvwWq!q8E2za;4b;|9*ChmwIn1 z!-Xb(U0v7v;%|^^uZnciwIv-qQs+;<>xU~KDazikSI3wM8*_%X?% z;~4++KN?4Wn|8c2PONFNn$<2-&$TD_fcHYyc=_NTk`VzrE^gEk65qwOdPCv`yY%p? zx+z8eVLlsfwV2ix-!u++l3VfHJ!SL4z`PFQc?%BNu3cDgDRc+JeZC7TquP>~=Os?e z+}*sqYlE7s@Zw)AcF87X!tF`cB9R|zrXLsKi)WT`vu!Qztq_l4*I`$ycii}V&EvRW zuANaDMu`$X4WGQPy_Kyz<+$XocWQqdDvnLQnA6FBn~`rj)0}M6J?n(ld`w#KTI1cV z!zbLIFh0NNv#a--$MFyABO9LIns+EryQW?s@^++4p^@UIYkaQfZY-Ws&yyclE%)F$ z|8|kSsE3h1`!pG??Zv-Ob9vqz{^xf2oF6X_1~xbw_*u2ZzslE~^Yu4t=VHEspXU#R ol!s{^T|Mvp)TdVU&xJqUznAdrM09K7W>A*#boFyt=akR{0P(4V5&!@I literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/3a68be8ed48ce0799d2da0027b48dfc94dade8d3.png b/doc/_build/html/_images/math/3a68be8ed48ce0799d2da0027b48dfc94dade8d3.png new file mode 100644 index 0000000000000000000000000000000000000000..e392d1873d691b0a2cc242e0b64aaf8b27db7c16 GIT binary patch literal 2146 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 LcXO(QT}=KLPFwO? literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/4323a5c5edaef294453f24e767d1772c0bc233ca.png b/doc/_build/html/_images/math/4323a5c5edaef294453f24e767d1772c0bc233ca.png new file mode 100644 index 0000000000000000000000000000000000000000..f8a3b011e624f7ae6771d7ad3934c6509aeb98c0 GIT binary patch literal 328 zcmeAS@N?(olHy`uVBq!ia0vp^h9EWzGm!kmHTx%!G6?VqasB`QKafd0(7(H&8mOAT zB*-tAq5Jd8^LLHb?=O)^@RPZ}t=*we)^MB;L? zfKebHSBe9hf#5bK_HF0bQY2?^gf}xcH=AtY@nP|qe{_On_mcLvOw7#R*+OjZ>`SQ5 zl9X8H@U_8phm=$AqJzse#6Ku$IN{*3Lu!u#`|_Qw}I8{LX7U`@AGUzhNhX3ey)u=j(hM#Ms)3G9(&Y8y0R!Tq%EHVva-V d8)=CLN(|?I8z-$^uJ95R7@n?vF6*2UngCojW(5EM literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/437f2299194c0bf019dd646a9e9c76092e57d919.png b/doc/_build/html/_images/math/437f2299194c0bf019dd646a9e9c76092e57d919.png new file mode 100644 index 0000000000000000000000000000000000000000..6a8d02201753ac5ce9838e96c1a0c03a2eea8ee9 GIT binary patch literal 626 zcmeAS@N?(olHy`uVBq!ia0vp^F+eQM!VDyt=X~7{qznRlLR|m<{|{sm5A^RYs0OO$ zFA4GsW{|i$_k65*Hm-cFDb_4r{mQ8>bu2E+tN*`s~bKv|LEuy8X&b+X8{gymUzD-ZFA23|rp`IyKb3c|l zSi1eU|E(Q@2Sqj=F!Q=0VAP{%uIJOL_;;oA%Ee_m&QC3_d#7po2OV7}ExzoO>TT1m z^fwp^SMHMd?r!w@38ao~D;=Fi$+xsF@k??D_ z3xp1wYdYjzDIK9aVt$8S9$TIHq4Yc*HmtbM<*|HA;8Qs}i@hgf=titWXqw4q# zTMQNeINA4;LL|MD$^gJIj2#l;;nO?e<9}b-QGtyY)iOL53LkL*f)f7C~=Pi3g2hS!(S=DF;~# z7Bljf_YY`6VKm1(9_QipxW#ignhL{yF-&ghnw(2MgHFFUNLa+3k5_d4b{bBYZ{5Zs z&AW>r3)##*IW(`xFLyD)qSo9G#u+Oey9K)3M)O&0u&s&8%rCc!bo+6piCMNwCpLLH zy8T)^S{&k#+_$bfvXTMZcR`>D(lL%%m+Xm=XBGEh*UH8iHp0ZbI&Hg8;X{Uhbw>Ma zIH5-RUY3u=or#NMN7#1`;cs0>Xs)}{Jz_YfnGu1!)bz05P`neezSzTxNl4D@fADL zhE+NR*yMiDW1QgmNrX7ty|nKOu8TOPN4pGx95w_uUNwGxCW(5n)J-nHENw655npY8 zQ0L(56!&1fDR!D$bNsd-UpSsh!r`>nf}-wZtX|2D_~&%7Hu`a_YsYa6CHiGOu3yZH zC_PqLu{(u`<#Cz9-NGf?{j>incQrLK0b_F3W3lSvT;fhO#G#4>_B10 z%(34-+v%0iSv){spT=%9e zT4&N5da5O3$>Acyu`^bjui~Y{s|Md!7IrCjZdX-F*v#Oyhn*l$D3eNCR`nqzK zvAH|qY*0P^$yPc&lgcvSIjj4Teu1hJ2v=4r6~#KlI;kW$^+#g#u^7 zg@cfe+D>AKZONOfh)oLxe!o<|K;=IQ`$9Sx&m6LRa>qpdTyZRNIJg8Gd`sXikO&R4`sm z6zvuraa)PKfFHHqkjzRk1(U7powCrUDT0Wm*KB> e%hRyBa{|DcMz_ZK^M4uqyf8bI6SC1dFyp_x7Go;_ literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/4b19c5c53c58678e9292c8e646b72103694e99f2.png b/doc/_build/html/_images/math/4b19c5c53c58678e9292c8e646b72103694e99f2.png new file mode 100644 index 0000000000000000000000000000000000000000..b1343c713ff8d20d1c0730208da70e9fef453931 GIT binary patch literal 507 zcmeAS@N?(olHy`uVBq!ia0vp^*+4AB!VDzW?XfijQU(D&A+G=b{|7RO2l{sxR0CD> zmjw9*Gn90D%#}F5KH;;`%l&tM>(Al#21;=jctjR6Fz_7#VaBQ2e9{aIjA5QGjv*T7 zlM@;k!dMj+9&q4Tp#7MWLCEljiH<|~F^(g032bt&bLtHjXeKi~;!U{57P55JiEV$A z9D>t$%nxveMr#>87iXSj#LmWck5yp$f)`1@y4LY}O0M<}Vq}(g>Ed^tedfDUo5RAz zJlFP%7)walF>|VyG6MZVehckDAV_Rx>uzqXCRM`6lGV-}+v7fzua%8~nx3~SON&Np6Y3pl2xaO!b` zEt7=Z<_&de6ZoAnoP(ZKoZyylolsHYa#d~FL4{>Ip0wP&|LhNsLE{>pBPn|ubPE%g zrK_YeDJ+t3DG)eg$&o5ELFS-?!efWe;xUrSO8-|1P4{g)#b8_-!`1jlOb`@*p00i_ I>zopr009uD)c^nh literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/4c7d40be0b140d6249e2761f424632441eb1f475.png b/doc/_build/html/_images/math/4c7d40be0b140d6249e2761f424632441eb1f475.png new file mode 100644 index 0000000000000000000000000000000000000000..254c158f5379cd2bff75412e52bef5a6ce15c279 GIT binary patch literal 2110 zcma);=T{O88^&=P3b@P4k>)^fXU=k$3=zYq7v>kiWCG6;AQ2mk;;2s;~B0Dy;llnwd$ zj`lMh?5iWwK{~kG9v&VZ#s6R0Gf$F_Xvi&BCpSRd3IG2d+!|^l=#|gdaaLc+F^^8i zBJI3l0040J-{E-x1D^r_gh&V*OZVW}0dHKGlNeDwlv$ z=T0DU$5A@C;IT;(x2&bSMUU|??hlK#zPftAG~F;AI$-haP82ISBo=WSF)pcWOh;(z z(C+d%3jsp^MduU2m0)VI^hIa1U6lEDJG@1i$!4nrcK(6$~yLxQ$D9f%Mv6tB7uD zU=ldr_YfGKtBa2~`9h{YEjoU1za~U&#rb#bXS4A>yNj&O%J*}?Ec`^P0_V1dcih&P zU+v*rreR1Y-$(+O*W>5<=`BF$TE_fys#PeMp)CKipjf1jL7E~> zP2|^?EyAsxSPLE9pXG&Fm#!`HHh~=GzuY%??U$jwTpT4V7F9@}WJFa+tMWTBd8d7y zW42$Qgil693=)ze_??ES!{Dntz<3N*1@|zltsqtN6lwZV8u2MoZauH{aQ zg;umGZ>xh~;BV(_8k(tsBb`Dt1Hu!n$N&lZ)R=Ex*?WmI^`(;HJjZP4+pex5zqfQ{4(xu&-!?Hw;ej@m6@w^OTRpZb}=36{#(+|Uydj> zKJoJpe5q`--KV$DW&P?)aRq$Kakiw*>Xvxn{V>uDU2_j878YbpeTrnFi zNdNq5J0>sDi<;A?6t0Tpy*$+nGPU$hwlFR~Ol%g~7|2yqinAVF_iTsQ-~8Hu<~y?p zsrK}0hGP`ajDcAz){>`im88(9@{&%^!B_vSMznN5$}-1I%8y#Mcq2;l`v%(r2O~Vv zyv+-@#Rn@vs)or#&^-qQ^gkutjZje$haLc@p1!8oKqu9{)et_oXT87%gT{I>P<`w!{r%0bhTic=zg0VL!eE{z?lr2^#F_dkeB-=UNS>#Y<3c!dtHv0f+6l0 zGz?3$Y6gmmL!YJ1R&nb0SO=4Xb9|a$0xaBlY-A$Hh+Jm`vk=UTpg@&Bn`lpWY5x+{ zFCo2~kVa8@Td7x9V*2;<8hD>K$D<%&hpE90o_#4!1e_rBe0U0}^`}c6BDE?6zat$e zV3!x#d;jubjslV+fFhd)PH9&5%b{3t?1}-q|ahz?bIc>s>;1Uv4U!- z@RXu8Hoo(winREfR@YC!M4Sw(%P=2E6-23}i3+%C)iCw?c@APVPx_Ec%^q65fK#m7 zGewCrJR$}BuHqqMB9k6e=^?A6DNqA1IeiB&6u_%;yh$xYM3ZcbCF~R~VZBSn&Y&|4 zL{OQ2;+PfNCZO{-ugD=kjY-V0uHV#XWURQDFzW-Y1w{)PaW^>&#d-EI?qPtAAiX*a z+Nxl=uh?5I*s~UO?>*+qv><#W^UtOj-At-S+rz{yffS-S1y6)~Jxs_EO{)Ax;V5@6 zx!X!PU-qF?`1Za_hP59~H|s2@MtnrOxJe+InKT((iCGEUQSrXzk}S2q>n~nx*HefZ z(!x$-1oY>yrdX{}gf*cTRBCoTzO0@G=7E^>=TUr+QZ-@HE=nH3Z<69I_^nWtpH(UOYavmL%cJ;27Onqddi@5D{m&g@GgF)TRs-ve= zsaey1NRIz1oBP}+&p;AL9}f)flpCM7(Ok}poQwhmSWhg`Z)gif?OzC-y?|22M!a*p zxCkSwLxoBn2(eV+P!1&l`R3}ml2>~3mPC*?liYajhe<4B;&&T`_g(may6qzPzSAznmerS%b+7x!_YmaSE4tPLQh?f$GcM7Miz94 zu{Tz+sW9cNCodBX@08EP=|A9RsqFnTv+`?}p07#%SGFXwI>(LW!1-OtK#v8XH>YnQ lKkuhh>K2od-1SsRhdi4#Ds0BmWaQrpfUtG4d2QvN@jsQv;eP-C literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/4cd3f22296f0a10cf5a10a200669957cf04dc550.png b/doc/_build/html/_images/math/4cd3f22296f0a10cf5a10a200669957cf04dc550.png new file mode 100644 index 0000000000000000000000000000000000000000..b82c1f25ffd4501bd2e791eeac4e3f747663ad4e GIT binary patch literal 1410 zcmV-|1%3L7P)O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000EtNklIjKVw!Vi1yt6hSLpf1!vPEL8F!EGU$Sl+8=4FLniA zL;}+{OKk`he9@I6inaw^^w~OyfenaRiPWwN4nYEihI;Ou|CxJdW*1+C9(I?zXU@+z z_ug~w`2dmVrZ=(@8X9OAQ-UZliRt$PKSmT29u71Unm)ztj0q@+5|e)9-@+nFFBoCX zT?hes-S9O1yXmJ!Z*zG}KomuPQuLq}nIg3fG$Md{VL%g2PxI_o?!(D30rgNE?n<77 zC(?`o3gIO%r5#tJ?{U>MP%y{B!=s1+O^5$fjToS^5e9@$T}^G>Sz*H1919SSA_lY& z3=7j=fB`zZbN&=1-S^=8P$=c+sI^@{_kd}j|8cFw9N2hK81>O6zDxteJY#@77bQ>~ z#c2*mzllQxXv>_KqNkh6d}ZJQ+G;uWWoMxp^tHuBeGG4n2FQ15_$sZ3H#s1(+_Lc4 zA=KNmKx+<4t2W?(Hrklw@#aAqRH=5mqI_!6#&LWt2Q-@iaS>y$~0;WkR`-U~wGP@&{z2_2? zz53^8D;7#;o_YA6SI(S*wsO{hMhMr|Y&^tf=tH2=VH$h{rojvy6_1$AFlWbGXS6k?s{%yYv zU8ON;RB~SyJ0GV>tZt_4>TQ{eDt(PP=XRrh;0Exk5wssr)>>R6Z$I=-y@UGxwDv>h z(wBLtKdd?jsJ3QC`XSw{pLIqTXyGMi&AH*o4Vvq6A@_aQ#vK`7CQdUM{Krvmk0*9k z5IcNhHO7p4XUYEevMHu4b*FLu<&*1C8YioRh<&2z7If1I0=g*4Q#LDf#p}Cn(4$crCv7Yu_6a5_1Qa8n zwj|F7yp7dgLXpqpF(AyEq<}*9j4F1sC}NU;b|rb1pwPnhzi|@ic0NF1dn*l)f8izw zs02`Phf)0EbBd|6B~aIqXAi~f6MINN5fcPdvWJM-9#C=Es`q$MhxcUy3fps+>`k2@ zpt4Qr|cv4jQ8az`#1rWmi@`A58PKJGV}({vE9Qfawh8(3fnW@ z7iW?JiWn!L%q1hwPkzB?UmYQP#``AoP{b$!oy^WtpNI7-zdG~vAFe&4ip$v)F-}02 zbL8n@>G~+`hhtB?PtblysiR9k)7pi_@%07*qoM6N<$f;z>0EC2ui literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/4f8a60521b12d9341a7d63d315e8c4d6d4944769.png b/doc/_build/html/_images/math/4f8a60521b12d9341a7d63d315e8c4d6d4944769.png new file mode 100644 index 0000000000000000000000000000000000000000..3c4baf722860c066e5ba5bf42b8f54750c74f66c GIT binary patch literal 824 zcmeAS@N?(olHy`uVBq!ia0vp^r9iCB!VDz0th>blqznRlLR|m<{|{sm5A^RYs0OO$ zFA4GsW|(W_arbw^`TgCWOI}K>zccO2U!W9cfk$L90|Va?5N4dJ%_q&kz%<#@#WBR= z_}LKK3=v0(+V9(Up1qgn^C5mpu8T*q0PDd+**Zs_8BFac;82use4o?QI>GFQkCf|_ zCms{^3O@4ltHwyTY*1)wtq?r8BE2vsQM}~Y?%Q`~-rjk1iD%sA{Qb50&t}h^$u5w? z#;NvCUin1Tr`@)T!+(10V6=@s;P~-R$&K|_Ov2W^;tHC6XjPz7tj+p8AGIxer?0L# zm=bZ;$Xn<7J+9eFf%(%|n{IBfda>*%(;BY;&!>y;IhqUTuocTxw)V{UcD*WaPkp5k zk4V+rn5W!r^TiVW&$)g4Wvb6)@yslfojLy*qxQxve8q7oXF*Hg`h&*}U+?G-3_R0w zF+b_S>8N)bC#_PhXk%h4hkLuO+9hm>wc~&@?3`nLBvSys}`{8j+)# zze+^T`IPKkqU5-#x7Z`(L-Xfuk0;$*?l~{H<+4ud>!dE0m15td{W#ydn%{fQ>sB4| ztl92>x6Y1>wo0KhU+`An-SR0dT4wsQ&zsV_>~|btmu)Y8!*G9M*87D*t5g@2--P!a4nKO! zFD*DTQ#r}h|HI@5nR{Xx6H8N>tA%f7HqLnW?^~mi6xV6R+_zEZs~MCx#xHf4o*{A1 zZ~{~8xo-x09viG&>R55SDt)U7$NPx)i>9#&=AXS^cPE`e^8)MI+VyvX5C2a4RHfdm z4Ac;C*fvr&{P6CqFTbw_E#S^dTx7oIsYs9_>#hYNSy>gQHJ3PWl`H}=7eAEx)hx(n z6?h|8Wa@{ykcb14e~$pQSS4-?S|@Z*UM?;}>}wp*3fuolU%#5^cL(44>3VwOT&t-L e_tlgd|M6EhKc8$ZSaS)K_&r_yT-G@yGywp;E@lb< literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/4fbab675639838c2c3f11f9ad372ec258a842318.png b/doc/_build/html/_images/math/4fbab675639838c2c3f11f9ad372ec258a842318.png new file mode 100644 index 0000000000000000000000000000000000000000..169212a0b8be870f1fd3d54f8f75f5db55bfa3e3 GIT binary patch literal 1224 zcmV;(1ULJMP)O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000CdNklf6N5CSqAW#Pkb-$o3T+_ULZu?o#Xw6Q3JaEsrO4*Rs1Le< zP$;D^c`B*4EEaq+MN5m?pe}t^hPHx%&}=EFX$vl)s3A!FzI*46bF*{zr_>h@WcTjL z_kCyX{~3TWw;9hCjimc*1@g(hCT?Ce>?VeuCf!y2ek^#vFFN^!Y9yPO+oW3QqW-R8 zb{~*h!W^= zaeqA*8~hQ|_dFIDUOs)4n2Y^06%>It3b^D8#HfeF;P>-)L>K zxtgd*dBn63IEK& z8~^?NxR{W{sXed#d+-#k(=P}6ff<_rrTfUaBtY8-$CyE;#0<7jUoJ%MgSEAXD$fkD zs(#~-O~}j#haEGtK8Z0O6+T3s8KeA>8=|##4!Qn7fEe#XFk`tq*hctyM#SYBtJsxX zMLVu57`xNKajo)<_~el%ua}u6{XUq-lDwC`=3~=bz|ZR#DLl{UonX{kg{=K|XmyTJxsU_VD2Mscpb z4f_V|Xm%Mdi0Ye#*J=YTUb>tG!+t-6ALuadEl7(6?7QqYT0guN&&Mqr#z=eyj8jLJ zrAdVSSbD8C(Bp+OOGOV6&Yr<}02 zkZ*+|H zvP9zs{*h$|IuZ!Sr@6l-`~87^Q@r85o+n!=mfbiyS*BY2t0regI5PLjR{s8$_DLnp z^L>tgZfPf=#V?thS<}Q7)SEyJ-Netjt)1CZ{0ZCQB+Kn8{*QbsXQrKC==rA9&2jC= mcl;u4ySZuKYjqVLII}0 zmjw9*GjxCceSW{h-Sr7CJxYw``uIHrnZ;S)5n0T@z;^_M8K-LVNdpDfdAc};NL)@% zU}&yf%QK_Fw_z(|@RZ=jLPoKp;ubOwa&}%XP`k`3(f$5_?v54eb4*(s<<})J$E-Cw zT&r+$#sB}thiBelH|Q2O;9%CgzJ-hJ-v9rJddcw@7qW Wda&X?jLlLg&Df!jy|O zZ13`Uc&1BAC{1uRH{QTBm+wkmn@&}yqT~x1HMVKY33}_LkHl=ayiO-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000GONklbDVAZTe1rc>=pppk+KtWnWHcwHMI)YG& zq)fpFt2KrQzGx(f($=B|1${D|hXxvuW+k9T1(zW8DaLc}o!z~6=FaT4^htV1b|+`f z{q8qs&b{}10d!{j?W-W_G3nP&8zGySe2d!(bg09y9VKj_%>uQk$M%3rap3L<^gi|&e` zL-Wh1<|1CA6FHAf{wu~{^X%AfwFI42Fi#R48o@TRV^gpFFm+U=(*{HK z5oSYt)A&Zvv0GxV4N*rN_KpOd4W7G-zf9jBGr?+PZsJU9X*)s7fpLQ^{um}HqJ z^S;d{F3c*ZV=!v2L}!yqJSW$7hoP_Wk|b>yPdG$Avk0(t%0*W@cKrhh^tO8saezJ_7R?3&5?hvy$$gJ*DhB zm!Dp$vS0~J+I8pvc^Pa#$wg){0hMOv+b>&BMh)woBb0ln=++bVeY+;@(ADnspaK>< z)xcMG*-t!8@*Hc87ADc2_d6&08tejHljksHG`{bz>5uHg3Ru+2RRqsdf>w}#iV<;& z(P{r1@UzoxFp!^dnJ1~iKyri80gIW33EGp(!%1yR;li}&n9Lbp>33|ud{R^fRpk49 zw_kw*rfI*{htg1E*1!$BHaj*&cJ%sUZe5$Tt_MimZoI7ji>*lFt-sJT2^mVe!W~|G zyVLljKGsoGneFwaGo5%RDi~LALh~>ulA*JYMpW6ko@@+P=hX_vBRCxk)cLyhLPV7f z_N1ea&QPlz??s0K_SbMG>edRzn=%TWcel3c%(uU0AJib{{9+@j%38hY*#0ChZ>PJ591+?5M+WSfVn^4c&j$NN?FDR<4&r+@gxu&5skLiL@(4jY#7YVBb*{TNlS$oM; zR9T-3y%LPLzVcSn1!Gt{vv@UBiGiU*e(C((w=1elXtH#pP;>n+F5tSBE*L{P56y%* zv5xoHY(rIsJ`M>MitSv$=>(xpFk02C>@Px9Cd6CM&_k4ilBUn-B^diRq00JdFg)8U zdrZJ-1Yx>hyqfllt1>g_C-l^MQu~!I7!~^u+Fm_DbW4FJ00000NkvXXu0mjf?s(BL literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/5821f26082a79756b532348fdc05c458a1b4d96c.png b/doc/_build/html/_images/math/5821f26082a79756b532348fdc05c458a1b4d96c.png new file mode 100644 index 0000000000000000000000000000000000000000..1529b4e19331b54625885fbd0ace069aa3b39213 GIT binary patch literal 1194 zcmV;b1XcTqP)HBogzl$=R-AME7s~yY$000SaNLh0L01m_e01m_fl`9S#000C9NklX5gy^9v{>4AyMXU-I6=98D zY7tkViYTT^w_yR(_CEh6s02ieTd=6&ybZ{B+| zS>Ufo0zMO^T;Ah1O6Q;XE=p+mL(gTM?+rx2-_ZhS^F!o9RHa9%>@g zy+9ps@q&f(l5_9sD+i;PQIohy5oldatgA5e(Q#*VZVMQxMZ@Gi%A$0JbMG>jL^VzO zt|9{6>W;MyqY^6XScx#{5m0KH*@1^*N>lM0O5sh{M4%7(RMH$Uu>zD-xEmp&eETZ# zCgdue59P1q@G}~zT1qr)yMSw5V=P@arETZh^nCdv165m3$jdYBD`tOgJq8obPG>dk zgh@fpcQ3MPIu@~obL0}_!8&j-DJ;YLDYOa5T5S`EBa*hO)=epN zyn|eGXg6d{MCmLXonyw!sNQnm`{;>macUnBB6AqZDhHV2#KU zO?tAZ$WcM1OXasc+N&%5A?<0R}w*!a+Wt5z7L0)xk_1pvR!-*-w zIviFV(4_(Ujst!1tvDo{)a*LKb7==7t977~7 zCnq#C>=osi(eS&9dCF1M1Az^i`zI`%>v+P&Qe#46bmK(^&!)heCqqIT5`~)$n4=q+ zqtlt4nRYX8I#(jr)+5Q2!=uU*!^_9RcZr9`hx5cI?Ffko33CI36^>8N8yQp>FF5@< zCL!S_!{zhU3`^#}Wx8-tTHx3F4UJEB)=EpH>Fs8?6n^@E0qd&z)4XiwB6m9c3|O4O zw(bA_ga4BEAK)x|&UG!}DlgB^|NEJr?v-H@5WDWzcx!))sFV>e-}dK9Pa;JZeA;8J zf8a@Egh1WwAim=L&C)*eev8@USjgVsUht`UdV_1j!{ZmWGOwH4xKKu_PGzopr0MARD2LJ#7 literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/5d7004dd45c58bd71e97c825ae1e74559b30bfbd.png b/doc/_build/html/_images/math/5d7004dd45c58bd71e97c825ae1e74559b30bfbd.png new file mode 100644 index 0000000000000000000000000000000000000000..50a88a44c0f600f8120bc2bbc420d69f7ca6ce3a GIT binary patch literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^!ayv-!VDzmR!h4BDT4r?5ZC|z{{xxC1O2-Ts)4Hc zOM?7@8M;6JKEGe$?)rq69wkO|ef%DR%;GHYh%9Dc;5!1sj8nDwq=AC1o-U3d9M_W* z7@8~B@&p`EJ8+93wMffAuYoiEK|zC|suav1)q5goMwzGgjpU{2r2m7JFs{X4?|Uv)a8o5WuJi#V(@hJb6Mw<&;$T9!da^T literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/5fb1ead7a3ae880faf3e493e050ee55a0e435038.png b/doc/_build/html/_images/math/5fb1ead7a3ae880faf3e493e050ee55a0e435038.png new file mode 100644 index 0000000000000000000000000000000000000000..e7738c1a0bcfe127aaf85dfb6894fe9d64b1723c GIT binary patch literal 987 zcmeAS@N?(olHy`uVBq!ia0vp^zkyhkg&9Z|3ALsJDT4r?5ZC|z{{xxC1O2-Ts)4Hc zOM?7@86@`4y<75m{mX>z-yY|UL>m1+0i`$#JR*x382FBWFymBhK4}I9W;0J0#}JR> zQ^R~SgdHVnZ>#v0Pi_lk>9#ddYMOpY;KC)RrQ#p2NbTWJn(@fh-`Dnwf|HWc*Pz%g z4UJ0<2ebSy2J4$H{1$e>f&Z99HaO2$ zKYXB}^uaQlw?7{)URR>|MDo8$OX#+1JdV8F_dMc!)z6$&ud$yOas1wth;Mb%{!V>; zgl*H|l*6KpH;r23C&*{Mt?}cX{`7CgA{08dKSg21N6w%14|``g+)3f?urYJKZFSAs^w2it)8gMI z-00c0qx`C>?W;Z`H_qoD!+zG5aC^VK@l?BQlZHUNo5Yg`lA6JJy#+mi)z34!3*T2d zZB9)*;pD`dRlVkh(7DHJKWUc86{MWetM>@g=DDWKvuKHCL8j9zy*=BPZkN~XR^iP* zvi0;6)tDoT&9@uQjeh>=-u_88Ctqlu?l^V)=-W?|{*+!mx3&Mk?x$}fV&6`bYg}!l z_3OojyQ!+F$1C^D*{eA}Yr(! z>W-63v-8h*ET41ScIK}0Em^x$rGsu9?QRcyQ(9bEcCgBLZM~Yw!_Q|oug!AS){oiu yyT;C>s%OrD_`ELScS_V&7KbLh*2~7aXuESIS literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/604066808935cbbebeeb48a5590ae334a9511f26.png b/doc/_build/html/_images/math/604066808935cbbebeeb48a5590ae334a9511f26.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4b9c26708a27d7641305ae9af2885b45d8a58f GIT binary patch literal 1202 zcmV;j1Wo&iP)O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000CHNklHmEdKCAX|5lALOFaiWY(h zCSW#{#U8qZ**_d67~PpaOUP>9Tm?no#R4w71Th*DA-MC+UG9^Dd<`&l1}AY&Hmtm{ zi(}OIaThbx->}E=DSi?J#yvOUNe}{y&rUGGrhgCg8b0v|aF5qG@k;c0A|rzM>6Fa~v?|j_?7^z?HilTCq!L(8uFCx_Ct0_bnPAj0Ya${= zCnTIev*DjY%Gs#fD#2L(zz8R$ zrcXTo@7vRqrx%9$fH~U#?SEj}M35Z;K4t{j5+gWFb6E)@cx!L39A2A5R{hG4eq`61 z#f}lmPeQ^=MYN6c!yKU;U4q%yBp}3j2aM1vV{-rT<1!U1M#Zcs<+_52yZb8FE%xDm zj=Wyxw$=M!9oq-pdI{ZmaMxWLkFsUXvDL#|_V#Z|9ILZW;}KY*j+R@kJP7(=!D#W# zB~_Q*)LLDc=P#65pkRzW*}Rl8PE%`jw`Se}`0LaY<8gWU8h_p_$yS6Z{&Z<;LNK;j z(oUE4BP`W7OERoTHY=LI=bx*yG82Na%@&Y$Gv-zq&k9{I;!2?i^ZD~f%W|N0O-U7O zeBO{9HqjM<>K{lz`sA2wJ>^W`7B}Aa^lrHM{Re`D6RE|1O*C%cZy9!=D+0g2&hrgY zW^Wod#TVZ3JjqItc2npkO%?y=LX_D@YtK9(KU9#e=)B)c{CYTwK=I!WQ)bG>6}&Hj z8hY_xw!2kkzr)Z9QqlI}|69IWWtKtet5PrJ+V$^RnHjb@>uRl@{F}<`KGbAmA?1wW Q;{X5v07*qoM6N<$g3qQUhyVZp literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/61987fe37668cce0640009518e7aa9451c370b03.png b/doc/_build/html/_images/math/61987fe37668cce0640009518e7aa9451c370b03.png new file mode 100644 index 0000000000000000000000000000000000000000..c7e4655798a5e05d89c5cb914eb740268aab4ca0 GIT binary patch literal 1500 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 Xd@`iSPH?x__|xDVT(Pxwq~!kq#d|Y- literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/66e9ec52652f5885327c00676d9a4a1c4d4f7f47.png b/doc/_build/html/_images/math/66e9ec52652f5885327c00676d9a4a1c4d4f7f47.png new file mode 100644 index 0000000000000000000000000000000000000000..600852cc72ea11f809fce22f85da68fc6f7e703d GIT binary patch literal 2640 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 literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/68a2d79b5ad6f38311ea4b1bc63bdbc4b67df02b.png b/doc/_build/html/_images/math/68a2d79b5ad6f38311ea4b1bc63bdbc4b67df02b.png new file mode 100644 index 0000000000000000000000000000000000000000..7361b46cacdc1c3572f7cd1d1032ab8eb1492448 GIT binary patch literal 845 zcmeAS@N?(olHy`uVBq!ia0vp^e}Gt+g&9b?O|Jz}1_3@HuK)l42QrBV`ga#p16A{v z1o;IsNEmtCJ)iKhyX5!W{p&xoA5hr~l;SM#h%9Dc;5!1sj8nDwq!}2PR(QHNhIky` zJ8f^bu%pDW`DfMA%Zh($=rp-(nj2mz_)Z{4udAbX!ZEL-thzeQ{}{KIHOWQHSMMMyjwtKeMio^hR&7y|>Ek%FN%V2(7J2G@d;7`Cr@58#ixe;8*w3Iytv0 zNb{0tV&alpFXCO8Ua+jm-MLKr=aX}Jw>H~dFt9p3**G`3(Uy7L(KT;*jeakk9Wu>H z@sEp_4U3K48l9ULs;)hZZg}wRu4Z-3g4YxNd|t7Bbu8bRNxZq&tqQm&+)Upq_D#C+ zmEx=-Pp>OGjL+Y@@Gj!5u0z^<{$+2qnIH80`0R48=(fq-&u@6&&boS!spsz5sq9NkbGJGE3P(`44B^vUZd`RZ;D_s}*_++mn^ve*2i>;sA3dw=_4biR8oY>z2F zckD962)3C2rEg#D{CZ!pYx+AjjZ57L+1Wj{o7Qh>IK4wz%*bV?l-Kvha-P|0=QDQt zDXu-B!u6>2`Ie(switFzQhsjmL~qrVwfeDg!BNiY6T=dO>b(EdEz@P?WtJS z^_3N@cNV0lJ?xyFxzkTM_kc;*)kg31r{-l3zI`mpzt@=Uw(2P`kQpx@E+`JK%@f(K xloo%y&c9anLfF2)+t2f^1)aaxf7n1d!qe5yWt~$(69A9Tax(w` literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/68a7f1a9ea162f83dbb18eb5eeada4da9ec1805d.png b/doc/_build/html/_images/math/68a7f1a9ea162f83dbb18eb5eeada4da9ec1805d.png new file mode 100644 index 0000000000000000000000000000000000000000..c1024f8e2d45b54990dda34d402ca987fbb9ece2 GIT binary patch literal 1077 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 literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/72ccd2a09fe1d38b26319c571d7072d31e08bce3.png b/doc/_build/html/_images/math/72ccd2a09fe1d38b26319c571d7072d31e08bce3.png new file mode 100644 index 0000000000000000000000000000000000000000..711b3c087021e500d1cb906dc5374346c3b69616 GIT binary patch literal 1483 zcmV;+1vL7JP)O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000FhNkl6&p*W&cQmbxWn)-uT zp;$yB6Y#;GCM+%ZqR}W7tFbodgHN`Lw2)wRQ-Zb8f=kr)p~UgrduOtol!Otx+he=fT*Axc58@=x+Zt_wX(SqUwc>TGf*-tEe;04og@;h(%iP7`rJV2= zb6W$ixbEhK4{c4V%rr8odRp*$M#j5JR#n6PmP8G49W9L8`jFJ1BZ+eVlOU&?SU62jD9zl#p z$HP2TGTbryLrgp*cU#1=C;`V;vMX!TA;0=@auM!=;tAShx3BS8Zb>TFX=(}#g_x=l1-KLBqu_o%&`Vu zO6By7S?5K`>KneP7btvhW&XNDC!g|d-Vde;$P>4VVD`%sHe_AogNV)ZJdw;GHtFOE z5f8t8(qF;GKc5)fy78g`wSQQLN<>FTYnWra4$)gBronq)8fhH3uK6+eC|Q<#+*pTn zWv?8t7jLtXfwakS8N81qd17arr98$==iKHRicQi4okLBI%{t^#ISHO1+NT%KAs?Y! zKr%}^nm*x-zF1GpLQBw?G=1db@P&@7F9JA_OC_B{dOeg^1b5f^uFO_c%SW_7!{`hfwy+6 zGddmRi=T385k11@tHdrjS;BP-I4P{JcBop2$x#! zM&v1aq3BdmACAnclXcFie5eGOLDVUzdD?)R;pFV_lA?C2fN)2|$A~1002ovPDHLkV1iWZ(kK7` literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/775e11e817ec90bc434b37341dd7c56d71ae492e.png b/doc/_build/html/_images/math/775e11e817ec90bc434b37341dd7c56d71ae492e.png new file mode 100644 index 0000000000000000000000000000000000000000..651440ec066444a07ad8fdc2558daa8d53feba18 GIT binary patch literal 1930 zcmV;52X**~P)`(V$%i}Q5p7_WhgZA5MW000SaNLh0L01m_e01m_fl`9S#000Kz zNkl6)`D3}#bAgya2R?U7AE!)B+o&&;2Yi%Mks$Ic*d<%mT-GdxC(wG!zW3s)~ z+%qcmMAOA9tlkBwDZX?zfL`88Q)X18;5+yh2Bo@tIbcgrHsmS$moxEqYr#)=M6jF2 zgR%@3`%YS;)Y*M z6T5U_QckCVOTU{kLuf1|(PAAdjChOL^=3V_ie6F6%BLcEIY9DLX&RfCm?Bbl6Ep|B zgwzi^x~Me@09eGAj+R@1;$-#UCdc7ADpIg!?}7I&{Ic?i?m-UF62%3-y_8ZBTz3;A zSvR3spSs97iLCLZqcPIwCdc72Dps%-KkaH_q({o4^0Dr_92ZMqEM#_TaxclcHGQ~= zE-Mi-gb9f;5yC8CM}|tvkf(0KPO!j9>3PwSDTm}zo1KP(8c530J*c?J4G3(+Y&1I* zywU*zA43^c3ma%r`9t@}&?ifr@w;JE+~ zy|h8ku=VkkD(kN;k0f@^jN6$u*Hw zrPHOyP5z7{B6|A+v(NLbEsOcpMK@VnNd^+O+r!?HZHo^GRy8}OqI}&=#Mql=b_Dok zz3d?M~W%ybTz~Wf8V8hZ?YV$HDi{^*}b?oxlzRarnQ+1om19s z9IH3IK~;0DraY+okfw^JJ3}L!M?x>JZZfONrY^&AzlD5ZXM}YVUADjU5_89H-iArj z=O)8}Qk1fE586`*7w!fH6Ncxl@giR{s^+3(P5HW;jFf88mkH!*PvFaoo9wAzp+~~G z$xe(}$l_NMwF$pnoO@2nZBQT!l#q)SH{m$PJsxx<V+&ZwI4QcZdA zFmg)BM=d4cSb?=C;3efN8^e!F$py#4?YhF*S7@PEe`dFCnyF8$_AcAAF&yjd^pf$V zTHKRUpyRK{1ISHEvvtw*;NUvbO-`C4oXM;;<}#;hCP3GePjyEKxO=Hk7N*8=w%(@z zw%##olAVidNy0h%lJTjA(|*QRnFFz;rP`9}K1S#H9;&tvN|XodS5393uG-pgSj0|F zlb_n@qRkpR8^m@|XmroDTZW^r!ug1aB zMXcx(_&GhwH{E*R6-0S)J5q-#b)lGn^jl!nNgCB9)KI!xntj1-HKBAaqEJPfs z8BjymqH?<5tN7Ac-0S)*sP2r)^G#K49F!`5)%|jp4P)r%8oxK}Cq?+J?F($Q{_{e0 zx0#=pVLvX~(vNHUuQ_5Zw8Ks7BMnuHd+Q%*wS8{*7kB^dO?@K#<)8|?+bFC z&izK&+mw6Qw)R{q@oixu#HD!UQ1K%O(x#GD$8oAdsCU351ADQjv8;znT;hn3pRbg> z@P9WDq_0)0;PZZxgLJ@J-vN^h><`c+!yS<&*@PnG=k1c0A(=h|YQ^gb4Mjmw@7N4%V7}KztWWGO!OdW!@h2&hx7c`B^6!(UA`o zG_JX7R=LzoZ-Png?9HA1pNmGr>?q0rDeOUh7D*m-&X~#1AG^-V0eH#OP49t8Mm8DT z&fEC^A3IQThZH8z)>|{!kxb|?@yu#E<0ZXN5MB~+(~rX>Bb%6qVmn1O#q}L1d4Uw( zZXot@ppST|2QQhp>C-UD+H4CzNdQuKcLD?0OZCwAh&H?=0KEJ#OtPj%07^oT!kdcLAwDa6NMk~K8~P!fO?-n9&X zz2x{IH+A48!G!!%Fv(i6AOIx+Na5Z30|3mN$A{e1ftO6(^c674Pq)Vq4IRbf6nOa+ zFv-uFD!>MxXtzVe7r-Pxyp0PzKF57}Vc^3s$q!FxfuCH<;)Q|F!X!icA3JAXVhWir QY5)KL07*qoM6N<$f`=26ivR!s literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/78f08794d1aed52b66ce2b784d263d3e7376acf0.png b/doc/_build/html/_images/math/78f08794d1aed52b66ce2b784d263d3e7376acf0.png new file mode 100644 index 0000000000000000000000000000000000000000..4e89df5dc4688882b6bcf9e6dce3c313a4a4e6d1 GIT binary patch literal 1658 zcma)-dpHvc8^9-*SkZRE!6;8FXQRlaou=ApWuFaWuDQe^mk>v;9nE!#nPihooF#Tv zd@d7fluM2^3S*_V(-O)pN@tj?%-E;;Npc*DwSLK|A*ChHF3+{mE_^-3Akm09hV0SdJ3dT z3kJ<^%2pLyE3J!IzeE5)hxaX2N-cCC0D!s>=YaN#ocQDy7-{Tna6+ym-oVpDb*0(B zJLp9eQ-f4YXaKzgt)iu-JAJ8?!8!Q)xmt59?ZXTjOV+L-S#esIx5rvk)?1<^m*6Nr0@@i1{+NNF;p3Znfvqf= z0zJA0tFKV?*bTSHZMtaY(EbT!;RM-(asSf?jB{FrYua$Pu zW7+P!$TtES9EQ1+Z5y0<*7~ce>WZWCSzZWBQ<{>~Kgb^&FxEc$fH^de?}CF>!mF=j+Ldj$KI-^!@k<>nVjBM6r=Vk( zb}{t#Dt}(h%154)9K>OyZ?8!xI!0+NOh&6O&xe>BB$(R6VM`Jy3g2bmi(|rwwl!IqklZmSx+t&$o7fOaEIXj^q?e&UD3YvyuT{u zo(n|SS^Pvjs<_^4G2pfia=t^cvHYZC)0$>vWKCrV@Gb}6WuP4QZqq8T{h~?N(#!6I zocDhcT684x+*NPY*$gpAi$+h)xq7+9H{QRO@X87i4@Mxk-Ga~}QWIOHLVc1bN->1V zoSp1LA9i5)(vNtc;(mT&N}oKA)VEM|Gt{m*`NGl;MkFU=K9r#Daet+@o5W4MM)@7~cS~vUlWyHRjivO)BLuLuoZ2ed(Z|i*hS;sB+3#`6 zup<8T+D~Jz6DUHB1y=*{DG^0qts*LuUHqQnwi@RFtPwwI)E#&3!!t_whTo(%u0x#2 zY3P@!K&PIzm7#sD$|3EEJ!V}al8n11X7sx*uDU_Ev6`si=qpJOw@8}{9R07*nT7>{ z%R)Kd!C9w4sqJhTd;h%~7Groh6zK&DCk1oR2^bpG`1m97q+bE0TIXGZ7%^KOPpN)0 z*H}65;=K#TJuUju)vfE+Rn5&kXvy%!UoorqUOO^jvA>Pfi^(p7>AIHC)*nVk(2WRe z5o1YSZj4?djC*@z;9N($k)AxK2N8Ai$^x@0NMQsAoq`you4zgp%Vrge$8 zOnqTZ+dl7?p-li43;y{V@G}Mq9NN0G-9W-T4-%8nKzA^ zBuAIpTK=((Llz%EQ0pb(VJ73}b>8x?v3E^DScNj{yoZ|45u)@tzzF|A$(7E7rLm#H z?*cS8ujGH6k?O@_RmMOXP|~vLol^>aiVP7p=KHy#-FVlv+Y>!MAOAGcBb`O!^m- CG#V%X literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/7a9b78bdb36f2fbd5ca087212e58fc74dde40e86.png b/doc/_build/html/_images/math/7a9b78bdb36f2fbd5ca087212e58fc74dde40e86.png new file mode 100644 index 0000000000000000000000000000000000000000..899ffb83374ae000b23a800310bdf1380bc5eac1 GIT binary patch literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngd!VDytmPFqHQn~>?A+G=b{|7RO1P81(F90g# zD+%%oW-z+@^7HxM5+!r@cPDt5+DcUeWjG5wB8!0vj({-ZRBb+KpkTPCi(?4K_2h&G zM#bIgj6Riq4q~4-GqLeb5O}4d@;}p22WQ%mvv4FO#nZd BLvjEB literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/7af82c540112d04a12bed95744925acfebcedf6e.png b/doc/_build/html/_images/math/7af82c540112d04a12bed95744925acfebcedf6e.png new file mode 100644 index 0000000000000000000000000000000000000000..4543a0b272ecf91e81e77d6a7c03edce8aaeb624 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^f zmjw9*GjxCceSW{h-Sr7CJxYw``uIHrnZ;S)5n0T@z;^_M8K-LVNdpCIJY5_^IIbrr zFf>=L6`0lN+pv}K(4&xq7zWWj2Oct{8XCklY_v(_*~jZ(==S&je93c9>=F_Rd{-wt z`1^l(^b literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/812f92da6db61fb4e16c0060582e4cab04c5cb60.png b/doc/_build/html/_images/math/812f92da6db61fb4e16c0060582e4cab04c5cb60.png new file mode 100644 index 0000000000000000000000000000000000000000..2717dd62adc8e44a7e10c610254ce8958131b2b3 GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eK!VDxY_&1vXDT4r?5ZC|z{{xxC1O2-Ts)4Hc zOM?7@8P-cAy!>5qet);o+`As1->jBB1C-({@Q5sCVBk9f!i-b3`J{n@VV*9IAsp9} z6B0ra7?{$+*$h0|1Lg{7arqRnZpdX1n!`HTr%~j*nZm>q2kLoN_%}Y(5|21r)|P(e z4lB<*p8TomHc1sn3<{a1Ge_t@W-&Orob%yZCWhx{1dJ>y`xk@U@9FC2vd$@?2>>k2 BLY@Es literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/836d46125c08b336c780001fd9b6cfa2ecd6f6d6.png b/doc/_build/html/_images/math/836d46125c08b336c780001fd9b6cfa2ecd6f6d6.png new file mode 100644 index 0000000000000000000000000000000000000000..1fc99aa0e5f699c002fff04e6a6d9ab1901c5f94 GIT binary patch literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^NR4=BZ1;1OBOz`%C|gc+x5^GO2*k9oQ{hDcma zPH1Ql;W&DTfjv>6OP4|Iz!!#70*##?k_;XM`S1lCOPj&*n~jZ4F?Bja8ynlS&-RjE z&KojB@+8GeG&z*~GvA;nFLC3tv_zVrd_uy5Kc^OOh*+|jWHTNPo4|4Ve+##OU>gX*3=J4d^%z&4 zO-m?duoi#PP&R=ho$5qet);o+`As1->jBB1C-({@Q5sCVBk9f!i-b3`J{n@r#xL8LnJOI zCnSU6->ezZkMHeT*`AZVX_6c z+DxTx|K}lWx6f?m^;qNBG2bsCVZ*e9ga`J^4jj;I7x+K<$N`f^=Z1$`;ujv379`$l zSjs&^zQD>LC%xiWkIK2&1Je^WG;C}*IQijPBab<&Idsk$HNKz3$b6rv&7DVBz2Qh@ zebdpOA{MHW5?u>-IX>H<_~zNZ4GgO*W?f_RnDOm>Qi4Gfck$o<`V9e78iafpS}HVq TDo+I0g2K$x)z4*}Q$iB}^kscP literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/908550a4d7fbf593ce9180499b72adbf17b50d99.png b/doc/_build/html/_images/math/908550a4d7fbf593ce9180499b72adbf17b50d99.png new file mode 100644 index 0000000000000000000000000000000000000000..904dbf21fd3300598b0c735704d8bc9959cc0b89 GIT binary patch literal 1218 zcmeAS@N?(olHy`uVBq!ia0vp^7lBxpgBeJ&Z>if4q>KZ6LR|m<{|{u61U@$S@BlRk zlmz(&Gt4#excfWd{QmCGB`+n`H+JW`X1JO1Gi^=F)BmJ=&CoqJ(|mE@wmq_UJb#p2QG6&GDzJ9a zo-={cc8VMxyYtc$w&aEFNi8m$;O;2Z;ngNtvSs6ROP>ziXifGH0=&ngwokkE^oFC4 zU}g7;ildC2yrEfxt=ufrA39$5;;B>c8L0r9JI|q|zJ4IqI5wz2|alxwETZz;JO!T=C*d z3$9MII>YewIQRF&!;Uh-bHpESxD(TGfm7*ee|%nbyJgw+=dn~+r>}_3TDCfN>0R{>G41z3g}sj!xVz|GKNc3U z%{4Rk*&_F6?peaec_;2#oh+r4pd$Eh&WsfS?wC0W*n>%buU1G}$wE8d3-ksx+qF8mBFK1w%o0&AG&P$ozhTU#3*edR=~ zeSYcw^Zkoh_J)0Lvykn$cV98KeUbTl1;0d-gQA|-=VZy;Fqu+WTb$Zk;nNXpI^)5I z`9d#e1@|(uJa!OuXoXjm=2NGu0_%fL{Wv}w7j^iyBvfdw5Vs9^yS}wkT!{8eC zxeoUmxtC1$FFTT1AMoL}N_KR}<1H@Yt=nYWj_H2#)m(PhSzXa@_kG#A*(JHHS#zQq z+!o6EHss$?G7w)dFD|rk(VBo>{ueubZDd`jy!}O=u>afL4uNJXk9l@*Il1Rew0K zmjw9*Gpv_Lc=@~J{QhpExpzH2zgaDN1}Mc@;1OBOz`%C|gc+x5^GP!>Fk5)KIEF+V zUOU}4L)cNIAzoW9j`rD z%AP4&rP1Xn7~S0w=*Ta6$NPfw!mG{gP8m4{QI6MU{`LHpUbgGaj|DU5-h8<||NeU& zhl-is_BMMRP=B%Z|6WPIZ^1V$?=RlAPIyk2e3_rTUrNqqEpe+!#kx!0zUex1c;2MQ zoP~4S|FT8od}(LiTiJWE&5&=~gyhZBEqLxN-gGl)fySNvt=oRd{JF7lrVZ!frwlJv zOj_{sPqTitc#QHtjz?#1Y`Wne8TUO^zTtO@M5g9)elA|SmnVfjx%5Zfw&#`5bGYEx zrhLTU$U@G;tF2eg@}7KeYfA6ORoYLU>xDfK*jbULb8KZ-{IXVs!=X)ib2$H$x5Y$= zEsZo=8T4h^sef<6JO0QW5!;n|y?ov#)7`U$R^|Tts#N#NP_k<=gZhUVn@pmYY+>+S zTyW{%%D^jiFHSCHkm@<_C|!5!k4f0BvpaobuGYciNZt>$T(gFLGMfZT8zZ zPwyF5Ez8Z&5WR=2&#$evUXxYMzD!}Nc*+*ONl6*5!p%t=ZY!F4-x79s*7QzEsN4Mb zh6%b!l2x-+gHO4%a|^^W7hc$+=E~FcaH7qU`=_m<{X?4X?pk}O@^h^8&CQZ8P79d* z%1+j=JF>~)%9RZ>M7m=gZ_K>=qbef4VB553_jb(F^8dvdySW6wa>^bd z*_&pY9b~h-m!&*8Kq}+bk>mGPr1dXZ9Pn1jFhfKooySWdBJC|hpxBdlK3f6V?AbhP zc5cwA>X5pR=M3XF-I}m6-iPy)m`#*OOkw54Q(svOvev}f{ST_m%DEaU9lyKES+PL7 zud+`-S)kD7z1Isf`L+2Wm)j4`SKJrWCt6m$xT@lt+51aP$~jpNZ+g#5n^LkQSWAB1 zTU+zFw;$XQjd}Dgt*3bLk!_I$l7(mYzqy-k?mV}>_Liyr%1q0wi(HDcXM9~4{WNj0 z=(W47``&Mfo3{LP%^MZvCUMLCu@6&M_&@uv{GVaH%;_ELcBZ@s zmjw9*GjxCceSW{h-Sr7CJxYw``uIHrnZ;S)5n0T@z;^_M8K-LVNdpBFJzX3_IIbrr zFf>=L6`0lN+pv}K(4&xq7zWWj2Oct{8XCklY_v(_*~jZ(==S&je93c9>=F_Rd{-wt z`1^l zmjw9*Gf1rOo@?|u;pP7GC3k;&tUFa(4wT|7@Q5sCVBk9f!i-b3`J@>b7$11LIEGl9 zUOL6ngV|A}?f+fhJ1ZiE0|XpBJwmQHnW=R|Rf;S!TY0IoEGloYf|;YYw5#@N0hWVa zdp=}r+qkK7>Rgs=?&he>ht-=szjdfIt)Fpo?$775%g^w92>(3$$NXNM|H2Q}b5AH) zeO;R2*4^Z7dn|Ll#_}>$zcY-s)2@4d;Z@O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000HhNklh$W-U0E8Ohk`tDL zXPPH_66RZQne?Rf!bSqnnc#rX^?ll+@CR$CQK`0vU>o1}`d#iQPEXjeYA{TG?xxqj zq|;-?PLO{VF4pOTd{9F}4U9%CBG9p_<#HH_l2imeIm;)YgS_W8dOiH59PM_b7z3Cj zKkchEJk-F(pkow)NHx>tT6q&G6+ur}=iFLp0RlQ@!<*_8Io90tJe(mvn`pvJHzYd^ zcjOSLGqzj~>x@$>oSw9p1W%gNqojVFpH4_~Dq+04fO}w9Op&*s zMv1*u(qloTHF%rfF~);zZN)$)%#u-e9y-Ky8_|Z=p(pW@H9)KyPp@270v5%or1V%& zA%^D_*-du&Mp9g`$-W2$KHb7yJXE|%wsx->AXbg1PhEBb7PYA^)1ZMU&nM^4{6wL4 zACzm>oXzdQ6Jjq}z(Z{da1DGNh6!TTc>2_(5=diFC)H&d^fa_pM$N#bEUHgkra^^d<0`Acwl1>e=iY^ja4xd9u9w5h zykQVq^c6l7R7!iimC%lGH;7eZ>6MEo(53;6npBr*P;uw8NjAMpbnHBN;t?p{e;0Wb zb))XG z?7ODh4coFwD}j%2Vsm}51ybp;l_y+%A!G&p4q;J#`gMSDAJ^nnqj%_z#jThhkMrbl zc*6pz^w_$^Q{~m+rl^=f;tYnuS@yQdYr&ekMdZ8Dme!U1319P8q9l*-S)Q%}FIb>7 zJu;Di&O~)K2r7;s@i1|DhW~fj=_f$%Mt_~ZzvJTe((+Z_N)+W0J}VR6us~^gWFmo1 zR#0&SwPaQ6o*v>OHNJ9n_kIRqwRmZ?Qt2ZgjWRW$s zpk7=4a4H&Hmib8+BTy@G!39#!D8{`b)VuE)D zxD}1&K^VbBj_quaGl+``-5H0Mp=h)QLI@#ptY?DUL0nAOjEa5*TURt%10e(#Il?^{ z%>cQBsF*NYJtzK|I!!4Wt%ERvx=xgK^HCPa8AQc|A3uC*C!>{6ibm@ojG(S3FI@T} z6XXxtk7X{W{~wg4H5@unmez2{KnI{T92n?dn2Wl~;a>AZ00000NkvXXu0mjfw=3+Z literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/98a5b90f5f53332b472e7f022af254db7c92c86c.png b/doc/_build/html/_images/math/98a5b90f5f53332b472e7f022af254db7c92c86c.png new file mode 100644 index 0000000000000000000000000000000000000000..2112213f3d5696bbb6bdbb18296cc00bd77bc644 GIT binary patch literal 713 zcmeAS@N?(olHy`uVBq!ia0vp^SAbZEg&9a*bbQ+cqznRlLR|m<{|{sm5A^RYs0OO$ zFA4GsW>_zg@bY)b`TgBSbMJb5ezRKk3{Z-*z$3Dlfr0M`2s2LA=96Y%U{djPaSX9I z-FwwOLpV@|{lojarq}OzUs_^uCFn}C(v7zQMkSiDRwdj!M7aXn16BycvMeuo^Tc)6 zj?}_UD!RJ59ZtJS$^!39;gV%hytPvA>-XyN=}-3Fn{VTBZ}0EgPxtP=|EtG-BJEee ztmYOoy`IuG@A%+#YO`Egn=(AlpH0&W`Iz4|l3wcjV>an+6VgCX0U zb)Jm#a~!qCSG$y|rXo35%euD(`s-)Zr@tM=sDGn|QAr*pjA)>M^{E^8v1-f1VdQG4#rBDMsxJbCes`ghk0e)pamXD2>ka=-B1Yn30@n)5t&jLJgIV^6Q& zV12Mvwfy2A_DJU+-Ioj65}B61Qs4}#l{m9RxWu|kduOZBZqq+;4{oio_?r~H=Yiyr zr@cwjS2eqMSeqIb{8+kc((SJ|<}QAE_~Xa7Hym)<(!wwQ{_f3{|8fJDc+QHG(-Q~Qc$;**@k%fomzosU?M*=z?2UQm+b!8kp>)7Nm zx5ejCn&Zai?#ON@cJa~;j}$Ccl&fbJFX@u~v+Viq@5<%Vs~hHfy*Tz)=GJ79u6dPM7QOupm!nHP#?H?DT?Yyw4vx=WG3jvnKQyLhWn~7QhTm{P7pF ztDZ(HnlDrMvEP()kMr{)ta?@tt zKRk)^KbNtG@2P1kN)OaDPJOi8Cg@|8_3H$ipQnpC&3X5{ot9x@F!$yU!(U7)%U7HT TJbUpED5ZG1`njxgN@xNA#gO`` literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/a51d2cde832e2fe0f2df87be7c62ffc60a456418.png b/doc/_build/html/_images/math/a51d2cde832e2fe0f2df87be7c62ffc60a456418.png new file mode 100644 index 0000000000000000000000000000000000000000..8043556e616bc62f5a6fed1b80f9fdff06f4cdb0 GIT binary patch literal 1332 zcmV-41O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000D!Nkl0YRw>1|Jp$#XaZVNoF$l=61Y|PkJCTbCcZf z`|i0vb3TBM@r2(zziGPsj<+nt4j;sfw6h$jEkXo5RsuW_5zq5m*>Cpx`sNY9kqAgw z3J@dGCWQGAeT0C;rV6BXSptpSl68cBT+O=t0DU-`Igvm0iwXo~W$rfH=9ohWeQt|h zAfU)p0g3`*9$K<`DPuKi?7YDq@{(*FP=Qdk&NSP`Er&hSTJ!<|%bqJkoC{>7-uYuQ zKjCE%2knZo&Z9#t}|I{0May;SNCoHREhHUU#O@+ zNLFH!_j~sD3yzQu=mi4U0mqrFL>=eh6pSSSZhwF=>}R@r@C%Z)VDtYPl;|RU8WB~7 z+f!A6kSy~*e>gjUBNPLAfgoFhlS~%Qc*(m0KVpI(R^VlF5;DmK>}9eZS79UdN)J)e zacNwQ$hrtUt_p<7`W=!qN3e%3S2>VRFA$_%*v(|!!HYe>hLWhluY^#jrWz#6JlEj8 z7NCQy5lCAq5Rx^2hs!b>Az7SWBq&*_N+9cSzs*zm!NhNKGl?3>+Te}AW9o2-jYwQu z$#<|>34*eczolJjLx!cyUt64BBp8N7*(Su21;gG7#!~cfN6-@Xj5^9n-GeuL>IXW= z!hEdCs6bHG&t9R%`e7OaS&UvnkoKO|*|I3qafz;Fh{INXi1u>PE7>S(i-m(?`*##N z91#1=`&ku;0jVjs4)*o99A@myZ&p`Ko^8@Bi@22P6dT(T6YgWBv{<4B^I}4l0P}U}oq!gQGgAk|hIa z%EGp{pB@f!pm2lI!HT&YS{TsCe<59!L1xl+a2ip|Ci>42^*nJZPuiqFOj z>8SQ3N?fVxfQZe;4C%D?5ifD2g6Gv{>q3$g qr3#zaY}`#QzYOF!OL^Wlw*LVpaV44ckDAIKyg=-*vX4OGov z666=mP%>Ad`+S1Y%g=ZBumA0_{JrrtpcH3;M`SSr1K$x4W}K?cCk+%_;pyTSB5^r6 z;Q-SNt__`^)}|id3fjn>?`UvSR6^p0kiwgnJUl&KYU>j2DYCHzZdfqsF)JI}<|_7M zYy$o6jfM;^#g-eGUb1+yEn`gxZCB{Bm57jSxFW|E#%eG>n`y?bLkGBvzL~Psb-Z>x z->~-IxesD4wFwham_JG~SMW9b`PAsheIh+G;l^Q>urmi3!s=%3Y-fGJz}{wlP9fIe ib)|#eSwWr9GzNxQ-(}X!Iv(!_3K36NKbLh*2~7YCVQ0Sp literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/a8ab03f1f7e4f60328e1b8d96389e2d5a31e6e24.png b/doc/_build/html/_images/math/a8ab03f1f7e4f60328e1b8d96389e2d5a31e6e24.png new file mode 100644 index 0000000000000000000000000000000000000000..2ab8289baee4bfd57b87f6b9978b11acdfd9f77b GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^f6f&SeE)j-w! zB|(0{3?*|Vy3Z#Vz5IN4|N7q^%ikMc14?lgctjR6Fz_7#VaBQ2e9}O{1Wy;o5RU7~ z2_Z&>z6lJBo2%H5u^DJPPHN0#biS0SP|VM~nrSohcSg3hY@R=?Il>WA5;yD(JT@7M zd|)wPu&kaTAz{HSQ6VF7&%)TC#n6HAax;^L_k|e7LkVCnFdY|Wa|`&&2J(rgtDnm{ Hr-UW|V$(q8 literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/ae3bd00b8434112f53b49d89e8e598ca33f5cc34.png b/doc/_build/html/_images/math/ae3bd00b8434112f53b49d89e8e598ca33f5cc34.png new file mode 100644 index 0000000000000000000000000000000000000000..ee2de9ed7e6c951677aebe152e22a6f5c7939c3c GIT binary patch literal 1970 zcmbW2`#%$k8^_0%NOLcQ)*<9l$7QRLLvop0E}Ls?*>O9}b*>#Fw+Rb}^)o{FJ~0EinZE;JARbxv6v9?1q;|VJiIOj-XK3@Vzg0rt^ZoO-Kxk zIq(O#_BwbkS8Gk-dwE}74Vrmomc`k_OeqP1F9;&vjo{@;{-l{>yE3(YKd`$X%FyVv zNi(P``0x^&c8W6eCBN1mOj{LSHAWdN*>G%M%{q;3J$!GNp3A-KH8E9nb6n{g>_JaI z5B5=hzy1Z>@dLpZ7~w8~>1PIvsFY_-Su!5MPr1k^Ea=xz`57RUg5QO10)G5up zm@N^5cN|94Ar%fk26<}sk6S=6agwRKANW%Cn$ouT3o8t?dZN&&VSGav8@(L1fNvAD ztB#YNar(9Mr1oQ=_Bz;H3#}ZY@8ikUzFJFYEYzv(n2#}RC|uX#;FLS1(z$sw`rI;`~PHSfEvIAtvhKC5?RlVwxMjN!^;CpO{2kE?sJQ#=^s+0Od~v1Z zoHodHHdMq|e^&;3nb?|2=h1>Fw=>l3Oiwef`J1ElnwSz8zph?Z2GV$J{k@prm!?}L z(ymKPRqpv&GR^jP>a>NsD^KJ$l|la$j8FnpJrAj7bx-Zt@v>`lVjC^W6Gb~2p~G?< z#}>S=ujM}Q%>_xvUueBK%8`cJIT^pUdB@&5j~Hp+9bO{}!&8T#ZVI@UdOS-%>u0*q3!m3}*9!m_19z@EEXk|j+ zaTc>nn~iYgJ~d~TAF>|X)J5;UKu^*?J=w<;+trQYsI9k99H?DqvhV6^M+Hf~-6OZ5 z?_L2ue$Y#G4Jr3|DH>`&dSZ8Uh(-pQObVKq+n@|_5MEF!qBI$PoqI3UsXAHYRq8I@ zpS^)I($0|szYaS&itd;E3{%3P=cGz&yXI$l-weWVyeF@abz`NJX_Bl9tQo)hWtnVo zfBZS4e;32jG>IOx5}9z3301C8ER^@W^5nuBf(m8;f4V^&{cjN+qccHD-&whmW*qaJ zj!TE-qF)9SP7Bk}F(WR%E*;_Oc^bue_a6~b!ee)y6`4h>;y2Xq3@&CF5UQMxYw8!U zD--?4p4l)!^RG)vf^L3Oe6O_|WEoGw0@HZR4)Tnse=YB#rx1!5+bg&ucfsy$2RUGd z_4VSbj8nwTELmKvgAq&~CsQ47FiNlGp6Q0g&mjx*Q$9<@x9~hV{Xd38Ru;GSmEYQQ zFF&}c`Wtcu6rUBA+|X71@N8Ci{%>6Z#*lyyBKh0vKa@tHboL^q3Nb|X8U*ZEk9Pmj&4hC4;M>~=^74O1^@wO?DQ!U^Nx3+|WyScM#6`yh#m?HZ8ryC&C~+S4 zqvU+H?ur>Rz`D`6zdTfHlOSl^L|Y0rPWc}e60NlW literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/ae9f0580cb8ea29c74c8e96c3d9d7d4d77ba3e46.png b/doc/_build/html/_images/math/ae9f0580cb8ea29c74c8e96c3d9d7d4d77ba3e46.png new file mode 100644 index 0000000000000000000000000000000000000000..0fba1af95ba5877586456ca836bc27aacf390f7c GIT binary patch literal 1013 zcmeAS@N?(olHy`uVBq!ia0vp^AAwkmg&9abUXl(Z84Ln^LR|m<{|{ml4fO9Ws0J$L zFA4GsW+<6!)V*KAFi)9J>#!E{>7AozS_UPzoxu7*7nMW3T6>Est zc<3Aqx+vwsU)A-a_+x@&N5uvfE~k9%SDxGl!}=f1p80pKPDQqSiSgfW)$eCl8oxiw zbUVX~**Yaz+j{AmBbw9qG~Q~Q;h<$UA*)T}4)2G+Onk~dxgs0^2nC!H8-7&cHc;fe)#=eku(!~+&e~jH7@hJ4(j?ALbHoE zIc_V@KB)McvUJ+qmY zEFT{Bf7hPt3M`dUTUDP*wreXVD+Q)bSs1eQbg?>lVs>i&=7hXr* zKKt#7qo9-MSikIVtcY z?8cr)-+oT9ZPzsWanfqif)A2MQ*S>#;m%q)`&?Y>-?UX}lQr*e`zrQ)qK@Leq6xWg zx#c*wGG3d=^z=q;nWgNh%|~-)iaOtuE1M#wnJvE{=hLSbdJPk1tlAZNq+nwBRpAF) zH1;g8NliWYQp0D?>-WrVD`#Jmb2j(9x!~FN9z_G0wg&=h_o+YnJTWbGX@q(tYt{pi z#3yB6|5k0O>}6$|f9exK`Ox{M2S?gDqQ95b bO8sT-opb%fz7|n7P{#Fi^>bP0l+XkKMr*zl literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/afb7f8aa812a6bafd2d1c4423555e766bce85146.png b/doc/_build/html/_images/math/afb7f8aa812a6bafd2d1c4423555e766bce85146.png new file mode 100644 index 0000000000000000000000000000000000000000..d1932792884adfac74ec4ef471e4e6438a0a7b09 GIT binary patch literal 1492 zcmb7E_d6R17>??xU56?`%p#|DTw6O5B-ChvL(v9NRMn=9(Hgbl&?-f1HH1fF+)+-W z9;>yJ#)=#L~000Of5pWboS2(cZ<>v4h zJKLTkdJfkeE!b=}$NsO`eso=sb089qvO@!2=_002Zd2MbSm7&@b&oUd!Gky%UogTo z3;+=B{tm9^>cY|hzz^z3IMgwkvEjDT`dVHP`y-d@hl6+qMvS|hH1@WnZSiC9pXGfD zkCXJEYBpIUvv?>Tj-aEbvO{JcuN}q3=4Vb4JzHx^u2dIio?cAX_?51G3L7GNMeG zGt##f(4RCG!>!YHY+`9aHrrQHZ3iS~P9i$Qb3P)9Opv_(4}*%mKU^!VPwKi6BH_L1 zSu2a8^^yF*kk%Hbev!W<{jJ7x$~&CHMgiQy!d5+BA-+l|oi}dIe%&rVJ?UNU9!6Ay z(j3ud>iD!=69<a$`f%8`4y+0(6#ndW6=W+gn|9{EFNPN z-YK^sy?e{tHFFg2M=M_LI4Mgk3G6t+IkLo_UjAa^|3w zDqm8Ailq3)5=2g4m(8oBK{)$TjSgFeTh5`iWNTsrl7Iq)%B>kB;!eg8!k8w~_iTJi zohCVvp7s&8M&iyE6?vkWU|VR=g6%dSnVDM~h>1(_2-Nuxe~L92`$F}q$dvF|_BQ%* z>lO4{bm6XLW`|Y_?3A0pY@UDcOsy00Wj&z41beQX`+d+oKVO3K95xDk zvn-3!TX_Z9cLsOrOc~~8d6=GxvG5BnAI#B~LNx2Od`dsxiimxr=8nvPM>M_iDYOIA zywED+hCgx_vLtm|U$Q+kUYRC_n7p)&BPvs7=fYIBDxC-3G1r-N3cutG>My`h(Rm2Ag zBZq3#K+g;sQ&nRXm(lr6oA%EZMZHq>RiFPv-~>`ML1;V}6SP^yWp;k!;l$5qOev85 zUYi{zUTMIG1&qMWy!K zZ=pJizdf3MLQe0@?HIJZ!53f6e*aNI~zGHW1g#+Izt)Ba8DuTtDdeZZE&ZOu8qP zj^3x001il0{{R3QmfMm0000mP)t-s|Ns90 z0000000000000000000000000000000000000000000000000000000FWsPf0000F zbW%=J0G%>O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000CjNklC}Q>@BB&*+*n*VWpis$!Fr|Vhp=@6Kc+n9G zMIb}U;_zW9?aD?Fbs#MaB^QrI!Oj$Jb^;;Lm=(dU?=(Cu2E zQPN9dCyY9F*r;XWH&;mxGesq-DPNQ7r>fFhW^!0%2=54hXiv_tF}KEk=5VZs>g8`h}8U=fRW!*_{Sk zYQZk^6r}AbdjAz4xqEGc(+j5HxcEkJ`R<02HEY;&xWk8@!+u%=Vyl1Sm4L0`uK?Ma z^Qd4~*;LH;c}2~I-o|NZv)EzK+VC3d2UA+r*i2JYgC|5@{@(9k`|EGde!l&kiFp4d z19AFbXsCoOY~ELasKpdq15=byV147jkH4A_O?9Ao4{PBGQQpAV?pCrWE_ex7sJMzv zd+I{F@LhT-Ptf>}pQQpzm>97ad~6nagziZ>Mr*Z*iLUUUvWzEmibrWlo&!&es)s@w zGMUoKLvQ=4GM*5b91y!AK4g3RTenk}#6F><{jvyqkH0ME3Es&4*Set!+?mC#dRfjB z+Ke7rqJub7FUxs?eEe{dqK*<8MkG|i*Z9k;`+CCs(xT)UxhfNz%t$TqLuS`rirsv> z$azA0p;IOkqe^`NNqRziYtBYZJK=)j*`%_b&}Qsm>`v1jsTE~Cp(bXktzRa-p>~8p zdcOECLY`HZ^aS2^+_U09we`!S+K$lkThPy0P5NX*PaLN6 z7g8B2uxm*8SgDjJ90k6w*g|;BYT^$KVWijwvvezEA+^fKP-HyeJRN5Y*B0`QX#KJW zecB|0#b!y7@PsQgOu@BaZ=ht1Hql`_ zN@>&Iy2O2M>t8%h{j(n!d(hD)`)7V`(ho6Ppg0K8eixs17JUfK&llQc_d=tko4za9 zdP#;&?sPMNo){`)8(qKDY-S5ow2;X6M&M!qY_h-A5$tkOJ>JBR%6i)nHozVIvND~yRlC`PS8pD6te{+SYK6I4XhSt1GYnE3+d)(?qvO-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000CaNklmo_o(@ZaIF7J9E$c{@-`c^Zo|_$GIO6Eh2+e zwOKE*97z@#tgdy(lXJLHMv^)m1^+KX+LnB-2#_cT9_zYBN5MeE^0q=PCT&jvQb^f~ zzc20OtuNIK420|r@j!LQY$cI^C*)e*>mpo1AEf6eUhvk8W_TzF^|SsU3|hytC=zll zi-Z^J%0n7YXLi#cG*3xEL4b-h3nR9g2~Q;CS{AAN?1v_($1Uk`(OTE1q@Wx&*MSLOZ*f`*$F*Kh71edRi_y+WH8Z~!ZR|P{s?LNpM=qSYc`o(;<;R`x1 z-l;VO2r+)1)UCsAm(c*9;I=Ag3u?bZW*U_$e_kf@O!mq!z@c)wFS()a6#+s+6Fsv5 z&Sn>ql=ko#Jx~S1LG3emgvz*UPlm}7NaDsxfZi_nI)nNcn+}~R9E22kWPChdnmu%Y z(o1NhQ7;t1WKf&izbA00<9@N#fluR%ai=$uYpb}&G&#jI=Rw4~vJ zsbu*)`S4#%n8vpaY@2rb{cx4TY(986f-^=`zu>juT}C$uIfc^vI3_eeJHW0uZ5j2a zbS!vU~3lUQ(sJlb*oN@`jE%$iB?may}DJWL^5R2_D8CzWN)cz)ro;-uD>tnnkCUwt>M;Y@1ZYD z)v80tKvQBx7J=)Tc}sS;$X%hapMw&S2#A(!yg7SU~u)MexQ zP1%X-opuYBfl>{$T_o{(kh)&;HqjbryGY{oAa%VN&s;KSpsR~yUJp{&Tgkh|nn43y zT_p2*5WC*d!XwGEDd8LFXd;Q%gV^R4=BZ1;1OBOz`%C|gc+x5^GO2*k9oQ{hDcma zPH1Ql;W&DTfjv>6OP4|Iz!!#70*##?k_;XM`S1lCOPj&*n~jZ4F?Bja8ynlS&-RjE z&KojB@+8GeG&z*~GvA;nFLC3tv_zVrd_uy5Kc^OOh*+|jWHTNPo4|4Ve+##OU>gX*3=J4d^%z&4 zO-m?duoi#PP&R=ho$ zmjw9*Gt4#excfWd{QmCGB`+n`-shoEMU zw&qtskr>H9#~KmS9ou=L7P4k4HwlUII3Ce+IbZ8zHTj&1`N7tT4CCeI&(BP+em}GL zzevGW$ItOemp?g@By4k)>-hE00zFs4CGCCB{at4$o0*W!)vuDNDv%WX%jV?v z{-2rGqfg4{-)=UZv*c{Du;uw@hEC>}dYCQrJ&Psl%2|%iI{I?^n=*CnIuu#Ia4JyJ)evoBvE&{m%NuP$ZAsXt!)r3VdHO}S+LgWF{n>z0>- zVP)GJzm`P0&aOPacb7}wqK!^RM5UOdwNl^ymmQ_LbEG(8m%sSlX|=p<>f>$A z-JZ_&zJ)@4Q)Qk{PCKH<{a)&A`*CCC;wv6oryY$qWEJ|y8T4B+%{BDW`)g-zp0Q;z zd#7;woBjHG`wf@RWHnrwa`jt)wrx7Q+T?ealpbE0ez|MO#n!xq(*$mGe(?5=&r;rX zA>pg)V&%BlDmiAoh+jq)3%z3_uh02->e6Q=Yk{Zi$+wz1PqIDh37Ao7R zqbbUzuR6k~%=13(srsYHN$1SHpBhV@nQLEld>4}P>if9O*=QP%8gzW^t7*HneNn8 zf1Vtp}OhW5@=tG2m3P43d=)5}(Ujm=P-mw8%kKgZ;KCjFoOWts?| z-}3aM+IfB1X8GBcrY<&_rkq^UN$t9>Us|5X40 literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/b75a7991cbb1a7fc99730d8856ca842ee8171eae.png b/doc/_build/html/_images/math/b75a7991cbb1a7fc99730d8856ca842ee8171eae.png new file mode 100644 index 0000000000000000000000000000000000000000..737f010adb0db7fdfd2300cacf3b367c88e2bc0d GIT binary patch literal 1931 zcmb7F`#aMM82`FwvdpEq6~<|+M5C<^F)>Uuvqfg^p%@agT4RW1nxyE0#ttPSRMw47 zoejHvxW2x=0sn6}o0n8=a3C}yo&@kLaFW%)k1x6Nv@z}K6sNBT zcUf)>m1A(^H~;`Q{z{o^yTN(@pxEbvJ#_S}c*=L;b;+*Hnrd2*@3TM6nZO>XV}_== z1cm9W{`_vUvJwB0=c0ILC;tJHIUp!g_VSc0FEvm_9in4edVRjjJHD0;+|%uS*(^$r z`{QTII`VX(LOSVcTz4?2%@!u)H)4wR`uKMJGnnJ4OrK*(3{iU0e`5atMC10!@q_iF zYYyTBJ2HouOot4J>$HOaWIVZhI7%)kqdE+_K+VrZ6G=BzT=vMsh|aIcKhc>TuOH2h z=DN?d9O^L!a?=sYCzT-6j(~!_+hR?TjavEMv|+*IYZg1(qD#OsOXK@F_3I1$URVXh z^)dQiMF`Xg;NpG!D6Cw-Ar}o&OomPKGw&lPifMHSbZK{5?w^?}&(xCXs4pY*mNm*5 z{}zTmY{Y=b*azgMB2-UmczC<(B7op=UFkE+>+hVj-@Ep(e}IfoN;&V@KrJfE+4=Kj z?tJ|dax2EfRQ^AX3ZxW9^xKg!7L9q@gzT5v)48l8Irf~>xD3dj`<_6+J92-xQaY?wFhvmm+lZAE&?7{qN8L zSa96D5-8hy*bHBgG(qidlA;{nnMR9ayhtbSt|(O`G2_8UP#{Pe{*wh7*;S^p@Int` zb&`6K#k7oY6)=q2xRPkD%)3MKfTr`%L47+H4He^x^N;G&{AvS8x6A%49K2(`ta*A@ zEn&h@(;^3VV&?9|e%Ol)0&V0*m5ouwaS=o=H+2($xQN54r^*_J{lwOcZu0hjZPr=6 zlNeTNLTiRz%3sSjoGXijj|42NX^aXaj_rHp7mE%YRT|Gi@b$5Pod=flhHuBw`My|l zX(@SFYclvpzDcMo z(?jCKPv)#p8#`>hUws2@7^;v>tk{pt9C-8G$tr7p+F(#+TJAK}kiFHNed&U$5Y(zB zpx)l<+3Zz|wELaYo;=7gp*YAu=1Vuf5)N+Ym)r|5x}AR|?r+$sk>BoDY5^CzTQGXo z4Kz|G3~du1I1e?}yW^Mqk;#ra@v&kivgSi=;*#h`gBJfFHhe?SrTxo$G}Rt3x*$u2 zZ;vw|b)GM`8wz-G6gED4>_pX&7QLQtwdCDWc;o$xFV+3$0N7!{5t7rFG!(Eps8m1GThzVI|#sGY6rJ$SOO+IK%BeQNF84XqM9f z_HES8N4M2{tS=~>XZ4woF+_AujpV7dRDPX`-D#)Ckq$W}-MU$jhdT)W0*qL9B^ zY3zj}zaJVDvAq&q>`-KocR%*#>=t(977tLHA}l}Qs5*S4^WL0t0m?n_hRZmW`8PE- zFWE#|MK&Urk1m%_|J?7!qClh4jtz{SodRq0J2x*oIqOXLP`5ymBCn~<}tDwtd^q zG&RInebc^Q(vX=FG~4`Yaq``{F$2`v2h$m0Y?x%u>rP+snp2Zc%KHG?pu`hhIH)t-y;> z#AC+dwuYQ}ZUAr1{M2MO)YzobPTn~rzHstNva5K9D1wjh(b?vjWBPVF66162!_Ov$`ZnA3e+V2 zNqfmRLxSjErJ{(i#>Bc=hy+aF%KMB&nOgZ)Fgqru<*zFA@W!3*=7me^&Kno^rbJu` zB&i&(eeU3gBNm2u&`(H3;bCo2r{MSFtpoR{w+!x9ul~Gk{CGfN2$_EO*IgglF{*Y(LX#3&yq#T-1nq5+RF3X^3B?9+2 z5?+%s>;cVP1L{8g&~Ay?9@_Je#}Di6A@!B`mjncEIFv|kZJ1>CWKAy^rCU`erAm5O z3!y0Y0?Ne}I@+LZh5%ozu31&U*oxZ*qE&t}hr0Y%d#94N1SCCHad>X_>z}$f;;~is Hf#?4PK!9_< literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/b9164be40b826a2f164f45571034ed55764d3b7e.png b/doc/_build/html/_images/math/b9164be40b826a2f164f45571034ed55764d3b7e.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ed228769badbc60511407421bc393b9589dffa GIT binary patch literal 1636 zcmV-q2AlbbP)`(V$%i}Q5p7_WhgZA5MW000SaNLh0L01m_e01m_fl`9S#000HM zNklDHqv5M*;fgz^2K_Ocn9RaDH}GbjA`oMgJ`qG+%oh0v#sSk36y3ayo$ zQ#;8Kn$?fcXY8EYjSE72Z44QI)nLPe$K?>k#$&H5&dq>Z*-7o9jxiw!smTQ;wXWub zRm2)>=0lbj5ZX>&3z@wRiX^&RpIk$LxKF=(%VM5H2=lSX@SWt+HD87xk ze%C8mdWI zj4>AjBAagN!!uns!o|J@1jdAOv!Dj&Ds1d2;u$-X!=4;!Srs5>2p+`-Ldb!f^Xwdk z#QDHiPQF&akezG}EXLqqF+lISVLGj+5Ru7ex#{nzk0k7;8G9dH1r7QoH0ch70z6AM z^n*y|mh?V-!K2Qz53!C7JZ~}2F~0J{FLJECfx_~7k?>Khj9>`dlFz0?A2g4z%ySRG8X2?I3n(iB z^wxhc6b~fBGXbv!Z1Ax81Ig5gbc^<9Ig2fTEyGN>!m}?!{ru09ZtH6Pss^58e0G!k zGz@CnJAl)!?Cgl(y#vu(e1=XMZJB^)0@jn>JEXTi+D#^7u+K+6OQq)*w7?L-Ygkla3i0>pYvhw(sKM_^dZ1?&jL^OjrF+wL)Cj zP3oQxm)?Um1f}TKdoaRRsOowFc00xpM1trC|KD;|;W0en*%q2BJxU+>z>cl z9)s-i_>@VLT~}niRo5A$_-*+A4KOkZI0+QqL@!@vsuY?JHFo}djMV?c^QP%&? zzG#IsP-;`rmkh7*{DKk&bQueYBA$04%x;$mVOj-Cl{|7n8Ysyr=u7Om`71nkQoyZiGSN|=g31Lkv!5a#g-B@xn;^d(QH1gaegn2x? zNJvxGmwdIZ>!F0H31Nc$xkU)`_#_w!Y0CN%n=j%up8G3dYC@QR=Warnn_DJJin;am zXdRU>wS&B97m=*!?H1}w&~s7Ad9;p7nC}Z=?q7SLKwt9qz3AuBLkaVJA_zg@bY)b`TgBSbMJb5ezRKk3{Z-*z$3Dlfr0M`2s2LA=96Y%VEX6j;uzv_ zd~LXIhOnbZ-Ob#(GV`@EnHy|$I-?%l~Rq`n$D zIlOoyZ1j+ECr6d`2H$(T^Pj%Ge{_=d$vV_w&8@qZg*muqPl)I<<&eDLFSu-v$UUTs^&VBl^{?P0XG7D3* zC4FA3GAJ_JKDGbT7Fo5Q#@mY+g?9xmUwYBV>q_pvs(C4%+wZh<+WO4>m@#eV^VQq0 z>%{MMO*vlXa@eUwPW$4blL7B5s%0NcFFf_rwfM|rRhJhB8~s-Ng?cOsNrh9V;Ira^!W(^=(K0-tJy_ zY=ZWzZ=e4D5>&QWr`+(aWu4rlq~9gME2kH~Sl26;=@y%_e&b!92fb%>OG9(y+Zle} zGvy3f+E{e>S(VeXC;$57Uh1u{a%L;lzP8~+(?Y%GU2~l8oKO*+S|yuMKG}2sZr|e~ zLic?`xVirE{9InR@ayTmyYDVZ7p-{Sa?N;~uYPw_5Z~7G-**}ZO>@2){wGR2Rld>s tZ%yPRSJN7$PqY7Ye+^xK{#dVHJ)>Upw)z*5H6oyV=IQF^vd$@?2>^P;qKW_j literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/c582b5b606a2c3060394219159d4b17ff4611044.png b/doc/_build/html/_images/math/c582b5b606a2c3060394219159d4b17ff4611044.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0d92bdfa4698e1b8f66e9393b82c65860c9f04 GIT binary patch literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^f zmjw9*GjxCceSW{h-Sr7CJxYw``uIHrnZ;S)5n0T@z;^_M8K-LVNdpDjJzX3_IIbrr zFf>=L6`0lN+pv}K(4&xq7zWWj2Oct{8XCklY_v(_*~jZ(==S&je93c9>=F_Rd{-wt z`1^lsUOfKFoYboFyt=akR{0F?h+ Am;e9( literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/c6550fb5636af16f487a8b9739f9abe82dbf07b8.png b/doc/_build/html/_images/math/c6550fb5636af16f487a8b9739f9abe82dbf07b8.png new file mode 100644 index 0000000000000000000000000000000000000000..96a9c9b7122cbad1e19611ff955e05c020760328 GIT binary patch literal 346 zcmeAS@N?(olHy`uVBq!ia0vp^mLN6@Gmw0E_ckw(G6?VqasB`QKafd0(7(H&8mOAT zB*-tAp=7Q^_xS{)m!I$MU;o=<`FrDQKq<}wkH}&M2EHR8%s5q>PZ}t=)zif>MB;LC zf&-JQ!<;sq0|!>5JetLj`dP!kfNep?%&XQ0W(TIoB?-8SdQV76h&pg!AH$+ZLk7iZ zB~mBu96qq>zyo8(MU|>8Or3_-1@Z|AJB}TQKX8C=Vrq{i!!pOD9N`Eli5vC?9-9uP zxJsUD(CCO@^k-lWI4GyKLg&Ik8-=q1hHU4U*yPyT%+Cef3{tRTE0T%mQRI0hy5gip w!%Ig-xk$%iRt@dn!Hm09e*gc^F7bhhL2H_}oZUMIK2Y#@y85}Sb4q9e0N4^~o&W#< literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/cea5452e08d6d9f15b2b63894d4554bfeb9d951d.png b/doc/_build/html/_images/math/cea5452e08d6d9f15b2b63894d4554bfeb9d951d.png new file mode 100644 index 0000000000000000000000000000000000000000..ade6c6a971a8dad952ba98a8f621e04567c5d475 GIT binary patch literal 416 zcmeAS@N?(olHy`uVBq!ia0vp^Hb5-E!VDyL>|x{qQU(D&A+G=b{|7RO2l{sxR0CD> zmjw9*Gpv_Lc=@~J{QhpExpzH2zgaDN1}Mc@;1OBOz`%C|gc+x5^GO2*e|x$(hDcnl z?O*8494K?#{$1bUy>Bgenl>m&=o}K;qO(?lr&+aGN#@Xn75`YTZTzIx^mRsJ>OsRB zykaJ6*YG@?<*3HP()l7uU+)ApWEahUBwnAFp!6m0o|uTxryr&> zKCQ1~JEkLBQ6F?UFXAX~;xTa{X8#{In_mdb+dFH?nh%=Bfd>z;%66LHbmNWjnDxN? zhUacmpUbKjtfr~F_;>s?&$5Xug8EaQ?-0F}b>E=bNzopr0Ew-fp#T5? literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/d46f1c279ce0c199db52748ba5f2feb62a46363b.png b/doc/_build/html/_images/math/d46f1c279ce0c199db52748ba5f2feb62a46363b.png new file mode 100644 index 0000000000000000000000000000000000000000..8dea4ee38b9315f4a1345d9c244a830a926e52e6 GIT binary patch literal 1560 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 KMNUMnLSTaBnkU2n literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/d891af7e39e0ff3708b97ef66c7e246a93aee52e.png b/doc/_build/html/_images/math/d891af7e39e0ff3708b97ef66c7e246a93aee52e.png new file mode 100644 index 0000000000000000000000000000000000000000..4a8cebcea5b4e076c2c68fb3d3e20ab9274e4cb7 GIT binary patch literal 2324 zcmb7GdpHw}7oO(lTT-_b5`yatSfyGNH*zqH-se5fd!F;pxr;#~K|p070002l*&>_)0AcZ6 zY#=7QTb~o;KkPO`jDzc$ot>Rs_C*)|?dG&wL zo1&08MeEN_-Zx9S_@9zv)WFuY2^2%$&HAJfwLLdk)z8fHNt)$?6Npv3`T_0SyXz@K z4^{RbEHNxklSyW5J{w=ol^AYP1Ds8{mMvBn1}zwG0A;#mVLDfdf=NfVqVtGFX`Rbl z3X#jUYsGTS~@7X&^oxvetK(LUU&R zGMkyvxqJ@H5{}F$!`qDx?;Clm9SU7+-fX97--SU%!pSgOrju%N1n>SiczuOQZV=mi z`H7IJF)Fq9dU7SCV4~q7FT1SMVazH3J>E|+x?Ow6kVsv(SbXw;Dh|z5aXY@0&H)r~ z54VSt1Iq&S({98J$Sfs@AiHtI7ksG2Y16V$6{@mfPE|mp_(cP5+)%x(t)XpDWor^~ zg?;+ZLIkPabh8h;E)p5A=o<>m3*JjiCEB};%tHvjWt;S`P!Wzf2s1{Sd?{LX4-REP zXocS-5jUd`Y@m>1AZVhB_@&kjWMukdL-enL^N4&p%C;|0*@e^uqAM?qEoww;u?}ze zo$UP-GjdZ6E8E#gbhy|rPr%@3td8e=K5}loqe;t7opjWTrSxa&SCs7-sHjS1941@x zn@SJkfTWGvsXeo`8e>nFF8ginsrEcZAqB#mo*0z!45qzb3~!mnC{k?v{z|C6BSrmU zWTkyfIwvmcgC87(g3vbhsW+NuydyoL%37Z?;mjH|lOCZ=mpxsNZ_haH?`x$}5#s}+ zE6&(+=JFU?gCzS7$5L_B{fffl{x%1-yfdZ9T5*5yD?5Ct(BX97oFvVxi4gvtnZnX| zSsA^=kYHE-^LM6%LB8=JnIiOW>dAY}hI-}IrOInZ(75JeW|5+VpC$$Qo!|EMc9{G8 z^=HTf)xB1-_PYm|jTMPnK0c2_2sK7pTE3)B$XbB0=BQb(P}}@&{c6`0{v&o>j6sR7 z*yv@h2K3soe4*jR3IAfv{|CQ8@#1YGZbqDx%2Sbjp(68q^~nO%^Z)o9py??Gh6#H>U3Y`fpo9WaTZ&(}VD$$q)GGiBbDYobyzuMM5Wn^#F=xhX5GTCQ+BV;wXwJ(^(#)KwZ_Rgn z-Ljb#3NMDdTgVhNVqYC9Zz}fAkk|x3>bB;t;HT+l!%FpJ)V*}}Mny++wm>-ijS76K zW}-sx>1tk$bV~EaR1QOFlN*IywsY@apBV79gme0fud#mWMVzEhv4|(gSG6)tcpjiC z>BK?yP zcroA(!pLWPW21wSAPatPu;5|-+gekgIecq?-m{zlyS{j8;uZxN$|g*XOo1FZPJ0%U zqFr0_zrKy#uuktAz)1S@6@$z$7Op6s|105Tk(kv}#3(rQ(Hl)!Trv2y*>J$))FqGp zEoSxArz3?X$d76ac;70qe8I{_P`<1xJ2yQHrpYGjF2%ery7f`$dk=g;$vSdN9itVT z8|@^~4l9@A_#SP_^@pW258*4Z)>ag*xIs`C87{t(`Q&kd+=0Y*yG5jo(w z{j9%>>V9P9jsJ^MThO3D*6{#_6A z-ddhK+8VexCklYe`?ETQN^|2UV&lb zV&@m@bkD8QdX=HNw%u+zIU723KkAc*w;H)F$Jn3t+<69TC-NdzJ`i;V7N&58chKmd zH{Wd%89=+5?paZW_$DBTRrsV--`0~;#7^%3S+*Vt<2)y?pqMKY*K~#*c1CsFnLx|? zHsNj2Oo1EeAze_;CD%^Wbia_#c!L{~+7&Cyk*=|Wf2sbDd@9XwH1mvq0vvBwKb|J{ z@^p(+F!zyePkac|=9fgfz&z`b)@2Hn35*;Ja9w zTjkq*l+$uppB)931l@u2uQ{T*P2!zAI<{M&<;)Dc(o_1_(bR)iIeb6*s`KQ$_6V;r p58o^uf2$1ibV|NCPpj-PU{|5nkTa^F+ literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/d91c19e81a73403c46fc57af8f02014851713dbe.png b/doc/_build/html/_images/math/d91c19e81a73403c46fc57af8f02014851713dbe.png new file mode 100644 index 0000000000000000000000000000000000000000..6afe16f3eb27124929a6ff4561d570cf7111a80e GIT binary patch literal 2302 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 W*2xs!ux{{Agu$BN&{U(F#Qy@iLNcTP literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/dd6e77999bb2b0a71f5089b6a48aabd729045633.png b/doc/_build/html/_images/math/dd6e77999bb2b0a71f5089b6a48aabd729045633.png new file mode 100644 index 0000000000000000000000000000000000000000..282640141ee717bc9c538bc655c3a05a4d509f49 GIT binary patch literal 1062 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 literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/e70d5f1b33598371cd2960cbd61cdc79f720732f.png b/doc/_build/html/_images/math/e70d5f1b33598371cd2960cbd61cdc79f720732f.png new file mode 100644 index 0000000000000000000000000000000000000000..0c5dd5771c8555a4cf9bde4f1923a1184a25509b GIT binary patch literal 567 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 literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/math/f9939fafeac3df2cd993cd6d46762f5c9e184253.png b/doc/_build/html/_images/math/f9939fafeac3df2cd993cd6d46762f5c9e184253.png new file mode 100644 index 0000000000000000000000000000000000000000..6e16b74a40f2411f7064ca0041d856507c6717d3 GIT binary patch literal 1479 zcmV;&1vvVNP)O-TPqAzl-y9=@_rvmh}Aq000SaNLh0L01m_e01m_fl`9S#000FdNkl1 z$=4YAuh;8-CcDhesolSS=x9S*-;CTN7cDrMnickSR`NAtiOiaJ4<_mAIiuQQR~ym3 z>!bS0T1sF2MKhD1X*)X|=4;=^Np?d&o|tQ)0o-55 z=fYQJ0W5se5S z;s7Xv68$VGec98<*`{*$-GjaYMXzYi!P9}S4ezAZSqLIv?p>7%h1ZeTqitV z_yD(Jw{q_fgV!ri^oq_PQ@3SbRkysrj;OlXjwf4*>>CW?0_CxAJ6CD#8y#UWp%8t@9spk%WQrs&F@QTv*o?_yoKx9Gt9`R_|n zinyZS@8|dI*DjP+gLRu_Xo8?j;yRS6V@bIln02KhesMd%epPBTNt{MyBJf2S_eHRb zL1P|_nK*5_tUp=G{g;%AgK@SrJ{PpiR;4BNIW5dyPSfYCAin)As1)(d)8W5d-UZIB z%l+3X*2le#_vj&U)dh<4&X9efP{b7-j6AN#{}qK}EUpH$?2H~#ovP}PU=geiQM!Bm zK3<&|fyj;9M`XD~;c9@Jsfpa5n;fQoJ0;Ni`JzhbFIJWWvNR1x5_uf6(volpr&0o~ zpJ(%Zq)@b-kAy&$2+bq%_&98FW~JIUGZ@pT3rz%CNyG+<6pDB$1hQiu%q3o`IwxM> z@h|wsVlvRmqA^4ZMZ6ILS%#ZO6K|ouA(++N=IEQZlYv$iv4J9lek_JSmfA><$P?lt z(TkQBIQrhGr2tw<#QN0;A&(nQHo_p=fJfvBaSQL=&0o*kY^!|kj^xH(7O^2Cg#4_W zd{YKl!c9)(39)ALp|g(H*-r2LlfsuIVq6;`^x_oqjtsJK3@ZUxle1y2CJ-|jXhR}4 zkP4(`k+Z@eo648@W|t4Kh9qA-pp`{2z6i+n${-uhioLkgo#o7WD7b0KKr4&*^A-KJ zcd^TmKsKc>{agIbi|$tViu#Zvi(-7?IrDr`0@;+`y6&?uZF#T!5%GyE1<-~>VxEYM zmzVFlO#;~@+!XOXokXk1-m25=->FnU8xpaBrV>XIAUn*rRF7G^@Yj|UKr4yHqJ^Ol zAd7h13^S`~uwe`*70}8eHjt6xyR87(VZPNDkej!8pOXe?Ws&G}5<`IOFt}+tm3IXC hrU6=6#0C<=e*r;c7wLLnV0r)m002ovPDHLkV1ldzxqSct literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/tick.png b/doc/_build/html/_images/tick.png new file mode 100644 index 0000000000000000000000000000000000000000..1175c8021717199329a79061bbf1e02c49f677fc GIT binary patch literal 175 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 YqCBSGx#a$eJ_lSwMF(D{WEt{507p-mga7~l literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/tuto_GP_regression_m2.png b/doc/_build/html/_images/tuto_GP_regression_m2.png new file mode 100644 index 0000000000000000000000000000000000000000..7e54e9195692d4a56cb5bb960903b38b88f2ff80 GIT binary patch literal 51925 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%0AJs+pdonR)7*}NfaOS{ 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�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 Kv_Rzf>;DHsk<8ct literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/tuto_kern_overview_basicplot.png b/doc/_build/html/_images/tuto_kern_overview_basicplot.png new file mode 100644 index 0000000000000000000000000000000000000000..bad43b09a26c2ca1566cb59fc763449bb5ae8819 GIT binary patch literal 38628 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 DcsJ0) literal 0 HcmV?d00001 diff --git a/doc/_build/html/_images/tuto_kern_overview_mANOVAdec.png b/doc/_build/html/_images/tuto_kern_overview_mANOVAdec.png new file mode 100644 index 0000000000000000000000000000000000000000..45b7ae2a2c25d7feefc113260345aee14edfceab GIT binary patch literal 132944 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
      ZCZZBXppV4ZW$Uq`wydOsPe0kJO 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%0ArMj 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%0A`lCogJ@_~EO90+m!cf3=H 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%0A79-2PSkrKNx^ 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 + + + + + + + GPy — GPy documentation + + + + + + + + + + + + +

      + +
      +
      +
      +
      + +

      Source code for GPy

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import warnings
      +warnings.filterwarnings("ignore", category=DeprecationWarning)
      +
      +import core
      +from core.parameterization import transformations, priors
      +constraints = transformations
      +import models
      +import mappings
      +import inference
      +import util
      +import examples
      +import likelihoods
      +import testing
      +from numpy.testing import Tester
      +import kern
      +import plotting
      +
      +# Direct imports for convenience:
      +from core import Model
      +from core.parameterization import Param, Parameterized, ObsAr
      +
      +#@nottest
      +try:
      +    #Get rid of nose dependency by only ignoring if you have nose installed
      +    from nose.tools import nottest
      +    @nottest
      +    def tests():
      +        Tester(testing).test(verbose=10)
      +except:
      +
      [docs] def tests(): + Tester(testing).test(verbose=10) +
      +
      [docs]def load(file_path): + """ + Load a previously pickled model, using `m.pickle('path/to/file.pickle)' + + :param file_name: path/to/file.pickle + """ + import cPickle as pickle + try: + with open(file_path, 'rb') as f: + m = pickle.load(f) + except: + import pickle as pickle + with open(file_path, 'rb') as f: + m = pickle.load(f) + return m
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/gp.html b/doc/_build/html/_modules/GPy/core/gp.html new file mode 100644 index 00000000..f57e862e --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/gp.html @@ -0,0 +1,553 @@ + + + + + + + + GPy.core.gp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.gp

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +import sys
      +from .. import kern
      +from model import Model
      +from parameterization import ObsAr
      +from .. import likelihoods
      +from ..inference.latent_function_inference import exact_gaussian_inference, expectation_propagation
      +from parameterization.variational import VariationalPosterior
      +
      +import logging
      +from GPy.util.normalizer import MeanNorm
      +logger = logging.getLogger("GP")
      +
      +
      [docs]class GP(Model): + """ + General purpose Gaussian process model + + :param X: input observations + :param Y: output observations + :param kernel: a GPy kernel, defaults to rbf+white + :param likelihood: a GPy likelihood + :param inference_method: The :class:`~GPy.inference.latent_function_inference.LatentFunctionInference` inference method to use for this GP + :rtype: model object + :param Norm normalizer: + normalize the outputs Y. + Prediction will be un-normalized using this normalizer. + If normalizer is None, we will normalize using MeanNorm. + If normalizer is False, no normalization will be done. + + .. Note:: Multiple independent outputs are allowed using columns of Y + + + """ + def __init__(self, X, Y, kernel, likelihood, inference_method=None, name='gp', Y_metadata=None, normalizer=False): + super(GP, self).__init__(name) + + assert X.ndim == 2 + if isinstance(X, (ObsAr, VariationalPosterior)): + self.X = X.copy() + else: self.X = ObsAr(X) + + self.num_data, self.input_dim = self.X.shape + + assert Y.ndim == 2 + logger.info("initializing Y") + + if normalizer is True: + self.normalizer = MeanNorm() + elif normalizer is False: + self.normalizer = None + else: + self.normalizer = normalizer + + if self.normalizer is not None: + self.normalizer.scale_by(Y) + self.Y_normalized = ObsAr(self.normalizer.normalize(Y)) + self.Y = Y + else: + self.Y = ObsAr(Y) + self.Y_normalized = self.Y + + assert Y.shape[0] == self.num_data + _, self.output_dim = self.Y.shape + + #TODO: check the type of this is okay? + self.Y_metadata = Y_metadata + + assert isinstance(kernel, kern.Kern) + #assert self.input_dim == kernel.input_dim + self.kern = kernel + + assert isinstance(likelihood, likelihoods.Likelihood) + self.likelihood = likelihood + + #find a sensible inference method + logger.info("initializing inference method") + if inference_method is None: + if isinstance(likelihood, likelihoods.Gaussian) or isinstance(likelihood, likelihoods.MixedNoise): + inference_method = exact_gaussian_inference.ExactGaussianInference() + else: + inference_method = expectation_propagation.EP() + print "defaulting to ", inference_method, "for latent function inference" + self.inference_method = inference_method + + logger.info("adding kernel and likelihood as parameters") + self.link_parameter(self.kern) + self.link_parameter(self.likelihood) + +
      [docs] def set_XY(self, X=None, Y=None): + """ + Set the input / output data of the model + This is useful if we wish to change our existing data but maintain the same model + + :param X: input observations + :type X: np.ndarray + :param Y: output observations + :type Y: np.ndarray + """ + self.update_model(False) + if Y is not None: + if self.normalizer is not None: + self.normalizer.scale_by(Y) + self.Y_normalized = ObsAr(self.normalizer.normalize(Y)) + self.Y = Y + else: + self.Y = ObsAr(Y) + self.Y_normalized = self.Y + if X is not None: + if self.X in self.parameters: + # LVM models + if isinstance(self.X, VariationalPosterior): + assert isinstance(X, type(self.X)), "The given X must have the same type as the X in the model!" + self.unlink_parameter(self.X) + self.X = X + self.link_parameters(self.X) + else: + self.unlink_parameter(self.X) + from ..core import Param + self.X = Param('latent mean',X) + self.link_parameters(self.X) + else: + self.X = ObsAr(X) + self.update_model(True) +
      +
      [docs] def set_X(self,X): + """ + Set the input data of the model + + :param X: input observations + :type X: np.ndarray + """ + self.set_XY(X=X) +
      +
      [docs] def set_Y(self,Y): + """ + Set the output data of the model + + :param X: output observations + :type X: np.ndarray + """ + self.set_XY(Y=Y) +
      +
      [docs] def parameters_changed(self): + """ + Method that is called upon any changes to :class:`~GPy.core.parameterization.param.Param` variables within the model. + In particular in the GP class this method reperforms inference, recalculating the posterior and log marginal likelihood and gradients of the model + + .. warning:: + This method is not designed to be called manually, the framework is set up to automatically call this method upon changes to parameters, if you call + this method yourself, there may be unexpected consequences. + """ + self.posterior, self._log_marginal_likelihood, self.grad_dict = self.inference_method.inference(self.kern, self.X, self.likelihood, self.Y_normalized, self.Y_metadata) + self.likelihood.update_gradients(self.grad_dict['dL_dthetaL']) + self.kern.update_gradients_full(self.grad_dict['dL_dK'], self.X) +
      +
      [docs] def log_likelihood(self): + """ + The log marginal likelihood of the model, :math:`p(\mathbf{y})`, this is the objective function of the model being optimised + """ + return self._log_marginal_likelihood +
      + def _raw_predict(self, _Xnew, full_cov=False, kern=None): + """ + For making predictions, does not account for normalization or likelihood + + full_cov is a boolean which defines whether the full covariance matrix + of the prediction is computed. If full_cov is False (default), only the + diagonal of the covariance is returned. + + .. math:: + p(f*|X*, X, Y) = \int^{\inf}_{\inf} p(f*|f,X*)p(f|X,Y) df + = N(f*| K_{x*x}(K_{xx} + \Sigma)^{-1}Y, K_{x*x*} - K_{xx*}(K_{xx} + \Sigma)^{-1}K_{xx*} + \Sigma := \texttt{Likelihood.variance / Approximate likelihood covariance} + """ + if kern is None: + kern = self.kern + + Kx = kern.K(_Xnew, self.X).T + WiKx = np.dot(self.posterior.woodbury_inv, Kx) + mu = np.dot(Kx.T, self.posterior.woodbury_vector) + if full_cov: + Kxx = kern.K(_Xnew) + var = Kxx - np.dot(Kx.T, WiKx) + else: + Kxx = kern.Kdiag(_Xnew) + var = Kxx - np.sum(WiKx*Kx, 0) + var = var.reshape(-1, 1) + + #force mu to be a column vector + if len(mu.shape)==1: mu = mu[:,None] + return mu, var + +
      [docs] def predict(self, Xnew, full_cov=False, Y_metadata=None, kern=None): + """ + Predict the function(s) at the new point(s) Xnew. + + :param Xnew: The points at which to make a prediction + :type Xnew: np.ndarray (Nnew x self.input_dim) + :param full_cov: whether to return the full covariance matrix, or just + the diagonal + :type full_cov: bool + :param Y_metadata: metadata about the predicting point to pass to the likelihood + :param kern: The kernel to use for prediction (defaults to the model + kern). this is useful for examining e.g. subprocesses. + :returns: (mean, var, lower_upper): + mean: posterior mean, a Numpy array, Nnew x self.input_dim + var: posterior variance, a Numpy array, Nnew x 1 if full_cov=False, Nnew x Nnew otherwise + lower_upper: lower and upper boundaries of the 95% confidence intervals, Numpy arrays, Nnew x self.input_dim + + If full_cov and self.input_dim > 1, the return shape of var is Nnew x Nnew x self.input_dim. If self.input_dim == 1, the return shape is Nnew x Nnew. + This is to allow for different normalizations of the output dimensions. + """ + #predict the latent function values + mu, var = self._raw_predict(Xnew, full_cov=full_cov, kern=kern) + if self.normalizer is not None: + mu, var = self.normalizer.inverse_mean(mu), self.normalizer.inverse_variance(var) + + # now push through likelihood + mean, var = self.likelihood.predictive_values(mu, var, full_cov, Y_metadata) + return mean, var +
      +
      [docs] def predict_quantiles(self, X, quantiles=(2.5, 97.5), Y_metadata=None): + """ + Get the predictive quantiles around the prediction at X + + :param X: The points at which to make a prediction + :type X: np.ndarray (Xnew x self.input_dim) + :param quantiles: tuple of quantiles, default is (2.5, 97.5) which is the 95% interval + :type quantiles: tuple + :returns: list of quantiles for each X and predictive quantiles for interval combination + :rtype: [np.ndarray (Xnew x self.input_dim), np.ndarray (Xnew x self.input_dim)] + """ + m, v = self._raw_predict(X, full_cov=False) + if self.normalizer is not None: + m, v = self.normalizer.inverse_mean(m), self.normalizer.inverse_variance(v) + return self.likelihood.predictive_quantiles(m, v, quantiles, Y_metadata) +
      +
      [docs] def predictive_gradients(self, Xnew): + """ + Compute the derivatives of the latent function with respect to X* + + Given a set of points at which to predict X* (size [N*,Q]), compute the + derivatives of the mean and variance. Resulting arrays are sized: + dmu_dX* -- [N*, Q ,D], where D is the number of output in this GP (usually one). + + dv_dX* -- [N*, Q], (since all outputs have the same variance) + :param X: The points at which to get the predictive gradients + :type X: np.ndarray (Xnew x self.input_dim) + :returns: dmu_dX, dv_dX + :rtype: [np.ndarray (N*, Q ,D), np.ndarray (N*,Q) ] + + """ + dmu_dX = np.empty((Xnew.shape[0],Xnew.shape[1],self.output_dim)) + for i in range(self.output_dim): + dmu_dX[:,:,i] = self.kern.gradients_X(self.posterior.woodbury_vector[:,i:i+1].T, Xnew, self.X) + + # gradients wrt the diagonal part k_{xx} + dv_dX = self.kern.gradients_X(np.eye(Xnew.shape[0]), Xnew) + #grads wrt 'Schur' part K_{xf}K_{ff}^{-1}K_{fx} + alpha = -2.*np.dot(self.kern.K(Xnew, self.X),self.posterior.woodbury_inv) + dv_dX += self.kern.gradients_X(alpha, Xnew, self.X) + return dmu_dX, dv_dX + +
      +
      [docs] def posterior_samples_f(self,X,size=10, full_cov=True): + """ + Samples the posterior GP at the points X. + + :param X: The points at which to take the samples. + :type X: np.ndarray (Nnew x self.input_dim) + :param size: the number of a posteriori samples. + :type size: int. + :param full_cov: whether to return the full covariance matrix, or just the diagonal. + :type full_cov: bool. + :returns: Ysim: set of simulations + :rtype: np.ndarray (N x samples) + """ + m, v = self._raw_predict(X, full_cov=full_cov) + if self.normalizer is not None: + m, v = self.normalizer.inverse_mean(m), self.normalizer.inverse_variance(v) + v = v.reshape(m.size,-1) if len(v.shape)==3 else v + if not full_cov: + Ysim = np.random.multivariate_normal(m.flatten(), np.diag(v.flatten()), size).T + else: + Ysim = np.random.multivariate_normal(m.flatten(), v, size).T + + return Ysim +
      +
      [docs] def posterior_samples(self, X, size=10, full_cov=False, Y_metadata=None): + """ + Samples the posterior GP at the points X. + + :param X: the points at which to take the samples. + :type X: np.ndarray (Nnew x self.input_dim.) + :param size: the number of a posteriori samples. + :type size: int. + :param full_cov: whether to return the full covariance matrix, or just the diagonal. + :type full_cov: bool. + :param noise_model: for mixed noise likelihood, the noise model to use in the samples. + :type noise_model: integer. + :returns: Ysim: set of simulations, a Numpy array (N x samples). + """ + Ysim = self.posterior_samples_f(X, size, full_cov=full_cov) + Ysim = self.likelihood.samples(Ysim, Y_metadata) + + return Ysim +
      +
      [docs] def plot_f(self, plot_limits=None, which_data_rows='all', + which_data_ycols='all', fixed_inputs=[], + levels=20, samples=0, fignum=None, ax=None, resolution=None, + plot_raw=True, + linecol=None,fillcol=None, Y_metadata=None, data_symbol='kx'): + """ + Plot the GP's view of the world, where the data is normalized and before applying a likelihood. + This is a call to plot with plot_raw=True. + Data will not be plotted in this, as the GP's view of the world + may live in another space, or units then the data. + + Can plot only part of the data and part of the posterior functions + using which_data_rowsm which_data_ycols. + + :param plot_limits: The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits + :type plot_limits: np.array + :param which_data_rows: which of the training data to plot (default all) + :type which_data_rows: 'all' or a slice object to slice model.X, model.Y + :param which_data_ycols: when the data has several columns (independant outputs), only plot these + :type which_data_ycols: 'all' or a list of integers + :param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v. + :type fixed_inputs: a list of tuples + :param resolution: the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D + :type resolution: int + :param levels: number of levels to plot in a contour plot. + :param levels: for 2D plotting, the number of contour levels to use is ax is None, create a new figure + :type levels: int + :param samples: the number of a posteriori samples to plot + :type samples: int + :param fignum: figure to plot on. + :type fignum: figure number + :param ax: axes to plot on. + :type ax: axes handle + :param linecol: color of line to plot [Tango.colorsHex['darkBlue']] + :type linecol: color either as Tango.colorsHex object or character ('r' is red, 'g' is green) as is standard in matplotlib + :param fillcol: color of fill [Tango.colorsHex['lightBlue']] + :type fillcol: color either as Tango.colorsHex object or character ('r' is red, 'g' is green) as is standard in matplotlib + :param Y_metadata: additional data associated with Y which may be needed + :type Y_metadata: dict + :param data_symbol: symbol as used matplotlib, by default this is a black cross ('kx') + :type data_symbol: color either as Tango.colorsHex object or character ('r' is red, 'g' is green) alongside marker type, as is standard in matplotlib. + """ + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import models_plots + kw = {} + if linecol is not None: + kw['linecol'] = linecol + if fillcol is not None: + kw['fillcol'] = fillcol + return models_plots.plot_fit(self, plot_limits, which_data_rows, + which_data_ycols, fixed_inputs, + levels, samples, fignum, ax, resolution, + plot_raw=plot_raw, Y_metadata=Y_metadata, + data_symbol=data_symbol, **kw) +
      +
      [docs] def plot(self, plot_limits=None, which_data_rows='all', + which_data_ycols='all', fixed_inputs=[], + levels=20, samples=0, fignum=None, ax=None, resolution=None, + plot_raw=False, + linecol=None,fillcol=None, Y_metadata=None, data_symbol='kx'): + """ + Plot the posterior of the GP. + - In one dimension, the function is plotted with a shaded region identifying two standard deviations. + - In two dimsensions, a contour-plot shows the mean predicted function + - In higher dimensions, use fixed_inputs to plot the GP with some of the inputs fixed. + + Can plot only part of the data and part of the posterior functions + using which_data_rowsm which_data_ycols. + + :param plot_limits: The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits + :type plot_limits: np.array + :param which_data_rows: which of the training data to plot (default all) + :type which_data_rows: 'all' or a slice object to slice model.X, model.Y + :param which_data_ycols: when the data has several columns (independant outputs), only plot these + :type which_data_ycols: 'all' or a list of integers + :param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v. + :type fixed_inputs: a list of tuples + :param resolution: the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D + :type resolution: int + :param levels: number of levels to plot in a contour plot. + :param levels: for 2D plotting, the number of contour levels to use is ax is None, create a new figure + :type levels: int + :param samples: the number of a posteriori samples to plot + :type samples: int + :param fignum: figure to plot on. + :type fignum: figure number + :param ax: axes to plot on. + :type ax: axes handle + :param linecol: color of line to plot [Tango.colorsHex['darkBlue']] + :type linecol: color either as Tango.colorsHex object or character ('r' is red, 'g' is green) as is standard in matplotlib + :param fillcol: color of fill [Tango.colorsHex['lightBlue']] + :type fillcol: color either as Tango.colorsHex object or character ('r' is red, 'g' is green) as is standard in matplotlib + :param Y_metadata: additional data associated with Y which may be needed + :type Y_metadata: dict + :param data_symbol: symbol as used matplotlib, by default this is a black cross ('kx') + :type data_symbol: color either as Tango.colorsHex object or character ('r' is red, 'g' is green) alongside marker type, as is standard in matplotlib. + """ + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import models_plots + kw = {} + if linecol is not None: + kw['linecol'] = linecol + if fillcol is not None: + kw['fillcol'] = fillcol + return models_plots.plot_fit(self, plot_limits, which_data_rows, + which_data_ycols, fixed_inputs, + levels, samples, fignum, ax, resolution, + plot_raw=plot_raw, Y_metadata=Y_metadata, + data_symbol=data_symbol, **kw) +
      +
      [docs] def input_sensitivity(self, summarize=True): + """ + Returns the sensitivity for each dimension of this model + """ + return self.kern.input_sensitivity(summarize=summarize) +
      +
      [docs] def optimize(self, optimizer=None, start=None, **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_f_eval: maximum number of function evaluations + :type max_f_eval: int + :messages: whether to display during optimisation + :type messages: bool + :param optimizer: which optimizer to use (defaults to self.preferred optimizer), a range of optimisers can be found in :module:`~GPy.inference.optimization`, they include 'scg', 'lbfgs', 'tnc'. + :type optimizer: string + """ + self.inference_method.on_optimization_start() + try: + super(GP, self).optimize(optimizer, start, **kwargs) + except KeyboardInterrupt: + print "KeyboardInterrupt caught, calling on_optimization_end() to round things up" + self.inference_method.on_optimization_end() + raise +
      +
      [docs] def infer_newX(self, Y_new, optimize=True, ): + """ + Infer the distribution of X for the new observed data *Y_new*. + + :param Y_new: the new observed data for inference + :type Y_new: numpy.ndarray + :param optimize: whether to optimize the location of new X (True by default) + :type optimize: boolean + :return: a tuple containing the posterior estimation of X and the model that optimize X + :rtype: (:class:`~GPy.core.parameterization.variational.VariationalPosterior` or numpy.ndarray, :class:`~GPy.core.model.Model`) + """ + from ..inference.latent_function_inference.inferenceX import infer_newX + return infer_newX(self, Y_new, optimize=optimize)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/mapping.html b/doc/_build/html/_modules/GPy/core/mapping.html new file mode 100644 index 00000000..5d787fe0 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/mapping.html @@ -0,0 +1,238 @@ + + + + + + + + GPy.core.mapping — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.mapping

      +# Copyright (c) 2013,2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import sys
      +from parameterization import Parameterized
      +import numpy as np
      +
      +
      [docs]class Mapping(Parameterized): + """ + Base model for shared behavior between models that can act like a mapping. + """ + + def __init__(self, input_dim, output_dim, name='mapping'): + self.input_dim = input_dim + self.output_dim = output_dim + super(Mapping, self).__init__(name=name) + +
      [docs] def f(self, X): + raise NotImplementedError +
      +
      [docs] def df_dX(self, dL_df, X): + """Evaluate derivatives of mapping outputs with respect to inputs. + + :param dL_df: gradient of the objective with respect to the function. + :type dL_df: ndarray (num_data x output_dim) + :param X: the input locations where derivatives are to be evaluated. + :type X: ndarray (num_data x input_dim) + :returns: matrix containing gradients of the function with respect to the inputs. + """ + raise NotImplementedError +
      +
      [docs] def df_dtheta(self, dL_df, X): + """The gradient of the outputs of the mapping with respect to each of the parameters. + + :param dL_df: gradient of the objective with respect to the function. + :type dL_df: ndarray (num_data x output_dim) + :param X: input locations where the function is evaluated. + :type X: ndarray (num_data x input_dim) + :returns: Matrix containing gradients with respect to parameters of each output for each input data. + :rtype: ndarray (num_params length) + """ + + raise NotImplementedError +
      +
      [docs] def plot(self, *args): + """ + Plots the mapping associated with the model. + - In one dimension, the function is plotted. + - In two dimensions, a contour-plot shows the function + - In higher dimensions, we've not implemented this yet !TODO! + + Can plot only part of the data and part of the posterior functions + using which_data and which_functions + + This is a convenience function: arguments are passed to + GPy.plotting.matplot_dep.models_plots.plot_mapping + """ + + if "matplotlib" in sys.modules: + from ..plotting.matplot_dep import models_plots + mapping_plots.plot_mapping(self,*args) + else: + raise NameError, "matplotlib package has not been imported." +
      +
      [docs]class Bijective_mapping(Mapping): + """ + This is a mapping that is bijective, i.e. you can go from X to f and + also back from f to X. The inverse mapping is called g(). + """ + def __init__(self, input_dim, output_dim, name='bijective_mapping'): + super(Bijective_apping, self).__init__(name=name) + +
      [docs] def g(self, f): + """Inverse mapping from output domain of the function to the inputs.""" + raise NotImplementedError +
      +from model import Model + +
      [docs]class Mapping_check_model(Model): + """ + This is a dummy model class used as a base class for checking that the + gradients of a given mapping are implemented correctly. It enables + checkgradient() to be called independently on each mapping. + """ + def __init__(self, mapping=None, dL_df=None, X=None): + num_samples = 20 + if mapping==None: + mapping = GPy.mapping.linear(1, 1) + if X==None: + X = np.random.randn(num_samples, mapping.input_dim) + if dL_df==None: + dL_df = np.ones((num_samples, mapping.output_dim)) + + self.mapping=mapping + self.X = X + self.dL_df = dL_df + self.num_params = self.mapping.num_params + Model.__init__(self) + + + def _get_params(self): + return self.mapping._get_params() + + def _get_param_names(self): + return self.mapping._get_param_names() + + def _set_params(self, x): + self.mapping._set_params(x) + +
      [docs] def log_likelihood(self): + return (self.dL_df*self.mapping.f(self.X)).sum() +
      + def _log_likelihood_gradients(self): + raise NotImplementedError, "This needs to be implemented to use the Mapping_check_model class." +
      +
      [docs]class Mapping_check_df_dtheta(Mapping_check_model): + """This class allows gradient checks for the gradient of a mapping with respect to parameters. """ + def __init__(self, mapping=None, dL_df=None, X=None): + Mapping_check_model.__init__(self,mapping=mapping,dL_df=dL_df, X=X) + + def _log_likelihood_gradients(self): + return self.mapping.df_dtheta(self.dL_df, self.X) + +
      +
      [docs]class Mapping_check_df_dX(Mapping_check_model): + """This class allows gradient checks for the gradient of a mapping with respect to X. """ + def __init__(self, mapping=None, dL_df=None, X=None): + Mapping_check_model.__init__(self,mapping=mapping,dL_df=dL_df, X=X) + + if dL_df==None: + dL_df = np.ones((self.X.shape[0],self.mapping.output_dim)) + self.num_params = self.X.shape[0]*self.mapping.input_dim + + def _log_likelihood_gradients(self): + return self.mapping.df_dX(self.dL_df, self.X).flatten() + + def _get_param_names(self): + return ['X_' +str(i) + ','+str(j) for j in range(self.X.shape[1]) for i in range(self.X.shape[0])] + + def _get_params(self): + return self.X.flatten() + + def _set_params(self, x): + self.X=x.reshape(self.X.shape) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/model.html b/doc/_build/html/_modules/GPy/core/model.html new file mode 100644 index 00000000..d53e34e7 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/model.html @@ -0,0 +1,509 @@ + + + + + + + + GPy.core.model — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.model

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +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 numdifftools as ndt
      +
      +
      [docs]class Model(Parameterized): + _fail_count = 0 # Count of failed optimization steps (see objective) + _allowed_failures = 10 # number of allowed failures + + def __init__(self, name): + super(Model, self).__init__(name) # Parameterized.__init__(self) + self.optimization_runs = [] + self.sampling_runs = [] + self.preferred_optimizer = 'bfgs' + from .parameterization.ties_and_remappings import Tie + self.tie = Tie() + self.link_parameter(self.tie, -1) + self.add_observer(self.tie, self.tie._parameters_changed_notification, priority=-500) + +
      [docs] def log_likelihood(self): + raise NotImplementedError, "this needs to be implemented to use the model class"
      + def _log_likelihood_gradients(self): + return self.gradient + +
      [docs] 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): + 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: + 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.argmin([o.f_opt for o in self.optimization_runs]) + self.optimizer_array = self.optimization_runs[i].x_opt + else: + self.optimizer_array = initial_parameters +
      +
      [docs] 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' +
      +
      [docs] def objective_function(self): + """ + The objective function for the given algorithm. + + This function is the true objective, which wants to be minimized. + Note that all parameters are already set and in place, so you just need + to return the objective function here. + + For probabilistic models this is the negative log_likelihood + (including the MAP prior), so we return it here. If your model is not + probabilistic, just return your objective to minimize here! + """ + return -float(self.log_likelihood()) - self.log_prior() +
      +
      [docs] def objective_function_gradients(self): + """ + The gradients for the objective function for the given algorithm. + The gradients are w.r.t. the *negative* objective function, as + this framework works with *negative* log-likelihoods as a default. + + You can find the gradient for the parameters in self.gradient at all times. + This is the place, where gradients get stored for parameters. + + This function is the true objective, which wants to be minimized. + Note that all parameters are already set and in place, so you just need + to return the gradient here. + + For probabilistic models this is the gradient of the negative log_likelihood + (including the MAP prior), so we return it here. If your model is not + probabilistic, just return your *negative* gradient here! + """ + 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 + 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 + obj_grads = np.clip(self._transform_gradients(self.objective_function_gradients()), -1e100, 1e100) + return 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, 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 + obj_grads = np.clip(self._transform_gradients(self.objective_function_gradients()), -1e100, 1e100) + return obj_f, obj_grads + +
      [docs] def optimize(self, optimizer=None, start=None, **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_f_eval: maximum number of function evaluations + :type max_f_eval: int + :messages: whether to display during optimisation + :type messages: bool + :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: + print 'nothing to optimize' + if self.size == 0: + print 'nothing to optimize' + + if not self.update_model(): + print "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(start, model=self, **kwargs) + + opt.run(f_fp=self._objective_grads, f=self._objective, fp=self._grads) + + self.optimization_runs.append(opt) + + self.optimizer_array = opt.x_opt +
      +
      [docs] 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 = 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 itertools.izip(param_index, transformed_index): + xx = x.copy() + xx[xind] += step + f1 = self._objective(xx) + xx[xind] -= 2.*step + f2 = self._objective(xx) + df_ratio = np.abs((f1-f2)/min(f1,f2)) + 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)]] + from operator import itemgetter + to_print = [""] + ["{}: {}".format(name, detail) for name, detail in model_details] + ["<br><b>Parameters</b>:"] + to_print.append(super(Model, self)._repr_html_()) + return "\n".join(to_print) + + def __str__(self): + model_details = [['Name', self.name], + ['Log-likelihood', '{}'.format(float(self.log_likelihood()))], + ["Number of Parameters", '{}'.format(self.size)]] + 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__()) + return "\n".join(to_print) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/index_operations.html b/doc/_build/html/_modules/GPy/core/parameterization/index_operations.html new file mode 100644 index 00000000..53b17f41 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/index_operations.html @@ -0,0 +1,395 @@ + + + + + + + + GPy.core.parameterization.index_operations — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.index_operations

      +# 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
      +
      +
      [docs]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 + +
      +
      [docs]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: + for t, i in constraints.iteritems(): + self.add(t, i) + +
      [docs] def iteritems(self): + return self._properties.iteritems() +
      +
      [docs] def items(self): + return self._properties.items() +
      +
      [docs] def properties(self): + return self._properties.keys() +
      +
      [docs] def iterproperties(self): + return self._properties.iterkeys() +
      +
      [docs] def shift_right(self, start, size): + for ind in self.iterindices(): + toshift = ind>=start + ind[toshift] += size +
      +
      [docs] def shift_left(self, start, size): + for v, ind in 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] +
      +
      [docs] def clear(self): + self._properties.clear() +
      + @property + def size(self): + return reduce(lambda a,b: a+b.size, self.iterindices(), 0) + +
      [docs] def iterindices(self): + return self._properties.itervalues() +
      +
      [docs] def indices(self): + return self._properties.values() +
      +
      [docs] 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) +
      +
      [docs] 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 +
      +
      [docs] def add(self, prop, indices): + self._properties[prop] = combine_indices(self._properties[prop], indices) +
      +
      [docs] 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) +
      +
      [docs] def update(self, parameter_index_view, offset=0): + for i, v in parameter_index_view.iteritems(): + self.add(i, v+offset) +
      +
      [docs] def copy(self): + return self.__deepcopy__(None) +
      + def __deepcopy__(self, memo): + return ParameterIndexOperations(dict(self.iteritems())) + + 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)) +
      +
      [docs]def combine_indices(arr1, arr2): + return numpy.union1d(arr1, arr2) +
      +
      [docs]def remove_indices(arr, to_remove): + return numpy.setdiff1d(arr, to_remove, True) +
      +
      [docs]def index_empty(index): + return numpy.size(index) == 0 +
      +
      [docs]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 + + +
      [docs] def iteritems(self): + for i, ind in self._param_index_ops.iteritems(): + ind2 = self._filter_index(ind) + if ind2.size > 0: + yield i, ind2 +
      +
      [docs] def items(self): + return [[i,v] for i,v in self.iteritems()] +
      +
      [docs] def properties(self): + return [i for i in self.iterproperties()] + +
      +
      [docs] def iterproperties(self): + for i, _ in self.iteritems(): + yield i + +
      +
      [docs] def shift_right(self, start, size): + self._param_index_ops.shift_right(start+self._offset, size) +
      +
      [docs] def shift_left(self, start, size): + self._param_index_ops.shift_left(start+self._offset, size) +
      +
      [docs] 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) + + +
      [docs] def iterindices(self): + for _, ind in self.iteritems(): + yield ind + +
      +
      [docs] def indices(self): + return [ind for ind in self.iterindices()] + +
      +
      [docs] 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) +
      +
      [docs] 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)) + +
      +
      [docs] def add(self, prop, indices): + self._param_index_ops.add(prop, indices+self._offset) + +
      +
      [docs] 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 + return pprint.pformat(dict(self.iteritems())) + +
      [docs] def update(self, parameter_index_view, offset=0): + for i, v in parameter_index_view.iteritems(): + self.add(i, v+offset) + +
      +
      [docs] def copy(self): + return self.__deepcopy__(None) +
      + def __deepcopy__(self, memo): + return ParameterIndexOperations(dict(self.iteritems())) + pass +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/lists_and_dicts.html b/doc/_build/html/_modules/GPy/core/parameterization/lists_and_dicts.html new file mode 100644 index 00000000..74cdf4f5 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/lists_and_dicts.html @@ -0,0 +1,233 @@ + + + + + + + + GPy.core.parameterization.lists_and_dicts — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.lists_and_dicts

      +# Copyright (c) 2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from collections import defaultdict
      +import weakref
      +
      +
      [docs]def intarray_default_factory(): + import numpy as np + return np.int_([]) +
      +
      [docs]class IntArrayDict(defaultdict): + def __init__(self, default_factory=None): + """ + Default will be self._default, if not set otherwise + """ + defaultdict.__init__(self, intarray_default_factory) +
      +
      [docs]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 + +
      [docs] 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 +
      +
      [docs]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 + +
      [docs] 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__() + +
      [docs] 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) + +
      [docs] 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
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/observable_array.html b/doc/_build/html/_modules/GPy/core/parameterization/observable_array.html new file mode 100644 index 00000000..06ce7878 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/observable_array.html @@ -0,0 +1,241 @@ + + + + + + + + GPy.core.parameterization.observable_array — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.observable_array

      +# 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
      +
      +
      [docs]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) + +
      [docs] 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
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/param.html b/doc/_build/html/_modules/GPy/core/parameterization/param.html new file mode 100644 index 00000000..59068bac --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/param.html @@ -0,0 +1,570 @@ + + + + + + + + GPy.core.parameterization.param — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.param

      +# Copyright (c) 2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import itertools
      +import numpy
      +np = numpy
      +from parameter_core import Parameterizable, adjust_name_for_printing, Pickleable
      +from observable_array import ObsAr
      +
      +###### printing
      +__constraints_name__ = "Constraint"
      +__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
      +######
      +
      +
      [docs]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! + + 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 + +
      [docs] 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.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 + #=========================================================================== +
      [docs] 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)] +
      [docs] 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): + return [' '.join(map(lambda c: str(c[0]) if c[1].size == self._realsize_ else "{" + str(c[0]) + "}", self.constraints.iteritems()))] + @property + def _priors_str(self): + return [' '.join(map(lambda c: str(c[0]) if c[1].size == self._realsize_ else "{" + str(c[0]) + "}", self.priors.iteritems()))] + @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> + <td><b>{i}</b></td> + <td><b>{x}</b></td> + <td><b>{c}</b></td> + <td><b>{p}</b></td> + <td><b>{t}</b></td> +</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(['<table>'] + [header] + ["<tr><td>{i}</td><td align=\"right\">{x}</td><td>{c}</td><td>{p}</td><td>{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 itertools.izip(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 itertools.izip(indices, vals, constr_matrix, ties, prirs)]) # return all the constraints with right indices + # except: return super(Param, self).__str__() +
      +
      [docs]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 + self.parents = map(lambda x: x[0], sorted(parents.iteritems(), 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() +
      [docs] def values(self): + return numpy.hstack([p.param_array.flat for p in self.params]) + #=========================================================================== + # parameter operations: + #===========================================================================
      +
      [docs] def update_all_params(self): + for par in self.parents: + par.notify_observers() +
      +
      [docs] 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__ + +
      [docs] 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__ + +
      [docs] 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 + +
      [docs] 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__ + +
      [docs] 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__ + +
      [docs] def unconstrain(self, *constraints): + [param.unconstrain(*constraints) for param in self.params]
      + unconstrain.__doc__ = Param.unconstrain.__doc__ + +
      [docs] def unconstrain_negative(self): + [param.unconstrain_negative() for param in self.params]
      + unconstrain_negative.__doc__ = Param.unconstrain_negative.__doc__ + +
      [docs] def unconstrain_positive(self): + [param.unconstrain_positive() for param in self.params]
      + unconstrain_positive.__doc__ = Param.unconstrain_positive.__doc__ + +
      [docs] def unconstrain_fixed(self): + [param.unconstrain_fixed() for param in self.params]
      + unconstrain_fixed.__doc__ = Param.unconstrain_fixed.__doc__ + unfix = unconstrain_fixed + +
      [docs] def unconstrain_bounded(self, lower, upper): + [param.unconstrain_bounded(lower, upper) for param in self.params]
      + unconstrain_bounded.__doc__ = Param.unconstrain_bounded.__doc__ + +
      [docs] def untie(self, *ties): + [param.untie(*ties) for param in self.params] +
      +
      [docs] 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 itertools.izip(params, constr_matrices)]) + lx = max([p._max_len_values() for p in params]) + li = max([p._max_len_index(i) for p, i in itertools.izip(params, indices)]) + lt = max([p._max_len_names(tm, __tie_name__) for p, tm in itertools.izip(params, ties_matrices)]) + lp = max([p._max_len_names(pm, __constraints_name__) for p, pm in itertools.izip(params, prior_matrices)]) + strings = [] + start = True + for p, cm, i, tm, pm in itertools.izip(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)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/parameter_core.html b/doc/_build/html/_modules/GPy/core/parameterization/parameter_core.html new file mode 100644 index 00000000..51f2c794 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/parameter_core.html @@ -0,0 +1,1130 @@ + + + + + + + + GPy.core.parameterization.parameter_core — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.parameter_core

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +"""
      +Core module for parameterization.
      +This module implements all parameterization techniques, split up in modular bits.
      +
      +HierarchyError:
      +raised when an error with the hierarchy occurs (circles etc.)
      +
      +Observable:
      +Observable Pattern for patameterization
      +
      +
      +"""
      +
      +from transformations import Transformation,Logexp, NegativeLogexp, Logistic, __fixed__, FIXED, UNFIXED
      +import numpy as np
      +import re
      +import logging
      +from updateable import Updateable
      +
      +
      [docs]class HierarchyError(Exception): + """ + Gets thrown when something is wrong with the parameter hierarchy. + """ +
      +
      [docs]def adjust_name_for_printing(name): + """ + Make sure a name can be printed, alongside used as a variable name. + """ + if name is not None: + name2 = name + name = name.replace(" ", "_").replace(".", "_").replace("-", "_m_") + name = name.replace("+", "_p_").replace("!", "_I_") + name = name.replace("**", "_xx_").replace("*", "_x_") + name = name.replace("/", "_l_").replace("@", '_at_') + name = name.replace("(", "_of_").replace(")", "") + if re.match(r'^[a-zA-Z_][a-zA-Z0-9-_]*$', name) is None: + raise NameError, "name {} converted to {} cannot be further converted to valid python variable name!".format(name2, name) + return name + return '' + + +
      +
      [docs]class Parentable(object): + """ + Enable an Object to have a parent. + + Additionally this adds the parent_index, which is the index for the parent + to look for in its parameter list. + """ + _parent_ = None + _parent_index_ = None + def __init__(self, *args, **kwargs): + super(Parentable, self).__init__() + +
      [docs] def has_parent(self): + """ + Return whether this parentable object currently has a parent. + """ + return self._parent_ is not None +
      + def _parent_changed(self): + """ + Gets called, when the parent changed, so we can adjust our + inner attributes according to the new parent. + """ + raise NotImplementedError, "shouldnt happen, Parentable objects need to be able to change their parent" + + def _disconnect_parent(self, *args, **kw): + """ + Disconnect this object from its parent + """ + raise NotImplementedError, "Abstract superclass" + + @property + def _highest_parent_(self): + """ + Gets the highest parent by traversing up to the root node of the hierarchy. + """ + if self._parent_ is None: + return self + return self._parent_._highest_parent_ + + def _notify_parent_change(self): + """ + Dont do anything if in leaf node + """ + pass +
      +
      [docs]class Pickleable(object): + """ + Make an object pickleable (See python doc 'pickling'). + + This class allows for pickling support by Memento pattern. + _getstate returns a memento of the class, which gets pickled. + _setstate(<memento>) (re-)sets the state of the class to the memento + """ + def __init__(self, *a, **kw): + super(Pickleable, self).__init__() + + #=========================================================================== + # Pickling operations + #=========================================================================== +
      [docs] def pickle(self, f, protocol=-1): + """ + :param f: either filename or open file object to write to. + if it is an open buffer, you have to make sure to close + it properly. + :param protocol: pickling protocol to use, python-pickle for details. + """ + import cPickle as pickle + if isinstance(f, str): + with open(f, 'wb') as f: + pickle.dump(self, f, protocol) + else: + pickle.dump(self, f, protocol) + + #=========================================================================== + # copy and pickling + #===========================================================================
      +
      [docs] def copy(self, memo=None, which=None): + """ + Returns a (deep) copy of the current parameter handle. + + All connections to parents of the copy will be cut. + + :param dict memo: memo for deepcopy + :param Parameterized which: parameterized object which started the copy process [default: self] + """ + #raise NotImplementedError, "Copy is not yet implemented, TODO: Observable hierarchy" + if memo is None: + memo = {} + import copy + # the next part makes sure that we do not include parents in any form: + parents = [] + if which is None: + which = self + which.traverse_parents(parents.append) # collect parents + for p in parents: + if not memo.has_key(id(p)):memo[id(p)] = None # set all parents to be None, so they will not be copied + if not memo.has_key(id(self.gradient)):memo[id(self.gradient)] = None # reset the gradient + if not memo.has_key(id(self._fixes_)):memo[id(self._fixes_)] = None # fixes have to be reset, as this is now highest parent + copy = copy.deepcopy(self, memo) # and start the copy + copy._parent_index_ = None + copy._trigger_params_changed() + return copy +
      + def __deepcopy__(self, memo): + s = self.__new__(self.__class__) # fresh instance + memo[id(self)] = s # be sure to break all cycles --> self is already done + import copy + s.__setstate__(copy.deepcopy(self.__getstate__(), memo)) # standard copy + return s + + def __getstate__(self): + ignore_list = ['_param_array_', # parameters get set from bottom to top + '_gradient_array_', # as well as gradients + '_optimizer_copy_', + 'logger', + 'observers', + '_fixes_', # and fixes + '_Cacher_wrap__cachers', # never pickle cachers + ] + dc = dict() + for k,v in self.__dict__.iteritems(): + if k not in ignore_list: + dc[k] = v + return dc + + def __setstate__(self, state): + self.__dict__.update(state) + from lists_and_dicts import ObserverList + self.observers = ObserverList() + self._setup_observers() + self._optimizer_copy_transformed = False + +
      +
      [docs]class Gradcheckable(Pickleable, Parentable): + """ + Adds the functionality for an object to be gradcheckable. + It is just a thin wrapper of a call to the highest parent for now. + TODO: Can be done better, by only changing parameters of the current parameter handle, + such that object hierarchy only has to change for those. + """ + def __init__(self, *a, **kw): + super(Gradcheckable, self).__init__(*a, **kw) + +
      [docs] def checkgrad(self, verbose=0, step=1e-6, tolerance=1e-3, df_tolerance=1e-12): + """ + Check the gradient of this parameter with respect to the highest parent's + objective function. + This is a three point estimate of the gradient, wiggling at the parameters + with a stepsize step. + The check passes if either the ratio or the difference between numerical and + analytical gradient is smaller then tolerance. + + :param bool verbose: whether each parameter shall be checked individually. + :param float step: the stepsize for the numerical three point gradient estimate. + :param float tolerance: the tolerance for the gradient ratio or difference. + :param float df_tolerance: the tolerance for df_tolerance + + Note:- + The *dF_ratio* indicates the limit of 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). + """ + if self.has_parent(): + return self._highest_parent_._checkgrad(self, verbose=verbose, step=step, tolerance=tolerance, df_tolerance=df_tolerance) + return self._checkgrad(self, verbose=verbose, step=step, tolerance=tolerance, df_tolerance=df_tolerance) +
      + def _checkgrad(self, param, verbose=0, step=1e-6, tolerance=1e-3): + """ + Perform the checkgrad on the model. + TODO: this can be done more efficiently, when doing it inside here + """ + raise HierarchyError, "This parameter is not in a model with a likelihood, and, therefore, cannot be gradient checked!" +
      +
      [docs]class Nameable(Gradcheckable): + """ + Make an object nameable inside the hierarchy. + """ + def __init__(self, name, *a, **kw): + super(Nameable, self).__init__(*a, **kw) + self._name = name or self.__class__.__name__ + + @property + def name(self): + """ + The name of this object + """ + return self._name + @name.setter + def name(self, name): + """ + Set the name of this object. + Tell the parent if the name has changed. + """ + from_name = self.name + assert isinstance(name, str) + self._name = name + if self.has_parent(): + self._parent_._name_changed(self, from_name) +
      [docs] def hierarchy_name(self, adjust_for_printing=True): + """ + return the name for this object with the parents names attached by dots. + + :param bool adjust_for_printing: whether to call :func:`~adjust_for_printing()` + on the names, recursively + """ + if adjust_for_printing: adjust = lambda x: adjust_name_for_printing(x) + else: adjust = lambda x: x + if self.has_parent(): + return self._parent_.hierarchy_name() + "." + adjust(self.name) + return adjust(self.name) + +
      +
      [docs]class Indexable(Nameable, Updateable): + """ + Make an object constrainable with Priors and Transformations. + TODO: Mappings!! + Adding a constraint to a Parameter means to tell the highest parent that + the constraint was added and making sure that all parameters covered + by this object are indeed conforming to the constraint. + + :func:`constrain()` and :func:`unconstrain()` are main methods here + """ + def __init__(self, name, default_constraint=None, *a, **kw): + super(Indexable, self).__init__(name=name, *a, **kw) + self._default_constraint_ = default_constraint + from index_operations import ParameterIndexOperations + self.constraints = ParameterIndexOperations() + self.priors = ParameterIndexOperations() + if self._default_constraint_ is not None: + self.constrain(self._default_constraint_) + + def _disconnect_parent(self, constr=None, *args, **kw): + """ + From Parentable: + disconnect the parent and set the new constraints to constr + """ + if constr is None: + constr = self.constraints.copy() + self.constraints.clear() + self.constraints = constr + self._parent_ = None + self._parent_index_ = None + self._connect_fixes() + self._notify_parent_change() + + #=========================================================================== + # Indexable + #=========================================================================== + def _offset_for(self, param): + """ + Return the offset of the param inside this parameterized object. + This does not need to account for shaped parameters, as it + basically just sums up the parameter sizes which come before param. + """ + if param.has_parent(): + p = param._parent_._get_original(param) + if p in self.parameters: + return reduce(lambda a,b: a + b.size, self.parameters[:p._parent_index_], 0) + return self._offset_for(param._parent_) + param._parent_._offset_for(param) + return 0 + + def _raveled_index_for(self, param): + """ + get the raveled index for a param + that is an int array, containing the indexes for the flattened + param inside this parameterized logic. + """ + from param import ParamConcatenation + if isinstance(param, ParamConcatenation): + return np.hstack((self._raveled_index_for(p) for p in param.params)) + return param._raveled_index() + self._offset_for(param) + + def _raveled_index(self): + """ + Flattened array of ints, specifying the index of this object. + This has to account for shaped parameters! + """ + return np.r_[:self.size] + + #=========================================================================== + # Fixing Parameters: + #=========================================================================== +
      [docs] def constrain_fixed(self, value=None, warning=True, trigger_parent=True): + """ + Constrain this parameter to be fixed to the current value it carries. + + :param warning: print a warning for overwriting constraints. + """ + if value is not None: + self[:] = value + + index = self.unconstrain() + index = self._add_to_index_operations(self.constraints, index, __fixed__, warning) + self._highest_parent_._set_fixed(self, index) + self.notify_observers(self, None if trigger_parent else -np.inf) + return index
      + fix = constrain_fixed + +
      [docs] def unconstrain_fixed(self): + """ + This parameter will no longer be fixed. + """ + unconstrained = self.unconstrain(__fixed__) + self._highest_parent_._set_unfixed(self, unconstrained) + return unconstrained
      + unfix = unconstrain_fixed + + def _ensure_fixes(self): + # Ensure that the fixes array is set: + # Parameterized: ones(self.size) + # Param: ones(self._realsize_ + if not self._has_fixes(): self._fixes_ = np.ones(self.size, dtype=bool) + + def _set_fixed(self, param, index): + self._ensure_fixes() + offset = self._offset_for(param) + self._fixes_[index+offset] = FIXED + if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED + + def _set_unfixed(self, param, index): + self._ensure_fixes() + offset = self._offset_for(param) + self._fixes_[index+offset] = UNFIXED + if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED + + def _connect_fixes(self): + fixed_indices = self.constraints[__fixed__] + if fixed_indices.size > 0: + self._ensure_fixes() + self._fixes_[fixed_indices] = FIXED + else: + self._fixes_ = None + del self.constraints[__fixed__] + + #=========================================================================== + # Convenience for fixed + #=========================================================================== + def _has_fixes(self): + return hasattr(self, "_fixes_") and self._fixes_ is not None and self._fixes_.size == self.size + + @property + def is_fixed(self): + for p in self.parameters: + if not p.is_fixed: return False + return True + + def _get_original(self, param): + # if advanced indexing is activated it happens that the array is a copy + # you can retrieve the original param through this method, by passing + # the copy here + return self.parameters[param._parent_index_] + + #=========================================================================== + # Prior Operations + #=========================================================================== +
      [docs] 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 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' +
      +
      [docs] 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) +
      +
      [docs] def log_prior(self): + """evaluate the prior""" + if self.priors.size > 0: + x = self.param_array + return reduce(lambda a, b: a + b, (p.lnpdf(x[ind]).sum() for p, ind in self.priors.iteritems()), 0) + return 0. +
      + def _log_prior_gradients(self): + """evaluate the gradients of the priors""" + if self.priors.size > 0: + x = self.param_array + ret = np.zeros(x.size) + [np.put(ret, ind, p.lnpdf_grad(x[ind])) for p, ind in self.priors.iteritems()] + return ret + return 0. + + #=========================================================================== + # Tie parameters together + #=========================================================================== + + def _has_ties(self): + if self._highest_parent_.tie.tied_param is None: + return False + if self.has_parent(): + return self._highest_parent_.tie.label_buf[self._highest_parent_._raveled_index_for(self)].sum()>0 + return True + +
      [docs] def tie_together(self): + self._highest_parent_.tie.add_tied_parameter(self) + self._highest_parent_._set_fixed(self,self._raveled_index()) + self._trigger_params_changed() + + #=========================================================================== + # Constrain operations -> done + #=========================================================================== +
      +
      [docs] def constrain(self, transform, warning=True, trigger_parent=True): + """ + :param transform: the :py:class:`GPy.core.transformations.Transformation` + to constrain the this parameter to. + :param warning: print a warning if re-constraining parameters. + + Constrain the parameter to the given + :py:class:`GPy.core.transformations.Transformation`. + """ + if isinstance(transform, Transformation): + self.param_array[...] = transform.initialize(self.param_array) + reconstrained = self.unconstrain() + added = self._add_to_index_operations(self.constraints, reconstrained, transform, warning) + self.notify_observers(self, None if trigger_parent else -np.inf) + return added +
      +
      [docs] def unconstrain(self, *transforms): + """ + :param transforms: The transformations to unconstrain from. + + remove all :py:class:`GPy.core.transformations.Transformation` + transformats of this parameter object. + """ + return self._remove_from_index_operations(self.constraints, transforms) +
      +
      [docs] def constrain_positive(self, warning=True, trigger_parent=True): + """ + :param warning: print a warning if re-constraining parameters. + + Constrain this parameter to the default positive constraint. + """ + self.constrain(Logexp(), warning=warning, trigger_parent=trigger_parent) +
      +
      [docs] def constrain_negative(self, warning=True, trigger_parent=True): + """ + :param warning: print a warning if re-constraining parameters. + + Constrain this parameter to the default negative constraint. + """ + self.constrain(NegativeLogexp(), warning=warning, trigger_parent=trigger_parent) +
      +
      [docs] def constrain_bounded(self, lower, upper, warning=True, trigger_parent=True): + """ + :param lower, upper: the limits to bound this parameter to + :param warning: print a warning if re-constraining parameters. + + Constrain this parameter to lie within the given range. + """ + self.constrain(Logistic(lower, upper), warning=warning, trigger_parent=trigger_parent) +
      +
      [docs] def unconstrain_positive(self): + """ + Remove positive constraint of this parameter. + """ + self.unconstrain(Logexp()) +
      +
      [docs] def unconstrain_negative(self): + """ + Remove negative constraint of this parameter. + """ + self.unconstrain(NegativeLogexp()) +
      +
      [docs] def unconstrain_bounded(self, lower, upper): + """ + :param lower, upper: the limits to unbound this parameter from + + Remove (lower, upper) bounded constrain from this parameter/ + """ + self.unconstrain(Logistic(lower, upper)) +
      + def _parent_changed(self, parent): + """ + From Parentable: + Called when the parent changed + + update the constraints and priors view, so that + constraining is automized for the parent. + """ + from index_operations import ParameterIndexOperationsView + #if getattr(self, "_in_init_"): + #import ipdb;ipdb.set_trace() + #self.constraints.update(param.constraints, start) + #self.priors.update(param.priors, start) + offset = parent._offset_for(self) + self.constraints = ParameterIndexOperationsView(parent.constraints, offset, self.size) + self.priors = ParameterIndexOperationsView(parent.priors, offset, self.size) + self._fixes_ = None + for p in self.parameters: + p._parent_changed(parent) + + def _add_to_index_operations(self, which, reconstrained, what, warning): + """ + Helper preventing copy code. + This adds the given what (transformation, prior etc) to parameter index operations which. + reconstrained are reconstrained indices. + warn when reconstraining parameters if warning is True. + TODO: find out which parameters have changed specifically + """ + if warning and reconstrained.size > 0: + # TODO: figure out which parameters have changed and only print those + print "WARNING: reconstraining parameters {}".format(self.hierarchy_name() or self.name) + index = self._raveled_index() + which.add(what, index) + return index + + def _remove_from_index_operations(self, which, transforms): + """ + Helper preventing copy code. + Remove given what (transform prior etc) from which param index ops. + """ + if len(transforms) == 0: + transforms = which.properties() + removed = np.empty((0,), dtype=int) + for t in transforms: + unconstrained = which.remove(t, self._raveled_index()) + removed = np.union1d(removed, unconstrained) + if t is __fixed__: + self._highest_parent_._set_unfixed(self, unconstrained) + + return removed +
      +
      [docs]class OptimizationHandlable(Indexable): + """ + This enables optimization handles on an Object as done in GPy 0.4. + + `..._optimizer_copy_transformed`: make sure the transformations and constraints etc are handled + """ + def __init__(self, name, default_constraint=None, *a, **kw): + super(OptimizationHandlable, self).__init__(name, default_constraint=default_constraint, *a, **kw) + self._optimizer_copy_ = None + self._optimizer_copy_transformed = False + + #=========================================================================== + # Optimizer copy + #=========================================================================== + @property + def optimizer_array(self): + """ + Array for the optimizer to work on. + This array always lives in the space for the optimizer. + Thus, it is untransformed, going from Transformations. + + Setting this array, will make sure the transformed parameters for this model + will be set accordingly. It has to be set with an array, retrieved from + this method, as e.g. fixing will resize the array. + + The optimizer should only interfere with this array, such that transformations + are secured. + """ + if self.__dict__.get('_optimizer_copy_', None) is None or self.size != self._optimizer_copy_.size: + self._optimizer_copy_ = np.empty(self.size) + + if not self._optimizer_copy_transformed: + self._optimizer_copy_.flat = self.param_array.flat + [np.put(self._optimizer_copy_, ind, c.finv(self.param_array[ind])) for c, ind in self.constraints.iteritems() if c != __fixed__] + if self.has_parent() and (self.constraints[__fixed__].size != 0 or self._has_ties()): + fixes = np.ones(self.size).astype(bool) + fixes[self.constraints[__fixed__]] = FIXED + return self._optimizer_copy_[np.logical_and(fixes, self._highest_parent_.tie.getTieFlag(self))] + elif self._has_fixes(): + return self._optimizer_copy_[self._fixes_] + + self._optimizer_copy_transformed = True + + return self._optimizer_copy_ + + @optimizer_array.setter + def optimizer_array(self, p): + """ + Make sure the optimizer copy does not get touched, thus, we only want to + set the values *inside* not the array itself. + + Also we want to update param_array in here. + """ + f = None + if self.has_parent() and self.constraints[__fixed__].size != 0: + f = np.ones(self.size).astype(bool) + f[self.constraints[__fixed__]] = FIXED + elif self._has_fixes(): + f = self._fixes_ + if f is None: + self.param_array.flat = p + [np.put(self.param_array, ind, c.f(self.param_array.flat[ind])) + for c, ind in self.constraints.iteritems() if c != __fixed__] + else: + self.param_array.flat[f] = p + [np.put(self.param_array, ind[f[ind]], c.f(self.param_array.flat[ind[f[ind]]])) + for c, ind in self.constraints.iteritems() if c != __fixed__] + #self._highest_parent_.tie.propagate_val() + + self._optimizer_copy_transformed = False + self.trigger_update() + + def _get_params_transformed(self): + raise DeprecationWarning, "_get|set_params{_optimizer_copy_transformed} is deprecated, use self.optimizer array insetad!" +# + def _set_params_transformed(self, p): + raise DeprecationWarning, "_get|set_params{_optimizer_copy_transformed} is deprecated, use self.optimizer array insetad!" + + def _trigger_params_changed(self, trigger_parent=True): + """ + First tell all children to update, + then update yourself. + + If trigger_parent is True, we will tell the parent, otherwise not. + """ + [p._trigger_params_changed(trigger_parent=False) for p in self.parameters if not p.is_fixed] + self.notify_observers(None, None if trigger_parent else -np.inf) + + def _size_transformed(self): + """ + As fixes are not passed to the optimiser, the size of the model for the optimiser + is the size of all parameters minus the size of the fixes. + """ + return self.size - self.constraints[__fixed__].size + + def _transform_gradients(self, g): + """ + Transform the gradients by multiplying the gradient factor for each + constraint to it. + """ + self._highest_parent_.tie.collate_gradient() + [np.put(g, i, c.gradfactor(self.param_array[i], g[i])) for c, i in self.constraints.iteritems() if c != __fixed__] + if self._has_fixes(): return g[self._fixes_] + return g + + @property + def num_params(self): + """ + Return the number of parameters of this parameter_handle. + Param objects will always return 0. + """ + raise NotImplemented, "Abstract, please implement in respective classes" + +
      [docs] def parameter_names(self, add_self=False, adjust_for_printing=False, recursive=True): + """ + Get the names of all parameters of this model. + + :param bool add_self: whether to add the own name in front of names + :param bool adjust_for_printing: whether to call `adjust_name_for_printing` on names + :param bool recursive: whether to traverse through hierarchy and append leaf node names + """ + if adjust_for_printing: adjust = lambda x: adjust_name_for_printing(x) + else: adjust = lambda x: x + if recursive: names = [xi for x in self.parameters for xi in x.parameter_names(add_self=True, adjust_for_printing=adjust_for_printing)] + else: names = [adjust(x.name) for x in self.parameters] + if add_self: names = map(lambda x: adjust(self.name) + "." + x, names) + return names +
      + def _get_param_names(self): + n = np.array([p.hierarchy_name() + '[' + str(i) + ']' for p in self.flattened_parameters for i in p._indices()]) + return n + + def _get_param_names_transformed(self): + n = self._get_param_names() + if self._has_fixes(): + return n[self._fixes_] + return n + + #=========================================================================== + # Randomizeable + #=========================================================================== +
      [docs] 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.iteritems() if not p is None] + unfixlist = np.ones((self.size,),dtype=np.bool) + unfixlist[self.constraints[__fixed__]] = False + self.param_array.flat[unfixlist] = x.view(np.ndarray).ravel()[unfixlist] + self.update_model(updates) + + #=========================================================================== + # For shared memory arrays. This does nothing in Param, but sets the memory + # for all parameterized objects + #===========================================================================
      + @property + def gradient_full(self): + """ + Note to users: + This does not return the gradient in the right shape! Use self.gradient + for the right gradient array. + + To work on the gradient array, use this as the gradient handle. + This method exists for in memory use of parameters. + When trying to access the true gradient array, use this. + """ + self.gradient # <<< ensure _gradient_array_ + return self._gradient_array_ + + def _propagate_param_grad(self, parray, garray): + """ + For propagating the param_array and gradient_array. + This ensures the in memory view of each subsequent array. + + 1.) connect param_array of children to self.param_array + 2.) tell all children to propagate further + """ + 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) + + pi_old_size = 0 + for pi in self.parameters: + pislice = slice(pi_old_size, pi_old_size + pi.size) + + self.param_array[pislice] = pi.param_array.flat # , requirements=['C', 'W']).flat + self.gradient_full[pislice] = pi.gradient_full.flat # , requirements=['C', 'W']).flat + + pi.param_array.data = parray[pislice].data + pi.gradient_full.data = garray[pislice].data + + pi._propagate_param_grad(parray[pislice], garray[pislice]) + pi_old_size += pi.size + + def _connect_parameters(self): + pass +
      +_name_digit = re.compile("(?P<name>.*)_(?P<digit>\d+)$") +
      [docs]class Parameterizable(OptimizationHandlable): + """ + A parameterisable class. + + This class provides the parameters list (ArrayList) and standard parameter handling, + such as {add|remove}_parameter(), traverse hierarchy and param_array, gradient_array + and the empty parameters_changed(). + + This class is abstract and should not be instantiated. + Use GPy.core.Parameterized() as node (or leaf) in the parameterized hierarchy. + Use GPy.core.Param() for a leaf in the parameterized hierarchy. + """ + def __init__(self, *args, **kwargs): + super(Parameterizable, self).__init__(*args, **kwargs) + from GPy.core.parameterization.lists_and_dicts import ArrayList + self.parameters = ArrayList() + self._param_array_ = None + self._added_names_ = set() + self.logger = logging.getLogger(self.__class__.__name__) + self.__visited = False # for traversing in reverse order we need to know if we were here already + + @property + def param_array(self): + """ + Array representing the parameters of this class. + There is only one copy of all parameters in memory, two during optimization. + + !WARNING!: setting the parameter array MUST always be done in memory: + m.param_array[:] = m_copy.param_array + """ + if (self.__dict__.get('_param_array_', None) is None) or (self._param_array_.size != self.size): + self._param_array_ = np.empty(self.size, dtype=np.float64) + return self._param_array_ + + @property + def unfixed_param_array(self): + """ + Array representing the parameters of this class. + There is only one copy of all parameters in memory, two during optimization. + + !WARNING!: setting the parameter array MUST always be done in memory: + m.param_array[:] = m_copy.param_array + """ + if self.__dict__.get('_param_array_', None) is None: + self._param_array_ = np.empty(self.size, dtype=np.float64) + + if self.constraints[__fixed__].size !=0: + fixes = np.ones(self.size).astype(bool) + fixes[self.constraints[__fixed__]] = FIXED + return self._param_array_[fixes] + else: + return self._param_array_ + + @param_array.setter + def param_array(self, arr): + self._param_array_ = arr + +
      [docs] def traverse(self, visit, *args, **kwargs): + """ + Traverse the hierarchy performing visit(self, *args, **kwargs) + at every node passed by downwards. This function includes self! + + See "visitor pattern" in literature. This is implemented in pre-order fashion. + + Example: + Collect all children: + + children = [] + self.traverse(children.append) + print children + """ + if not self.__visited: + visit(self, *args, **kwargs) + self.__visited = True + for c in self.parameters: + c.traverse(visit, *args, **kwargs) + self.__visited = False +
      +
      [docs] def traverse_parents(self, visit, *args, **kwargs): + """ + Traverse the hierarchy upwards, visiting all parents and their children except self. + See "visitor pattern" in literature. This is implemented in pre-order fashion. + + Example: + + parents = [] + self.traverse_parents(parents.append) + print parents + """ + if self.has_parent(): + self.__visited = True + self._parent_._traverse_parents(visit, *args, **kwargs) + self.__visited = False +
      + def _traverse_parents(self, visit, *args, **kwargs): + if not self.__visited: + self.__visited = True + visit(self, *args, **kwargs) + if self.has_parent(): + self._parent_._traverse_parents(visit, *args, **kwargs) + self._parent_.traverse(visit, *args, **kwargs) + self.__visited = False + + #========================================================================= + # Gradient handling + #========================================================================= + @property + def gradient(self): + if (self.__dict__.get('_gradient_array_', None) is None) or self._gradient_array_.size != self.size: + self._gradient_array_ = np.empty(self.size, dtype=np.float64) + return self._gradient_array_ + + @gradient.setter + def gradient(self, val): + self._gradient_array_[:] = val + + @property + def num_params(self): + return len(self.parameters) + + def _add_parameter_name(self, param, ignore_added_names=False): + pname = adjust_name_for_printing(param.name) + if ignore_added_names: + self.__dict__[pname] = param + return + + def warn_and_retry(param, match=None): + #=================================================================== + # print """ + # WARNING: added a parameter with formatted name {}, + # which is already assigned to {}. + # Trying to change the parameter name to + # + # {}.{} + # """.format(pname, self.hierarchy_name(), self.hierarchy_name(), param.name + "_") + #=================================================================== + if match is None: + param.name += "_1" + else: + param.name = match.group('name') + "_" + str(int(match.group('digit'))+1) + self._add_parameter_name(param, ignore_added_names) + # and makes sure to not delete programmatically added parameters + for other in self.parameters[::-1]: + if other is not param and other.name.startswith(param.name): + warn_and_retry(param, _name_digit.match(other.name)) + return + if pname not in dir(self): + self.__dict__[pname] = param + self._added_names_.add(pname) + elif pname in self.__dict__: + if pname in self._added_names_: + other = self.__dict__[pname] + if not (param is other): + del self.__dict__[pname] + self._added_names_.remove(pname) + warn_and_retry(other) + warn_and_retry(param, _name_digit.match(other.name)) + return + + def _remove_parameter_name(self, param=None, pname=None): + assert param is None or pname is None, "can only delete either param by name, or the name of a param" + pname = adjust_name_for_printing(pname) or adjust_name_for_printing(param.name) + if pname in self._added_names_: + del self.__dict__[pname] + self._added_names_.remove(pname) + self._connect_parameters() + + def _name_changed(self, param, old_name): + self._remove_parameter_name(None, old_name) + self._add_parameter_name(param) + + def __setstate__(self, state): + super(Parameterizable, self).__setstate__(state) + self.logger = logging.getLogger(self.__class__.__name__) + return self + + #=========================================================================== + # notification system + #=========================================================================== + def _parameters_changed_notification(self, me, which=None): + """ + In parameterizable we just need to make sure, that the next call to optimizer_array + will update the optimizer_array to the latest parameters + """ + self._optimizer_copy_transformed = False # tells the optimizer array to update on next request + self.parameters_changed() + def _pass_through_notify_observers(self, me, which=None): + self.notify_observers(which=which) + def _setup_observers(self): + """ + Setup the default observers + + 1: parameters_changed_notify + 2: pass through to parent, if present + """ + self.add_observer(self, self._parameters_changed_notification, -100) + if self.has_parent(): + self.add_observer(self._parent_, self._parent_._pass_through_notify_observers, -np.inf) + #=========================================================================== + # From being parentable, we have to define the parent_change notification + #=========================================================================== + def _notify_parent_change(self): + """ + Notify all parameters that the parent has changed + """ + for p in self.parameters: + p._parent_changed(self) + +
      [docs] def parameters_changed(self): + """ + This method gets called when parameters have changed. + Another way of listening to param changes is to + add self as a listener to the param, such that + updates get passed through. See :py:function:``GPy.core.param.Observable.add_observer`` + """ + pass +
      +
      [docs] def save(self, filename, ftype='HDF5'): + """ + Save all the model parameters into a file (HDF5 by default). + """ + from . import Param + from ...util.misc import param_to_array + def gather_params(self, plist): + if isinstance(self,Param): + plist.append(self) + plist = [] + self.traverse(gather_params, plist) + names = self.parameter_names(adjust_for_printing=True) + if ftype=='HDF5': + try: + import h5py + f = h5py.File(filename,'w') + for p,n in zip(plist,names): + n = n.replace('.','_') + p = param_to_array(p) + d = f.create_dataset(n,p.shape,dtype=p.dtype) + d[:] = p + f.close() + except: + raise 'Fails to write the parameters into a HDF5 file!' +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/parameterized.html b/doc/_build/html/_modules/GPy/core/parameterization/parameterized.html new file mode 100644 index 00000000..2dc72f86 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/parameterized.html @@ -0,0 +1,510 @@ + + + + + + + + GPy.core.parameterization.parameterized — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.parameterized

      +# Copyright (c) 2014, Max Zwiessele, James Hensman
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy; np = numpy
      +import itertools
      +from re import compile, _pattern_type
      +from param import ParamConcatenation
      +from parameter_core import HierarchyError, Parameterizable, adjust_name_for_printing
      +
      +import logging
      +from GPy.core.parameterization.index_operations import ParameterIndexOperationsView
      +logger = logging.getLogger("parameters changed meta")
      +
      +
      [docs]class ParametersChangedMeta(type): + 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 +
      +
      [docs]class Parameterized(Parameterizable): + """ + Parameterized class + + Say m is a handle to a parameterized class. + + Printing parameters: + + - print m: prints a nice summary over all parameters + - print m.name: prints details for param with name 'name' + - print m[regexp]: prints details for all the parameters + which match (!) regexp + - print m['']: prints details for all parameters + + Fields: + + Name: The name of the param, can be renamed! + Value: Shape or value, if one-valued + Constrain: constraint of the param, curly "{c}" brackets indicate + some parameters are constrained by c. See detailed print + to get exact constraints. + Tied_to: which paramter it is tied to. + + Getting and setting parameters: + + Set all values in param to one: + + m.name.to.param = 1 + + Handling of constraining, fixing and tieing parameters: + + You can constrain parameters by calling the constrain on the param itself, e.g: + + - m.name[:,1].constrain_positive() + - m.name[0].tie_to(m.name[1]) + + Fixing parameters will fix them to the value they are right now. If you change + the parameters value, the param will be fixed to the new value! + + 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. + """ + #=========================================================================== + # Metaclass for parameters changed after init. + # This makes sure, that parameters changed will always be called after __init__ + # **Never** call parameters_changed() yourself + __metaclass__ = ParametersChangedMeta + #=========================================================================== + 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) + +
      [docs] 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: + #===========================================================================
      + + + +
      [docs] def add_parameter(self, *args, **kwargs): + raise DeprecationWarning, "add_parameter was renamed to link_parameter to avoid confusion of setting variables"
      +
      [docs] def remove_parameter(self, *args, **kwargs): + raise DeprecationWarning, "remove_parameter was renamed to link_parameter to avoid confusion of setting variables" +
      + 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: + #=========================================================================== +
      [docs] 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 itertools.izip(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_params_changed() + 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: + pass + 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) + +
      [docs] 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>{{name:<{0}s}}</td><td align=\"right\">{{desc:>{1}s}}</td><td>{{const:^{2}s}}</td><td>{{pri:^{3}s}}</td><td>{{t:^{4}s}}</td></tr>".format(nl, sl, cl, pl, tl) + to_print = [] + for n, d, c, t, p in itertools.izip(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> + <td><b>{name}</b> + <td><b>Value</b></td> + <td><b>Constraint</b></td> + <td><b>Prior</b></td> + <td><b>Tied to</b></td>""".format(name=name) + to_print.insert(0, header) + return '<table>' + '\n'.format(sep).join(to_print) + '\n</table>' + + def __str__(self, header=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"]]) + 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) + to_print = [] + for n, d, c, t, p in itertools.izip(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 +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/priors.html b/doc/_build/html/_modules/GPy/core/parameterization/priors.html new file mode 100644 index 00000000..9167e8a2 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/priors.html @@ -0,0 +1,864 @@ + + + + + + + + GPy.core.parameterization.priors — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.priors

      +# Copyright (c) 2012 - 2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from scipy.special import gammaln, digamma
      +from ...util.linalg import pdinv
      +from domains import _REAL, _POSITIVE
      +import warnings
      +import weakref
      +
      +
      +
      [docs]class Prior(object): + domain = None + _instance = None + def __new__(cls, *args, **kwargs): + if not cls._instance or cls._instance.__class__ is not cls: + cls._instance = super(Prior, cls).__new__(cls, *args, **kwargs) + return cls._instance + +
      [docs] def pdf(self, x): + return np.exp(self.lnpdf(x)) +
      +
      [docs] def plot(self): + import sys + + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ...plotting.matplot_dep import priors_plots + + priors_plots.univariate_plot(self) +
      + def __repr__(self, *args, **kwargs): + return self.__str__() + +
      +
      [docs]class Gaussian(Prior): + """ + Implementation of the univariate Gaussian probability function, coupled with random variables. + + :param mu: mean + :param sigma: standard deviation + + .. Note:: Bishop 2006 notation is used throughout the code + + """ + domain = _REAL + _instances = [] + + def __new__(cls, mu=0, sigma=1): # Singleton: + if cls._instances: + cls._instances[:] = [instance for instance in cls._instances if instance()] + for instance in cls._instances: + if instance().mu == mu and instance().sigma == sigma: + return instance() + o = super(Prior, cls).__new__(cls, mu, sigma) + cls._instances.append(weakref.ref(o)) + return cls._instances[-1]() + + def __init__(self, mu, sigma): + self.mu = float(mu) + self.sigma = float(sigma) + self.sigma2 = np.square(self.sigma) + self.constant = -0.5 * np.log(2 * np.pi * self.sigma2) + + def __str__(self): + return "N({:.2g}, {:.2g})".format(self.mu, self.sigma) + +
      [docs] def lnpdf(self, x): + return self.constant - 0.5 * np.square(x - self.mu) / self.sigma2 +
      +
      [docs] def lnpdf_grad(self, x): + return -(x - self.mu) / self.sigma2 +
      +
      [docs] def rvs(self, n): + return np.random.randn(n) * self.sigma + self.mu + +# def __getstate__(self): +# return self.mu, self.sigma +# +# def __setstate__(self, state): +# self.mu = state[0] +# self.sigma = state[1] +# self.sigma2 = np.square(self.sigma) +# self.constant = -0.5 * np.log(2 * np.pi * self.sigma2) +
      +
      [docs]class Uniform(Prior): + domain = _REAL + _instances = [] + + def __new__(cls, lower=0, upper=1): # Singleton: + 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() + o = super(Prior, cls).__new__(cls, lower, upper) + cls._instances.append(weakref.ref(o)) + return cls._instances[-1]() + + def __init__(self, lower, upper): + self.lower = float(lower) + self.upper = float(upper) + + def __str__(self): + return "[{:.2g}, {:.2g}]".format(self.lower, self.upper) + +
      [docs] def lnpdf(self, x): + region = (x >= self.lower) * (x <= self.upper) + return region +
      +
      [docs] def lnpdf_grad(self, x): + return np.zeros(x.shape) +
      +
      [docs] def rvs(self, n): + return np.random.uniform(self.lower, self.upper, size=n) + +# def __getstate__(self): +# return self.lower, self.upper +# +# def __setstate__(self, state): +# self.lower = state[0] +# self.upper = state[1] +
      +
      [docs]class LogGaussian(Gaussian): + """ + Implementation of the univariate *log*-Gaussian probability function, coupled with random variables. + + :param mu: mean + :param sigma: standard deviation + + .. Note:: Bishop 2006 notation is used throughout the code + + """ + domain = _POSITIVE + _instances = [] + + def __new__(cls, mu=0, sigma=1): # Singleton: + if cls._instances: + cls._instances[:] = [instance for instance in cls._instances if instance()] + for instance in cls._instances: + if instance().mu == mu and instance().sigma == sigma: + return instance() + o = super(Prior, cls).__new__(cls, mu, sigma) + cls._instances.append(weakref.ref(o)) + return cls._instances[-1]() + + def __init__(self, mu, sigma): + self.mu = float(mu) + self.sigma = float(sigma) + self.sigma2 = np.square(self.sigma) + self.constant = -0.5 * np.log(2 * np.pi * self.sigma2) + + def __str__(self): + return "lnN({:.2g}, {:.2g})".format(self.mu, self.sigma) + +
      [docs] def lnpdf(self, x): + return self.constant - 0.5 * np.square(np.log(x) - self.mu) / self.sigma2 - np.log(x) +
      +
      [docs] def lnpdf_grad(self, x): + return -((np.log(x) - self.mu) / self.sigma2 + 1.) / x +
      +
      [docs] def rvs(self, n): + return np.exp(np.random.randn(n) * self.sigma + self.mu) + +
      +
      [docs]class MultivariateGaussian(Prior): + """ + Implementation of the multivariate Gaussian probability function, coupled with random variables. + + :param mu: mean (N-dimensional array) + :param var: covariance matrix (NxN) + + .. Note:: Bishop 2006 notation is used throughout the code + + """ + domain = _REAL + _instances = [] + + def __new__(cls, mu=0, var=1): # Singleton: + if cls._instances: + cls._instances[:] = [instance for instance in cls._instances if instance()] + for instance in cls._instances: + if np.all(instance().mu == mu) and np.all(instance().var == var): + return instance() + o = super(Prior, cls).__new__(cls, mu, var) + cls._instances.append(weakref.ref(o)) + return cls._instances[-1]() + + def __init__(self, mu, var): + self.mu = np.array(mu).flatten() + self.var = np.array(var) + assert len(self.var.shape) == 2 + assert self.var.shape[0] == self.var.shape[1] + assert self.var.shape[0] == self.mu.size + self.input_dim = self.mu.size + self.inv, self.hld = pdinv(self.var) + self.constant = -0.5 * self.input_dim * np.log(2 * np.pi) - self.hld + +
      [docs] def summary(self): + raise NotImplementedError +
      +
      [docs] def pdf(self, x): + return np.exp(self.lnpdf(x)) +
      +
      [docs] def lnpdf(self, x): + d = x - self.mu + return self.constant - 0.5 * np.sum(d * np.dot(d, self.inv), 1) +
      +
      [docs] def lnpdf_grad(self, x): + d = x - self.mu + return -np.dot(self.inv, d) +
      +
      [docs] def rvs(self, n): + return np.random.multivariate_normal(self.mu, self.var, n) +
      +
      [docs] def plot(self): + import sys + + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import priors_plots + + priors_plots.multivariate_plot(self) +
      + def __getstate__(self): + return self.mu, self.var + + def __setstate__(self, state): + self.mu = state[0] + self.var = state[1] + assert len(self.var.shape) == 2 + assert self.var.shape[0] == self.var.shape[1] + assert self.var.shape[0] == self.mu.size + self.input_dim = self.mu.size + self.inv, self.hld = pdinv(self.var) + self.constant = -0.5 * self.input_dim * np.log(2 * np.pi) - self.hld +
      +
      [docs]def gamma_from_EV(E, V): + warnings.warn("use Gamma.from_EV to create Gamma Prior", FutureWarning) + return Gamma.from_EV(E, V) + +
      +
      [docs]class Gamma(Prior): + """ + Implementation of the Gamma probability function, coupled with random variables. + + :param a: shape parameter + :param b: rate parameter (warning: it's the *inverse* of the scale) + + .. Note:: Bishop 2006 notation is used throughout the code + + """ + domain = _POSITIVE + _instances = [] + + def __new__(cls, a=1, b=.5): # Singleton: + if cls._instances: + cls._instances[:] = [instance for instance in cls._instances if instance()] + for instance in cls._instances: + if instance().a == a and instance().b == b: + return instance() + o = super(Prior, cls).__new__(cls, a, b) + cls._instances.append(weakref.ref(o)) + return cls._instances[-1]() + + def __init__(self, a, b): + self.a = float(a) + self.b = float(b) + self.constant = -gammaln(self.a) + a * np.log(b) + + def __str__(self): + return "Ga({:.2g}, {:.2g})".format(self.a, self.b) + +
      [docs] def summary(self): + ret = {"E[x]": self.a / self.b, \ + "E[ln x]": digamma(self.a) - np.log(self.b), \ + "var[x]": self.a / self.b / self.b, \ + "Entropy": gammaln(self.a) - (self.a - 1.) * digamma(self.a) - np.log(self.b) + self.a} + if self.a > 1: + ret['Mode'] = (self.a - 1.) / self.b + else: + ret['mode'] = np.nan + return ret +
      +
      [docs] def lnpdf(self, x): + return self.constant + (self.a - 1) * np.log(x) - self.b * x +
      +
      [docs] def lnpdf_grad(self, x): + return (self.a - 1.) / x - self.b +
      +
      [docs] def rvs(self, n): + return np.random.gamma(scale=1. / self.b, shape=self.a, size=n) +
      + @staticmethod +
      [docs] def from_EV(E, V): + """ + Creates an instance of a Gamma Prior by specifying the Expected value(s) + and Variance(s) of the distribution. + + :param E: expected value + :param V: variance + """ + a = np.square(E) / V + b = E / V + return Gamma(a, b) +
      + def __getstate__(self): + return self.a, self.b + + def __setstate__(self, state): + self.a = state[0] + self.b = state[1] + self.constant = -gammaln(self.a) + self.a * np.log(self.b) +
      +
      [docs]class InverseGamma(Gamma): + """ + Implementation of the inverse-Gamma probability function, coupled with random variables. + + :param a: shape parameter + :param b: rate parameter (warning: it's the *inverse* of the scale) + + .. Note:: Bishop 2006 notation is used throughout the code + + """ + domain = _POSITIVE + _instances = [] + def __new__(cls, a=1, b=.5): # Singleton: + if cls._instances: + cls._instances[:] = [instance for instance in cls._instances if instance()] + for instance in cls._instances: + if instance().a == a and instance().b == b: + return instance() + o = super(Prior, cls).__new__(cls, a, b) + cls._instances.append(weakref.ref(o)) + return cls._instances[-1]() + + def __init__(self, a, b): + self.a = float(a) + self.b = float(b) + self.constant = -gammaln(self.a) + a * np.log(b) + + def __str__(self): + return "iGa({:.2g}, {:.2g})".format(self.a, self.b) + +
      [docs] def lnpdf(self, x): + return self.constant - (self.a + 1) * np.log(x) - self.b / x +
      +
      [docs] def lnpdf_grad(self, x): + return -(self.a + 1.) / x + self.b / x ** 2 +
      +
      [docs] def rvs(self, n): + return 1. / np.random.gamma(scale=1. / self.b, shape=self.a, size=n) +
      +
      [docs]class DGPLVM_KFDA(Prior): + """ + Implementation of the Discriminative Gaussian Process Latent Variable function using + Kernel Fisher Discriminant Analysis by Seung-Jean Kim for implementing Face paper + by Chaochao Lu. + + :param lambdaa: constant + :param sigma2: constant + + .. Note:: Surpassing Human-Level Face paper dgplvm implementation + + """ + domain = _REAL + # _instances = [] + # def __new__(cls, lambdaa, sigma2): # Singleton: + # if cls._instances: + # cls._instances[:] = [instance for instance in cls._instances if instance()] + # for instance in cls._instances: + # if instance().mu == mu and instance().sigma == sigma: + # return instance() + # o = super(Prior, cls).__new__(cls, mu, sigma) + # cls._instances.append(weakref.ref(o)) + # return cls._instances[-1]() + + def __init__(self, lambdaa, sigma2, lbl, kern, x_shape): + """A description for init""" + self.datanum = lbl.shape[0] + self.classnum = lbl.shape[1] + self.lambdaa = lambdaa + self.sigma2 = sigma2 + self.lbl = lbl + self.kern = kern + lst_ni = self.compute_lst_ni() + self.a = self.compute_a(lst_ni) + self.A = self.compute_A(lst_ni) + self.x_shape = x_shape + +
      [docs] def get_class_label(self, y): + for idx, v in enumerate(y): + if v == 1: + return idx + return -1 + + # This function assigns each data point to its own class + # and returns the dictionary which contains the class name and parameters.
      +
      [docs] def compute_cls(self, x): + cls = {} + # Appending each data point to its proper class + for j in xrange(self.datanum): + class_label = self.get_class_label(self.lbl[j]) + if class_label not in cls: + cls[class_label] = [] + cls[class_label].append(x[j]) + if len(cls) > 2: + for i in range(2, self.classnum): + del cls[i] + return cls +
      +
      [docs] def x_reduced(self, cls): + x1 = cls[0] + x2 = cls[1] + x = np.concatenate((x1, x2), axis=0) + return x +
      +
      [docs] def compute_lst_ni(self): + lst_ni = [] + lst_ni1 = [] + lst_ni2 = [] + f1 = (np.where(self.lbl[:, 0] == 1)[0]) + f2 = (np.where(self.lbl[:, 1] == 1)[0]) + for idx in f1: + lst_ni1.append(idx) + for idx in f2: + lst_ni2.append(idx) + lst_ni.append(len(lst_ni1)) + lst_ni.append(len(lst_ni2)) + return lst_ni +
      +
      [docs] def compute_a(self, lst_ni): + a = np.ones((self.datanum, 1)) + count = 0 + for N_i in lst_ni: + if N_i == lst_ni[0]: + a[count:count + N_i] = (float(1) / N_i) * a[count] + count += N_i + else: + if N_i == lst_ni[1]: + a[count: count + N_i] = -(float(1) / N_i) * a[count] + count += N_i + return a +
      +
      [docs] def compute_A(self, lst_ni): + A = np.zeros((self.datanum, self.datanum)) + idx = 0 + for N_i in lst_ni: + B = float(1) / np.sqrt(N_i) * (np.eye(N_i) - ((float(1) / N_i) * np.ones((N_i, N_i)))) + A[idx:idx + N_i, idx:idx + N_i] = B + idx += N_i + return A + + # Here log function
      +
      [docs] def lnpdf(self, x): + x = x.reshape(self.x_shape) + K = self.kern.K(x) + a_trans = np.transpose(self.a) + paran = self.lambdaa * np.eye(x.shape[0]) + self.A.dot(K).dot(self.A) + inv_part = pdinv(paran)[0] + J = a_trans.dot(K).dot(self.a) - a_trans.dot(K).dot(self.A).dot(inv_part).dot(self.A).dot(K).dot(self.a) + J_star = (1. / self.lambdaa) * J + return (-1. / self.sigma2) * J_star + + # Here gradient function
      +
      [docs] def lnpdf_grad(self, x): + x = x.reshape(self.x_shape) + K = self.kern.K(x) + paran = self.lambdaa * np.eye(x.shape[0]) + self.A.dot(K).dot(self.A) + inv_part = pdinv(paran)[0] + b = self.A.dot(inv_part).dot(self.A).dot(K).dot(self.a) + a_Minus_b = self.a - b + a_b_trans = np.transpose(a_Minus_b) + DJ_star_DK = (1. / self.lambdaa) * (a_Minus_b.dot(a_b_trans)) + DJ_star_DX = self.kern.gradients_X(DJ_star_DK, x) + return (-1. / self.sigma2) * DJ_star_DX +
      +
      [docs] def rvs(self, n): + return np.random.rand(n) # A WRONG implementation +
      + def __str__(self): + return 'DGPLVM_prior' + + def __getstate___(self): + return self.lbl, self.lambdaa, self.sigma2, self.kern, self.x_shape + + def __setstate__(self, state): + lbl, lambdaa, sigma2, kern, a, A, x_shape = state + self.datanum = lbl.shape[0] + self.classnum = lbl.shape[1] + self.lambdaa = lambdaa + self.sigma2 = sigma2 + self.lbl = lbl + self.kern = kern + lst_ni = self.compute_lst_ni() + self.a = self.compute_a(lst_ni) + self.A = self.compute_A(lst_ni) + self.x_shape = x_shape +
      +
      [docs]class DGPLVM(Prior): + """ + Implementation of the Discriminative Gaussian Process Latent Variable model paper, by Raquel. + + :param sigma2: constant + + .. Note:: DGPLVM for Classification paper implementation + + """ + domain = _REAL + # _instances = [] + # def __new__(cls, mu, sigma): # Singleton: + # if cls._instances: + # cls._instances[:] = [instance for instance in cls._instances if instance()] + # for instance in cls._instances: + # if instance().mu == mu and instance().sigma == sigma: + # return instance() + # o = super(Prior, cls).__new__(cls, mu, sigma) + # cls._instances.append(weakref.ref(o)) + # return cls._instances[-1]() + + def __init__(self, sigma2, lbl, x_shape): + self.sigma2 = sigma2 + # self.x = x + self.lbl = lbl + self.classnum = lbl.shape[1] + self.datanum = lbl.shape[0] + self.x_shape = x_shape + self.dim = x_shape[1] + +
      [docs] def get_class_label(self, y): + for idx, v in enumerate(y): + if v == 1: + return idx + return -1 + + # This function assigns each data point to its own class + # and returns the dictionary which contains the class name and parameters.
      +
      [docs] def compute_cls(self, x): + cls = {} + # Appending each data point to its proper class + for j in xrange(self.datanum): + class_label = self.get_class_label(self.lbl[j]) + if class_label not in cls: + cls[class_label] = [] + cls[class_label].append(x[j]) + return cls + + # This function computes mean of each class. The mean is calculated through each dimension
      +
      [docs] def compute_Mi(self, cls): + M_i = np.zeros((self.classnum, self.dim)) + for i in cls: + # Mean of each class + M_i[i] = np.mean(cls[i], axis=0) + return M_i + + # Adding data points as tuple to the dictionary so that we can access indices
      +
      [docs] def compute_indices(self, x): + data_idx = {} + for j in xrange(self.datanum): + class_label = self.get_class_label(self.lbl[j]) + if class_label not in data_idx: + data_idx[class_label] = [] + t = (j, x[j]) + data_idx[class_label].append(t) + return data_idx + + # Adding indices to the list so we can access whole the indices
      +
      [docs] def compute_listIndices(self, data_idx): + lst_idx = [] + lst_idx_all = [] + for i in data_idx: + if len(lst_idx) == 0: + pass + #Do nothing, because it is the first time list is created so is empty + else: + lst_idx = [] + # Here we put indices of each class in to the list called lst_idx_all + for m in xrange(len(data_idx[i])): + lst_idx.append(data_idx[i][m][0]) + lst_idx_all.append(lst_idx) + return lst_idx_all + + # This function calculates between classes variances
      +
      [docs] def compute_Sb(self, cls, M_i, M_0): + Sb = np.zeros((self.dim, self.dim)) + for i in cls: + B = (M_i[i] - M_0).reshape(self.dim, 1) + B_trans = B.transpose() + Sb += (float(len(cls[i])) / self.datanum) * B.dot(B_trans) + return Sb + + # This function calculates within classes variances
      +
      [docs] def compute_Sw(self, cls, M_i): + Sw = np.zeros((self.dim, self.dim)) + for i in cls: + N_i = float(len(cls[i])) + W_WT = np.zeros((self.dim, self.dim)) + for xk in cls[i]: + W = (xk - M_i[i]) + W_WT += np.outer(W, W) + Sw += (N_i / self.datanum) * ((1. / N_i) * W_WT) + return Sw + + # Calculating beta and Bi for Sb
      +
      [docs] def compute_sig_beta_Bi(self, data_idx, M_i, M_0, lst_idx_all): + # import pdb + # pdb.set_trace() + B_i = np.zeros((self.classnum, self.dim)) + Sig_beta_B_i_all = np.zeros((self.datanum, self.dim)) + for i in data_idx: + # pdb.set_trace() + # Calculating Bi + B_i[i] = (M_i[i] - M_0).reshape(1, self.dim) + for k in xrange(self.datanum): + for i in data_idx: + N_i = float(len(data_idx[i])) + if k in lst_idx_all[i]: + beta = (float(1) / N_i) - (float(1) / self.datanum) + Sig_beta_B_i_all[k] += float(N_i) / self.datanum * (beta * B_i[i]) + else: + beta = -(float(1) / self.datanum) + Sig_beta_B_i_all[k] += float(N_i) / self.datanum * (beta * B_i[i]) + Sig_beta_B_i_all = Sig_beta_B_i_all.transpose() + return Sig_beta_B_i_all + + + # Calculating W_j s separately so we can access all the W_j s anytime
      +
      [docs] def compute_wj(self, data_idx, M_i): + W_i = np.zeros((self.datanum, self.dim)) + for i in data_idx: + N_i = float(len(data_idx[i])) + for tpl in data_idx[i]: + xj = tpl[1] + j = tpl[0] + W_i[j] = (xj - M_i[i]) + return W_i + + # Calculating alpha and Wj for Sw
      +
      [docs] def compute_sig_alpha_W(self, data_idx, lst_idx_all, W_i): + Sig_alpha_W_i = np.zeros((self.datanum, self.dim)) + for i in data_idx: + N_i = float(len(data_idx[i])) + for tpl in data_idx[i]: + k = tpl[0] + for j in lst_idx_all[i]: + if k == j: + alpha = 1 - (float(1) / N_i) + Sig_alpha_W_i[k] += (alpha * W_i[j]) + else: + alpha = 0 - (float(1) / N_i) + Sig_alpha_W_i[k] += (alpha * W_i[j]) + Sig_alpha_W_i = (1. / self.datanum) * np.transpose(Sig_alpha_W_i) + return Sig_alpha_W_i + + # This function calculates log of our prior
      +
      [docs] def lnpdf(self, x): + x = x.reshape(self.x_shape) + cls = self.compute_cls(x) + M_0 = np.mean(x, axis=0) + M_i = self.compute_Mi(cls) + Sb = self.compute_Sb(cls, M_i, M_0) + Sw = self.compute_Sw(cls, M_i) + # Sb_inv_N = np.linalg.inv(Sb + np.eye(Sb.shape[0]) * (np.diag(Sb).min() * 0.1)) + #Sb_inv_N = np.linalg.inv(Sb+np.eye(Sb.shape[0])*0.1) + Sb_inv_N = pdinv(Sb+ np.eye(Sb.shape[0]) * (np.diag(Sb).min() * 0.1))[0] + return (-1 / self.sigma2) * np.trace(Sb_inv_N.dot(Sw)) + + # This function calculates derivative of the log of prior function
      +
      [docs] def lnpdf_grad(self, x): + x = x.reshape(self.x_shape) + cls = self.compute_cls(x) + M_0 = np.mean(x, axis=0) + M_i = self.compute_Mi(cls) + Sb = self.compute_Sb(cls, M_i, M_0) + Sw = self.compute_Sw(cls, M_i) + data_idx = self.compute_indices(x) + lst_idx_all = self.compute_listIndices(data_idx) + Sig_beta_B_i_all = self.compute_sig_beta_Bi(data_idx, M_i, M_0, lst_idx_all) + W_i = self.compute_wj(data_idx, M_i) + Sig_alpha_W_i = self.compute_sig_alpha_W(data_idx, lst_idx_all, W_i) + + # Calculating inverse of Sb and its transpose and minus + # Sb_inv_N = np.linalg.inv(Sb + np.eye(Sb.shape[0]) * (np.diag(Sb).min() * 0.1)) + # Sb_inv_N = np.linalg.inv(Sb+np.eye(Sb.shape[0])*0.1) + Sb_inv_N = pdinv(Sb+ np.eye(Sb.shape[0]) * (np.diag(Sb).min() * 0.1))[0] + Sb_inv_N_trans = np.transpose(Sb_inv_N) + Sb_inv_N_trans_minus = -1 * Sb_inv_N_trans + Sw_trans = np.transpose(Sw) + + # Calculating DJ/DXk + DJ_Dxk = 2 * ( + Sb_inv_N_trans_minus.dot(Sw_trans).dot(Sb_inv_N_trans).dot(Sig_beta_B_i_all) + Sb_inv_N_trans.dot( + Sig_alpha_W_i)) + # Calculating derivative of the log of the prior + DPx_Dx = ((-1 / self.sigma2) * DJ_Dxk) + return DPx_Dx.T + + # def frb(self, x): + # from functools import partial + # from GPy.models import GradientChecker + # f = partial(self.lnpdf) + # df = partial(self.lnpdf_grad) + # grad = GradientChecker(f, df, x, 'X') + # grad.checkgrad(verbose=1) +
      +
      [docs] def rvs(self, n): + return np.random.rand(n) # A WRONG implementation +
      + def __str__(self): + return 'DGPLVM_prior' +
      +
      [docs]class HalfT(Prior): + """ + Implementation of the half student t probability function, coupled with random variables. + + :param A: scale parameter + :param nu: degrees of freedom + + """ + domain = _POSITIVE + _instances = [] + def __new__(cls, A, nu): # Singleton: + if cls._instances: + cls._instances[:] = [instance for instance in cls._instances if instance()] + for instance in cls._instances: + if instance().A == A and instance().nu == nu: + return instance() + o = super(Prior, cls).__new__(cls, A, nu) + cls._instances.append(weakref.ref(o)) + return cls._instances[-1]() + def __init__(self, A, nu): + self.A = float(A) + self.nu = float(nu) + self.constant = gammaln(.5*(self.nu+1.)) - gammaln(.5*self.nu) - .5*np.log(np.pi*self.A*self.nu) + + def __str__(self): + return "hT({:.2g}, {:.2g})".format(self.A, self.nu) + +
      [docs] def lnpdf(self,theta): + return (theta>0) * ( self.constant -.5*(self.nu+1) * np.log( 1.+ (1./self.nu) * (theta/self.A)**2 ) ) + + #theta = theta if isinstance(theta,np.ndarray) else np.array([theta]) + #lnpdfs = np.zeros_like(theta) + #theta = np.array([theta]) + #above_zero = theta.flatten()>1e-6 + #v = self.nu + #sigma2=self.A + #stop + #lnpdfs[above_zero] = (+ gammaln((v + 1) * 0.5) + # - gammaln(v * 0.5) + # - 0.5*np.log(sigma2 * v * np.pi) + # - 0.5*(v + 1)*np.log(1 + (1/np.float(v))*((theta[above_zero][0]**2)/sigma2)) + #) + #return lnpdfs +
      +
      [docs] def lnpdf_grad(self,theta): + theta = theta if isinstance(theta,np.ndarray) else np.array([theta]) + grad = np.zeros_like(theta) + above_zero = theta>1e-6 + v = self.nu + sigma2=self.A + grad[above_zero] = -0.5*(v+1)*(2*theta[above_zero])/(v*sigma2 + theta[above_zero][0]**2) + return grad +
      +
      [docs] def rvs(self, n): + #return np.random.randn(n) * self.sigma + self.mu + from scipy.stats import t + #[np.abs(x) for x in t.rvs(df=4,loc=0,scale=50, size=10000)]) + ret = t.rvs(self.nu,loc=0,scale=self.A, size=n) + ret[ret<0] = 0 + return ret +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/ties_and_remappings.html b/doc/_build/html/_modules/GPy/core/parameterization/ties_and_remappings.html new file mode 100644 index 00000000..89eec658 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/ties_and_remappings.html @@ -0,0 +1,314 @@ + + + + + + + + GPy.core.parameterization.ties_and_remappings — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.ties_and_remappings

      +# 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
      +
      +
      [docs]class Remapping(Parameterized): +
      [docs] 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 +
      +
      [docs] def callback(self): + raise NotImplementedError +
      + def __str__(self): + return self.name + +
      [docs] 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] +
      +
      [docs]class Fix(Remapping): + pass + + + +
      +
      [docs]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 + +
      [docs] 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 + +
      [docs] 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 xrange(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 + +
      [docs] 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() +
      +
      [docs] 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 xrange(self.tied_param.size)] +
      +
      [docs] def propagate_val(self): + if self.tied_param is not None: + for i in xrange(self.tied_param.size): + self._highest_parent_.param_array[self.label_buf==self.label_buf[self.buf_idx[i]]] = self.tied_param[i] +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/transformations.html b/doc/_build/html/_modules/GPy/core/parameterization/transformations.html new file mode 100644 index 00000000..6bb2636f --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/transformations.html @@ -0,0 +1,525 @@ + + + + + + + + GPy.core.parameterization.transformations — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.transformations

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +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
      +#===============================================================================
      +
      +
      +
      [docs]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 +
      [docs] def f(self, opt_param): + raise NotImplementedError
      +
      [docs] def finv(self, model_param): + raise NotImplementedError
      +
      [docs] 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
      +
      [docs] def initialize(self, f): + """ produce a sensible initial value for f(x)""" + raise NotImplementedError
      +
      [docs] 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),axes=axes*args,**kw) + axes = plt.gca() + axes.set_xlabel(xlabel) + axes.set_ylabel(ylabel)
      + def __str__(self): + raise NotImplementedError + def __repr__(self): + return self.__class__.__name__ +
      +
      [docs]class Logexp(Transformation): + domain = _POSITIVE +
      [docs] 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)))
      +
      [docs] def finv(self, f): + return np.where(f>_lim_val, f, np.log(np.exp(f+1e-20) - 1.))
      +
      [docs] def gradfactor(self, f, df): + return np.einsum('i,i->i', df, np.where(f>_lim_val, 1., 1. - np.exp(-f)))
      +
      [docs] 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' + +
      +
      [docs]class NormalTheta(Transformation): + _instances = [] + def __new__(cls, mu_indices, var_indices): + 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 + +
      [docs] 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.mu_indices] *= theta[self.var_indices] + return theta # which is now {mu, var} +
      +
      [docs] def finv(self, muvar): + # before: + varp = muvar[self.var_indices] + muvar[self.mu_indices] /= varp + muvar[self.var_indices] = -.5/varp + + return muvar # which is now {theta1, theta2} +
      +
      [docs] 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} +
      +
      [docs] 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] +
      +
      [docs]class NormalNaturalAntti(NormalTheta): + _instances = [] + _logexp = Logexp() + def __new__(cls, mu_indices, var_indices): + 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 + +
      [docs] 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 +
      +
      [docs] 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" +
      +
      [docs]class NormalEta(Transformation): + _instances = [] + def __new__(cls, mu_indices, var_indices): + 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 + +
      [docs] 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} +
      +
      [docs] def finv(self, muvar): + muvar[self.var_indices] += muvar[self.mu_indices]**2 + return muvar # which is now {eta1, eta2} +
      +
      [docs] 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 +
      +
      [docs] 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" +
      +
      [docs]class NormalNaturalThroughTheta(NormalTheta): + _instances = [] + def __new__(cls, mu_indices, var_indices): + 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 + +
      [docs] 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" +
      +
      [docs]class NormalNaturalThroughEta(NormalEta): + _instances = [] + def __new__(cls, mu_indices, var_indices): + 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 + +
      [docs] 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" + +
      +
      [docs]class LogexpNeg(Transformation): + domain = _POSITIVE +
      [docs] 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)))
      +
      [docs] def finv(self, f): + return np.where(f>_lim_val, 0, np.log(np.exp(-f) - 1.))
      +
      [docs] def gradfactor(self, f, df): + return np.einsum('i,i->i', df, np.where(f>_lim_val, -1, -1 + np.exp(-f)))
      +
      [docs] 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' + +
      +
      [docs]class NegativeLogexp(Transformation): + domain = _NEGATIVE + logexp = Logexp() +
      [docs] def f(self, x): + return -self.logexp.f(x) # np.log(1. + np.exp(x))
      +
      [docs] def finv(self, f): + return self.logexp.finv(-f) # np.log(np.exp(-f) - 1.)
      +
      [docs] def gradfactor(self, f, df): + return np.einsum('i,i->i', df, -self.logexp.gradfactor(-f))
      +
      [docs] def initialize(self, f): + return -self.logexp.initialize(f) # np.abs(f)
      + def __str__(self): + return '-ve' +
      +
      [docs]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 +
      [docs] 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)
      +
      [docs] def finv(self, f): + return np.log(np.exp(f - 1.))
      +
      [docs] 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)
      +
      [docs] 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' +
      +
      [docs]class Exponent(Transformation): + # TODO: can't allow this to go to zero, need to set a lower bound. Similar with negative Exponent below. See old MATLAB code. + domain = _POSITIVE +
      [docs] 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))
      +
      [docs] def finv(self, x): + return np.log(x)
      +
      [docs] def gradfactor(self, f, df): + return np.einsum('i,i->i', df, f)
      +
      [docs] 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' +
      +
      [docs]class NegativeExponent(Exponent): + domain = _NEGATIVE +
      [docs] def f(self, x): + return -Exponent.f(x)
      +
      [docs] def finv(self, f): + return Exponent.finv(-f)
      +
      [docs] def gradfactor(self, f, df): + return np.einsum('i,i->i', df, f)
      +
      [docs] def initialize(self, f): + return -Exponent.initialize(f) #np.abs(f)
      + def __str__(self): + return '-ve' +
      +
      [docs]class Square(Transformation): + domain = _POSITIVE +
      [docs] def f(self, x): + return x ** 2
      +
      [docs] def finv(self, x): + return np.sqrt(x)
      +
      [docs] def gradfactor(self, f, df): + return np.einsum('i,i->i', df, 2 * np.sqrt(f))
      +
      [docs] def initialize(self, f): + return np.abs(f)
      + def __str__(self): + return '+sq' +
      +
      [docs]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() + o = super(Transformation, cls).__new__(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 +
      [docs] def f(self, x): + if (x<-300.).any(): + x = x.copy() + x[x<-300.] = -300. + return self.lower + self.difference / (1. + np.exp(-x))
      +
      [docs] 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))
      +
      [docs] def gradfactor(self, f, df): + return np.einsum('i,i->i', df, (f - self.lower) * (self.upper - f) / self.difference)
      +
      [docs] 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) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/parameterization/variational.html b/doc/_build/html/_modules/GPy/core/parameterization/variational.html new file mode 100644 index 00000000..c779d18e --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/parameterization/variational.html @@ -0,0 +1,314 @@ + + + + + + + + GPy.core.parameterization.variational — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.parameterization.variational

      +'''
      +Created on 6 Nov 2013
      +
      +@author: maxz
      +'''
      +
      +import numpy as np
      +from parameterized import Parameterized
      +from param import Param
      +from transformations import Logexp, Logistic,__fixed__
      +from GPy.util.misc import param_to_array
      +from GPy.util.caching import Cache_this
      +
      +
      [docs]class VariationalPrior(Parameterized): + def __init__(self, name='latent space', **kw): + super(VariationalPrior, self).__init__(name=name, **kw) + +
      [docs] def KL_divergence(self, variational_posterior): + raise NotImplementedError, "override this for variational inference of latent space" +
      +
      [docs] def update_gradients_KL(self, variational_posterior): + """ + updates the gradients for mean and variance **in place** + """ + raise NotImplementedError, "override this for variational inference of latent space" +
      +
      [docs]class NormalPrior(VariationalPrior): +
      [docs] def KL_divergence(self, variational_posterior): + var_mean = np.square(variational_posterior.mean).sum() + var_S = (variational_posterior.variance - np.log(variational_posterior.variance)).sum() + return 0.5 * (var_mean + var_S) - 0.5 * variational_posterior.input_dim * variational_posterior.num_data +
      +
      [docs] def update_gradients_KL(self, variational_posterior): + # dL: + variational_posterior.mean.gradient -= variational_posterior.mean + variational_posterior.variance.gradient -= (1. - (1. / (variational_posterior.variance))) * 0.5 +
      +
      [docs]class SpikeAndSlabPrior(VariationalPrior): + def __init__(self, pi=None, learnPi=False, variance = 1.0, name='SpikeAndSlabPrior', **kw): + super(SpikeAndSlabPrior, self).__init__(name=name, **kw) + self.variance = Param('variance',variance) + self.learnPi = learnPi + if learnPi: + self.pi = Param('Pi', pi, Logistic(1e-10,1.-1e-10)) + else: + self.pi = Param('Pi', pi, __fixed__) + self.link_parameter(self.pi) + + +
      [docs] def KL_divergence(self, variational_posterior): + mu = variational_posterior.mean + S = variational_posterior.variance + gamma,gamma1 = variational_posterior.gamma_probabilities() + log_gamma,log_gamma1 = variational_posterior.gamma_log_prob() + if len(self.pi.shape)==2: + idx = np.unique(gamma._raveled_index()/gamma.shape[-1]) + pi = self.pi[idx] + else: + pi = self.pi + + var_mean = np.square(mu)/self.variance + var_S = (S/self.variance - np.log(S)) + var_gamma = (gamma*(log_gamma-np.log(pi))).sum()+(gamma1*(log_gamma1-np.log(1-pi))).sum() + return var_gamma+ (gamma* (np.log(self.variance)-1. +var_mean + var_S)).sum()/2. +
      +
      [docs] def update_gradients_KL(self, variational_posterior): + mu = variational_posterior.mean + S = variational_posterior.variance + gamma,gamma1 = variational_posterior.gamma_probabilities() + log_gamma,log_gamma1 = variational_posterior.gamma_log_prob() + if len(self.pi.shape)==2: + idx = np.unique(gamma._raveled_index()/gamma.shape[-1]) + pi = self.pi[idx] + else: + pi = self.pi + + variational_posterior.binary_prob.gradient -= (np.log((1-pi)/pi)+log_gamma-log_gamma1+((np.square(mu)+S)/self.variance-np.log(S)+np.log(self.variance)-1.)/2.)*gamma*gamma1 + mu.gradient -= gamma*mu/self.variance + S.gradient -= (1./self.variance - 1./S) * gamma /2. + if self.learnPi: + if len(self.pi)==1: + self.pi.gradient = (gamma/self.pi - (1.-gamma)/(1.-self.pi)).sum() + elif len(self.pi.shape)==1: + self.pi.gradient = (gamma/self.pi - (1.-gamma)/(1.-self.pi)).sum(axis=0) + else: + self.pi[idx].gradient = (gamma/self.pi[idx] - (1.-gamma)/(1.-self.pi[idx])) +
      +
      [docs]class VariationalPosterior(Parameterized): + def __init__(self, means=None, variances=None, name='latent space', *a, **kw): + super(VariationalPosterior, self).__init__(name=name, *a, **kw) + self.mean = Param("mean", means) + self.variance = Param("variance", variances, Logexp()) + self.ndim = self.mean.ndim + self.shape = self.mean.shape + self.num_data, self.input_dim = self.mean.shape + self.link_parameters(self.mean, self.variance) + self.num_data, self.input_dim = self.mean.shape + if self.has_uncertain_inputs(): + assert self.variance.shape == self.mean.shape, "need one variance per sample and dimenion" + +
      [docs] def set_gradients(self, grad): + self.mean.gradient, self.variance.gradient = grad +
      + def _raveled_index(self): + index = np.empty(dtype=int, shape=0) + size = 0 + for p in self.parameters: + index = np.hstack((index, p._raveled_index()+size)) + size += p._realsize_ if hasattr(p, '_realsize_') else p.size + return index + +
      [docs] def has_uncertain_inputs(self): + return not self.variance is None +
      + def __getitem__(self, s): + if isinstance(s, (int, slice, tuple, list, np.ndarray)): + import copy + n = self.__new__(self.__class__, self.name) + dc = self.__dict__.copy() + dc['mean'] = self.mean[s] + dc['variance'] = self.variance[s] + dc['parameters'] = copy.copy(self.parameters) + n.__dict__.update(dc) + n.parameters[dc['mean']._parent_index_] = dc['mean'] + n.parameters[dc['variance']._parent_index_] = dc['variance'] + n._gradient_array_ = None + oversize = self.size - self.mean.size - self.variance.size + n.size = n.mean.size + n.variance.size + oversize + n.ndim = n.mean.ndim + n.shape = n.mean.shape + n.num_data = n.mean.shape[0] + n.input_dim = n.mean.shape[1] if n.ndim != 1 else 1 + return n + else: + return super(VariationalPosterior, self).__getitem__(s) +
      +
      [docs]class NormalPosterior(VariationalPosterior): + ''' + NormalPosterior distribution for variational approximations. + + holds the means and variances for a factorizing multivariate normal distribution + ''' + +
      [docs] def plot(self, *args): + """ + Plot latent space X in 1D: + + See GPy.plotting.matplot_dep.variational_plots + """ + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ...plotting.matplot_dep import variational_plots + import matplotlib + return variational_plots.plot(self,*args) +
      +
      [docs]class SpikeAndSlabPosterior(VariationalPosterior): + ''' + The SpikeAndSlab distribution for variational approximations. + ''' + def __init__(self, means, variances, binary_prob, name='latent space'): + """ + binary_prob : the probability of the distribution on the slab part. + """ + super(SpikeAndSlabPosterior, self).__init__(means, variances, name) + self.gamma = Param("binary_prob",binary_prob) + self.link_parameter(self.gamma) + + @Cache_this(limit=5) + def gamma_probabilities(self): + prob = np.zeros_like(param_to_array(self.gamma)) + prob[self.gamma>-710] = 1./(1.+np.exp(-self.gamma[self.gamma>-710])) + prob1 = -np.zeros_like(param_to_array(self.gamma)) + prob1[self.gamma<710] = 1./(1.+np.exp(self.gamma[self.gamma<710])) + return prob, prob1 + + @Cache_this(limit=5) + def gamma_log_prob(self): + loggamma = param_to_array(self.gamma).copy() + loggamma[loggamma>-40] = -np.log1p(np.exp(-loggamma[loggamma>-40])) + loggamma1 = -param_to_array(self.gamma).copy() + loggamma1[loggamma1>-40] = -np.log1p(np.exp(-loggamma1[loggamma1>-40])) + return loggamma,loggamma1 + +
      [docs] def set_gradients(self, grad): + self.mean.gradient, self.variance.gradient, self.gamma.gradient = grad +
      + def __getitem__(self, s): + if isinstance(s, (int, slice, tuple, list, np.ndarray)): + import copy + n = self.__new__(self.__class__, self.name) + dc = self.__dict__.copy() + dc['mean'] = self.mean[s] + dc['variance'] = self.variance[s] + dc['binary_prob'] = self.binary_prob[s] + dc['parameters'] = copy.copy(self.parameters) + n.__dict__.update(dc) + n.parameters[dc['mean']._parent_index_] = dc['mean'] + n.parameters[dc['variance']._parent_index_] = dc['variance'] + n.parameters[dc['binary_prob']._parent_index_] = dc['binary_prob'] + n._gradient_array_ = None + oversize = self.size - self.mean.size - self.variance.size + n.size = n.mean.size + n.variance.size + oversize + n.ndim = n.mean.ndim + n.shape = n.mean.shape + n.num_data = n.mean.shape[0] + n.input_dim = n.mean.shape[1] if n.ndim != 1 else 1 + return n + else: + return super(VariationalPrior, self).__getitem__(s) + +
      [docs] def plot(self, *args, **kwargs): + """ + Plot latent space X in 1D: + + See GPy.plotting.matplot_dep.variational_plots + """ + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ...plotting.matplot_dep import variational_plots + return variational_plots.plot_SpikeSlab(self,*args, **kwargs)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/sparse_gp.html b/doc/_build/html/_modules/GPy/core/sparse_gp.html new file mode 100644 index 00000000..fd6a53d9 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/sparse_gp.html @@ -0,0 +1,226 @@ + + + + + + + + GPy.core.sparse_gp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.sparse_gp

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from gp import GP
      +from parameterization.param import Param
      +from ..inference.latent_function_inference import var_dtc
      +from .. import likelihoods
      +from parameterization.variational import VariationalPosterior
      +
      +import logging
      +from GPy.inference.latent_function_inference.posterior import Posterior
      +from GPy.inference.optimization.stochastics import SparseGPStochastics,\
      +    SparseGPMissing
      +#no stochastics.py file added! from GPy.inference.optimization.stochastics import SparseGPStochastics,\
      +    #SparseGPMissing
      +logger = logging.getLogger("sparse gp")
      +
      +
      [docs]class SparseGP(GP): + """ + A general purpose Sparse GP model + + This model allows (approximate) inference using variational DTC or FITC + (Gaussian likelihoods) as well as non-conjugate sparse methods based on + these. + + :param X: inputs + :type X: np.ndarray (num_data x input_dim) + :param likelihood: a likelihood instance, containing the observed data + :type likelihood: GPy.likelihood.(Gaussian | EP | Laplace) + :param kernel: the kernel (covariance function). See link kernels + :type kernel: a GPy.kern.kern instance + :param X_variance: The uncertainty in the measurements of X (Gaussian variance) + :type X_variance: np.ndarray (num_data x input_dim) | None + :param Z: inducing inputs + :type Z: np.ndarray (num_inducing x input_dim) + :param num_inducing: Number of inducing points (optional, default 10. Ignored if Z is not None) + :type num_inducing: int + + """ + + def __init__(self, X, Y, Z, kernel, likelihood, inference_method=None, + name='sparse gp', Y_metadata=None, normalizer=False): + #pick a sensible inference method + if inference_method is None: + if isinstance(likelihood, likelihoods.Gaussian): + inference_method = var_dtc.VarDTC(limit=1 if not self.missing_data else Y.shape[1]) + else: + #inference_method = ?? + raise NotImplementedError, "what to do what to do?" + print "defaulting to ", inference_method, "for latent function inference" + + self.Z = Param('inducing inputs', Z) + self.num_inducing = Z.shape[0] + + GP.__init__(self, X, Y, kernel, likelihood, inference_method=inference_method, name=name, Y_metadata=Y_metadata, normalizer=normalizer) + + logger.info("Adding Z as parameter") + self.link_parameter(self.Z, index=0) + self.posterior = None + +
      [docs] def has_uncertain_inputs(self): + return isinstance(self.X, VariationalPosterior) +
      +
      [docs] def parameters_changed(self): + self.posterior, self._log_marginal_likelihood, self.grad_dict = self.inference_method.inference(self.kern, self.X, self.Z, self.likelihood, self.Y, self.Y_metadata) + + self.likelihood.update_gradients(self.grad_dict['dL_dthetaL']) + + if isinstance(self.X, VariationalPosterior): + #gradients wrt kernel + dL_dKmm = self.grad_dict['dL_dKmm'] + self.kern.update_gradients_full(dL_dKmm, self.Z, None) + kerngrad = self.kern.gradient.copy() + self.kern.update_gradients_expectations(variational_posterior=self.X, + Z=self.Z, + dL_dpsi0=self.grad_dict['dL_dpsi0'], + dL_dpsi1=self.grad_dict['dL_dpsi1'], + dL_dpsi2=self.grad_dict['dL_dpsi2']) + self.kern.gradient += kerngrad + + #gradients wrt Z + self.Z.gradient = self.kern.gradients_X(dL_dKmm, self.Z) + self.Z.gradient += self.kern.gradients_Z_expectations( + self.grad_dict['dL_dpsi0'], + self.grad_dict['dL_dpsi1'], + self.grad_dict['dL_dpsi2'], + Z=self.Z, + variational_posterior=self.X) + else: + #gradients wrt kernel + self.kern.update_gradients_diag(self.grad_dict['dL_dKdiag'], self.X) + kerngrad = self.kern.gradient.copy() + self.kern.update_gradients_full(self.grad_dict['dL_dKnm'], self.X, self.Z) + kerngrad += self.kern.gradient + self.kern.update_gradients_full(self.grad_dict['dL_dKmm'], self.Z, None) + self.kern.gradient += kerngrad + #gradients wrt Z + self.Z.gradient = self.kern.gradients_X(self.grad_dict['dL_dKmm'], self.Z) + self.Z.gradient += self.kern.gradients_X(self.grad_dict['dL_dKnm'].T, self.Z, self.X) + +
      + def _raw_predict(self, Xnew, full_cov=False, kern=None): + """ + Make a prediction for the latent function values + """ + + if kern is None: kern = self.kern + + if not isinstance(Xnew, VariationalPosterior): + Kx = kern.K(self.Z, Xnew) + mu = np.dot(Kx.T, self.posterior.woodbury_vector) + if full_cov: + Kxx = kern.K(Xnew) + if self.posterior.woodbury_inv.ndim == 2: + var = Kxx - np.dot(Kx.T, np.dot(self.posterior.woodbury_inv, Kx)) + elif self.posterior.woodbury_inv.ndim == 3: + var = Kxx[:,:,None] - np.tensordot(np.dot(np.atleast_3d(self.posterior.woodbury_inv).T, Kx).T, Kx, [1,0]).swapaxes(1,2) + var = var + else: + Kxx = kern.Kdiag(Xnew) + var = (Kxx - np.sum(np.dot(np.atleast_3d(self.posterior.woodbury_inv).T, Kx) * Kx[None,:,:], 1)).T + else: + Kx = kern.psi1(self.Z, Xnew) + mu = np.dot(Kx, self.posterior.woodbury_vector) + if full_cov: + raise NotImplementedError, "TODO" + else: + Kxx = kern.psi0(self.Z, Xnew) + psi2 = kern.psi2(self.Z, Xnew) + var = Kxx - np.sum(np.sum(psi2 * Kmmi_LmiBLmi[None, :, :], 1), 1) + return mu, var
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/core/sparse_gp_mpi.html b/doc/_build/html/_modules/GPy/core/sparse_gp_mpi.html new file mode 100644 index 00000000..72d9ebd3 --- /dev/null +++ b/doc/_build/html/_modules/GPy/core/sparse_gp_mpi.html @@ -0,0 +1,213 @@ + + + + + + + + GPy.core.sparse_gp_mpi — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.core.sparse_gp_mpi

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from sparse_gp import SparseGP
      +from numpy.linalg.linalg import LinAlgError
      +from ..inference.latent_function_inference.var_dtc_parallel import update_gradients, VarDTC_minibatch
      +
      +import logging
      +logger = logging.getLogger("sparse gp mpi")
      +
      +
      [docs]class SparseGP_MPI(SparseGP): + """ + A general purpose Sparse GP model with MPI parallelization support + + This model allows (approximate) inference using variational DTC or FITC + (Gaussian likelihoods) as well as non-conjugate sparse methods based on + these. + + :param X: inputs + :type X: np.ndarray (num_data x input_dim) + :param likelihood: a likelihood instance, containing the observed data + :type likelihood: GPy.likelihood.(Gaussian | EP | Laplace) + :param kernel: the kernel (covariance function). See link kernels + :type kernel: a GPy.kern.kern instance + :param X_variance: The uncertainty in the measurements of X (Gaussian variance) + :type X_variance: np.ndarray (num_data x input_dim) | None + :param Z: inducing inputs + :type Z: np.ndarray (num_inducing x input_dim) + :param num_inducing: Number of inducing points (optional, default 10. Ignored if Z is not None) + :type num_inducing: int + :param mpi_comm: The communication group of MPI, e.g. mpi4py.MPI.COMM_WORLD + :type mpi_comm: mpi4py.MPI.Intracomm + + """ + + def __init__(self, X, Y, Z, kernel, likelihood, variational_prior=None, inference_method=None, name='sparse gp mpi', Y_metadata=None, mpi_comm=None, normalizer=False): + self._IN_OPTIMIZATION_ = False + if mpi_comm != None: + if inference_method is None: + inference_method = VarDTC_minibatch(mpi_comm=mpi_comm) + else: + assert isinstance(inference_method, VarDTC_minibatch), 'inference_method has to support MPI!' + + super(SparseGP_MPI, self).__init__(X, Y, Z, kernel, likelihood, inference_method=inference_method, name=name, Y_metadata=Y_metadata, normalizer=normalizer) + self.update_model(False) + + if variational_prior is not None: + self.link_parameter(variational_prior) + + self.mpi_comm = mpi_comm + # Manage the data (Y) division + if mpi_comm != None: + from ..util.parallel import divide_data + N_start, N_end, N_list = divide_data(Y.shape[0], mpi_comm.rank, mpi_comm.size) + self.N_range = (N_start, N_end) + self.N_list = np.array(N_list) + self.Y_local = self.Y[N_start:N_end] + print 'MPI RANK '+str(self.mpi_comm.rank)+' with the data range '+str(self.N_range) + mpi_comm.Bcast(self.param_array, root=0) + self.update_model(True) + + def __getstate__(self): + dc = super(SparseGP_MPI, self).__getstate__() + dc['mpi_comm'] = None + if self.mpi_comm != None: + del dc['N_range'] + del dc['N_list'] + del dc['Y_local'] + if 'normalizer' not in dc: + dc['normalizer'] = None + dc['Y_normalized'] = dc['Y'] + return dc + + #===================================================== + # The MPI parallelization + # - can move to model at some point + #===================================================== + + @SparseGP.optimizer_array.setter + def optimizer_array(self, p): + if self.mpi_comm != None: + if self._IN_OPTIMIZATION_ and self.mpi_comm.rank==0: + self.mpi_comm.Bcast(np.int32(1),root=0) + self.mpi_comm.Bcast(p, root=0) + SparseGP.optimizer_array.fset(self,p) + +
      [docs] def optimize(self, optimizer=None, start=None, **kwargs): + self._IN_OPTIMIZATION_ = True + if self.mpi_comm==None: + super(SparseGP_MPI, self).optimize(optimizer,start,**kwargs) + elif self.mpi_comm.rank==0: + super(SparseGP_MPI, self).optimize(optimizer,start,**kwargs) + self.mpi_comm.Bcast(np.int32(-1),root=0) + elif self.mpi_comm.rank>0: + x = self.optimizer_array.copy() + flag = np.empty(1,dtype=np.int32) + while True: + self.mpi_comm.Bcast(flag,root=0) + if flag==1: + try: + self.optimizer_array = x + self._fail_count = 0 + except (LinAlgError, ZeroDivisionError, ValueError): + if self._fail_count >= self._allowed_failures: + raise + self._fail_count += 1 + elif flag==-1: + break + else: + self._IN_OPTIMIZATION_ = False + raise Exception("Unrecognizable flag for synchronization!") + self._IN_OPTIMIZATION_ = False +
      +
      [docs] def parameters_changed(self): + if isinstance(self.inference_method,VarDTC_minibatch): + update_gradients(self, mpi_comm=self.mpi_comm) + else: + super(SparseGP_MPI,self).parameters_changed() +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/examples/classification.html b/doc/_build/html/_modules/GPy/examples/classification.html new file mode 100644 index 00000000..42ad8eb8 --- /dev/null +++ b/doc/_build/html/_modules/GPy/examples/classification.html @@ -0,0 +1,322 @@ + + + + + + + + GPy.examples.classification — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.examples.classification

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +"""
      +Gaussian Processes classification examples
      +"""
      +import GPy
      +
      +default_seed = 10000
      +
      +
      [docs]def oil(num_inducing=50, max_iters=100, kernel=None, optimize=True, plot=True): + """ + Run a Gaussian process classification on the three phase oil data. The demonstration calls the basic GP classification model and uses EP to approximate the likelihood. + + """ + try:import pods + except ImportError:print 'pods unavailable, see https://github.com/sods/ods for example datasets' + data = pods.datasets.oil() + X = data['X'] + Xtest = data['Xtest'] + Y = data['Y'][:, 0:1] + Ytest = data['Ytest'][:, 0:1] + Y[Y.flatten()==-1] = 0 + Ytest[Ytest.flatten()==-1] = 0 + + # Create GP model + m = GPy.models.SparseGPClassification(X, Y, kernel=kernel, num_inducing=num_inducing) + + # Contrain all parameters to be positive + #m.tie_params('.*len') + m['.*len'] = 10. + + # Optimize + if optimize: + for _ in range(5): + m.optimize(max_iters=int(max_iters/5)) + print(m) + + #Test + probs = m.predict(Xtest)[0] + GPy.util.classification.conf_matrix(probs, Ytest) + return m +
      +
      [docs]def toy_linear_1d_classification(seed=default_seed, optimize=True, plot=True): + """ + Simple 1D classification example using EP approximation + + :param seed: seed value for data generation (default is 4). + :type seed: int + + """ + + try:import pods + except ImportError:print 'pods unavailable, see https://github.com/sods/ods for example datasets' + data = pods.datasets.toy_linear_1d_classification(seed=seed) + Y = data['Y'][:, 0:1] + Y[Y.flatten() == -1] = 0 + + # Model definition + m = GPy.models.GPClassification(data['X'], Y) + + # Optimize + if optimize: + #m.update_likelihood_approximation() + # Parameters optimization: + m.optimize() + #m.update_likelihood_approximation() + #m.pseudo_EM() + + # Plot + if plot: + from matplotlib import pyplot as plt + fig, axes = plt.subplots(2, 1) + m.plot_f(ax=axes[0]) + m.plot(ax=axes[1]) + + print m + return m +
      +
      [docs]def toy_linear_1d_classification_laplace(seed=default_seed, optimize=True, plot=True): + """ + Simple 1D classification example using Laplace approximation + + :param seed: seed value for data generation (default is 4). + :type seed: int + + """ + + try:import pods + except ImportError:print 'pods unavailable, see https://github.com/sods/ods for example datasets' + data = pods.datasets.toy_linear_1d_classification(seed=seed) + Y = data['Y'][:, 0:1] + Y[Y.flatten() == -1] = 0 + + likelihood = GPy.likelihoods.Bernoulli() + laplace_inf = GPy.inference.latent_function_inference.Laplace() + kernel = GPy.kern.RBF(1) + + # Model definition + m = GPy.core.GP(data['X'], Y, kernel=kernel, likelihood=likelihood, inference_method=laplace_inf) + + # Optimize + if optimize: + try: + m.optimize('scg', messages=1) + except Exception as e: + return m + + # Plot + if plot: + from matplotlib import pyplot as plt + fig, axes = plt.subplots(2, 1) + m.plot_f(ax=axes[0]) + m.plot(ax=axes[1]) + + print m + return m +
      +
      [docs]def sparse_toy_linear_1d_classification(num_inducing=10, seed=default_seed, optimize=True, plot=True): + """ + Sparse 1D classification example + + :param seed: seed value for data generation (default is 4). + :type seed: int + + """ + + try:import pods + except ImportError:print 'pods unavailable, see https://github.com/sods/ods for example datasets' + data = pods.datasets.toy_linear_1d_classification(seed=seed) + Y = data['Y'][:, 0:1] + Y[Y.flatten() == -1] = 0 + + # Model definition + m = GPy.models.SparseGPClassification(data['X'], Y, num_inducing=num_inducing) + m['.*len'] = 4. + + # Optimize + if optimize: + m.optimize() + + # Plot + if plot: + from matplotlib import pyplot as plt + fig, axes = plt.subplots(2, 1) + m.plot_f(ax=axes[0]) + m.plot(ax=axes[1]) + + print m + return m +
      +
      [docs]def toy_heaviside(seed=default_seed, max_iters=100, optimize=True, plot=True): + """ + Simple 1D classification example using a heavy side gp transformation + + :param seed: seed value for data generation (default is 4). + :type seed: int + + """ + + try:import pods + except ImportError:print 'pods unavailable, see https://github.com/sods/ods for example datasets' + data = pods.datasets.toy_linear_1d_classification(seed=seed) + Y = data['Y'][:, 0:1] + Y[Y.flatten() == -1] = 0 + + # Model definition + kernel = GPy.kern.RBF(1) + likelihood = GPy.likelihoods.Bernoulli(gp_link=GPy.likelihoods.link_functions.Heaviside()) + ep = GPy.inference.latent_function_inference.expectation_propagation.EP() + m = GPy.core.GP(X=data['X'], Y=Y, kernel=kernel, likelihood=likelihood, inference_method=ep, name='gp_classification_heaviside') + #m = GPy.models.GPClassification(data['X'], likelihood=likelihood) + + # Optimize + if optimize: + # Parameters optimization: + for _ in range(5): + m.optimize(max_iters=int(max_iters/5)) + print m + + # Plot + if plot: + from matplotlib import pyplot as plt + fig, axes = plt.subplots(2, 1) + m.plot_f(ax=axes[0]) + m.plot(ax=axes[1]) + + print m + return m +
      +
      [docs]def crescent_data(model_type='Full', num_inducing=10, seed=default_seed, kernel=None, optimize=True, plot=True): + """ + Run a Gaussian process classification on the crescent data. The demonstration calls the basic GP classification model and uses EP to approximate the likelihood. + + :param model_type: type of model to fit ['Full', 'FITC', 'DTC']. + :param inducing: number of inducing variables (only used for 'FITC' or 'DTC'). + :type inducing: int + :param seed: seed value for data generation. + :type seed: int + :param kernel: kernel to use in the model + :type kernel: a GPy kernel + """ + try:import pods + except ImportError:print 'pods unavailable, see https://github.com/sods/ods for example datasets' + data = pods.datasets.crescent_data(seed=seed) + Y = data['Y'] + Y[Y.flatten()==-1] = 0 + + if model_type == 'Full': + m = GPy.models.GPClassification(data['X'], Y, kernel=kernel) + + elif model_type == 'DTC': + m = GPy.models.SparseGPClassification(data['X'], Y, kernel=kernel, num_inducing=num_inducing) + m['.*len'] = 10. + + elif model_type == 'FITC': + m = GPy.models.FITCClassification(data['X'], Y, kernel=kernel, num_inducing=num_inducing) + m['.*len'] = 3. + + if optimize: + m.pseudo_EM() + + if plot: + m.plot() + + print m + return m
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/examples/dimensionality_reduction.html b/doc/_build/html/_modules/GPy/examples/dimensionality_reduction.html new file mode 100644 index 00000000..2b490bf9 --- /dev/null +++ b/doc/_build/html/_modules/GPy/examples/dimensionality_reduction.html @@ -0,0 +1,762 @@ + + + + + + + + GPy.examples.dimensionality_reduction — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.examples.dimensionality_reduction

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import numpy as _np
      +
      +# default_seed = _np.random.seed(123344)
      +
      +
      [docs]def bgplvm_test_model(optimize=False, verbose=1, plot=False, output_dim=200, nan=False): + """ + model for testing purposes. Samples from a GP with rbf kernel and learns + the samples with a new kernel. Normally not for optimization, just model cheking + """ + import GPy + + num_inputs = 13 + num_inducing = 5 + if plot: + output_dim = 1 + input_dim = 3 + else: + input_dim = 2 + output_dim = output_dim + + # generate GPLVM-like data + X = _np.random.rand(num_inputs, input_dim) + lengthscales = _np.random.rand(input_dim) + k = GPy.kern.RBF(input_dim, .5, lengthscales, ARD=True) + K = k.K(X) + Y = _np.random.multivariate_normal(_np.zeros(num_inputs), K, (output_dim,)).T + + # k = GPy.kern.RBF_inv(input_dim, .5, _np.ones(input_dim) * 2., ARD=True) + GPy.kern.bias(input_dim) + GPy.kern.white(input_dim) + # k = GPy.kern.linear(input_dim)# + GPy.kern.bias(input_dim) + GPy.kern.white(input_dim, 0.00001) + # k = GPy.kern.RBF(input_dim, ARD = False) + GPy.kern.white(input_dim, 0.00001) + # k = GPy.kern.RBF(input_dim, .5, _np.ones(input_dim) * 2., ARD=True) + GPy.kern.RBF(input_dim, .3, _np.ones(input_dim) * .2, ARD=True) + # k = GPy.kern.RBF(input_dim, .5, 2., ARD=0) + GPy.kern.RBF(input_dim, .3, .2, ARD=0) + # k = GPy.kern.RBF(input_dim, .5, _np.ones(input_dim) * 2., ARD=True) + GPy.kern.linear(input_dim, _np.ones(input_dim) * .2, ARD=True) + + p = .3 + + m = GPy.models.BayesianGPLVM(Y, input_dim, kernel=k, num_inducing=num_inducing) + + if nan: + m.inference_method = GPy.inference.latent_function_inference.var_dtc.VarDTCMissingData() + m.Y[_np.random.binomial(1, p, size=(Y.shape)).astype(bool)] = _np.nan + m.parameters_changed() + + #=========================================================================== + # randomly obstruct data with percentage p + #=========================================================================== + # m2 = GPy.models.BayesianGPLVMWithMissingData(Y_obstruct, input_dim, kernel=k, num_inducing=num_inducing) + # m.lengthscales = lengthscales + + if plot: + import matplotlib.pyplot as pb + m.plot() + pb.title('PCA initialisation') + # m2.plot() + # pb.title('PCA initialisation') + + if optimize: + m.optimize('scg', messages=verbose) + # m2.optimize('scg', messages=verbose) + if plot: + m.plot() + pb.title('After optimisation') + # m2.plot() + # pb.title('After optimisation') + + return m +
      +
      [docs]def gplvm_oil_100(optimize=True, verbose=1, plot=True): + import GPy + import pods + data = pods.datasets.oil_100() + Y = data['X'] + # create simple GP model + kernel = GPy.kern.RBF(6, ARD=True) + GPy.kern.Bias(6) + m = GPy.models.GPLVM(Y, 6, kernel=kernel) + m.data_labels = data['Y'].argmax(axis=1) + if optimize: m.optimize('scg', messages=verbose) + if plot: m.plot_latent(labels=m.data_labels) + return m +
      +
      [docs]def sparse_gplvm_oil(optimize=True, verbose=0, plot=True, N=100, Q=6, num_inducing=15, max_iters=50): + import GPy + import pods + + _np.random.seed(0) + data = pods.datasets.oil() + Y = data['X'][:N] + Y = Y - Y.mean(0) + Y /= Y.std(0) + # Create the model + kernel = GPy.kern.RBF(Q, ARD=True) + GPy.kern.Bias(Q) + m = GPy.models.SparseGPLVM(Y, Q, kernel=kernel, num_inducing=num_inducing) + m.data_labels = data['Y'][:N].argmax(axis=1) + + if optimize: m.optimize('scg', messages=verbose, max_iters=max_iters) + if plot: + m.plot_latent(labels=m.data_labels) + m.kern.plot_ARD() + return m +
      +
      [docs]def swiss_roll(optimize=True, verbose=1, plot=True, N=1000, num_inducing=25, Q=4, sigma=.2): + import GPy + from pods.datasets import swiss_roll_generated + from GPy.models import BayesianGPLVM + + data = swiss_roll_generated(num_samples=N, sigma=sigma) + Y = data['Y'] + Y -= Y.mean() + Y /= Y.std() + + t = data['t'] + c = data['colors'] + + try: + from sklearn.manifold.isomap import Isomap + iso = Isomap().fit(Y) + X = iso.embedding_ + if Q > 2: + X = _np.hstack((X, _np.random.randn(N, Q - 2))) + except ImportError: + X = _np.random.randn(N, Q) + + if plot: + import matplotlib.pyplot as plt + from mpl_toolkits.mplot3d import Axes3D # @UnusedImport + fig = plt.figure("Swiss Roll Data") + ax = fig.add_subplot(121, projection='3d') + ax.scatter(*Y.T, c=c) + ax.set_title("Swiss Roll") + + ax = fig.add_subplot(122) + ax.scatter(*X.T[:2], c=c) + ax.set_title("BGPLVM init") + + var = .5 + S = (var * _np.ones_like(X) + _np.clip(_np.random.randn(N, Q) * var ** 2, + - (1 - var), + (1 - var))) + .001 + Z = _np.random.permutation(X)[:num_inducing] + + kernel = GPy.kern.RBF(Q, ARD=True) + GPy.kern.Bias(Q, _np.exp(-2)) + GPy.kern.White(Q, _np.exp(-2)) + + m = BayesianGPLVM(Y, Q, X=X, X_variance=S, num_inducing=num_inducing, Z=Z, kernel=kernel) + m.data_colors = c + m.data_t = t + + if optimize: + m.optimize('bfgs', messages=verbose, max_iters=2e3) + + if plot: + fig = plt.figure('fitted') + ax = fig.add_subplot(111) + s = m.input_sensitivity().argsort()[::-1][:2] + ax.scatter(*m.X.mean.T[s], c=c) + + return m +
      +
      [docs]def bgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, max_iters=1000, **k): + import GPy + from matplotlib import pyplot as plt + import numpy as np + _np.random.seed(0) + try: + import pods + data = pods.datasets.oil() + except ImportError: + data = GPy.util.datasets.oil() + + + kernel = GPy.kern.RBF(Q, 1., 1. / _np.random.uniform(0, 1, (Q,)), ARD=True) # + GPy.kern.Bias(Q, _np.exp(-2)) + Y = data['X'][:N] + m = GPy.models.BayesianGPLVM(Y, Q, kernel=kernel, num_inducing=num_inducing, **k) + m.data_labels = data['Y'][:N].argmax(axis=1) + + if optimize: + m.optimize('bfgs', messages=verbose, max_iters=max_iters, gtol=.05) + + if plot: + fig, (latent_axes, sense_axes) = plt.subplots(1, 2) + m.plot_latent(ax=latent_axes, labels=m.data_labels) + data_show = GPy.plotting.matplot_dep.visualize.vector_show((m.Y[0, :])) + lvm_visualizer = GPy.plotting.matplot_dep.visualize.lvm_dimselect(m.X.mean.values[0:1, :], # @UnusedVariable + m, data_show, latent_axes=latent_axes, sense_axes=sense_axes, labels=m.data_labels) + raw_input('Press enter to finish') + plt.close(fig) + return m +
      +
      [docs]def ssgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, max_iters=1000, **k): + import GPy + from matplotlib import pyplot as plt + import pods + + _np.random.seed(0) + data = pods.datasets.oil() + + kernel = GPy.kern.RBF(Q, 1., 1. / _np.random.uniform(0, 1, (Q,)), ARD=True) # + GPy.kern.Bias(Q, _np.exp(-2)) + Y = data['X'][:N] + m = GPy.models.SSGPLVM(Y, Q, kernel=kernel, num_inducing=num_inducing, **k) + m.data_labels = data['Y'][:N].argmax(axis=1) + + if optimize: + m.optimize('bfgs', messages=verbose, max_iters=max_iters, gtol=.05) + + if plot: + fig, (latent_axes, sense_axes) = plt.subplots(1, 2) + m.plot_latent(ax=latent_axes, labels=m.data_labels) + data_show = GPy.plotting.matplot_dep.visualize.vector_show((m.Y[0, :])) + lvm_visualizer = GPy.plotting.matplot_dep.visualize.lvm_dimselect(m.X.mean.values[0:1, :], # @UnusedVariable + m, data_show, latent_axes=latent_axes, sense_axes=sense_axes, labels=m.data_labels) + raw_input('Press enter to finish') + plt.close(fig) + return m +
      +def _simulate_matern(D1, D2, D3, N, num_inducing, plot_sim=False): + Q_signal = 4 + import GPy + import numpy as np + np.random.seed(3000) + + k = GPy.kern.Matern32(Q_signal, 1., lengthscale=(np.random.uniform(1, 6, Q_signal)), ARD=1) + for i in range(Q_signal): + k += GPy.kern.PeriodicExponential(1, variance=1., active_dims=[i], period=3., lower=-2, upper=6) + t = np.c_[[np.linspace(-1, 5, N) for _ in range(Q_signal)]].T + K = k.K(t) + s2, s1, s3, sS = np.random.multivariate_normal(np.zeros(K.shape[0]), K, size=(4))[:, :, None] + + Y1, Y2, Y3, S1, S2, S3 = _generate_high_dimensional_output(D1, D2, D3, s1, s2, s3, sS) + + slist = [sS, s1, s2, s3] + slist_names = ["sS", "s1", "s2", "s3"] + Ylist = [Y1, Y2, Y3] + + if plot_sim: + from matplotlib import pyplot as plt + import matplotlib.cm as cm + import itertools + fig = plt.figure("MRD Simulation Data", figsize=(8, 6)) + fig.clf() + ax = fig.add_subplot(2, 1, 1) + labls = slist_names + for S, lab in itertools.izip(slist, labls): + ax.plot(S, label=lab) + ax.legend() + for i, Y in enumerate(Ylist): + ax = fig.add_subplot(2, len(Ylist), len(Ylist) + 1 + i) + ax.imshow(Y, aspect='auto', cmap=cm.gray) # @UndefinedVariable + ax.set_title("Y{}".format(i + 1)) + plt.draw() + plt.tight_layout() + + return slist, [S1, S2, S3], Ylist + +def _simulate_sincos(D1, D2, D3, N, num_inducing, plot_sim=False): + _np.random.seed(1234) + + x = _np.linspace(0, 4 * _np.pi, N)[:, None] + s1 = _np.vectorize(lambda x: _np.sin(x)) + s2 = _np.vectorize(lambda x: _np.cos(x) ** 2) + s3 = _np.vectorize(lambda x:-_np.exp(-_np.cos(2 * x))) + sS = _np.vectorize(lambda x: _np.cos(x)) + + s1 = s1(x) + s2 = s2(x) + s3 = s3(x) + sS = sS(x) + + s1 -= s1.mean(); s1 /= s1.std(0) + s2 -= s2.mean(); s2 /= s2.std(0) + s3 -= s3.mean(); s3 /= s3.std(0) + sS -= sS.mean(); sS /= sS.std(0) + + Y1, Y2, Y3, S1, S2, S3 = _generate_high_dimensional_output(D1, D2, D3, s1, s2, s3, sS) + + slist = [sS, s1, s2, s3] + slist_names = ["sS", "s1", "s2", "s3"] + Ylist = [Y1, Y2, Y3] + + if plot_sim: + from matplotlib import pyplot as plt + import matplotlib.cm as cm + import itertools + fig = plt.figure("MRD Simulation Data", figsize=(8, 6)) + fig.clf() + ax = fig.add_subplot(2, 1, 1) + labls = slist_names + for S, lab in itertools.izip(slist, labls): + ax.plot(S, label=lab) + ax.legend() + for i, Y in enumerate(Ylist): + ax = fig.add_subplot(2, len(Ylist), len(Ylist) + 1 + i) + ax.imshow(Y, aspect='auto', cmap=cm.gray) # @UndefinedVariable + ax.set_title("Y{}".format(i + 1)) + plt.draw() + plt.tight_layout() + + return slist, [S1, S2, S3], Ylist + +def _generate_high_dimensional_output(D1, D2, D3, s1, s2, s3, sS): + S1 = _np.hstack([s1, sS]) + S2 = _np.hstack([s2, s3, sS]) + S3 = _np.hstack([s3, sS]) + Y1 = S1.dot(_np.random.randn(S1.shape[1], D1)) + Y2 = S2.dot(_np.random.randn(S2.shape[1], D2)) + Y3 = S3.dot(_np.random.randn(S3.shape[1], D3)) + Y1 += .3 * _np.random.randn(*Y1.shape) + Y2 += .2 * _np.random.randn(*Y2.shape) + Y3 += .25 * _np.random.randn(*Y3.shape) + Y1 -= Y1.mean(0) + Y2 -= Y2.mean(0) + Y3 -= Y3.mean(0) + Y1 /= Y1.std(0) + Y2 /= Y2.std(0) + Y3 /= Y3.std(0) + return Y1, Y2, Y3, S1, S2, S3 + +
      [docs]def bgplvm_simulation(optimize=True, verbose=1, + plot=True, plot_sim=False, + max_iters=2e4, + ): + from GPy import kern + from GPy.models import BayesianGPLVM + + D1, D2, D3, N, num_inducing, Q = 13, 5, 8, 45, 3, 9 + _, _, Ylist = _simulate_matern(D1, D2, D3, N, num_inducing, plot_sim) + Y = Ylist[0] + k = kern.Linear(Q, ARD=True) # + kern.white(Q, _np.exp(-2)) # + kern.bias(Q) + # k = kern.RBF(Q, ARD=True, lengthscale=10.) + m = BayesianGPLVM(Y, Q, init="PCA", num_inducing=num_inducing, kernel=k) + m.X.variance[:] = _np.random.uniform(0, .01, m.X.shape) + m.likelihood.variance = .1 + + if optimize: + print "Optimizing model:" + m.optimize('bfgs', messages=verbose, max_iters=max_iters, + gtol=.05) + if plot: + m.X.plot("BGPLVM Latent Space 1D") + m.kern.plot_ARD('BGPLVM Simulation ARD Parameters') + return m +
      +
      [docs]def ssgplvm_simulation(optimize=True, verbose=1, + plot=True, plot_sim=False, + max_iters=2e4, useGPU=False + ): + from GPy import kern + from GPy.models import SSGPLVM + + D1, D2, D3, N, num_inducing, Q = 13, 5, 8, 45, 3, 9 + _, _, Ylist = _simulate_matern(D1, D2, D3, N, num_inducing, plot_sim) + Y = Ylist[0] + k = kern.Linear(Q, ARD=True) # + kern.white(Q, _np.exp(-2)) # + kern.bias(Q) + # k = kern.RBF(Q, ARD=True, lengthscale=10.) + m = SSGPLVM(Y, Q, init="pca", num_inducing=num_inducing, kernel=k) + m.X.variance[:] = _np.random.uniform(0, .01, m.X.shape) + m.likelihood.variance = .1 + + if optimize: + print "Optimizing model:" + m.optimize('scg', messages=verbose, max_iters=max_iters, + gtol=.05) + if plot: + m.X.plot("SSGPLVM Latent Space 1D") + m.kern.plot_ARD('SSGPLVM Simulation ARD Parameters') + return m +
      +
      [docs]def bgplvm_simulation_missing_data(optimize=True, verbose=1, + plot=True, plot_sim=False, + max_iters=2e4, percent_missing=.1, + ): + from GPy import kern + from GPy.models.bayesian_gplvm_minibatch import BayesianGPLVMMiniBatch + + D1, D2, D3, N, num_inducing, Q = 13, 5, 8, 400, 3, 4 + _, _, Ylist = _simulate_matern(D1, D2, D3, N, num_inducing, plot_sim) + Y = Ylist[0] + k = kern.Linear(Q, ARD=True) # + kern.white(Q, _np.exp(-2)) # + kern.bias(Q) + + inan = _np.random.binomial(1, percent_missing, size=Y.shape).astype(bool) # 80% missing data + Ymissing = Y.copy() + Ymissing[inan] = _np.nan + + m = BayesianGPLVMMiniBatch(Ymissing, Q, init="random", num_inducing=num_inducing, + kernel=k, missing_data=True) + + m.Yreal = Y + + if optimize: + print "Optimizing model:" + m.optimize('bfgs', messages=verbose, max_iters=max_iters, + gtol=.05) + if plot: + m.X.plot("BGPLVM Latent Space 1D") + m.kern.plot_ARD('BGPLVM Simulation ARD Parameters') + return m + +
      +
      [docs]def mrd_simulation(optimize=True, verbose=True, plot=True, plot_sim=True, **kw): + from GPy import kern + from GPy.models import MRD + + D1, D2, D3, N, num_inducing, Q = 60, 20, 36, 60, 6, 5 + _, _, Ylist = _simulate_matern(D1, D2, D3, N, num_inducing, plot_sim) + + # Ylist = [Ylist[0]] + k = kern.Linear(Q, ARD=True) + m = MRD(Ylist, input_dim=Q, num_inducing=num_inducing, kernel=k, initx="PCA_concat", initz='permute', **kw) + + m['.*noise'] = [Y.var() / 40. for Y in Ylist] + + if optimize: + print "Optimizing Model:" + m.optimize(messages=verbose, max_iters=8e3) + if plot: + m.X.plot("MRD Latent Space 1D") + m.plot_scales("MRD Scales") + return m +
      +
      [docs]def mrd_simulation_missing_data(optimize=True, verbose=True, plot=True, plot_sim=True, **kw): + from GPy import kern + from GPy.models import MRD + + D1, D2, D3, N, num_inducing, Q = 60, 20, 36, 60, 6, 5 + _, _, Ylist = _simulate_matern(D1, D2, D3, N, num_inducing, plot_sim) + + # Ylist = [Ylist[0]] + k = kern.Linear(Q, ARD=True) + inanlist = [] + + for Y in Ylist: + inan = _np.random.binomial(1, .6, size=Y.shape).astype(bool) + inanlist.append(inan) + Y[inan] = _np.nan + + m = MRD(Ylist, input_dim=Q, num_inducing=num_inducing, + kernel=k, inference_method=None, + initx="random", initz='permute', **kw) + + if optimize: + print "Optimizing Model:" + m.optimize('bfgs', messages=verbose, max_iters=8e3, gtol=.1) + if plot: + m.X.plot("MRD Latent Space 1D") + m.plot_scales("MRD Scales") + return m +
      +
      [docs]def brendan_faces(optimize=True, verbose=True, plot=True): + import GPy + import pods + + data = pods.datasets.brendan_faces() + Q = 2 + Y = data['Y'] + Yn = Y - Y.mean() + Yn /= Yn.std() + + m = GPy.models.BayesianGPLVM(Yn, Q, num_inducing=20) + + # optimize + + if optimize: m.optimize('bfgs', messages=verbose, max_iters=1000) + + if plot: + ax = m.plot_latent(which_indices=(0, 1)) + y = m.Y[0, :] + data_show = GPy.plotting.matplot_dep.visualize.image_show(y[None, :], dimensions=(20, 28), transpose=True, order='F', invert=False, scale=False) + lvm = GPy.plotting.matplot_dep.visualize.lvm(m.X.mean[0, :].copy(), m, data_show, ax) + raw_input('Press enter to finish') + + return m +
      +
      [docs]def olivetti_faces(optimize=True, verbose=True, plot=True): + import GPy + import pods + + data = pods.datasets.olivetti_faces() + Q = 2 + Y = data['Y'] + Yn = Y - Y.mean() + Yn /= Yn.std() + + m = GPy.models.BayesianGPLVM(Yn, Q, num_inducing=20) + + if optimize: m.optimize('bfgs', messages=verbose, max_iters=1000) + if plot: + ax = m.plot_latent(which_indices=(0, 1)) + y = m.Y[0, :] + data_show = GPy.plotting.matplot_dep.visualize.image_show(y[None, :], dimensions=(112, 92), transpose=False, invert=False, scale=False) + lvm = GPy.plotting.matplot_dep.visualize.lvm(m.X.mean[0, :].copy(), m, data_show, ax) + raw_input('Press enter to finish') + + return m +
      +
      [docs]def stick_play(range=None, frame_rate=15, optimize=False, verbose=True, plot=True): + import GPy + import pods + + data = pods.datasets.osu_run1() + # optimize + if range == None: + Y = data['Y'].copy() + else: + Y = data['Y'][range[0]:range[1], :].copy() + if plot: + y = Y[0, :] + data_show = GPy.plotting.matplot_dep.visualize.stick_show(y[None, :], connect=data['connect']) + GPy.plotting.matplot_dep.visualize.data_play(Y, data_show, frame_rate) + return Y +
      +
      [docs]def stick(kernel=None, optimize=True, verbose=True, plot=True): + from matplotlib import pyplot as plt + import GPy + import pods + + data = pods.datasets.osu_run1() + # optimize + m = GPy.models.GPLVM(data['Y'], 2, kernel=kernel) + if optimize: m.optimize('bfgs', messages=verbose, max_f_eval=10000) + if plot: + plt.clf + ax = m.plot_latent() + y = m.Y[0, :] + data_show = GPy.plotting.matplot_dep.visualize.stick_show(y[None, :], connect=data['connect']) + lvm_visualizer = GPy.plotting.matplot_dep.visualize.lvm(m.X[:1, :].copy(), m, data_show, latent_axes=ax) + raw_input('Press enter to finish') + lvm_visualizer.close() + data_show.close() + return m +
      +
      [docs]def bcgplvm_linear_stick(kernel=None, optimize=True, verbose=True, plot=True): + from matplotlib import pyplot as plt + import GPy + import pods + + data = pods.datasets.osu_run1() + # optimize + mapping = GPy.mappings.Linear(data['Y'].shape[1], 2) + m = GPy.models.BCGPLVM(data['Y'], 2, kernel=kernel, mapping=mapping) + if optimize: m.optimize(messages=verbose, max_f_eval=10000) + if plot and GPy.plotting.matplot_dep.visualize.visual_available: + plt.clf + ax = m.plot_latent() + y = m.likelihood.Y[0, :] + data_show = GPy.plotting.matplot_dep.visualize.stick_show(y[None, :], connect=data['connect']) + GPy.plotting.matplot_dep.visualize.lvm(m.X[0, :].copy(), m, data_show, ax) + raw_input('Press enter to finish') + + return m +
      +
      [docs]def bcgplvm_stick(kernel=None, optimize=True, verbose=True, plot=True): + from matplotlib import pyplot as plt + import GPy + import pods + + data = pods.datasets.osu_run1() + # optimize + back_kernel = GPy.kern.RBF(data['Y'].shape[1], lengthscale=5.) + mapping = GPy.mappings.Kernel(X=data['Y'], output_dim=2, kernel=back_kernel) + m = GPy.models.BCGPLVM(data['Y'], 2, kernel=kernel, mapping=mapping) + if optimize: m.optimize(messages=verbose, max_f_eval=10000) + if plot and GPy.plotting.matplot_dep.visualize.visual_available: + plt.clf + ax = m.plot_latent() + y = m.likelihood.Y[0, :] + data_show = GPy.plotting.matplot_dep.visualize.stick_show(y[None, :], connect=data['connect']) + GPy.plotting.matplot_dep.visualize.lvm(m.X[0, :].copy(), m, data_show, ax) + # raw_input('Press enter to finish') + + return m +
      +
      [docs]def robot_wireless(optimize=True, verbose=True, plot=True): + from matplotlib import pyplot as plt + import GPy + import pods + + data = pods.datasets.robot_wireless() + # optimize + m = GPy.models.BayesianGPLVM(data['Y'], 4, num_inducing=25) + if optimize: m.optimize(messages=verbose, max_f_eval=10000) + if plot: + m.plot_latent() + + return m +
      +
      [docs]def stick_bgplvm(model=None, optimize=True, verbose=True, plot=True): + from GPy.models import BayesianGPLVM + from matplotlib import pyplot as plt + import numpy as np + import GPy + import pods + + data = pods.datasets.osu_run1() + Q = 6 + kernel = GPy.kern.RBF(Q, lengthscale=np.repeat(.5, Q), ARD=True) + m = BayesianGPLVM(data['Y'], Q, init="PCA", num_inducing=20, kernel=kernel) + + m.data = data + m.likelihood.variance = 0.001 + + # optimize + try: + if optimize: m.optimize('bfgs', messages=verbose, max_iters=5e3, bfgs_factor=10) + except KeyboardInterrupt: + print "Keyboard interrupt, continuing to plot and return" + + if plot: + fig, (latent_axes, sense_axes) = plt.subplots(1, 2) + plt.sca(latent_axes) + m.plot_latent(ax=latent_axes) + y = m.Y[:1, :].copy() + data_show = GPy.plotting.matplot_dep.visualize.stick_show(y, connect=data['connect']) + dim_select = GPy.plotting.matplot_dep.visualize.lvm_dimselect(m.X.mean[:1, :].copy(), m, data_show, latent_axes=latent_axes, sense_axes=sense_axes) + fig.canvas.draw() + fig.canvas.show() + raw_input('Press enter to finish') + + return m + +
      +
      [docs]def cmu_mocap(subject='35', motion=['01'], in_place=True, optimize=True, verbose=True, plot=True): + import GPy + import pods + + data = pods.datasets.cmu_mocap(subject, motion) + if in_place: + # Make figure move in place. + data['Y'][:, 0:3] = 0.0 + Y = data['Y'] + Y_mean = Y.mean(0) + Y_std = Y.std(0) + m = GPy.models.GPLVM((Y - Y_mean) / Y_std, 2) + + if optimize: m.optimize(messages=verbose, max_f_eval=10000) + if plot: + ax = m.plot_latent() + y = m.Y[0, :] + data_show = GPy.plotting.matplot_dep.visualize.skeleton_show(y[None, :], data['skel']) + lvm_visualizer = GPy.plotting.matplot_dep.visualize.lvm(m.X[0].copy(), m, data_show, latent_axes=ax) + raw_input('Press enter to finish') + lvm_visualizer.close() + data_show.close() + + return m +
      +
      [docs]def ssgplvm_simulation_linear(): + import numpy as np + import GPy + N, D, Q = 1000, 20, 5 + pi = 0.2 + + def sample_X(Q, pi): + x = np.empty(Q) + dies = np.random.rand(Q) + for q in xrange(Q): + if dies[q] < pi: + x[q] = np.random.randn() + else: + x[q] = 0. + return x + + Y = np.empty((N, D)) + X = np.empty((N, Q)) + # Generate data from random sampled weight matrices + for n in xrange(N): + X[n] = sample_X(Q, pi) + w = np.random.randn(D, Q) + Y[n] = np.dot(w, X[n]) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/examples/non_gaussian.html b/doc/_build/html/_modules/GPy/examples/non_gaussian.html new file mode 100644 index 00000000..3f7fb9f7 --- /dev/null +++ b/doc/_build/html/_modules/GPy/examples/non_gaussian.html @@ -0,0 +1,389 @@ + + + + + + + + GPy.examples.non_gaussian — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.examples.non_gaussian

      +# Copyright (c) 2014, Alan Saul
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import GPy
      +import numpy as np
      +from GPy.util import datasets
      +try:
      +    import matplotlib.pyplot as plt
      +except:
      +    pass
      +
      +
      [docs]def student_t_approx(optimize=True, plot=True): + """ + Example of regressing with a student t likelihood using Laplace + """ + real_std = 0.1 + #Start a function, any function + X = np.linspace(0.0, np.pi*2, 100)[:, None] + Y = np.sin(X) + np.random.randn(*X.shape)*real_std + Y = Y/Y.max() + Yc = Y.copy() + + X_full = np.linspace(0.0, np.pi*2, 500)[:, None] + Y_full = np.sin(X_full) + Y_full = Y_full/Y_full.max() + + #Slightly noisy data + Yc[75:80] += 1 + + #Very noisy data + #Yc[10] += 100 + #Yc[25] += 10 + #Yc[23] += 10 + #Yc[26] += 1000 + #Yc[24] += 10 + #Yc = Yc/Yc.max() + + #Add student t random noise to datapoints + deg_free = 1 + print "Real noise: ", real_std + initial_var_guess = 0.5 + edited_real_sd = initial_var_guess + + # Kernel object + kernel1 = GPy.kern.RBF(X.shape[1]) + GPy.kern.White(X.shape[1]) + kernel2 = GPy.kern.RBF(X.shape[1]) + GPy.kern.White(X.shape[1]) + kernel3 = GPy.kern.RBF(X.shape[1]) + GPy.kern.White(X.shape[1]) + kernel4 = GPy.kern.RBF(X.shape[1]) + GPy.kern.White(X.shape[1]) + + #Gaussian GP model on clean data + m1 = GPy.models.GPRegression(X, Y.copy(), kernel=kernel1) + # optimize + m1['.*white'].constrain_fixed(1e-5) + m1.randomize() + + #Gaussian GP model on corrupt data + m2 = GPy.models.GPRegression(X, Yc.copy(), kernel=kernel2) + m2['.*white'].constrain_fixed(1e-5) + m2.randomize() + + #Student t GP model on clean data + t_distribution = GPy.likelihoods.StudentT(deg_free=deg_free, sigma2=edited_real_sd) + laplace_inf = GPy.inference.latent_function_inference.Laplace() + m3 = GPy.core.GP(X, Y.copy(), kernel3, likelihood=t_distribution, inference_method=laplace_inf) + m3['.*t_scale2'].constrain_bounded(1e-6, 10.) + m3['.*white'].constrain_fixed(1e-5) + m3.randomize() + + #Student t GP model on corrupt data + t_distribution = GPy.likelihoods.StudentT(deg_free=deg_free, sigma2=edited_real_sd) + laplace_inf = GPy.inference.latent_function_inference.Laplace() + m4 = GPy.core.GP(X, Yc.copy(), kernel4, likelihood=t_distribution, inference_method=laplace_inf) + m4['.*t_scale2'].constrain_bounded(1e-6, 10.) + m4['.*white'].constrain_fixed(1e-5) + m4.randomize() + print m4 + debug=True + if debug: + m4.optimize(messages=1) + import pylab as pb + pb.plot(m4.X, m4.inference_method.f_hat) + pb.plot(m4.X, m4.Y, 'rx') + m4.plot() + print m4 + return m4 + + if optimize: + optimizer='scg' + print "Clean Gaussian" + m1.optimize(optimizer, messages=1) + print "Corrupt Gaussian" + m2.optimize(optimizer, messages=1) + print "Clean student t" + m3.optimize(optimizer, messages=1) + print "Corrupt student t" + m4.optimize(optimizer, messages=1) + + if plot: + plt.figure(1) + plt.suptitle('Gaussian likelihood') + ax = plt.subplot(211) + m1.plot(ax=ax) + plt.plot(X_full, Y_full) + plt.ylim(-1.5, 1.5) + plt.title('Gaussian clean') + + ax = plt.subplot(212) + m2.plot(ax=ax) + plt.plot(X_full, Y_full) + plt.ylim(-1.5, 1.5) + plt.title('Gaussian corrupt') + + plt.figure(2) + plt.suptitle('Student-t likelihood') + ax = plt.subplot(211) + m3.plot(ax=ax) + plt.plot(X_full, Y_full) + plt.ylim(-1.5, 1.5) + plt.title('Student-t rasm clean') + + ax = plt.subplot(212) + m4.plot(ax=ax) + plt.plot(X_full, Y_full) + plt.ylim(-1.5, 1.5) + plt.title('Student-t rasm corrupt') + + return m1, m2, m3, m4 +
      +
      [docs]def boston_example(optimize=True, plot=True): + raise NotImplementedError("Needs updating") + import sklearn + from sklearn.cross_validation import KFold + optimizer='bfgs' + messages=0 + data = datasets.boston_housing() + degrees_freedoms = [3, 5, 8, 10] + X = data['X'].copy() + Y = data['Y'].copy() + X = X-X.mean(axis=0) + X = X/X.std(axis=0) + Y = Y-Y.mean() + Y = Y/Y.std() + num_folds = 10 + kf = KFold(len(Y), n_folds=num_folds, indices=True) + num_models = len(degrees_freedoms) + 3 #3 for baseline, gaussian, gaussian laplace approx + score_folds = np.zeros((num_models, num_folds)) + pred_density = score_folds.copy() + + def rmse(Y, Ystar): + return np.sqrt(np.mean((Y-Ystar)**2)) + + for n, (train, test) in enumerate(kf): + X_train, X_test, Y_train, Y_test = X[train], X[test], Y[train], Y[test] + print "Fold {}".format(n) + + noise = 1e-1 #np.exp(-2) + rbf_len = 0.5 + data_axis_plot = 4 + kernelstu = GPy.kern.RBF(X.shape[1]) + GPy.kern.white(X.shape[1]) + GPy.kern.bias(X.shape[1]) + kernelgp = GPy.kern.RBF(X.shape[1]) + GPy.kern.white(X.shape[1]) + GPy.kern.bias(X.shape[1]) + + #Baseline + score_folds[0, n] = rmse(Y_test, np.mean(Y_train)) + + #Gaussian GP + print "Gauss GP" + mgp = GPy.models.GPRegression(X_train.copy(), Y_train.copy(), kernel=kernelgp.copy()) + mgp.constrain_fixed('.*white', 1e-5) + mgp['.*len'] = rbf_len + mgp['.*noise'] = noise + print mgp + if optimize: + mgp.optimize(optimizer=optimizer, messages=messages) + Y_test_pred = mgp.predict(X_test) + score_folds[1, n] = rmse(Y_test, Y_test_pred[0]) + pred_density[1, n] = np.mean(mgp.log_predictive_density(X_test, Y_test)) + print mgp + print pred_density + + print "Gaussian Laplace GP" + N, D = Y_train.shape + g_distribution = GPy.likelihoods.noise_model_constructors.gaussian(variance=noise, N=N, D=D) + g_likelihood = GPy.likelihoods.Laplace(Y_train.copy(), g_distribution) + mg = GPy.models.GPRegression(X_train.copy(), Y_train.copy(), kernel=kernelstu.copy(), likelihood=g_likelihood) + mg.constrain_positive('noise_variance') + mg.constrain_fixed('.*white', 1e-5) + mg['rbf_len'] = rbf_len + mg['noise'] = noise + print mg + if optimize: + mg.optimize(optimizer=optimizer, messages=messages) + Y_test_pred = mg.predict(X_test) + score_folds[2, n] = rmse(Y_test, Y_test_pred[0]) + pred_density[2, n] = np.mean(mg.log_predictive_density(X_test, Y_test)) + print pred_density + print mg + + for stu_num, df in enumerate(degrees_freedoms): + #Student T + print "Student-T GP {}df".format(df) + t_distribution = GPy.likelihoods.noise_model_constructors.student_t(deg_free=df, sigma2=noise) + stu_t_likelihood = GPy.likelihoods.Laplace(Y_train.copy(), t_distribution) + mstu_t = GPy.models.GPRegression(X_train.copy(), Y_train.copy(), kernel=kernelstu.copy(), likelihood=stu_t_likelihood) + mstu_t.constrain_fixed('.*white', 1e-5) + mstu_t.constrain_bounded('.*t_scale2', 0.0001, 1000) + mstu_t['rbf_len'] = rbf_len + mstu_t['.*t_scale2'] = noise + print mstu_t + if optimize: + mstu_t.optimize(optimizer=optimizer, messages=messages) + Y_test_pred = mstu_t.predict(X_test) + score_folds[3+stu_num, n] = rmse(Y_test, Y_test_pred[0]) + pred_density[3+stu_num, n] = np.mean(mstu_t.log_predictive_density(X_test, Y_test)) + print pred_density + print mstu_t + + if plot: + plt.figure() + plt.scatter(X_test[:, data_axis_plot], Y_test_pred[0]) + plt.scatter(X_test[:, data_axis_plot], Y_test, c='r', marker='x') + plt.title('GP gauss') + + plt.figure() + plt.scatter(X_test[:, data_axis_plot], Y_test_pred[0]) + plt.scatter(X_test[:, data_axis_plot], Y_test, c='r', marker='x') + plt.title('Lap gauss') + + plt.figure() + plt.scatter(X_test[:, data_axis_plot], Y_test_pred[0]) + plt.scatter(X_test[:, data_axis_plot], Y_test, c='r', marker='x') + plt.title('Stu t {}df'.format(df)) + + print "Average scores: {}".format(np.mean(score_folds, 1)) + print "Average pred density: {}".format(np.mean(pred_density, 1)) + + if plot: + #Plotting + stu_t_legends = ['Student T, df={}'.format(df) for df in degrees_freedoms] + legends = ['Baseline', 'Gaussian', 'Laplace Approx Gaussian'] + stu_t_legends + + #Plot boxplots for RMSE density + fig = plt.figure() + ax=fig.add_subplot(111) + plt.title('RMSE') + bp = ax.boxplot(score_folds.T, notch=0, sym='+', vert=1, whis=1.5) + plt.setp(bp['boxes'], color='black') + plt.setp(bp['whiskers'], color='black') + plt.setp(bp['fliers'], color='red', marker='+') + xtickNames = plt.setp(ax, xticklabels=legends) + plt.setp(xtickNames, rotation=45, fontsize=8) + ax.set_ylabel('RMSE') + ax.set_xlabel('Distribution') + #Make grid and put it below boxes + ax.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', + alpha=0.5) + ax.set_axisbelow(True) + + #Plot boxplots for predictive density + fig = plt.figure() + ax=fig.add_subplot(111) + plt.title('Predictive density') + bp = ax.boxplot(pred_density[1:,:].T, notch=0, sym='+', vert=1, whis=1.5) + plt.setp(bp['boxes'], color='black') + plt.setp(bp['whiskers'], color='black') + plt.setp(bp['fliers'], color='red', marker='+') + xtickNames = plt.setp(ax, xticklabels=legends[1:]) + plt.setp(xtickNames, rotation=45, fontsize=8) + ax.set_ylabel('Mean Log probability P(Y*|Y)') + ax.set_xlabel('Distribution') + #Make grid and put it below boxes + ax.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', + alpha=0.5) + ax.set_axisbelow(True) + return mstu_t + +#def precipitation_example(): + #import sklearn + #from sklearn.cross_validation import KFold + #data = datasets.boston_housing() + #X = data['X'].copy() + #Y = data['Y'].copy() + #X = X-X.mean(axis=0) + #X = X/X.std(axis=0) + #Y = Y-Y.mean() + #Y = Y/Y.std() + #import ipdb; ipdb.set_trace() # XXX BREAKPOINT + #num_folds = 10 + #kf = KFold(len(Y), n_folds=num_folds, indices=True) + #score_folds = np.zeros((4, num_folds)) + #def rmse(Y, Ystar): + #return np.sqrt(np.mean((Y-Ystar)**2)) + ##for train, test in kf: + #for n, (train, test) in enumerate(kf): + #X_train, X_test, Y_train, Y_test = X[train], X[test], Y[train], Y[test] + #print "Fold {}".format(n) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/examples/regression.html b/doc/_build/html/_modules/GPy/examples/regression.html new file mode 100644 index 00000000..f027e0ca --- /dev/null +++ b/doc/_build/html/_modules/GPy/examples/regression.html @@ -0,0 +1,601 @@ + + + + + + + + GPy.examples.regression — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.examples.regression

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +"""
      +Gaussian Processes regression examples
      +"""
      +try:
      +    import pylab as pb
      +except:
      +    pass
      +import numpy as np
      +import GPy
      +
      +
      [docs]def olympic_marathon_men(optimize=True, plot=True): + """Run a standard Gaussian process regression on the Olympic marathon data.""" + try:import pods + except ImportError: + print 'pods unavailable, see https://github.com/sods/ods for example datasets' + return + data = pods.datasets.olympic_marathon_men() + + # create simple GP Model + m = GPy.models.GPRegression(data['X'], data['Y']) + + # set the lengthscale to be something sensible (defaults to 1) + m.kern.lengthscale = 10. + + if optimize: + m.optimize('bfgs', max_iters=200) + if plot: + m.plot(plot_limits=(1850, 2050)) + + return m +
      +
      [docs]def coregionalization_toy(optimize=True, plot=True): + """ + A simple demonstration of coregionalization on two sinusoidal functions. + """ + #build a design matrix with a column of integers indicating the output + X1 = np.random.rand(50, 1) * 8 + X2 = np.random.rand(30, 1) * 5 + + #build a suitable set of observed variables + Y1 = np.sin(X1) + np.random.randn(*X1.shape) * 0.05 + Y2 = np.sin(X2) + np.random.randn(*X2.shape) * 0.05 + 2. + + m = GPy.models.GPCoregionalizedRegression(X_list=[X1,X2], Y_list=[Y1,Y2]) + + if optimize: + m.optimize('bfgs', max_iters=100) + + if plot: + slices = GPy.util.multioutput.get_slices([X1,X2]) + m.plot(fixed_inputs=[(1,0)],which_data_rows=slices[0],Y_metadata={'output_index':0}) + m.plot(fixed_inputs=[(1,1)],which_data_rows=slices[1],Y_metadata={'output_index':1},ax=pb.gca()) + return m +
      +
      [docs]def coregionalization_sparse(optimize=True, plot=True): + """ + A simple demonstration of coregionalization on two sinusoidal functions using sparse approximations. + """ + #build a design matrix with a column of integers indicating the output + X1 = np.random.rand(50, 1) * 8 + X2 = np.random.rand(30, 1) * 5 + + #build a suitable set of observed variables + Y1 = np.sin(X1) + np.random.randn(*X1.shape) * 0.05 + Y2 = np.sin(X2) + np.random.randn(*X2.shape) * 0.05 + 2. + + m = GPy.models.SparseGPCoregionalizedRegression(X_list=[X1,X2], Y_list=[Y1,Y2]) + + if optimize: + m.optimize('bfgs', max_iters=100) + + if plot: + slices = GPy.util.multioutput.get_slices([X1,X2]) + m.plot(fixed_inputs=[(1,0)],which_data_rows=slices[0],Y_metadata={'output_index':0}) + m.plot(fixed_inputs=[(1,1)],which_data_rows=slices[1],Y_metadata={'output_index':1},ax=pb.gca()) + pb.ylim(-3,) + + return m +
      +
      [docs]def epomeo_gpx(max_iters=200, optimize=True, plot=True): + """ + Perform Gaussian process regression on the latitude and longitude data + from the Mount Epomeo runs. Requires gpxpy to be installed on your system + to load in the data. + """ + try:import pods + except ImportError: + print 'pods unavailable, see https://github.com/sods/ods for example datasets' + return + data = pods.datasets.epomeo_gpx() + num_data_list = [] + for Xpart in data['X']: + num_data_list.append(Xpart.shape[0]) + + num_data_array = np.array(num_data_list) + num_data = num_data_array.sum() + Y = np.zeros((num_data, 2)) + t = np.zeros((num_data, 2)) + start = 0 + for Xpart, index in zip(data['X'], range(len(data['X']))): + end = start+Xpart.shape[0] + t[start:end, :] = np.hstack((Xpart[:, 0:1], + index*np.ones((Xpart.shape[0], 1)))) + Y[start:end, :] = Xpart[:, 1:3] + + num_inducing = 200 + Z = np.hstack((np.linspace(t[:,0].min(), t[:, 0].max(), num_inducing)[:, None], + np.random.randint(0, 4, num_inducing)[:, None])) + + k1 = GPy.kern.RBF(1) + k2 = GPy.kern.Coregionalize(output_dim=5, rank=5) + k = k1**k2 + + m = GPy.models.SparseGPRegression(t, Y, kernel=k, Z=Z, normalize_Y=True) + m.constrain_fixed('.*variance', 1.) + m.inducing_inputs.constrain_fixed() + m.Gaussian_noise.variance.constrain_bounded(1e-3, 1e-1) + m.optimize(max_iters=max_iters,messages=True) + + return m +
      +
      [docs]def multiple_optima(gene_number=937, resolution=80, model_restarts=10, seed=10000, max_iters=300, optimize=True, plot=True): + """ + Show an example of a multimodal error surface for Gaussian process + regression. Gene 939 has bimodal behaviour where the noisy mode is + higher. + """ + + # Contour over a range of length scales and signal/noise ratios. + length_scales = np.linspace(0.1, 60., resolution) + log_SNRs = np.linspace(-3., 4., resolution) + + try:import pods + except ImportError: + print 'pods unavailable, see https://github.com/sods/ods for example datasets' + return + data = pods.datasets.della_gatta_TRP63_gene_expression(data_set='della_gatta',gene_number=gene_number) + # data['Y'] = data['Y'][0::2, :] + # data['X'] = data['X'][0::2, :] + + data['Y'] = data['Y'] - np.mean(data['Y']) + + lls = GPy.examples.regression._contour_data(data, length_scales, log_SNRs, GPy.kern.RBF) + if plot: + pb.contour(length_scales, log_SNRs, np.exp(lls), 20, cmap=pb.cm.jet) + ax = pb.gca() + pb.xlabel('length scale') + pb.ylabel('log_10 SNR') + + xlim = ax.get_xlim() + ylim = ax.get_ylim() + + # Now run a few optimizations + models = [] + optim_point_x = np.empty(2) + optim_point_y = np.empty(2) + np.random.seed(seed=seed) + for i in range(0, model_restarts): + # kern = GPy.kern.RBF(1, variance=np.random.exponential(1.), lengthscale=np.random.exponential(50.)) + kern = GPy.kern.RBF(1, variance=np.random.uniform(1e-3, 1), lengthscale=np.random.uniform(5, 50)) + + m = GPy.models.GPRegression(data['X'], data['Y'], kernel=kern) + m.likelihood.variance = np.random.uniform(1e-3, 1) + optim_point_x[0] = m.rbf.lengthscale + optim_point_y[0] = np.log10(m.rbf.variance) - np.log10(m.likelihood.variance); + + # optimize + if optimize: + m.optimize('scg', xtol=1e-6, ftol=1e-6, max_iters=max_iters) + + optim_point_x[1] = m.rbf.lengthscale + optim_point_y[1] = np.log10(m.rbf.variance) - np.log10(m.likelihood.variance); + + if plot: + pb.arrow(optim_point_x[0], optim_point_y[0], optim_point_x[1] - optim_point_x[0], optim_point_y[1] - optim_point_y[0], label=str(i), head_length=1, head_width=0.5, fc='k', ec='k') + models.append(m) + + if plot: + ax.set_xlim(xlim) + ax.set_ylim(ylim) + return m # (models, lls) +
      +def _contour_data(data, length_scales, log_SNRs, kernel_call=GPy.kern.RBF): + """ + Evaluate the GP objective function for a given data set for a range of + signal to noise ratios and a range of lengthscales. + + :data_set: A data set from the utils.datasets director. + :length_scales: a list of length scales to explore for the contour plot. + :log_SNRs: a list of base 10 logarithm signal to noise ratios to explore for the contour plot. + :kernel: a kernel to use for the 'signal' portion of the data. + """ + + lls = [] + total_var = np.var(data['Y']) + kernel = kernel_call(1, variance=1., lengthscale=1.) + model = GPy.models.GPRegression(data['X'], data['Y'], kernel=kernel) + for log_SNR in log_SNRs: + SNR = 10.**log_SNR + noise_var = total_var / (1. + SNR) + signal_var = total_var - noise_var + model.kern['.*variance'] = signal_var + model.likelihood.variance = noise_var + length_scale_lls = [] + + for length_scale in length_scales: + model['.*lengthscale'] = length_scale + length_scale_lls.append(model.log_likelihood()) + + lls.append(length_scale_lls) + + return np.array(lls) + + +
      [docs]def olympic_100m_men(optimize=True, plot=True): + """Run a standard Gaussian process regression on the Rogers and Girolami olympics data.""" + try:import pods + except ImportError: + print 'pods unavailable, see https://github.com/sods/ods for example datasets' + return + data = pods.datasets.olympic_100m_men() + + # create simple GP Model + m = GPy.models.GPRegression(data['X'], data['Y']) + + # set the lengthscale to be something sensible (defaults to 1) + m.rbf.lengthscale = 10 + + if optimize: + m.optimize('bfgs', max_iters=200) + + if plot: + m.plot(plot_limits=(1850, 2050)) + return m +
      +
      [docs]def toy_rbf_1d(optimize=True, plot=True): + """Run a simple demonstration of a standard Gaussian process fitting it to data sampled from an RBF covariance.""" + try:import pods + except ImportError: + print 'pods unavailable, see https://github.com/sods/ods for example datasets' + return + data = pods.datasets.toy_rbf_1d() + + # create simple GP Model + m = GPy.models.GPRegression(data['X'], data['Y']) + + if optimize: + m.optimize('bfgs') + if plot: + m.plot() + + return m +
      +
      [docs]def toy_rbf_1d_50(optimize=True, plot=True): + """Run a simple demonstration of a standard Gaussian process fitting it to data sampled from an RBF covariance.""" + try:import pods + except ImportError: + print 'pods unavailable, see https://github.com/sods/ods for example datasets' + return + data = pods.datasets.toy_rbf_1d_50() + + # create simple GP Model + m = GPy.models.GPRegression(data['X'], data['Y']) + + if optimize: + m.optimize('bfgs') + if plot: + m.plot() + + return m +
      +
      [docs]def toy_poisson_rbf_1d_laplace(optimize=True, plot=True): + """Run a simple demonstration of a standard Gaussian process fitting it to data sampled from an RBF covariance.""" + optimizer='scg' + x_len = 30 + X = np.linspace(0, 10, x_len)[:, None] + f_true = np.random.multivariate_normal(np.zeros(x_len), GPy.kern.RBF(1).K(X)) + Y = np.array([np.random.poisson(np.exp(f)) for f in f_true])[:,None] + + kern = GPy.kern.RBF(1) + poisson_lik = GPy.likelihoods.Poisson() + laplace_inf = GPy.inference.latent_function_inference.Laplace() + + # create simple GP Model + m = GPy.core.GP(X, Y, kernel=kern, likelihood=poisson_lik, inference_method=laplace_inf) + + if optimize: + m.optimize(optimizer) + if plot: + m.plot() + # plot the real underlying rate function + pb.plot(X, np.exp(f_true), '--k', linewidth=2) + + return m +
      +
      [docs]def toy_ARD(max_iters=1000, kernel_type='linear', num_samples=300, D=4, optimize=True, plot=True): + # Create an artificial dataset where the values in the targets (Y) + # only depend in dimensions 1 and 3 of the inputs (X). Run ARD to + # see if this dependency can be recovered + X1 = np.sin(np.sort(np.random.rand(num_samples, 1) * 10, 0)) + X2 = np.cos(np.sort(np.random.rand(num_samples, 1) * 10, 0)) + X3 = np.exp(np.sort(np.random.rand(num_samples, 1), 0)) + X4 = np.log(np.sort(np.random.rand(num_samples, 1), 0)) + X = np.hstack((X1, X2, X3, X4)) + + Y1 = np.asarray(2 * X[:, 0] + 3).reshape(-1, 1) + Y2 = np.asarray(4 * (X[:, 2] - 1.5 * X[:, 0])).reshape(-1, 1) + Y = np.hstack((Y1, Y2)) + + Y = np.dot(Y, np.random.rand(2, D)); + Y = Y + 0.2 * np.random.randn(Y.shape[0], Y.shape[1]) + Y -= Y.mean() + Y /= Y.std() + + if kernel_type == 'linear': + kernel = GPy.kern.Linear(X.shape[1], ARD=1) + elif kernel_type == 'rbf_inv': + kernel = GPy.kern.RBF_inv(X.shape[1], ARD=1) + else: + kernel = GPy.kern.RBF(X.shape[1], ARD=1) + kernel += GPy.kern.White(X.shape[1]) + GPy.kern.Bias(X.shape[1]) + m = GPy.models.GPRegression(X, Y, kernel) + # len_prior = GPy.priors.inverse_gamma(1,18) # 1, 25 + # m.set_prior('.*lengthscale',len_prior) + + if optimize: + m.optimize(optimizer='scg', max_iters=max_iters) + + if plot: + m.kern.plot_ARD() + + return m +
      +
      [docs]def toy_ARD_sparse(max_iters=1000, kernel_type='linear', num_samples=300, D=4, optimize=True, plot=True): + # Create an artificial dataset where the values in the targets (Y) + # only depend in dimensions 1 and 3 of the inputs (X). Run ARD to + # see if this dependency can be recovered + X1 = np.sin(np.sort(np.random.rand(num_samples, 1) * 10, 0)) + X2 = np.cos(np.sort(np.random.rand(num_samples, 1) * 10, 0)) + X3 = np.exp(np.sort(np.random.rand(num_samples, 1), 0)) + X4 = np.log(np.sort(np.random.rand(num_samples, 1), 0)) + X = np.hstack((X1, X2, X3, X4)) + + Y1 = np.asarray(2 * X[:, 0] + 3)[:, None] + Y2 = np.asarray(4 * (X[:, 2] - 1.5 * X[:, 0]))[:, None] + Y = np.hstack((Y1, Y2)) + + Y = np.dot(Y, np.random.rand(2, D)); + Y = Y + 0.2 * np.random.randn(Y.shape[0], Y.shape[1]) + Y -= Y.mean() + Y /= Y.std() + + if kernel_type == 'linear': + kernel = GPy.kern.Linear(X.shape[1], ARD=1) + elif kernel_type == 'rbf_inv': + kernel = GPy.kern.RBF_inv(X.shape[1], ARD=1) + else: + kernel = GPy.kern.RBF(X.shape[1], ARD=1) + #kernel += GPy.kern.Bias(X.shape[1]) + X_variance = np.ones(X.shape) * 0.5 + m = GPy.models.SparseGPRegression(X, Y, kernel, X_variance=X_variance) + # len_prior = GPy.priors.inverse_gamma(1,18) # 1, 25 + # m.set_prior('.*lengthscale',len_prior) + + if optimize: + m.optimize(optimizer='scg', max_iters=max_iters) + + if plot: + m.kern.plot_ARD() + + return m +
      +
      [docs]def robot_wireless(max_iters=100, kernel=None, optimize=True, plot=True): + """Predict the location of a robot given wirelss signal strength readings.""" + try:import pods + except ImportError: + print 'pods unavailable, see https://github.com/sods/ods for example datasets' + return + data = pods.datasets.robot_wireless() + + # create simple GP Model + m = GPy.models.GPRegression(data['Y'], data['X'], kernel=kernel) + + # optimize + if optimize: + m.optimize(max_iters=max_iters) + + Xpredict = m.predict(data['Ytest'])[0] + if plot: + pb.plot(data['Xtest'][:, 0], data['Xtest'][:, 1], 'r-') + pb.plot(Xpredict[:, 0], Xpredict[:, 1], 'b-') + pb.axis('equal') + pb.title('WiFi Localization with Gaussian Processes') + pb.legend(('True Location', 'Predicted Location')) + + sse = ((data['Xtest'] - Xpredict)**2).sum() + + print('Sum of squares error on test data: ' + str(sse)) + return m +
      +
      [docs]def silhouette(max_iters=100, optimize=True, plot=True): + """Predict the pose of a figure given a silhouette. This is a task from Agarwal and Triggs 2004 ICML paper.""" + try:import pods + except ImportError: + print 'pods unavailable, see https://github.com/sods/ods for example datasets' + return + data = pods.datasets.silhouette() + + # create simple GP Model + m = GPy.models.GPRegression(data['X'], data['Y']) + + # optimize + if optimize: + m.optimize(messages=True, max_iters=max_iters) + + print m + return m +
      +
      [docs]def sparse_GP_regression_1D(num_samples=400, num_inducing=5, max_iters=100, optimize=True, plot=True, checkgrad=False): + """Run a 1D example of a sparse GP regression.""" + # sample inputs and outputs + X = np.random.uniform(-3., 3., (num_samples, 1)) + Y = np.sin(X) + np.random.randn(num_samples, 1) * 0.05 + # construct kernel + rbf = GPy.kern.RBF(1) + # create simple GP Model + m = GPy.models.SparseGPRegression(X, Y, kernel=rbf, num_inducing=num_inducing) + + if checkgrad: + m.checkgrad() + + if optimize: + m.optimize('tnc', max_iters=max_iters) + + if plot: + m.plot() + + return m +
      +
      [docs]def sparse_GP_regression_2D(num_samples=400, num_inducing=50, max_iters=100, optimize=True, plot=True, nan=False): + """Run a 2D example of a sparse GP regression.""" + np.random.seed(1234) + X = np.random.uniform(-3., 3., (num_samples, 2)) + Y = np.sin(X[:, 0:1]) * np.sin(X[:, 1:2]) + np.random.randn(num_samples, 1) * 0.05 + if nan: + inan = np.random.binomial(1,.2,size=Y.shape) + Y[inan] = np.nan + + # construct kernel + rbf = GPy.kern.RBF(2) + + # create simple GP Model + m = GPy.models.SparseGPRegression(X, Y, kernel=rbf, num_inducing=num_inducing) + + # contrain all parameters to be positive (but not inducing inputs) + m['.*len'] = 2. + + m.checkgrad() + + # optimize + if optimize: + m.optimize('tnc', messages=1, max_iters=max_iters) + + # plot + if plot: + m.plot() + + print m + return m +
      +
      [docs]def uncertain_inputs_sparse_regression(max_iters=200, optimize=True, plot=True): + """Run a 1D example of a sparse GP regression with uncertain inputs.""" + fig, axes = pb.subplots(1, 2, figsize=(12, 5), sharex=True, sharey=True) + + # sample inputs and outputs + S = np.ones((20, 1)) + X = np.random.uniform(-3., 3., (20, 1)) + Y = np.sin(X) + np.random.randn(20, 1) * 0.05 + # likelihood = GPy.likelihoods.Gaussian(Y) + Z = np.random.uniform(-3., 3., (7, 1)) + + k = GPy.kern.RBF(1) + # create simple GP Model - no input uncertainty on this one + m = GPy.models.SparseGPRegression(X, Y, kernel=k, Z=Z) + + if optimize: + m.optimize('scg', messages=1, max_iters=max_iters) + + if plot: + m.plot(ax=axes[0]) + axes[0].set_title('no input uncertainty') + print m + + # the same Model with uncertainty + m = GPy.models.SparseGPRegression(X, Y, kernel=GPy.kern.RBF(1), Z=Z, X_variance=S) + if optimize: + m.optimize('scg', messages=1, max_iters=max_iters) + if plot: + m.plot(ax=axes[1]) + axes[1].set_title('with input uncertainty') + fig.canvas.draw() + + print m + return m
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference.html new file mode 100644 index 00000000..bf507670 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference.html @@ -0,0 +1,192 @@ + + + + + + + + GPy.inference.latent_function_inference — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference

      +# Copyright (c) 2012, James Hensman
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +__doc__ = """
      +Inference over Gaussian process latent functions
      +
      +In all our GP models, the consistency propery means that we have a Gaussian
      +prior over a finite set of points f. This prior is
      +
      +  math:: N(f | 0, K)
      +
      +where K is the kernel matrix.
      +
      +We also have a likelihood (see GPy.likelihoods) which defines how the data are
      +related to the latent function: p(y | f).  If the likelihood is also a Gaussian,
      +the inference over f is tractable (see exact_gaussian_inference.py).
      +
      +If the likelihood object is something other than Gaussian, then exact inference
      +is not tractable. We then resort to a Laplace approximation (laplace.py) or
      +expectation propagation (ep.py).
      +
      +The inference methods return a
      +:class:`~GPy.inference.latent_function_inference.posterior.Posterior`
      +instance, which is a simple
      +structure which contains a summary of the posterior. The model classes can then
      +use this posterior object for making predictions, optimizing hyper-parameters,
      +etc.
      +
      +"""
      +
      +
      [docs]class LatentFunctionInference(object): +
      [docs] def on_optimization_start(self): + """ + This function gets called, just before the optimization loop to start. + """ + pass +
      +
      [docs] def on_optimization_end(self): + """ + This function gets called, just after the optimization loop ended. + """ + pass +
      +
      [docs]class InferenceMethodList(LatentFunctionInference, list): + +
      [docs] def on_optimization_start(self): + for inf in self: + inf.on_optimization_start() +
      +
      [docs] def on_optimization_end(self): + for inf in self: + inf.on_optimization_end() +
      + def __getstate__(self): + state = [] + for inf in self: + state.append(inf) + return state + + def __setstate__(self, state): + for inf in state: + self.append(inf) +
      +from exact_gaussian_inference import ExactGaussianInference +from laplace import Laplace +from GPy.inference.latent_function_inference.var_dtc import VarDTC +from expectation_propagation import EP +from expectation_propagation_dtc import EPDTC +from dtc import DTC +from fitc import FITC +from var_dtc_parallel import VarDTC_minibatch + +# class FullLatentFunctionData(object): +# +# + +# class EMLikeLatentFunctionInference(LatentFunctionInference): +# def update_approximation(self): +# """ +# This function gets called when the +# """ +# +# def inference(self, kern, X, Z, likelihood, Y, Y_metadata=None): +# """ +# Do inference on the latent functions given a covariance function `kern`, +# inputs and outputs `X` and `Y`, inducing_inputs `Z`, and a likelihood `likelihood`. +# Additional metadata for the outputs `Y` can be given in `Y_metadata`. +# """ +# raise NotImplementedError, "Abstract base class for full inference" +# +# class VariationalLatentFunctionInference(LatentFunctionInference): +# def inference(self, kern, X, Z, likelihood, Y, Y_metadata=None): +# """ +# Do inference on the latent functions given a covariance function `kern`, +# inputs and outputs `X` and `Y`, inducing_inputs `Z`, and a likelihood `likelihood`. +# Additional metadata for the outputs `Y` can be given in `Y_metadata`. +# """ +# raise NotImplementedError, "Abstract base class for full inference" +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/dtc.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/dtc.html new file mode 100644 index 00000000..8abe6060 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/dtc.html @@ -0,0 +1,256 @@ + + + + + + + + GPy.inference.latent_function_inference.dtc — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.dtc

      +# Copyright (c) 2012-2014, James Hensman
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from posterior import Posterior
      +from ...util.linalg import jitchol, tdot, dtrtrs, dpotri, pdinv
      +import numpy as np
      +from . import LatentFunctionInference
      +log_2_pi = np.log(2*np.pi)
      +
      +
      [docs]class DTC(LatentFunctionInference): + """ + An object for inference when the likelihood is Gaussian, but we want to do sparse inference. + + The function self.inference returns a Posterior object, which summarizes + the posterior. + + NB. It's not recommended to use this function! It's here for historical purposes. + + """ + def __init__(self): + self.const_jitter = 1e-6 + +
      [docs] def inference(self, kern, X, Z, likelihood, Y, Y_metadata=None): + assert X_variance is None, "cannot use X_variance with DTC. Try varDTC." + + num_inducing, _ = Z.shape + num_data, output_dim = Y.shape + + #make sure the noise is not hetero + beta = 1./likelihood.gaussian_variance(Y_metadata) + if beta.size > 1: + raise NotImplementedError, "no hetero noise with this implementation of DTC" + + Kmm = kern.K(Z) + Knn = kern.Kdiag(X) + Knm = kern.K(X, Z) + U = Knm + Uy = np.dot(U.T,Y) + + #factor Kmm + Kmmi, L, Li, _ = pdinv(Kmm) + + # Compute A + LiUTbeta = np.dot(Li, U.T)*np.sqrt(beta) + A = tdot(LiUTbeta) + np.eye(num_inducing) + + # factor A + LA = jitchol(A) + + # back substutue to get b, P, v + tmp, _ = dtrtrs(L, Uy, lower=1) + b, _ = dtrtrs(LA, tmp*beta, lower=1) + tmp, _ = dtrtrs(LA, b, lower=1, trans=1) + v, _ = dtrtrs(L, tmp, lower=1, trans=1) + tmp, _ = dtrtrs(LA, Li, lower=1, trans=0) + P = tdot(tmp.T) + + #compute log marginal + log_marginal = -0.5*num_data*output_dim*np.log(2*np.pi) + \ + -np.sum(np.log(np.diag(LA)))*output_dim + \ + 0.5*num_data*output_dim*np.log(beta) + \ + -0.5*beta*np.sum(np.square(Y)) + \ + 0.5*np.sum(np.square(b)) + + # Compute dL_dKmm + vvT_P = tdot(v.reshape(-1,1)) + P + dL_dK = 0.5*(Kmmi - vvT_P) + + # Compute dL_dU + vY = np.dot(v.reshape(-1,1),Y.T) + dL_dU = vY - np.dot(vvT_P, U.T) + dL_dU *= beta + + #compute dL_dR + Uv = np.dot(U, v) + dL_dR = 0.5*(np.sum(U*np.dot(U,P), 1) - 1./beta + np.sum(np.square(Y), 1) - 2.*np.sum(Uv*Y, 1) + np.sum(np.square(Uv), 1))*beta**2 + + dL_dthetaL = likelihood.exact_inference_gradients(dL_dR) + + grad_dict = {'dL_dKmm': dL_dK, 'dL_dKdiag':np.zeros_like(Knn), 'dL_dKnm':dL_dU.T, 'dL_dthetaL':dL_dthetaL} + + #construct a posterior object + post = Posterior(woodbury_inv=Kmmi-P, woodbury_vector=v, K=Kmm, mean=None, cov=None, K_chol=L) + + return post, log_marginal, grad_dict +
      +
      [docs]class vDTC(object): + def __init__(self): + self.const_jitter = 1e-6 + +
      [docs] def inference(self, kern, X, X_variance, Z, likelihood, Y, Y_metadata): + assert X_variance is None, "cannot use X_variance with DTC. Try varDTC." + + num_inducing, _ = Z.shape + num_data, output_dim = Y.shape + + #make sure the noise is not hetero + beta = 1./likelihood.gaussian_variance(Y_metadata) + if beta.size > 1: + raise NotImplementedError, "no hetero noise with this implementation of DTC" + + Kmm = kern.K(Z) + Knn = kern.Kdiag(X) + Knm = kern.K(X, Z) + U = Knm + Uy = np.dot(U.T,Y) + + #factor Kmm + Kmmi, L, Li, _ = pdinv(Kmm) + + # Compute A + LiUTbeta = np.dot(Li, U.T)*np.sqrt(beta) + A_ = tdot(LiUTbeta) + trace_term = -0.5*(np.sum(Knn)*beta - np.trace(A_)) + A = A_ + np.eye(num_inducing) + + # factor A + LA = jitchol(A) + + # back substutue to get b, P, v + tmp, _ = dtrtrs(L, Uy, lower=1) + b, _ = dtrtrs(LA, tmp*beta, lower=1) + tmp, _ = dtrtrs(LA, b, lower=1, trans=1) + v, _ = dtrtrs(L, tmp, lower=1, trans=1) + tmp, _ = dtrtrs(LA, Li, lower=1, trans=0) + P = tdot(tmp.T) + stop + + #compute log marginal + log_marginal = -0.5*num_data*output_dim*np.log(2*np.pi) + \ + -np.sum(np.log(np.diag(LA)))*output_dim + \ + 0.5*num_data*output_dim*np.log(beta) + \ + -0.5*beta*np.sum(np.square(Y)) + \ + 0.5*np.sum(np.square(b)) + \ + trace_term + + # Compute dL_dKmm + vvT_P = tdot(v.reshape(-1,1)) + P + LAL = Li.T.dot(A).dot(Li) + dL_dK = Kmmi - 0.5*(vvT_P + LAL) + + # Compute dL_dU + vY = np.dot(v.reshape(-1,1),Y.T) + #dL_dU = vY - np.dot(vvT_P, U.T) + dL_dU = vY - np.dot(vvT_P - Kmmi, U.T) + dL_dU *= beta + + #compute dL_dR + Uv = np.dot(U, v) + dL_dR = 0.5*(np.sum(U*np.dot(U,P), 1) - 1./beta + np.sum(np.square(Y), 1) - 2.*np.sum(Uv*Y, 1) + np.sum(np.square(Uv), 1) )*beta**2 + dL_dR -=beta*trace_term/num_data + + dL_dthetaL = likelihood.exact_inference_gradients(dL_dR) + grad_dict = {'dL_dKmm': dL_dK, 'dL_dKdiag':np.zeros_like(Knn) + -0.5*beta, 'dL_dKnm':dL_dU.T, 'dL_dthetaL':dL_dthetaL} + + #construct a posterior object + post = Posterior(woodbury_inv=Kmmi-P, woodbury_vector=v, K=Kmm, mean=None, cov=None, K_chol=L) + + + return post, log_marginal, grad_dict +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/exact_gaussian_inference.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/exact_gaussian_inference.html new file mode 100644 index 00000000..7a4a7b3f --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/exact_gaussian_inference.html @@ -0,0 +1,155 @@ + + + + + + + + GPy.inference.latent_function_inference.exact_gaussian_inference — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.exact_gaussian_inference

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from posterior import Posterior
      +from ...util.linalg import pdinv, dpotrs, tdot
      +from ...util import diag
      +import numpy as np
      +from . import LatentFunctionInference
      +log_2_pi = np.log(2*np.pi)
      +
      +
      +
      [docs]class ExactGaussianInference(LatentFunctionInference): + """ + An object for inference when the likelihood is Gaussian. + + The function self.inference returns a Posterior object, which summarizes + the posterior. + + For efficiency, we sometimes work with the cholesky of Y*Y.T. To save repeatedly recomputing this, we cache it. + + """ + def __init__(self): + pass#self._YYTfactor_cache = caching.cache() + +
      [docs] def get_YYTfactor(self, Y): + """ + find a matrix L which satisfies LL^T = YY^T. + + Note that L may have fewer columns than Y, else L=Y. + """ + N, D = Y.shape + if (N>D): + return Y + else: + #if Y in self.cache, return self.Cache[Y], else store Y in cache and return L. + #print "WARNING: N>D of Y, we need caching of L, such that L*L^T = Y, returning Y still!" + return Y +
      +
      [docs] def inference(self, kern, X, likelihood, Y, Y_metadata=None): + """ + Returns a Posterior class containing essential quantities of the posterior + """ + YYT_factor = self.get_YYTfactor(Y) + + K = kern.K(X) + + Ky = K.copy() + diag.add(Ky, likelihood.gaussian_variance(Y_metadata)) + Wi, LW, LWi, W_logdet = pdinv(Ky) + + alpha, _ = dpotrs(LW, YYT_factor, lower=1) + + log_marginal = 0.5*(-Y.size * log_2_pi - Y.shape[1] * W_logdet - np.sum(alpha * YYT_factor)) + + dL_dK = 0.5 * (tdot(alpha) - Y.shape[1] * Wi) + + dL_dthetaL = likelihood.exact_inference_gradients(np.diag(dL_dK),Y_metadata) + + return Posterior(woodbury_chol=LW, woodbury_vector=alpha, K=K), log_marginal, {'dL_dK':dL_dK, 'dL_dthetaL':dL_dthetaL}
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/expectation_propagation.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/expectation_propagation.html new file mode 100644 index 00000000..5b36371d --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/expectation_propagation.html @@ -0,0 +1,218 @@ + + + + + + + + GPy.inference.latent_function_inference.expectation_propagation — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.expectation_propagation

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import numpy as np
      +from ...util.linalg import pdinv,jitchol,DSYR,tdot,dtrtrs, dpotrs
      +from posterior import Posterior
      +from . import LatentFunctionInference
      +log_2_pi = np.log(2*np.pi)
      +
      +
      [docs]class EP(LatentFunctionInference): + def __init__(self, epsilon=1e-6, eta=1., delta=1.): + """ + The expectation-propagation algorithm. + For nomenclature see Rasmussen & Williams 2006. + + :param epsilon: Convergence criterion, maximum squared difference allowed between mean updates to stop iterations (float) + :type epsilon: float + :param eta: parameter for fractional EP updates. + :type eta: float64 + :param delta: damping EP updates factor. + :type delta: float64 + """ + self.epsilon, self.eta, self.delta = epsilon, eta, delta + self.reset() + +
      [docs] def reset(self): + self.old_mutilde, self.old_vtilde = None, None + self._ep_approximation = None +
      +
      [docs] def on_optimization_start(self): + self._ep_approximation = None +
      +
      [docs] def on_optimization_end(self): + # TODO: update approximation in the end as well? Maybe even with a switch? + pass +
      +
      [docs] def inference(self, kern, X, likelihood, Y, Y_metadata=None, Z=None): + num_data, output_dim = Y.shape + assert output_dim ==1, "ep in 1D only (for now!)" + + K = kern.K(X) + + if self._ep_approximation is None: + mu, Sigma, mu_tilde, tau_tilde, Z_hat = self._ep_approximation = self.expectation_propagation(K, Y, likelihood, Y_metadata) + else: + mu, Sigma, mu_tilde, tau_tilde, Z_hat = self._ep_approximation + + Wi, LW, LWi, W_logdet = pdinv(K + np.diag(1./tau_tilde)) + + alpha, _ = dpotrs(LW, mu_tilde, lower=1) + + log_marginal = 0.5*(-num_data * log_2_pi - W_logdet - np.sum(alpha * mu_tilde)) # TODO: add log Z_hat?? + + dL_dK = 0.5 * (tdot(alpha[:,None]) - Wi) + + dL_dthetaL = np.zeros(likelihood.size)#TODO: derivatives of the likelihood parameters + + return Posterior(woodbury_inv=Wi, woodbury_vector=alpha, K=K), log_marginal, {'dL_dK':dL_dK, 'dL_dthetaL':dL_dthetaL} +
      +
      [docs] def expectation_propagation(self, K, Y, likelihood, Y_metadata): + + num_data, data_dim = Y.shape + assert data_dim == 1, "This EP methods only works for 1D outputs" + + + #Initial values - Posterior distribution parameters: q(f|X,Y) = N(f|mu,Sigma) + mu = np.zeros(num_data) + Sigma = K.copy() + + #Initial values - Marginal moments + Z_hat = np.empty(num_data,dtype=np.float64) + mu_hat = np.empty(num_data,dtype=np.float64) + sigma2_hat = np.empty(num_data,dtype=np.float64) + + #initial values - Gaussian factors + if self.old_mutilde is None: + tau_tilde, mu_tilde, v_tilde = np.zeros((3, num_data)) + else: + assert old_mutilde.size == num_data, "data size mis-match: did you change the data? try resetting!" + mu_tilde, v_tilde = self.old_mutilde, self.old_vtilde + tau_tilde = v_tilde/mu_tilde + + #Approximation + tau_diff = self.epsilon + 1. + v_diff = self.epsilon + 1. + iterations = 0 + while (tau_diff > self.epsilon) or (v_diff > self.epsilon): + update_order = np.random.permutation(num_data) + for i in update_order: + #Cavity distribution parameters + tau_cav = 1./Sigma[i,i] - self.eta*tau_tilde[i] + v_cav = mu[i]/Sigma[i,i] - self.eta*v_tilde[i] + #Marginal moments + Z_hat[i], mu_hat[i], sigma2_hat[i] = likelihood.moments_match_ep(Y[i], tau_cav, v_cav)#, Y_metadata=None)#=(None if Y_metadata is None else Y_metadata[i])) + #Site parameters update + delta_tau = self.delta/self.eta*(1./sigma2_hat[i] - 1./Sigma[i,i]) + delta_v = self.delta/self.eta*(mu_hat[i]/sigma2_hat[i] - mu[i]/Sigma[i,i]) + tau_tilde[i] += delta_tau + v_tilde[i] += delta_v + #Posterior distribution parameters update + DSYR(Sigma, Sigma[:,i].copy(), -delta_tau/(1.+ delta_tau*Sigma[i,i])) + mu = np.dot(Sigma, v_tilde) + + #(re) compute Sigma and mu using full Cholesky decompy + tau_tilde_root = np.sqrt(tau_tilde) + Sroot_tilde_K = tau_tilde_root[:,None] * K + B = np.eye(num_data) + Sroot_tilde_K * tau_tilde_root[None,:] + L = jitchol(B) + V, _ = dtrtrs(L, Sroot_tilde_K, lower=1) + Sigma = K - np.dot(V.T,V) + mu = np.dot(Sigma,v_tilde) + + #monitor convergence + if iterations>0: + tau_diff = np.mean(np.square(tau_tilde-tau_tilde_old)) + v_diff = np.mean(np.square(v_tilde-v_tilde_old)) + tau_tilde_old = tau_tilde.copy() + v_tilde_old = v_tilde.copy() + + iterations += 1 + + mu_tilde = v_tilde/tau_tilde + return mu, Sigma, mu_tilde, tau_tilde, Z_hat
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/expectation_propagation_dtc.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/expectation_propagation_dtc.html new file mode 100644 index 00000000..e2013da3 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/expectation_propagation_dtc.html @@ -0,0 +1,447 @@ + + + + + + + + GPy.inference.latent_function_inference.expectation_propagation_dtc — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.expectation_propagation_dtc

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ...util import diag
      +from ...util.linalg import mdot, jitchol, backsub_both_sides, tdot, dtrtrs, dtrtri, dpotri, dpotrs, symmetrify, DSYR
      +from ...core.parameterization.variational import VariationalPosterior
      +from . import LatentFunctionInference
      +from posterior import Posterior
      +log_2_pi = np.log(2*np.pi)
      +
      +
      [docs]class EPDTC(LatentFunctionInference): + const_jitter = 1e-6 + def __init__(self, epsilon=1e-6, eta=1., delta=1., limit=1): + from ...util.caching import Cacher + self.limit = limit + self.get_trYYT = Cacher(self._get_trYYT, limit) + self.get_YYTfactor = Cacher(self._get_YYTfactor, limit) + + self.epsilon, self.eta, self.delta = epsilon, eta, delta + self.reset() + +
      [docs] def set_limit(self, limit): + self.get_trYYT.limit = limit + self.get_YYTfactor.limit = limit +
      +
      [docs] def on_optimization_start(self): + self._ep_approximation = None +
      +
      [docs] def on_optimization_end(self): + # TODO: update approximation in the end as well? Maybe even with a switch? + pass +
      + def _get_trYYT(self, Y): + return np.sum(np.square(Y)) + + def __getstate__(self): + # has to be overridden, as Cacher objects cannot be pickled. + return self.limit + + def __setstate__(self, state): + # has to be overridden, as Cacher objects cannot be pickled. + self.limit = state + from ...util.caching import Cacher + self.get_trYYT = Cacher(self._get_trYYT, self.limit) + self.get_YYTfactor = Cacher(self._get_YYTfactor, self.limit) + + def _get_YYTfactor(self, Y): + """ + find a matrix L which satisfies LLT = YYT. + + Note that L may have fewer columns than Y. + """ + N, D = Y.shape + if (N>=D): + return Y + else: + return jitchol(tdot(Y)) + +
      [docs] def get_VVTfactor(self, Y, prec): + return Y * prec # TODO chache this, and make it effective +
      +
      [docs] def reset(self): + self.old_mutilde, self.old_vtilde = None, None + self._ep_approximation = None +
      +
      [docs] def inference(self, kern, X, Z, likelihood, Y, Y_metadata=None): + num_data, output_dim = Y.shape + assert output_dim ==1, "ep in 1D only (for now!)" + + Kmm = kern.K(Z) + Kmn = kern.K(Z,X) + + if self._ep_approximation is None: + mu, Sigma, mu_tilde, tau_tilde, Z_hat = self._ep_approximation = self.expectation_propagation(Kmm, Kmn, Y, likelihood, Y_metadata) + else: + mu, Sigma, mu_tilde, tau_tilde, Z_hat = self._ep_approximation + + + if isinstance(X, VariationalPosterior): + uncertain_inputs = True + psi0 = kern.psi0(Z, X) + psi1 = Kmn.T#kern.psi1(Z, X) + psi2 = kern.psi2(Z, X) + else: + uncertain_inputs = False + psi0 = kern.Kdiag(X) + psi1 = Kmn.T#kern.K(X, Z) + psi2 = None + + #see whether we're using variational uncertain inputs + + _, output_dim = Y.shape + + #see whether we've got a different noise variance for each datum + #beta = 1./np.fmax(likelihood.gaussian_variance(Y_metadata), 1e-6) + beta = tau_tilde + VVT_factor = beta[:,None]*mu_tilde[:,None] + trYYT = self.get_trYYT(mu_tilde[:,None]) + + # do the inference: + het_noise = beta.size > 1 + num_inducing = Z.shape[0] + num_data = Y.shape[0] + # kernel computations, using BGPLVM notation + + Kmm = kern.K(Z).copy() + diag.add(Kmm, self.const_jitter) + Lm = jitchol(Kmm) + + # The rather complex computations of A + if uncertain_inputs: + if het_noise: + psi2_beta = psi2 * (beta.flatten().reshape(num_data, 1, 1)).sum(0) + else: + psi2_beta = psi2.sum(0) * beta + LmInv = dtrtri(Lm) + A = LmInv.dot(psi2_beta.dot(LmInv.T)) + else: + if het_noise: + tmp = psi1 * (np.sqrt(beta.reshape(num_data, 1))) + else: + tmp = psi1 * (np.sqrt(beta)) + tmp, _ = dtrtrs(Lm, tmp.T, lower=1) + A = tdot(tmp) #print A.sum() + + # factor B + B = np.eye(num_inducing) + A + LB = jitchol(B) + psi1Vf = np.dot(psi1.T, VVT_factor) + # back substutue C into psi1Vf + tmp, _ = dtrtrs(Lm, psi1Vf, lower=1, trans=0) + _LBi_Lmi_psi1Vf, _ = dtrtrs(LB, tmp, lower=1, trans=0) + tmp, _ = dtrtrs(LB, _LBi_Lmi_psi1Vf, lower=1, trans=1) + Cpsi1Vf, _ = dtrtrs(Lm, tmp, lower=1, trans=1) + + # data fit and derivative of L w.r.t. Kmm + delit = tdot(_LBi_Lmi_psi1Vf) + data_fit = np.trace(delit) + DBi_plus_BiPBi = backsub_both_sides(LB, output_dim * np.eye(num_inducing) + delit) + delit = -0.5 * DBi_plus_BiPBi + delit += -0.5 * B * output_dim + delit += output_dim * np.eye(num_inducing) + # Compute dL_dKmm + dL_dKmm = backsub_both_sides(Lm, delit) + + # derivatives of L w.r.t. psi + dL_dpsi0, dL_dpsi1, dL_dpsi2 = _compute_dL_dpsi(num_inducing, num_data, output_dim, beta, Lm, + VVT_factor, Cpsi1Vf, DBi_plus_BiPBi, + psi1, het_noise, uncertain_inputs) + + # log marginal likelihood + log_marginal = _compute_log_marginal_likelihood(likelihood, num_data, output_dim, beta, het_noise, + psi0, A, LB, trYYT, data_fit, VVT_factor) + + #put the gradients in the right places + dL_dR = _compute_dL_dR(likelihood, + het_noise, uncertain_inputs, LB, + _LBi_Lmi_psi1Vf, DBi_plus_BiPBi, Lm, A, + psi0, psi1, beta, + data_fit, num_data, output_dim, trYYT, mu_tilde[:,None]) + + dL_dthetaL = 0#likelihood.exact_inference_gradients(dL_dR,Y_metadata) + + if uncertain_inputs: + grad_dict = {'dL_dKmm': dL_dKmm, + 'dL_dpsi0':dL_dpsi0, + 'dL_dpsi1':dL_dpsi1, + 'dL_dpsi2':dL_dpsi2, + 'dL_dthetaL':dL_dthetaL} + else: + grad_dict = {'dL_dKmm': dL_dKmm, + 'dL_dKdiag':dL_dpsi0, + 'dL_dKnm':dL_dpsi1, + 'dL_dthetaL':dL_dthetaL} + + #get sufficient things for posterior prediction + #TODO: do we really want to do this in the loop? + if VVT_factor.shape[1] == Y.shape[1]: + woodbury_vector = Cpsi1Vf # == Cpsi1V + else: + print 'foobar' + psi1V = np.dot(mu_tilde[:,None].T*beta, psi1).T + tmp, _ = dtrtrs(Lm, psi1V, lower=1, trans=0) + tmp, _ = dpotrs(LB, tmp, lower=1) + woodbury_vector, _ = dtrtrs(Lm, tmp, lower=1, trans=1) + Bi, _ = dpotri(LB, lower=1) + symmetrify(Bi) + Bi = -dpotri(LB, lower=1)[0] + diag.add(Bi, 1) + + woodbury_inv = backsub_both_sides(Lm, Bi) + + #construct a posterior object + post = Posterior(woodbury_inv=woodbury_inv, woodbury_vector=woodbury_vector, K=Kmm, mean=None, cov=None, K_chol=Lm) + return post, log_marginal, grad_dict + + + + +
      +
      [docs] def expectation_propagation(self, Kmm, Kmn, Y, likelihood, Y_metadata): + + num_data, data_dim = Y.shape + assert data_dim == 1, "This EP methods only works for 1D outputs" + + KmnKnm = np.dot(Kmn,Kmn.T) + Lm = jitchol(Kmm) + Lmi = dtrtrs(Lm,np.eye(Lm.shape[0]))[0] #chol_inv(Lm) + Kmmi = np.dot(Lmi.T,Lmi) + KmmiKmn = np.dot(Kmmi,Kmn) + Qnn_diag = np.sum(Kmn*KmmiKmn,-2) + LLT0 = Kmm.copy() + + #Initial values - Posterior distribution parameters: q(f|X,Y) = N(f|mu,Sigma) + mu = np.zeros(num_data) + LLT = Kmm.copy() #Sigma = K.copy() + Sigma_diag = Qnn_diag.copy() + + #Initial values - Marginal moments + Z_hat = np.empty(num_data,dtype=np.float64) + mu_hat = np.empty(num_data,dtype=np.float64) + sigma2_hat = np.empty(num_data,dtype=np.float64) + + #initial values - Gaussian factors + if self.old_mutilde is None: + tau_tilde, mu_tilde, v_tilde = np.zeros((3, num_data)) + else: + assert old_mutilde.size == num_data, "data size mis-match: did you change the data? try resetting!" + mu_tilde, v_tilde = self.old_mutilde, self.old_vtilde + tau_tilde = v_tilde/mu_tilde + + #Approximation + tau_diff = self.epsilon + 1. + v_diff = self.epsilon + 1. + iterations = 0 + while (tau_diff > self.epsilon) or (v_diff > self.epsilon): + update_order = np.random.permutation(num_data) + for i in update_order: + #Cavity distribution parameters + tau_cav = 1./Sigma_diag[i] - self.eta*tau_tilde[i] + v_cav = mu[i]/Sigma_diag[i] - self.eta*v_tilde[i] + #Marginal moments + Z_hat[i], mu_hat[i], sigma2_hat[i] = likelihood.moments_match_ep(Y[i], tau_cav, v_cav)#, Y_metadata=None)#=(None if Y_metadata is None else Y_metadata[i])) + #Site parameters update + delta_tau = self.delta/self.eta*(1./sigma2_hat[i] - 1./Sigma_diag[i]) + delta_v = self.delta/self.eta*(mu_hat[i]/sigma2_hat[i] - mu[i]/Sigma_diag[i]) + tau_tilde[i] += delta_tau + v_tilde[i] += delta_v + #Posterior distribution parameters update + + #DSYR(Sigma, Sigma[:,i].copy(), -delta_tau/(1.+ delta_tau*Sigma[i,i])) + DSYR(LLT,Kmn[:,i].copy(),delta_tau) + L = jitchol(LLT) + + V,info = dtrtrs(L,Kmn,lower=1) + Sigma_diag = np.sum(V*V,-2) + si = np.sum(V.T*V[:,i],-1) + mu += (delta_v-delta_tau*mu[i])*si + #mu = np.dot(Sigma, v_tilde) + + #(re) compute Sigma and mu using full Cholesky decompy + LLT = LLT0 + np.dot(Kmn*tau_tilde[None,:],Kmn.T) + L = jitchol(LLT) + V,info = dtrtrs(L,Kmn,lower=1) + V2,info = dtrtrs(L.T,V,lower=0) + #Sigma_diag = np.sum(V*V,-2) + #Knmv_tilde = np.dot(Kmn,v_tilde) + #mu = np.dot(V2.T,Knmv_tilde) + Sigma = np.dot(V2.T,V2) + mu = np.dot(Sigma,v_tilde) + + #monitor convergence + if iterations>0: + tau_diff = np.mean(np.square(tau_tilde-tau_tilde_old)) + v_diff = np.mean(np.square(v_tilde-v_tilde_old)) + tau_tilde_old = tau_tilde.copy() + v_tilde_old = v_tilde.copy() + + tau_diff = 0 + v_diff = 0 + iterations += 1 + + mu_tilde = v_tilde/tau_tilde + return mu, Sigma, mu_tilde, tau_tilde, Z_hat +
      +def _compute_dL_dpsi(num_inducing, num_data, output_dim, beta, Lm, VVT_factor, Cpsi1Vf, DBi_plus_BiPBi, psi1, het_noise, uncertain_inputs): + dL_dpsi0 = -0.5 * output_dim * (beta[:,None] * np.ones([num_data, 1])).flatten() + dL_dpsi1 = np.dot(VVT_factor, Cpsi1Vf.T) + dL_dpsi2_beta = 0.5 * backsub_both_sides(Lm, output_dim * np.eye(num_inducing) - DBi_plus_BiPBi) + if het_noise: + if uncertain_inputs: + dL_dpsi2 = beta[:, None, None] * dL_dpsi2_beta[None, :, :] + else: + dL_dpsi1 += 2.*np.dot(dL_dpsi2_beta, (psi1 * beta.reshape(num_data, 1)).T).T + dL_dpsi2 = None + else: + dL_dpsi2 = beta * dL_dpsi2_beta + if uncertain_inputs: + # repeat for each of the N psi_2 matrices + dL_dpsi2 = np.repeat(dL_dpsi2[None, :, :], num_data, axis=0) + else: + # subsume back into psi1 (==Kmn) + dL_dpsi1 += 2.*np.dot(psi1, dL_dpsi2) + dL_dpsi2 = None + + return dL_dpsi0, dL_dpsi1, dL_dpsi2 + + +def _compute_dL_dR(likelihood, het_noise, uncertain_inputs, LB, _LBi_Lmi_psi1Vf, DBi_plus_BiPBi, Lm, A, psi0, psi1, beta, data_fit, num_data, output_dim, trYYT, Y): + # the partial derivative vector for the likelihood + if likelihood.size == 0: + # save computation here. + dL_dR = None + elif het_noise: + if uncertain_inputs: + raise NotImplementedError, "heteroscedatic derivates with uncertain inputs not implemented" + else: + #from ...util.linalg import chol_inv + #LBi = chol_inv(LB) + LBi, _ = dtrtrs(LB,np.eye(LB.shape[0])) + + Lmi_psi1, nil = dtrtrs(Lm, psi1.T, lower=1, trans=0) + _LBi_Lmi_psi1, _ = dtrtrs(LB, Lmi_psi1, lower=1, trans=0) + + dL_dR = -0.5 * beta + 0.5 * (beta*Y)**2 + dL_dR += 0.5 * output_dim * (psi0 - np.sum(Lmi_psi1**2,0))[:,None] * beta**2 + + dL_dR += 0.5*np.sum(mdot(LBi.T,LBi,Lmi_psi1)*Lmi_psi1,0)[:,None]*beta**2 + + dL_dR += -np.dot(_LBi_Lmi_psi1Vf.T,_LBi_Lmi_psi1).T * Y * beta**2 + dL_dR += 0.5*np.dot(_LBi_Lmi_psi1Vf.T,_LBi_Lmi_psi1).T**2 * beta**2 + else: + # likelihood is not heteroscedatic + dL_dR = -0.5 * num_data * output_dim * beta + 0.5 * trYYT * beta ** 2 + dL_dR += 0.5 * output_dim * (psi0.sum() * beta ** 2 - np.trace(A) * beta) + dL_dR += beta * (0.5 * np.sum(A * DBi_plus_BiPBi) - data_fit) + return dL_dR + +def _compute_log_marginal_likelihood(likelihood, num_data, output_dim, beta, het_noise, psi0, A, LB, trYYT, data_fit,Y): + #compute log marginal likelihood + if het_noise: + lik_1 = -0.5 * num_data * output_dim * np.log(2. * np.pi) + 0.5 * np.sum(np.log(beta)) - 0.5 * np.sum(beta * np.square(Y).sum(axis=-1)) + lik_2 = -0.5 * output_dim * (np.sum(beta.flatten() * psi0) - np.trace(A)) + else: + lik_1 = -0.5 * num_data * output_dim * (np.log(2. * np.pi) - np.log(beta)) - 0.5 * beta * trYYT + lik_2 = -0.5 * output_dim * (np.sum(beta * psi0) - np.trace(A)) + lik_3 = -output_dim * (np.sum(np.log(np.diag(LB)))) + lik_4 = 0.5 * data_fit + log_marginal = lik_1 + lik_2 + lik_3 + lik_4 + return log_marginal +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/fitc.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/fitc.html new file mode 100644 index 00000000..c089147c --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/fitc.html @@ -0,0 +1,183 @@ + + + + + + + + GPy.inference.latent_function_inference.fitc — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.fitc

      +# Copyright (c) 2012, James Hensman
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from posterior import Posterior
      +from ...util.linalg import jitchol, tdot, dtrtrs, dpotri, pdinv
      +from ...util import diag
      +import numpy as np
      +from . import LatentFunctionInference
      +log_2_pi = np.log(2*np.pi)
      +
      +
      [docs]class FITC(LatentFunctionInference): + """ + An object for inference when the likelihood is Gaussian, but we want to do sparse inference. + + The function self.inference returns a Posterior object, which summarizes + the posterior. + + """ + const_jitter = 1e-6 + +
      [docs] def inference(self, kern, X, Z, likelihood, Y, Y_metadata=None): + + num_inducing, _ = Z.shape + num_data, output_dim = Y.shape + + #make sure the noise is not hetero + sigma_n = likelihood.gaussian_variance(Y_metadata) + if sigma_n.size >1: + raise NotImplementedError, "no hetero noise with this implementation of FITC" + + Kmm = kern.K(Z) + Knn = kern.Kdiag(X) + Knm = kern.K(X, Z) + U = Knm + + #factor Kmm + diag.add(Kmm, self.const_jitter) + Kmmi, L, Li, _ = pdinv(Kmm) + + #compute beta_star, the effective noise precision + LiUT = np.dot(Li, U.T) + sigma_star = Knn + sigma_n - np.sum(np.square(LiUT),0) + beta_star = 1./sigma_star + + # Compute and factor A + A = tdot(LiUT*np.sqrt(beta_star)) + np.eye(num_inducing) + LA = jitchol(A) + + # back substutue to get b, P, v + URiy = np.dot(U.T*beta_star,Y) + tmp, _ = dtrtrs(L, URiy, lower=1) + b, _ = dtrtrs(LA, tmp, lower=1) + tmp, _ = dtrtrs(LA, b, lower=1, trans=1) + v, _ = dtrtrs(L, tmp, lower=1, trans=1) + tmp, _ = dtrtrs(LA, Li, lower=1, trans=0) + P = tdot(tmp.T) + + #compute log marginal + log_marginal = -0.5*num_data*output_dim*np.log(2*np.pi) + \ + -np.sum(np.log(np.diag(LA)))*output_dim + \ + 0.5*output_dim*np.sum(np.log(beta_star)) + \ + -0.5*np.sum(np.square(Y.T*np.sqrt(beta_star))) + \ + 0.5*np.sum(np.square(b)) + #compute dL_dR + Uv = np.dot(U, v) + dL_dR = 0.5*(np.sum(U*np.dot(U,P), 1) - 1./beta_star + np.sum(np.square(Y), 1) - 2.*np.sum(Uv*Y, 1) + np.sum(np.square(Uv), 1))*beta_star**2 + + + # Compute dL_dKmm + vvT_P = tdot(v.reshape(-1,1)) + P + dL_dK = 0.5*(Kmmi - vvT_P) + KiU = np.dot(Kmmi, U.T) + dL_dK += np.dot(KiU*dL_dR, KiU.T) + + # Compute dL_dU + vY = np.dot(v.reshape(-1,1),Y.T) + dL_dU = vY - np.dot(vvT_P, U.T) + dL_dU *= beta_star + dL_dU -= 2.*KiU*dL_dR + + dL_dthetaL = likelihood.exact_inference_gradients(dL_dR) + grad_dict = {'dL_dKmm': dL_dK, 'dL_dKdiag':dL_dR, 'dL_dKnm':dL_dU.T, 'dL_dthetaL':dL_dthetaL} + + #construct a posterior object + post = Posterior(woodbury_inv=Kmmi-P, woodbury_vector=v, K=Kmm, mean=None, cov=None, K_chol=L) + + return post, log_marginal, grad_dict +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/inferenceX.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/inferenceX.html new file mode 100644 index 00000000..8099181d --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/inferenceX.html @@ -0,0 +1,257 @@ + + + + + + + + GPy.inference.latent_function_inference.inferenceX — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.inferenceX

      +# Copyright (c) 2014, Zhenwen Dai
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ...core import Model
      +from ...core.parameterization import variational
      +
      +
      [docs]def infer_newX(model, Y_new, optimize=True, init='L2'): + """ + Infer the distribution of X for the new observed data *Y_new*. + + :param model: the GPy model used in inference + :type model: GPy.core.Model + :param Y_new: the new observed data for inference + :type Y_new: numpy.ndarray + :param optimize: whether to optimize the location of new X (True by default) + :type optimize: boolean + :return: a tuple containing the estimated posterior distribution of X and the model that optimize X + :rtype: (GPy.core.parameterization.variational.VariationalPosterior, GPy.core.Model) + """ + infr_m = InferenceX(model, Y_new, init=init) + + if optimize: + infr_m.optimize() + + return infr_m.X, infr_m +
      +
      [docs]class InferenceX(Model): + """ + The class for inference of new X with given new Y. (do_test_latent) + + :param model: the GPy model used in inference + :type model: GPy.core.Model + :param Y: the new observed data for inference + :type Y: numpy.ndarray + """ + def __init__(self, model, Y, name='inferenceX', init='L2'): + if np.isnan(Y).any() or getattr(model, 'missing_data', False): + assert Y.shape[0]==1, "The current implementation of inference X only support one data point at a time with missing data!" + self.missing_data = True + self.valid_dim = np.logical_not(np.isnan(Y[0])) + self.ninan = getattr(model, 'ninan', None) + else: + self.missing_data = False + super(InferenceX, self).__init__(name) + self.likelihood = model.likelihood.copy() + self.kern = model.kern.copy() + if model.kern.useGPU: + from ...models import SSGPLVM + if isinstance(model, SSGPLVM): + self.kern.GPU_SSRBF(True) + else: + self.kern.GPU(True) + from copy import deepcopy + self.posterior = deepcopy(model.posterior) + if hasattr(model, 'variational_prior'): + self.uncertain_input = True + self.variational_prior = model.variational_prior.copy() + else: + self.uncertain_input = False + if hasattr(model, 'inducing_inputs'): + self.sparse_gp = True + self.Z = model.Z.copy() + else: + self.sparse_gp = False + self.uncertain_input = False + self.Z = model.X.copy() + self.Y = Y + self.X = self._init_X(model, Y, init=init) + self.compute_dL() + + self.link_parameter(self.X) + + def _init_X(self, model, Y_new, init='L2'): + # Initialize the new X by finding the nearest point in Y space. + + Y = model.Y + if self.missing_data: + Y = Y[:,self.valid_dim] + Y_new = Y_new[:,self.valid_dim] + dist = -2.*Y_new.dot(Y.T) + np.square(Y_new).sum(axis=1)[:,None]+ np.square(Y).sum(axis=1)[None,:] + else: + if init=='L2': + dist = -2.*Y_new.dot(Y.T) + np.square(Y_new).sum(axis=1)[:,None]+ np.square(Y).sum(axis=1)[None,:] + elif init=='NCC': + dist = Y_new.dot(Y.T) + elif init=='rand': + dist = np.random.rand(Y_new.shape[0],Y.shape[0]) + idx = dist.argmin(axis=1) + + from ...models import SSGPLVM + from ...util.misc import param_to_array + 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])) + if model.group_spike: + X.gamma.fix() + else: + 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])) + else: + from ...core import Param + X = Param('latent mean',param_to_array(model.X[idx]).copy()) + + return X + +
      [docs] def compute_dL(self): + # Common computation + beta = 1./np.fmax(self.likelihood.variance, 1e-6) + output_dim = self.Y.shape[-1] + wv = self.posterior.woodbury_vector + if self.missing_data: + wv = wv[:,self.valid_dim] + output_dim = self.valid_dim.sum() + if self.ninan is not None: + self.dL_dpsi2 = beta/2.*(self.posterior.woodbury_inv[:,:,self.valid_dim] - np.einsum('md,od->mo',wv, wv)[:, :, None]).sum(-1) + else: + self.dL_dpsi2 = beta/2.*(output_dim*self.posterior.woodbury_inv - np.einsum('md,od->mo',wv, wv)) + self.dL_dpsi1 = beta*np.dot(self.Y[:,self.valid_dim], wv.T) + self.dL_dpsi0 = - beta/2.* np.ones(self.Y.shape[0]) + else: + self.dL_dpsi2 = beta*(output_dim*self.posterior.woodbury_inv - np.einsum('md,od->mo',wv, wv))/2. + self.dL_dpsi1 = beta*np.dot(self.Y, wv.T) + self.dL_dpsi0 = -beta/2.*output_dim* np.ones(self.Y.shape[0]) +
      +
      [docs] def parameters_changed(self): + if self.uncertain_input: + psi0 = self.kern.psi0(self.Z, self.X) + psi1 = self.kern.psi1(self.Z, self.X) + psi2 = self.kern.psi2(self.Z, self.X) + else: + psi0 = self.kern.Kdiag(self.X) + psi1 = self.kern.K(self.X, self.Z) + psi2 = np.dot(psi1.T,psi1) + + self._log_marginal_likelihood = (self.dL_dpsi2*psi2).sum()+(self.dL_dpsi1*psi1).sum()+(self.dL_dpsi0*psi0).sum() + + if self.uncertain_input: + X_grad = self.kern.gradients_qX_expectations(variational_posterior=self.X, Z=self.Z, dL_dpsi0=self.dL_dpsi0, dL_dpsi1=self.dL_dpsi1, dL_dpsi2=self.dL_dpsi2) + self.X.set_gradients(X_grad) + else: + dL_dpsi1 = self.dL_dpsi1 + 2.*np.dot(psi1,self.dL_dpsi2) + X_grad = self.kern.gradients_X_diag(self.dL_dpsi0, self.X) + X_grad += self.kern.gradients_X(dL_dpsi1, self.X, self.Z) + self.X.gradient = X_grad + + if self.uncertain_input: + from ...core.parameterization.variational import SpikeAndSlabPrior + if isinstance(self.variational_prior, SpikeAndSlabPrior): + # Update Log-likelihood + KL_div = self.variational_prior.KL_divergence(self.X, N=self.Y.shape[0]) + # update for the KL divergence + self.variational_prior.update_gradients_KL(self.X, N=self.Y.shape[0]) + else: + # Update Log-likelihood + KL_div = self.variational_prior.KL_divergence(self.X) + # update for the KL divergence + self.variational_prior.update_gradients_KL(self.X) + self._log_marginal_likelihood += -KL_div +
      +
      [docs] def log_likelihood(self): + return self._log_marginal_likelihood +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/laplace.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/laplace.html new file mode 100644 index 00000000..d0041980 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/laplace.html @@ -0,0 +1,346 @@ + + + + + + + + GPy.inference.latent_function_inference.laplace — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.laplace

      +# Copyright (c) 2013, 2014 Alan Saul
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +#
      +#Parts of this file were influenced by the Matlab GPML framework written by
      +#Carl Edward Rasmussen & Hannes Nickisch, however all bugs are our own.
      +#
      +#The GPML code is released under the FreeBSD License.
      +#Copyright (c) 2005-2013 Carl Edward Rasmussen & Hannes Nickisch. All rights reserved.
      +#
      +#The code and associated documentation is available from
      +#http://gaussianprocess.org/gpml/code.
      +
      +import numpy as np
      +from ...util.linalg import mdot, jitchol, dpotrs, dtrtrs, dpotri, symmetrify, pdinv
      +from posterior import Posterior
      +import warnings
      +
      [docs]def warning_on_one_line(message, category, filename, lineno, file=None, line=None): + return ' %s:%s: %s:%s\n' % (filename, lineno, category.__name__, message)
      +warnings.formatwarning = warning_on_one_line +from scipy import optimize +from . import LatentFunctionInference + +
      [docs]class Laplace(LatentFunctionInference): + + def __init__(self): + """ + Laplace Approximation + + Find the moments \hat{f} and the hessian at this point + (using Newton-Raphson) of the unnormalised posterior + + """ + + self._mode_finding_tolerance = 1e-7 + self._mode_finding_max_iter = 60 + self.bad_fhat = False + #Store whether it is the first run of the inference so that we can choose whether we need + #to calculate things or reuse old variables + self.first_run = True + self._previous_Ki_fhat = None + +
      [docs] def inference(self, kern, X, likelihood, Y, Y_metadata=None): + """ + Returns a Posterior class containing essential quantities of the posterior + """ + + # Compute K + K = kern.K(X) + + #Find mode + if self.bad_fhat or self.first_run: + Ki_f_init = np.zeros_like(Y) + first_run = False + else: + Ki_f_init = self._previous_Ki_fhat + + f_hat, Ki_fhat = self.rasm_mode(K, Y, likelihood, Ki_f_init, Y_metadata=Y_metadata) + self.f_hat = f_hat + self.Ki_fhat = Ki_fhat + self.K = K.copy() + #Compute hessian and other variables at mode + log_marginal, woodbury_inv, dL_dK, dL_dthetaL = self.mode_computations(f_hat, Ki_fhat, K, Y, likelihood, kern, Y_metadata) + + self._previous_Ki_fhat = Ki_fhat.copy() + return Posterior(woodbury_vector=Ki_fhat, woodbury_inv=woodbury_inv, K=K), log_marginal, {'dL_dK':dL_dK, 'dL_dthetaL':dL_dthetaL} +
      +
      [docs] def rasm_mode(self, K, Y, likelihood, Ki_f_init, Y_metadata=None): + """ + Rasmussen's numerically stable mode finding + For nomenclature see Rasmussen & Williams 2006 + Influenced by GPML (BSD) code, all errors are our own + + :param K: Covariance matrix evaluated at locations X + :type K: NxD matrix + :param Y: The data + :type Y: np.ndarray + :param likelihood: the likelihood of the latent function value for the given data + :type likelihood: a GPy.likelihood object + :param Ki_f_init: the initial guess at the mode + :type Ki_f_init: np.ndarray + :param Y_metadata: information about the data, e.g. which likelihood to take from a multi-likelihood object + :type Y_metadata: np.ndarray | None + :returns: f_hat, mode on which to make laplace approxmiation + :rtype: np.ndarray + """ + + Ki_f = Ki_f_init.copy() + f = np.dot(K, Ki_f) + + #define the objective function (to be maximised) + def obj(Ki_f, f): + return -0.5*np.dot(Ki_f.flatten(), f.flatten()) + np.sum(likelihood.logpdf(f, Y, Y_metadata=Y_metadata)) + + difference = np.inf + iteration = 0 + while difference > self._mode_finding_tolerance and iteration < self._mode_finding_max_iter: + W = -likelihood.d2logpdf_df2(f, Y, Y_metadata=Y_metadata) + if np.any(np.isnan(W)): + raise ValueError('One or more element(s) of W is NaN') + grad = likelihood.dlogpdf_df(f, Y, Y_metadata=Y_metadata) + if np.any(np.isnan(grad)): + raise ValueError('One or more element(s) of grad is NaN') + + W_f = W*f + + b = W_f + grad # R+W p46 line 6. + W12BiW12, _, _ = self._compute_B_statistics(K, W, likelihood.log_concave) + W12BiW12Kb = np.dot(W12BiW12, np.dot(K, b)) + + #Work out the DIRECTION that we want to move in, but don't choose the stepsize yet + full_step_Ki_f = b - W12BiW12Kb # full_step_Ki_f = a in R&W p46 line 6. + dKi_f = full_step_Ki_f - Ki_f + + #define an objective for the line search (minimize this one) + def inner_obj(step_size): + Ki_f_trial = Ki_f + step_size*dKi_f + f_trial = np.dot(K, Ki_f_trial) + return -obj(Ki_f_trial, f_trial) + + #use scipy for the line search, the compute new values of f, Ki_f + step = optimize.brent(inner_obj, tol=1e-4, maxiter=12) + Ki_f_new = Ki_f + step*dKi_f + f_new = np.dot(K, Ki_f_new) + + difference = np.abs(np.sum(f_new - f)) + np.abs(np.sum(Ki_f_new - Ki_f)) + Ki_f = Ki_f_new + f = f_new + iteration += 1 + + #Warn of bad fits + if difference > self._mode_finding_tolerance: + if not self.bad_fhat: + warnings.warn("Not perfect mode found (f_hat). difference: {}, iteration: {} out of max {}".format(difference, iteration, self._mode_finding_max_iter)) + self.bad_fhat = True + elif self.bad_fhat: + self.bad_fhat = False + warnings.warn("f_hat now fine again. difference: {}, iteration: {} out of max {}".format(difference, iteration, self._mode_finding_max_iter)) + + return f, Ki_f +
      +
      [docs] def mode_computations(self, f_hat, Ki_f, K, Y, likelihood, kern, Y_metadata): + """ + At the mode, compute the hessian and effective covariance matrix. + + returns: logZ : approximation to the marginal likelihood + woodbury_inv : variable required for calculating the approximation to the covariance matrix + dL_dthetaL : array of derivatives (1 x num_kernel_params) + dL_dthetaL : array of derivatives (1 x num_likelihood_params) + """ + #At this point get the hessian matrix (or vector as W is diagonal) + W = -likelihood.d2logpdf_df2(f_hat, Y, Y_metadata=Y_metadata) + if np.any(np.isnan(W)): + raise ValueError('One or more element(s) of W is NaN') + + K_Wi_i, L, LiW12 = self._compute_B_statistics(K, W, likelihood.log_concave) + + #compute vital matrices + C = np.dot(LiW12, K) + Ki_W_i = K - C.T.dot(C) + + #compute the log marginal + log_marginal = -0.5*np.dot(Ki_f.flatten(), f_hat.flatten()) + np.sum(likelihood.logpdf(f_hat, Y, Y_metadata=Y_metadata)) - np.sum(np.log(np.diag(L))) + + # Compute matrices for derivatives + dW_df = -likelihood.d3logpdf_df3(f_hat, Y, Y_metadata=Y_metadata) # -d3lik_d3fhat + if np.any(np.isnan(dW_df)): + raise ValueError('One or more element(s) of dW_df is NaN') + + dL_dfhat = -0.5*(np.diag(Ki_W_i)[:, None]*dW_df) # s2 in R&W p126 line 9. + #BiK, _ = dpotrs(L, K, lower=1) + #dL_dfhat = 0.5*np.diag(BiK)[:, None]*dW_df + I_KW_i = np.eye(Y.shape[0]) - np.dot(K, K_Wi_i) + + #################### + # compute dL_dK # + #################### + if kern.size > 0 and not kern.is_fixed: + #Explicit + explicit_part = 0.5*(np.dot(Ki_f, Ki_f.T) - K_Wi_i) + + #Implicit + implicit_part = np.dot(Ki_f, dL_dfhat.T).dot(I_KW_i) + + dL_dK = explicit_part + implicit_part + else: + dL_dK = np.zeros(likelihood.size) + + #################### + #compute dL_dthetaL# + #################### + if likelihood.size > 0 and not likelihood.is_fixed: + dlik_dthetaL, dlik_grad_dthetaL, dlik_hess_dthetaL = likelihood._laplace_gradients(f_hat, Y, Y_metadata=Y_metadata) + + num_params = likelihood.size + # make space for one derivative for each likelihood parameter + dL_dthetaL = np.zeros(num_params) + for thetaL_i in range(num_params): + #Explicit + dL_dthetaL_exp = ( np.sum(dlik_dthetaL[thetaL_i]) + # The + comes from the fact that dlik_hess_dthetaL == -dW_dthetaL + + 0.5*np.sum(np.diag(Ki_W_i).flatten()*dlik_hess_dthetaL[:, thetaL_i].flatten()) + ) + + #Implicit + dfhat_dthetaL = mdot(I_KW_i, K, dlik_grad_dthetaL[:, thetaL_i]) + #dfhat_dthetaL = mdot(Ki_W_i, dlik_grad_dthetaL[:, thetaL_i]) + dL_dthetaL_imp = np.dot(dL_dfhat.T, dfhat_dthetaL) + dL_dthetaL[thetaL_i] = dL_dthetaL_exp + dL_dthetaL_imp + + else: + dL_dthetaL = np.zeros(likelihood.size) + + return log_marginal, K_Wi_i, dL_dK, dL_dthetaL +
      + def _compute_B_statistics(self, K, W, log_concave): + """ + Rasmussen suggests the use of a numerically stable positive definite matrix B + Which has a positive diagonal elements and can be easily inverted + + :param K: Prior Covariance matrix evaluated at locations X + :type K: NxN matrix + :param W: Negative hessian at a point (diagonal matrix) + :type W: Vector of diagonal values of Hessian (1xN) + :returns: (W12BiW12, L_B, Li_W12) + """ + if not log_concave: + #print "Under 1e-10: {}".format(np.sum(W < 1e-6)) + W[W<1e-6] = 1e-6 + # NOTE: when setting a parameter inside parameters_changed it will allways come to closed update circles!!! + #W.__setitem__(W < 1e-6, 1e-6, update=False) # FIXME-HACK: This is a hack since GPy can't handle negative variances which can occur + # If the likelihood is non-log-concave. We wan't to say that there is a negative variance + # To cause the posterior to become less certain than the prior and likelihood, + # This is a property only held by non-log-concave likelihoods + if np.any(np.isnan(W)): + raise ValueError('One or more element(s) of W is NaN') + #W is diagonal so its sqrt is just the sqrt of the diagonal elements + W_12 = np.sqrt(W) + B = np.eye(K.shape[0]) + W_12*K*W_12.T + L = jitchol(B) + + LiW12, _ = dtrtrs(L, np.diagflat(W_12), lower=1, trans=0) + K_Wi_i = np.dot(LiW12.T, LiW12) # R = W12BiW12, in R&W p 126, eq 5.25 + + #here's a better way to compute the required matrix. + # you could do the model finding witha backsub, instead of a dot... + #L2 = L/W_12 + #K_Wi_i_2 , _= dpotri(L2) + #symmetrify(K_Wi_i_2) + + return K_Wi_i, L, LiW12 +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/posterior.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/posterior.html new file mode 100644 index 00000000..3557c290 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/posterior.html @@ -0,0 +1,282 @@ + + + + + + + + GPy.inference.latent_function_inference.posterior — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.posterior

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ...util.linalg import pdinv, dpotrs, dpotri, symmetrify, jitchol
      +
      +
      [docs]class Posterior(object): + """ + An object to represent a Gaussian posterior over latent function values, p(f|D). + This may be computed exactly for Gaussian likelihoods, or approximated for + non-Gaussian likelihoods. + + The purpose of this class is to serve as an interface between the inference + schemes and the model classes. the model class can make predictions for + the function at any new point x_* by integrating over this posterior. + + """ + def __init__(self, woodbury_chol=None, woodbury_vector=None, K=None, mean=None, cov=None, K_chol=None, woodbury_inv=None): + """ + woodbury_chol : a lower triangular matrix L that satisfies posterior_covariance = K - K L^{-T} L^{-1} K + woodbury_vector : a matrix (or vector, as Nx1 matrix) M which satisfies posterior_mean = K M + K : the proir covariance (required for lazy computation of various quantities) + mean : the posterior mean + cov : the posterior covariance + + Not all of the above need to be supplied! You *must* supply: + + K (for lazy computation) + or + K_chol (for lazy computation) + + You may supply either: + + woodbury_chol + woodbury_vector + + Or: + + mean + cov + + Of course, you can supply more than that, but this class will lazily + compute all other quantites on demand. + + """ + #obligatory + self._K = K + + if ((woodbury_chol is not None) and (woodbury_vector is not None))\ + or ((woodbury_inv is not None) and (woodbury_vector is not None))\ + or ((woodbury_inv is not None) and (mean is not None))\ + or ((mean is not None) and (cov is not None)): + pass # we have sufficient to compute the posterior + else: + raise ValueError, "insufficient information to compute the posterior" + + self._K_chol = K_chol + self._K = K + #option 1: + self._woodbury_chol = woodbury_chol + self._woodbury_vector = woodbury_vector + + #option 2. + self._woodbury_inv = woodbury_inv + #and woodbury vector + + #option 2: + self._mean = mean + self._covariance = cov + + #compute this lazily + self._precision = None + + @property + def mean(self): + """ + Posterior mean + $$ + K_{xx}v + v := \texttt{Woodbury vector} + $$ + """ + if self._mean is None: + self._mean = np.dot(self._K, self.woodbury_vector) + return self._mean + + @property + def covariance(self): + """ + Posterior covariance + $$ + K_{xx} - K_{xx}W_{xx}^{-1}K_{xx} + W_{xx} := \texttt{Woodbury inv} + $$ + """ + if self._covariance is None: + #LiK, _ = dtrtrs(self.woodbury_chol, self._K, lower=1) + self._covariance = (np.atleast_3d(self._K) - np.tensordot(np.dot(np.atleast_3d(self.woodbury_inv).T, self._K), self._K, [1,0]).T).squeeze() + #self._covariance = self._K - self._K.dot(self.woodbury_inv).dot(self._K) + return self._covariance + + @property + def precision(self): + """ + Inverse of posterior covariance + """ + if self._precision is None: + cov = np.atleast_3d(self.covariance) + self._precision = np.zeros(cov.shape) # if one covariance per dimension + for p in xrange(cov.shape[-1]): + self._precision[:,:,p] = pdinv(cov[:,:,p])[0] + return self._precision + + @property + def woodbury_chol(self): + """ + return $L_{W}$ where L is the lower triangular Cholesky decomposition of the Woodbury matrix + $$ + L_{W}L_{W}^{\top} = W^{-1} + W^{-1} := \texttt{Woodbury inv} + $$ + """ + if self._woodbury_chol is None: + #compute woodbury chol from + if self._woodbury_inv is not None: + winv = np.atleast_3d(self._woodbury_inv) + self._woodbury_chol = np.zeros(winv.shape) + for p in xrange(winv.shape[-1]): + self._woodbury_chol[:,:,p] = pdinv(winv[:,:,p])[2] + #Li = jitchol(self._woodbury_inv) + #self._woodbury_chol, _ = dtrtri(Li) + #W, _, _, _, = pdinv(self._woodbury_inv) + #symmetrify(W) + #self._woodbury_chol = jitchol(W) + #try computing woodbury chol from cov + elif self._covariance is not None: + raise NotImplementedError, "TODO: check code here" + B = self._K - self._covariance + tmp, _ = dpotrs(self.K_chol, B) + self._woodbury_inv, _ = dpotrs(self.K_chol, tmp.T) + _, _, self._woodbury_chol, _ = pdinv(self._woodbury_inv) + else: + raise ValueError, "insufficient information to compute posterior" + return self._woodbury_chol + + @property + def woodbury_inv(self): + """ + The inverse of the woodbury matrix, in the gaussian likelihood case it is defined as + $$ + (K_{xx} + \Sigma_{xx})^{-1} + \Sigma_{xx} := \texttt{Likelihood.variance / Approximate likelihood covariance} + $$ + """ + if self._woodbury_inv is None: + if self._woodbury_chol is not None: + self._woodbury_inv, _ = dpotri(self._woodbury_chol, lower=1) + #self._woodbury_inv, _ = dpotrs(self.woodbury_chol, np.eye(self.woodbury_chol.shape[0]), lower=1) + symmetrify(self._woodbury_inv) + elif self._covariance is not None: + B = self._K - self._covariance + tmp, _ = dpotrs(self.K_chol, B) + self._woodbury_inv, _ = dpotrs(self.K_chol, tmp.T) + return self._woodbury_inv + + @property + def woodbury_vector(self): + """ + Woodbury vector in the gaussian likelihood case only is defined as + $$ + (K_{xx} + \Sigma)^{-1}Y + \Sigma := \texttt{Likelihood.variance / Approximate likelihood covariance} + $$ + """ + if self._woodbury_vector is None: + self._woodbury_vector, _ = dpotrs(self.K_chol, self.mean) + return self._woodbury_vector + + @property + def K_chol(self): + """ + Cholesky of the prior covariance K + """ + if self._K_chol is None: + self._K_chol = jitchol(self._K) + return self._K_chol
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/var_dtc.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/var_dtc.html new file mode 100644 index 00000000..b7a4d8b5 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/var_dtc.html @@ -0,0 +1,345 @@ + + + + + + + + GPy.inference.latent_function_inference.var_dtc — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.var_dtc

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from posterior import Posterior
      +from ...util.linalg import mdot, jitchol, backsub_both_sides, tdot, dtrtrs, dtrtri, dpotri, dpotrs, symmetrify
      +from ...util import diag
      +from ...core.parameterization.variational import VariationalPosterior
      +import numpy as np
      +from . import LatentFunctionInference
      +log_2_pi = np.log(2*np.pi)
      +import logging, itertools
      +logger = logging.getLogger('vardtc')
      +
      +
      [docs]class VarDTC(LatentFunctionInference): + """ + An object for inference when the likelihood is Gaussian, but we want to do sparse inference. + + The function self.inference returns a Posterior object, which summarizes + the posterior. + + For efficiency, we sometimes work with the cholesky of Y*Y.T. To save repeatedly recomputing this, we cache it. + + """ + const_jitter = 1e-6 + def __init__(self, limit=1): + #self._YYTfactor_cache = caching.cache() + from ...util.caching import Cacher + self.limit = limit + self.get_trYYT = Cacher(self._get_trYYT, limit) + self.get_YYTfactor = Cacher(self._get_YYTfactor, limit) + +
      [docs] def set_limit(self, limit): + self.get_trYYT.limit = limit + self.get_YYTfactor.limit = limit +
      + def _get_trYYT(self, Y): + return np.einsum("ij,ij->", Y, Y) + # faster than, but same as: + # return np.sum(np.square(Y)) + + def __getstate__(self): + # has to be overridden, as Cacher objects cannot be pickled. + return self.limit + + def __setstate__(self, state): + # has to be overridden, as Cacher objects cannot be pickled. + self.limit = state + from ...util.caching import Cacher + self.get_trYYT = Cacher(self._get_trYYT, self.limit) + self.get_YYTfactor = Cacher(self._get_YYTfactor, self.limit) + + def _get_YYTfactor(self, Y): + """ + find a matrix L which satisfies LLT = YYT. + + Note that L may have fewer columns than Y. + """ + N, D = Y.shape + if (N>=D): + return Y.view(np.ndarray) + else: + return jitchol(tdot(Y)) + +
      [docs] def get_VVTfactor(self, Y, prec): + return Y * prec # TODO chache this, and make it effective + + +
      +
      [docs] def inference(self, kern, X, Z, likelihood, Y, Y_metadata=None, Lm=None, dL_dKmm=None): + + _, output_dim = Y.shape + uncertain_inputs = isinstance(X, VariationalPosterior) + + #see whether we've got a different noise variance for each datum + beta = 1./np.fmax(likelihood.gaussian_variance(Y_metadata), 1e-6) + # VVT_factor is a matrix such that tdot(VVT_factor) = VVT...this is for efficiency! + #self.YYTfactor = self.get_YYTfactor(Y) + #VVT_factor = self.get_VVTfactor(self.YYTfactor, beta) + het_noise = beta.size > 1 + if beta.ndim == 1: + beta = beta[:, None] + VVT_factor = beta*Y + #VVT_factor = beta*Y + trYYT = self.get_trYYT(Y) + + # do the inference: + num_inducing = Z.shape[0] + num_data = Y.shape[0] + # kernel computations, using BGPLVM notation + + Kmm = kern.K(Z).copy() + diag.add(Kmm, self.const_jitter) + if Lm is None: + Lm = jitchol(Kmm) + + # The rather complex computations of A, and the psi stats + if uncertain_inputs: + psi0 = kern.psi0(Z, X) + psi1 = kern.psi1(Z, X) + if het_noise: + psi2_beta = np.sum([kern.psi2(Z,X[i:i+1,:]) * beta_i for i,beta_i in enumerate(beta)],0) + else: + psi2_beta = kern.psi2(Z,X) * beta + LmInv = dtrtri(Lm) + A = LmInv.dot(psi2_beta.dot(LmInv.T)) + else: + psi0 = kern.Kdiag(X) + psi1 = kern.K(X, Z) + if het_noise: + tmp = psi1 * (np.sqrt(beta)) + else: + tmp = psi1 * (np.sqrt(beta)) + tmp, _ = dtrtrs(Lm, tmp.T, lower=1) + A = tdot(tmp) #print A.sum() + + # factor B + B = np.eye(num_inducing) + A + LB = jitchol(B) + psi1Vf = np.dot(psi1.T, VVT_factor) + # back substutue C into psi1Vf + tmp, _ = dtrtrs(Lm, psi1Vf, lower=1, trans=0) + _LBi_Lmi_psi1Vf, _ = dtrtrs(LB, tmp, lower=1, trans=0) + tmp, _ = dtrtrs(LB, _LBi_Lmi_psi1Vf, lower=1, trans=1) + Cpsi1Vf, _ = dtrtrs(Lm, tmp, lower=1, trans=1) + + # data fit and derivative of L w.r.t. Kmm + delit = tdot(_LBi_Lmi_psi1Vf) + data_fit = np.trace(delit) + DBi_plus_BiPBi = backsub_both_sides(LB, output_dim * np.eye(num_inducing) + delit) + if dL_dKmm is None: + delit = -0.5 * DBi_plus_BiPBi + delit += -0.5 * B * output_dim + delit += output_dim * np.eye(num_inducing) + # Compute dL_dKmm + dL_dKmm = backsub_both_sides(Lm, delit) + + # derivatives of L w.r.t. psi + dL_dpsi0, dL_dpsi1, dL_dpsi2 = _compute_dL_dpsi(num_inducing, num_data, output_dim, beta, Lm, + VVT_factor, Cpsi1Vf, DBi_plus_BiPBi, + psi1, het_noise, uncertain_inputs) + + # log marginal likelihood + log_marginal = _compute_log_marginal_likelihood(likelihood, num_data, output_dim, beta, het_noise, + psi0, A, LB, trYYT, data_fit, Y) + + #noise derivatives + dL_dR = _compute_dL_dR(likelihood, + het_noise, uncertain_inputs, LB, + _LBi_Lmi_psi1Vf, DBi_plus_BiPBi, Lm, A, + psi0, psi1, beta, + data_fit, num_data, output_dim, trYYT, Y, VVT_factor) + + dL_dthetaL = likelihood.exact_inference_gradients(dL_dR,Y_metadata) + + #put the gradients in the right places + if uncertain_inputs: + grad_dict = {'dL_dKmm': dL_dKmm, + 'dL_dpsi0':dL_dpsi0, + 'dL_dpsi1':dL_dpsi1, + 'dL_dpsi2':dL_dpsi2, + 'dL_dthetaL':dL_dthetaL} + else: + grad_dict = {'dL_dKmm': dL_dKmm, + 'dL_dKdiag':dL_dpsi0, + 'dL_dKnm':dL_dpsi1, + 'dL_dthetaL':dL_dthetaL} + + #get sufficient things for posterior prediction + #TODO: do we really want to do this in the loop? + if VVT_factor.shape[1] == Y.shape[1]: + woodbury_vector = Cpsi1Vf # == Cpsi1V + else: + print 'foobar' + import ipdb; ipdb.set_trace() + psi1V = np.dot(Y.T*beta, psi1).T + tmp, _ = dtrtrs(Lm, psi1V, lower=1, trans=0) + tmp, _ = dpotrs(LB, tmp, lower=1) + woodbury_vector, _ = dtrtrs(Lm, tmp, lower=1, trans=1) + Bi, _ = dpotri(LB, lower=1) + symmetrify(Bi) + Bi = -dpotri(LB, lower=1)[0] + diag.add(Bi, 1) + + woodbury_inv = backsub_both_sides(Lm, Bi) + + #construct a posterior object + post = Posterior(woodbury_inv=woodbury_inv, woodbury_vector=woodbury_vector, K=Kmm, mean=None, cov=None, K_chol=Lm) + return post, log_marginal, grad_dict +
      +def _compute_dL_dpsi(num_inducing, num_data, output_dim, beta, Lm, VVT_factor, Cpsi1Vf, DBi_plus_BiPBi, psi1, het_noise, uncertain_inputs): + dL_dpsi0 = -0.5 * output_dim * (beta* np.ones([num_data, 1])).flatten() + dL_dpsi1 = np.dot(VVT_factor, Cpsi1Vf.T) + dL_dpsi2_beta = 0.5 * backsub_both_sides(Lm, output_dim * np.eye(num_inducing) - DBi_plus_BiPBi) + if het_noise: + if uncertain_inputs: + dL_dpsi2 = beta[:, None] * dL_dpsi2_beta[None, :, :] + else: + dL_dpsi1 += 2.*np.dot(dL_dpsi2_beta, (psi1 * beta).T).T + dL_dpsi2 = None + else: + dL_dpsi2 = beta * dL_dpsi2_beta + if not uncertain_inputs: + # subsume back into psi1 (==Kmn) + dL_dpsi1 += 2.*np.dot(psi1, dL_dpsi2) + dL_dpsi2 = None + return dL_dpsi0, dL_dpsi1, dL_dpsi2 + + +def _compute_dL_dR(likelihood, het_noise, uncertain_inputs, LB, _LBi_Lmi_psi1Vf, DBi_plus_BiPBi, Lm, A, psi0, psi1, beta, data_fit, num_data, output_dim, trYYT, Y, VVT_factr=None): + # the partial derivative vector for the likelihood + if likelihood.size == 0: + # save computation here. + dL_dR = None + elif het_noise: + if uncertain_inputs: + raise NotImplementedError, "heteroscedatic derivates with uncertain inputs not implemented" + else: + #from ...util.linalg import chol_inv + #LBi = chol_inv(LB) + LBi, _ = dtrtrs(LB,np.eye(LB.shape[0])) + + Lmi_psi1, nil = dtrtrs(Lm, psi1.T, lower=1, trans=0) + _LBi_Lmi_psi1, _ = dtrtrs(LB, Lmi_psi1, lower=1, trans=0) + dL_dR = -0.5 * beta + 0.5 * VVT_factr**2 + dL_dR += 0.5 * output_dim * (psi0 - np.sum(Lmi_psi1**2,0))[:,None] * beta**2 + + dL_dR += 0.5*np.sum(mdot(LBi.T,LBi,Lmi_psi1)*Lmi_psi1,0)[:,None]*beta**2 + + dL_dR += -np.dot(_LBi_Lmi_psi1Vf.T,_LBi_Lmi_psi1).T * Y * beta**2 + dL_dR += 0.5*np.dot(_LBi_Lmi_psi1Vf.T,_LBi_Lmi_psi1).T**2 * beta**2 + else: + # likelihood is not heteroscedatic + dL_dR = -0.5 * num_data * output_dim * beta + 0.5 * trYYT * beta ** 2 + dL_dR += 0.5 * output_dim * (psi0.sum() * beta ** 2 - np.trace(A) * beta) + dL_dR += beta * (0.5 * np.sum(A * DBi_plus_BiPBi) - data_fit) + return dL_dR + +def _compute_log_marginal_likelihood(likelihood, num_data, output_dim, beta, het_noise, psi0, A, LB, trYYT, data_fit, Y): + #compute log marginal likelihood + if het_noise: + lik_1 = -0.5 * num_data * output_dim * np.log(2. * np.pi) + 0.5 * output_dim * np.sum(np.log(beta)) - 0.5 * np.sum(beta.ravel() * np.square(Y).sum(axis=-1)) + lik_2 = -0.5 * output_dim * (np.sum(beta.flatten() * psi0) - np.trace(A)) + else: + lik_1 = -0.5 * num_data * output_dim * (np.log(2. * np.pi) - np.log(beta)) - 0.5 * beta * trYYT + lik_2 = -0.5 * output_dim * (np.sum(beta * psi0) - np.trace(A)) + lik_3 = -output_dim * (np.sum(np.log(np.diag(LB)))) + lik_4 = 0.5 * data_fit + log_marginal = lik_1 + lik_2 + lik_3 + lik_4 + return log_marginal +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/latent_function_inference/var_dtc_parallel.html b/doc/_build/html/_modules/GPy/inference/latent_function_inference/var_dtc_parallel.html new file mode 100644 index 00000000..a2a22ee3 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/latent_function_inference/var_dtc_parallel.html @@ -0,0 +1,575 @@ + + + + + + + + GPy.inference.latent_function_inference.var_dtc_parallel — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.latent_function_inference.var_dtc_parallel

      +# Copyright (c) 2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from posterior import Posterior
      +from ...util.linalg import jitchol, backsub_both_sides, tdot, dtrtrs, dtrtri,pdinv
      +from ...util import diag
      +from ...core.parameterization.variational import VariationalPosterior
      +import numpy as np
      +from . import LatentFunctionInference
      +log_2_pi = np.log(2*np.pi)
      +
      +try:
      +    from mpi4py import MPI
      +except:
      +    pass
      +
      +
      [docs]class VarDTC_minibatch(LatentFunctionInference): + """ + An object for inference when the likelihood is Gaussian, but we want to do sparse inference. + + The function self.inference returns a Posterior object, which summarizes + the posterior. + + For efficiency, we sometimes work with the cholesky of Y*Y.T. To save repeatedly recomputing this, we cache it. + + """ + const_jitter = 1e-6 + def __init__(self, batchsize=None, limit=1, mpi_comm=None): + + self.batchsize = batchsize + self.mpi_comm = mpi_comm + self.limit = limit + + # Cache functions + from ...util.caching import Cacher + self.get_trYYT = Cacher(self._get_trYYT, limit) + self.get_YYTfactor = Cacher(self._get_YYTfactor, limit) + + self.midRes = {} + self.batch_pos = 0 # the starting position of the current mini-batch + self.Y_speedup = False # Replace Y with the cholesky factor of YY.T, but the computation of posterior object will be skipped. + + def __getstate__(self): + # has to be overridden, as Cacher objects cannot be pickled. + return self.batchsize, self.limit, self.Y_speedup + + def __setstate__(self, state): + # has to be overridden, as Cacher objects cannot be pickled. + self.batchsize, self.limit, self.Y_speedup = state + self.mpi_comm = None + self.midRes = {} + self.batch_pos = 0 + from ...util.caching import Cacher + self.get_trYYT = Cacher(self._get_trYYT, self.limit) + self.get_YYTfactor = Cacher(self._get_YYTfactor, self.limit) + +
      [docs] def set_limit(self, limit): + self.get_trYYT.limit = limit + self.get_YYTfactor.limit = limit +
      + def _get_trYYT(self, Y): + return np.sum(np.square(Y)) + + def _get_YYTfactor(self, Y): + """ + find a matrix L which satisfies LLT = YYT. + + Note that L may have fewer columns than Y. + """ + N, D = Y.shape + if (N>=D): + return Y.view(np.ndarray) + else: + return jitchol(tdot(Y)) + +
      [docs] def gatherPsiStat(self, kern, X, Z, Y, beta, uncertain_inputs): + + het_noise = beta.size > 1 + + assert beta.size == 1 + + trYYT = self.get_trYYT(Y) + if self.Y_speedup and not het_noise: + Y = self.get_YYTfactor(Y) + + num_inducing = Z.shape[0] + num_data, output_dim = Y.shape + batchsize = num_data if self.batchsize is None else self.batchsize + + psi2_full = np.zeros((num_inducing,num_inducing)) # MxM + psi1Y_full = np.zeros((output_dim,num_inducing)) # DxM + psi0_full = 0. + YRY_full = 0. + + for n_start in xrange(0,num_data,batchsize): + n_end = min(batchsize+n_start, num_data) + if batchsize==num_data: + Y_slice = Y + X_slice = X + else: + Y_slice = Y[n_start:n_end] + X_slice = X[n_start:n_end] + + if het_noise: + b = beta[n_start] + YRY_full += np.inner(Y_slice, Y_slice)*b + else: + b = beta + + if uncertain_inputs: + psi0 = kern.psi0(Z, X_slice) + psi1 = kern.psi1(Z, X_slice) + psi2_full += kern.psi2(Z, X_slice)*b + else: + psi0 = kern.Kdiag(X_slice) + psi1 = kern.K(X_slice, Z) + psi2_full += np.dot(psi1.T,psi1)*b + + psi0_full += psi0.sum()*b + psi1Y_full += np.dot(Y_slice.T,psi1)*b # DxM + + if not het_noise: + YRY_full = trYYT*beta + + if self.mpi_comm != None: + psi0_all = np.array(psi0_full) + psi1Y_all = psi1Y_full.copy() + psi2_all = psi2_full.copy() + YRY_all = np.array(YRY_full) + self.mpi_comm.Allreduce([psi0_full, MPI.DOUBLE], [psi0_all, MPI.DOUBLE]) + self.mpi_comm.Allreduce([psi1Y_full, MPI.DOUBLE], [psi1Y_all, MPI.DOUBLE]) + self.mpi_comm.Allreduce([psi2_full, MPI.DOUBLE], [psi2_all, MPI.DOUBLE]) + self.mpi_comm.Allreduce([YRY_full, MPI.DOUBLE], [YRY_all, MPI.DOUBLE]) + return psi0_all, psi1Y_all, psi2_all, YRY_all + + return psi0_full, psi1Y_full, psi2_full, YRY_full +
      +
      [docs] def inference_likelihood(self, kern, X, Z, likelihood, Y): + """ + The first phase of inference: + Compute: log-likelihood, dL_dKmm + + Cached intermediate results: Kmm, KmmInv, + """ + + num_data, output_dim = Y.shape + input_dim = Z.shape[0] + if self.mpi_comm != None: + num_data_all = np.array(num_data,dtype=np.int32) + self.mpi_comm.Allreduce([np.int32(num_data), MPI.INT], [num_data_all, MPI.INT]) + num_data = num_data_all + + if isinstance(X, VariationalPosterior): + uncertain_inputs = True + else: + uncertain_inputs = False + + #see whether we've got a different noise variance for each datum + beta = 1./np.fmax(likelihood.variance, 1e-6) + het_noise = beta.size > 1 + if het_noise: + self.batchsize = 1 + + psi0_full, psi1Y_full, psi2_full, YRY_full = self.gatherPsiStat(kern, X, Z, Y, beta, uncertain_inputs) + + #====================================================================== + # Compute Common Components + #====================================================================== + + Kmm = kern.K(Z).copy() + diag.add(Kmm, self.const_jitter) + Lm = jitchol(Kmm, maxtries=100) + + LmInvPsi2LmInvT = backsub_both_sides(Lm,psi2_full,transpose='right') + Lambda = np.eye(Kmm.shape[0])+LmInvPsi2LmInvT + LL = jitchol(Lambda, maxtries=100) + logdet_L = 2.*np.sum(np.log(np.diag(LL))) + b = dtrtrs(LL,dtrtrs(Lm,psi1Y_full.T)[0])[0] + bbt = np.square(b).sum() + v = dtrtrs(Lm,dtrtrs(LL,b,trans=1)[0],trans=1)[0] + + tmp = -backsub_both_sides(LL, tdot(b)+output_dim*np.eye(input_dim), transpose='left') + dL_dpsi2R = backsub_both_sides(Lm, tmp+output_dim*np.eye(input_dim), transpose='left')/2. + + # Cache intermediate results + self.midRes['dL_dpsi2R'] = dL_dpsi2R + self.midRes['v'] = v + + #====================================================================== + # Compute log-likelihood + #====================================================================== + if het_noise: + logL_R = -np.log(beta).sum() + else: + logL_R = -num_data*np.log(beta) + logL = -(output_dim*(num_data*log_2_pi+logL_R+psi0_full-np.trace(LmInvPsi2LmInvT))+YRY_full-bbt)/2.-output_dim*logdet_L/2. + + #====================================================================== + # Compute dL_dKmm + #====================================================================== + + dL_dKmm = dL_dpsi2R - output_dim*backsub_both_sides(Lm, LmInvPsi2LmInvT, transpose='left')/2. + + #====================================================================== + # Compute the Posterior distribution of inducing points p(u|Y) + #====================================================================== + + if not self.Y_speedup or het_noise: + wd_inv = backsub_both_sides(Lm, np.eye(input_dim)- backsub_both_sides(LL, np.identity(input_dim), transpose='left'), transpose='left') + post = Posterior(woodbury_inv=wd_inv, woodbury_vector=v, K=Kmm, mean=None, cov=None, K_chol=Lm) + else: + post = None + + #====================================================================== + # Compute dL_dthetaL for uncertian input and non-heter noise + #====================================================================== + + if not het_noise: + dL_dthetaL = (YRY_full*beta + beta*output_dim*psi0_full - num_data*output_dim*beta)/2. - beta*(dL_dpsi2R*psi2_full).sum() - beta*(v.T*psi1Y_full).sum() + self.midRes['dL_dthetaL'] = dL_dthetaL + + return logL, dL_dKmm, post +
      +
      [docs] def inference_minibatch(self, kern, X, Z, likelihood, Y): + """ + The second phase of inference: Computing the derivatives over a minibatch of Y + Compute: dL_dpsi0, dL_dpsi1, dL_dpsi2, dL_dthetaL + return a flag showing whether it reached the end of Y (isEnd) + """ + + num_data, output_dim = Y.shape + + if isinstance(X, VariationalPosterior): + uncertain_inputs = True + else: + uncertain_inputs = False + + #see whether we've got a different noise variance for each datum + beta = 1./np.fmax(likelihood.variance, 1e-6) + het_noise = beta.size > 1 + # VVT_factor is a matrix such that tdot(VVT_factor) = VVT...this is for efficiency! + #self.YYTfactor = beta*self.get_YYTfactor(Y) + if self.Y_speedup and not het_noise: + YYT_factor = self.get_YYTfactor(Y) + else: + YYT_factor = Y + + n_start = self.batch_pos + batchsize = num_data if self.batchsize is None else self.batchsize + n_end = min(batchsize+n_start, num_data) + if n_end==num_data: + isEnd = True + self.batch_pos = 0 + else: + isEnd = False + self.batch_pos = n_end + + if batchsize==num_data: + Y_slice = YYT_factor + X_slice =X + else: + Y_slice = YYT_factor[n_start:n_end] + X_slice = X[n_start:n_end] + + if not uncertain_inputs: + psi0 = kern.Kdiag(X_slice) + psi1 = kern.K(X_slice, Z) + psi2 = None + betapsi1 = np.einsum('n,nm->nm',beta,psi1) + elif het_noise: + psi0 = kern.psi0(Z, X_slice) + psi1 = kern.psi1(Z, X_slice) + psi2 = kern.psi2(Z, X_slice) + betapsi1 = np.einsum('n,nm->nm',beta,psi1) + + if het_noise: + beta = beta[n_start] # assuming batchsize==1 + + betaY = beta*Y_slice + + #====================================================================== + # Load Intermediate Results + #====================================================================== + + dL_dpsi2R = self.midRes['dL_dpsi2R'] + v = self.midRes['v'] + + #====================================================================== + # Compute dL_dpsi + #====================================================================== + + dL_dpsi0 = -output_dim * (beta * np.ones((n_end-n_start,)))/2. + + dL_dpsi1 = np.dot(betaY,v.T) + + if uncertain_inputs: + dL_dpsi2 = beta* dL_dpsi2R + else: + dL_dpsi1 += np.dot(betapsi1,dL_dpsi2R)*2. + dL_dpsi2 = None + + #====================================================================== + # Compute dL_dthetaL + #====================================================================== + + if het_noise: + if uncertain_inputs: + psiR = np.einsum('mo,mo->',dL_dpsi2R,psi2) + else: + psiR = np.einsum('nm,no,mo->',psi1,psi1,dL_dpsi2R) + + dL_dthetaL = ((np.square(betaY)).sum(axis=-1) + np.square(beta)*(output_dim*psi0)-output_dim*beta)/2. - np.square(beta)*psiR- (betaY*np.dot(betapsi1,v)).sum(axis=-1) + else: + if isEnd: + dL_dthetaL = self.midRes['dL_dthetaL'] + else: + dL_dthetaL = 0. + + if uncertain_inputs: + grad_dict = {'dL_dpsi0':dL_dpsi0, + 'dL_dpsi1':dL_dpsi1, + 'dL_dpsi2':dL_dpsi2, + 'dL_dthetaL':dL_dthetaL} + else: + grad_dict = {'dL_dKdiag':dL_dpsi0, + 'dL_dKnm':dL_dpsi1, + 'dL_dthetaL':dL_dthetaL} + + return isEnd, (n_start,n_end), grad_dict + +
      +
      [docs]def update_gradients(model, mpi_comm=None): + if mpi_comm == None: + Y = model.Y + X = model.X + else: + Y = model.Y_local + X = model.X[model.N_range[0]:model.N_range[1]] + + model._log_marginal_likelihood, dL_dKmm, model.posterior = model.inference_method.inference_likelihood(model.kern, X, model.Z, model.likelihood, Y) + + het_noise = model.likelihood.variance.size > 1 + + if het_noise: + dL_dthetaL = np.empty((model.Y.shape[0],)) + else: + dL_dthetaL = np.float64(0.) + + kern_grad = model.kern.gradient.copy() + kern_grad[:] = 0. + model.Z.gradient = 0. + + isEnd = False + while not isEnd: + isEnd, n_range, grad_dict = model.inference_method.inference_minibatch(model.kern, X, model.Z, model.likelihood, Y) + if isinstance(model.X, VariationalPosterior): + if (n_range[1]-n_range[0])==X.shape[0]: + X_slice = X + elif mpi_comm ==None: + X_slice = model.X[n_range[0]:n_range[1]] + else: + X_slice = model.X[model.N_range[0]+n_range[0]:model.N_range[0]+n_range[1]] + + #gradients w.r.t. kernel + model.kern.update_gradients_expectations(variational_posterior=X_slice, Z=model.Z, dL_dpsi0=grad_dict['dL_dpsi0'], dL_dpsi1=grad_dict['dL_dpsi1'], dL_dpsi2=grad_dict['dL_dpsi2']) + kern_grad += model.kern.gradient + + #gradients w.r.t. Z + model.Z.gradient += model.kern.gradients_Z_expectations( + dL_dpsi0=grad_dict['dL_dpsi0'], dL_dpsi1=grad_dict['dL_dpsi1'], dL_dpsi2=grad_dict['dL_dpsi2'], Z=model.Z, variational_posterior=X_slice) + + #gradients w.r.t. posterior parameters of X + X_grad = model.kern.gradients_qX_expectations(variational_posterior=X_slice, Z=model.Z, dL_dpsi0=grad_dict['dL_dpsi0'], dL_dpsi1=grad_dict['dL_dpsi1'], dL_dpsi2=grad_dict['dL_dpsi2']) + model.set_X_gradients(X_slice, X_grad) + + if het_noise: + dL_dthetaL[n_range[0]:n_range[1]] = grad_dict['dL_dthetaL'] + else: + dL_dthetaL += grad_dict['dL_dthetaL'] + + # Gather the gradients from multiple MPI nodes + if mpi_comm != None: + if het_noise: + raise "het_noise not implemented!" + kern_grad_all = kern_grad.copy() + Z_grad_all = model.Z.gradient.copy() + mpi_comm.Allreduce([kern_grad, MPI.DOUBLE], [kern_grad_all, MPI.DOUBLE]) + mpi_comm.Allreduce([model.Z.gradient, MPI.DOUBLE], [Z_grad_all, MPI.DOUBLE]) + kern_grad = kern_grad_all + model.Z.gradient = Z_grad_all + + #gradients w.r.t. kernel + model.kern.update_gradients_full(dL_dKmm, model.Z, None) + model.kern.gradient += kern_grad + + #gradients w.r.t. Z + model.Z.gradient += model.kern.gradients_X(dL_dKmm, model.Z) + + # Update Log-likelihood + KL_div = model.variational_prior.KL_divergence(X) + # update for the KL divergence + model.variational_prior.update_gradients_KL(X) + + if mpi_comm != None: + KL_div_all = np.array(KL_div) + mpi_comm.Allreduce([np.float64(KL_div), MPI.DOUBLE], [KL_div_all, MPI.DOUBLE]) + KL_div = KL_div_all + [mpi_comm.Allgatherv([pp.copy(), MPI.DOUBLE], [pa, (model.N_list*pa.shape[-1], None), MPI.DOUBLE]) for pp,pa in zip(model.get_X_gradients(X),model.get_X_gradients(model.X))] +# from ...models import SSGPLVM +# if isinstance(model, SSGPLVM): +# grad_pi = np.array(model.variational_prior.pi.gradient) +# mpi_comm.Allreduce([grad_pi.copy(), MPI.DOUBLE], [model.variational_prior.pi.gradient, MPI.DOUBLE]) + model._log_marginal_likelihood -= KL_div + + # dL_dthetaL + model.likelihood.update_gradients(dL_dthetaL) +
      +
      [docs]def update_gradients_sparsegp(model, mpi_comm=None): + if mpi_comm == None: + Y = model.Y + X = model.X + else: + Y = model.Y_local + X = model.X[model.N_range[0]:model.N_range[1]] + + model._log_marginal_likelihood, dL_dKmm, model.posterior = model.inference_method.inference_likelihood(model.kern, X, model.Z, model.likelihood, Y) + + het_noise = model.likelihood.variance.size > 1 + + if het_noise: + dL_dthetaL = np.empty((model.Y.shape[0],)) + else: + dL_dthetaL = np.float64(0.) + + kern_grad = model.kern.gradient.copy() + kern_grad[:] = 0. + model.Z.gradient = 0. + + isEnd = False + while not isEnd: + isEnd, n_range, grad_dict = model.inference_method.inference_minibatch(model.kern, X, model.Z, model.likelihood, Y) + + if (n_range[1]-n_range[0])==X.shape[0]: + X_slice = X + elif mpi_comm ==None: + X_slice = model.X[n_range[0]:n_range[1]] + else: + X_slice = model.X[model.N_range[0]+n_range[0]:model.N_range[0]+n_range[1]] + + model.kern.update_gradients_diag(grad_dict['dL_dKdiag'], X_slice) + kern_grad += model.kern.gradient + model.kern.update_gradients_full(grad_dict['dL_dKnm'], X_slice, model.Z) + kern_grad += model.kern.gradient + + model.Z.gradient += model.kern.gradients_X(grad_dict['dL_dKnm'].T, model.Z, X_slice) + + if het_noise: + dL_dthetaL[n_range[0]:n_range[1]] = grad_dict['dL_dthetaL'] + else: + dL_dthetaL += grad_dict['dL_dthetaL'] + + # Gather the gradients from multiple MPI nodes + if mpi_comm != None: + if het_noise: + raise "het_noise not implemented!" + kern_grad_all = kern_grad.copy() + Z_grad_all = model.Z.gradient.copy() + mpi_comm.Allreduce([kern_grad, MPI.DOUBLE], [kern_grad_all, MPI.DOUBLE]) + mpi_comm.Allreduce([model.Z.gradient, MPI.DOUBLE], [Z_grad_all, MPI.DOUBLE]) + kern_grad = kern_grad_all + model.Z.gradient = Z_grad_all + + model.kern.update_gradients_full(dL_dKmm, model.Z, None) + model.kern.gradient += kern_grad + + model.Z.gradient += model.kern.gradients_X(dL_dKmm, model.Z) + + # dL_dthetaL + model.likelihood.update_gradients(dL_dthetaL)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/mcmc/hmc.html b/doc/_build/html/_modules/GPy/inference/mcmc/hmc.html new file mode 100644 index 00000000..a5cc343b --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/mcmc/hmc.html @@ -0,0 +1,267 @@ + + + + + + + + GPy.inference.mcmc.hmc — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.mcmc.hmc

      +# ## Copyright (c) 2014, Zhenwen Dai
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +
      +
      +
      [docs]class HMC: + """ + An implementation of Hybrid Monte Carlo (HMC) for GPy models + + Initialize an object for HMC sampling. Note that the status of the model (model parameters) will be changed during sampling. + + :param model: the GPy model that will be sampled + :type model: GPy.core.Model + :param M: the mass matrix (an identity matrix by default) + :type M: numpy.ndarray + :param stepsize: the step size for HMC sampling + :type stepsize: float + """ + def __init__(self, model, M=None,stepsize=1e-1): + self.model = model + self.stepsize = stepsize + self.p = np.empty_like(model.optimizer_array.copy()) + if M is None: + self.M = np.eye(self.p.size) + else: + self.M = M + self.Minv = np.linalg.inv(self.M) + +
      [docs] def sample(self, num_samples=1000, hmc_iters=20): + """ + Sample the (unfixed) model parameters. + + :param num_samples: the number of samples to draw (1000 by default) + :type num_samples: int + :param hmc_iters: the number of leap-frog iterations (20 by default) + :type hmc_iters: int + :return: the list of parameters samples with the size N x P (N - the number of samples, P - the number of parameters to sample) + :rtype: numpy.ndarray + """ + params = np.empty((num_samples,self.p.size)) + for i in xrange(num_samples): + self.p[:] = np.random.multivariate_normal(np.zeros(self.p.size),self.M) + H_old = self._computeH() + theta_old = self.model.optimizer_array.copy() + params[i] = self.model.unfixed_param_array + #Matropolis + self._update(hmc_iters) + H_new = self._computeH() + + if H_old>H_new: + k = 1. + else: + k = np.exp(H_old-H_new) + if np.random.rand()<k: + params[i] = self.model.unfixed_param_array + else: + self.model.optimizer_array = theta_old + return params +
      + def _update(self, hmc_iters): + for i in xrange(hmc_iters): + self.p[:] += -self.stepsize/2.*self.model._transform_gradients(self.model.objective_function_gradients()) + self.model.optimizer_array = self.model.optimizer_array + self.stepsize*np.dot(self.Minv, self.p) + self.p[:] += -self.stepsize/2.*self.model._transform_gradients(self.model.objective_function_gradients()) + + def _computeH(self,): + return self.model.objective_function()+self.p.size*np.log(2*np.pi)/2.+np.log(np.linalg.det(self.M))/2.+np.dot(self.p, np.dot(self.Minv,self.p[:,None]))/2. +
      +
      [docs]class HMC_shortcut: + def __init__(self,model,M=None,stepsize_range=[1e-6, 1e-1],groupsize=5, Hstd_th=[1e-5, 3.]): + self.model = model + self.stepsize_range = np.log(stepsize_range) + self.p = np.empty_like(model.optimizer_array.copy()) + self.groupsize = groupsize + self.Hstd_th = Hstd_th + if M is None: + self.M = np.eye(self.p.size) + else: + self.M = M + self.Minv = np.linalg.inv(self.M) + +
      [docs] def sample(self, m_iters=1000, hmc_iters=20): + params = np.empty((m_iters,self.p.size)) + for i in xrange(m_iters): + # sample a stepsize from the uniform distribution + stepsize = np.exp(np.random.rand()*(self.stepsize_range[1]-self.stepsize_range[0])+self.stepsize_range[0]) + self.p[:] = np.random.multivariate_normal(np.zeros(self.p.size),self.M) + H_old = self._computeH() + params[i] = self.model.unfixed_param_array + theta_old = self.model.optimizer_array.copy() + #Matropolis + self._update(hmc_iters, stepsize) + H_new = self._computeH() + + if H_old>H_new: + k = 1. + else: + k = np.exp(H_old-H_new) + if np.random.rand()<k: + params[i] = self.model.unfixed_param_array + else: + self.model.optimizer_array = theta_old + return params +
      + def _update(self, hmc_iters, stepsize): + theta_buf = np.empty((2*hmc_iters+1,self.model.optimizer_array.size)) + p_buf = np.empty((2*hmc_iters+1,self.p.size)) + H_buf = np.empty((2*hmc_iters+1,)) + # Set initial position + theta_buf[hmc_iters] = self.model.optimizer_array + p_buf[hmc_iters] = self.p + H_buf[hmc_iters] = self._computeH() + + reversal = [] + pos = 1 + i=0 + while i<hmc_iters: + self.p[:] += -stepsize/2.*self.model._transform_gradients(self.model.objective_function_gradients()) + self.model.optimizer_array = self.model.optimizer_array + stepsize*np.dot(self.Minv, self.p) + self.p[:] += -stepsize/2.*self.model._transform_gradients(self.model.objective_function_gradients()) + + theta_buf[hmc_iters+pos] = self.model.optimizer_array + p_buf[hmc_iters+pos] = self.p + H_buf[hmc_iters+pos] = self._computeH() + i+=1 + + if i<self.groupsize: + pos += 1 + continue + else: + if len(reversal)==0: + Hlist = range(hmc_iters+pos,hmc_iters+pos-self.groupsize,-1) + if self._testH(H_buf[Hlist]): + pos += 1 + else: + # Reverse the trajectory for the 1st time + reversal.append(pos) + if hmc_iters-i>pos: + pos = -1 + i += pos + self.model.optimizer_array = theta_buf[hmc_iters] + self.p[:] = -p_buf[hmc_iters] + else: + pos_new = pos-hmc_iters+i + self.model.optimizer_array = theta_buf[hmc_iters+pos_new] + self.p[:] = -p_buf[hmc_iters+pos_new] + break + else: + Hlist = range(hmc_iters+pos,hmc_iters+pos+self.groupsize) + + if self._testH(H_buf[Hlist]): + pos += -1 + else: + # Reverse the trajectory for the 2nd time + r = (hmc_iters - i)%((reversal[0]-pos)*2) + if r>(reversal[0]-pos): + pos_new = 2*reversal[0] - r - pos + else: + pos_new = pos + r + self.model.optimizer_array = theta_buf[hmc_iters+pos_new] + self.p[:] = p_buf[hmc_iters+pos_new] # the sign of momentum might be wrong! + break + + def _testH(self, Hlist): + Hstd = np.std(Hlist) + if Hstd<self.Hstd_th[0] or Hstd>self.Hstd_th[1]: + return False + else: + return True + + def _computeH(self,): + return self.model.objective_function()+self.p.size*np.log(2*np.pi)/2.+np.log(np.linalg.det(self.M))/2.+np.dot(self.p, np.dot(self.Minv,self.p[:,None]))/2. +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/mcmc/samplers.html b/doc/_build/html/_modules/GPy/inference/mcmc/samplers.html new file mode 100644 index 00000000..2d0f6850 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/mcmc/samplers.html @@ -0,0 +1,175 @@ + + + + + + + + GPy.inference.mcmc.samplers — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.mcmc.samplers

      +# ## Copyright (c) 2014, Zhenwen Dai
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from scipy import linalg, optimize
      +import Tango
      +import sys
      +import re
      +import numdifftools as ndt
      +import pdb
      +import cPickle
      +
      +
      +
      [docs]class Metropolis_Hastings: + def __init__(self,model,cov=None): + """Metropolis Hastings, with tunings according to Gelman et al. """ + self.model = model + current = self.model._get_params_transformed() + self.D = current.size + self.chains = [] + if cov is None: + self.cov = model.Laplace_covariance() + else: + self.cov = cov + self.scale = 2.4/np.sqrt(self.D) + self.new_chain(current) + +
      [docs] def new_chain(self, start=None): + self.chains.append([]) + if start is None: + self.model.randomize() + else: + self.model._set_params_transformed(start) + + +
      +
      [docs] def sample(self, Ntotal, Nburn, Nthin, tune=True, tune_throughout=False, tune_interval=400): + current = self.model._get_params_transformed() + fcurrent = self.model.log_likelihood() + self.model.log_prior() + accepted = np.zeros(Ntotal,dtype=np.bool) + for it in range(Ntotal): + print "sample %d of %d\r"%(it,Ntotal), + sys.stdout.flush() + prop = np.random.multivariate_normal(current, self.cov*self.scale*self.scale) + self.model._set_params_transformed(prop) + fprop = self.model.log_likelihood() + self.model.log_prior() + + if fprop>fcurrent:#sample accepted, going 'uphill' + accepted[it] = True + current = prop + fcurrent = fprop + else: + u = np.random.rand() + if np.exp(fprop-fcurrent)>u:#sample accepted downhill + accepted[it] = True + current = prop + fcurrent = fprop + + #store current value + if (it > Nburn) & ((it%Nthin)==0): + self.chains[-1].append(current) + + #tuning! + if it & ((it%tune_interval)==0) & tune & ((it<Nburn) | (tune_throughout)): + pc = np.mean(accepted[it-tune_interval:it]) + self.cov = np.cov(np.vstack(self.chains[-1][-tune_interval:]).T) + if pc > .25: + self.scale *= 1.1 + if pc < .15: + self.scale /= 1.1 +
      +
      [docs] def predict(self,function,args): + """Make a prediction for the function, to which we will pass the additional arguments""" + param = self.model._get_params() + fs = [] + for p in self.chain: + self.model._set_params(p) + fs.append(function(*args)) + self.model._set_params(param)# reset model to starting state + return fs
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/optimization/conjugate_gradient_descent.html b/doc/_build/html/_modules/GPy/inference/optimization/conjugate_gradient_descent.html new file mode 100644 index 00000000..276b7fea --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/optimization/conjugate_gradient_descent.html @@ -0,0 +1,378 @@ + + + + + + + + GPy.inference.optimization.conjugate_gradient_descent — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.optimization.conjugate_gradient_descent

      +# Copyright (c) 2012-2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from gradient_descent_update_rules import FletcherReeves, \
      +    PolakRibiere
      +from Queue import Empty
      +from multiprocessing import Value
      +from multiprocessing.queues import Queue
      +from multiprocessing.synchronize import Event
      +from scipy.optimize.linesearch import line_search_wolfe1, line_search_wolfe2
      +from threading import Thread
      +import numpy
      +import sys
      +import time
      +
      +RUNNING = "running"
      +CONVERGED = "converged"
      +MAXITER = "maximum number of iterations reached"
      +MAX_F_EVAL = "maximum number of function calls reached"
      +LINE_SEARCH = "line search failed"
      +KBINTERRUPT = "interrupted"
      +
      +class _Async_Optimization(Thread):
      +
      +    def __init__(self, f, df, x0, update_rule, runsignal, SENTINEL,
      +                 report_every=10, messages=0, maxiter=5e3, max_f_eval=15e3,
      +                 gtol=1e-6, outqueue=None, *args, **kw):
      +        """
      +        Helper Process class for async optimization
      +        
      +        f_call and df_call are Multiprocessing Values, for synchronized assignment
      +        """
      +        self.f_call = Value('i', 0)
      +        self.df_call = Value('i', 0)
      +        self.f = self.f_wrapper(f, self.f_call)
      +        self.df = self.f_wrapper(df, self.df_call)
      +        self.x0 = x0
      +        self.update_rule = update_rule
      +        self.report_every = report_every
      +        self.messages = messages
      +        self.maxiter = maxiter
      +        self.max_f_eval = max_f_eval
      +        self.gtol = gtol
      +        self.SENTINEL = SENTINEL
      +        self.runsignal = runsignal
      +#         self.parent = parent
      +#         self.result = None
      +        self.outq = outqueue
      +        super(_Async_Optimization, self).__init__(target=self.run,
      +                                            name="CG Optimization",
      +                                            *args, **kw)
      +
      +#     def __enter__(self):
      +#         return self
      +#
      +#     def __exit__(self, type, value, traceback):
      +#         return isinstance(value, TypeError)
      +
      +    def f_wrapper(self, f, counter):
      +        def f_w(*a, **kw):
      +            counter.value += 1
      +            return f(*a, **kw)
      +        return f_w
      +
      +    def callback(self, *a):
      +        if self.outq is not None:
      +            self.outq.put(a)
      +#         self.parent and self.parent.callback(*a, **kw)
      +        pass
      +        # print "callback done"
      +
      +    def callback_return(self, *a):
      +        self.callback(*a)
      +        if self.outq is not None:
      +            self.outq.put(self.SENTINEL)
      +        if self.messages:
      +            print ""
      +        self.runsignal.clear()
      +
      +    def run(self, *args, **kwargs):
      +        raise NotImplementedError("Overwrite this with optimization (for async use)")
      +        pass
      +
      +class _CGDAsync(_Async_Optimization):
      +
      +    def reset(self, xi, *a, **kw):
      +        gi = -self.df(xi, *a, **kw)
      +        si = gi
      +        ur = self.update_rule(gi)
      +        return gi, ur, si
      +
      +    def run(self, *a, **kw):
      +        status = RUNNING
      +
      +        fi = self.f(self.x0)
      +        fi_old = fi + 5000
      +
      +        gi, ur, si = self.reset(self.x0, *a, **kw)
      +        xi = self.x0
      +        xi_old = numpy.nan
      +        it = 0
      +
      +        while it < self.maxiter:
      +            if not self.runsignal.is_set():
      +                break
      +
      +            if self.f_call.value > self.max_f_eval:
      +                status = MAX_F_EVAL
      +
      +            gi = -self.df(xi, *a, **kw)
      +            if numpy.dot(gi.T, gi) <= self.gtol:
      +                status = CONVERGED
      +                break
      +            if numpy.isnan(numpy.dot(gi.T, gi)):
      +                if numpy.any(numpy.isnan(xi_old)):
      +                    status = CONVERGED
      +                    break
      +                self.reset(xi_old)
      +
      +            gammai = ur(gi)
      +            if gammai < 1e-6 or it % xi.shape[0] == 0:
      +                gi, ur, si = self.reset(xi, *a, **kw)
      +            si = gi + gammai * si
      +            alphai, _, _, fi2, fi_old2, gfi = line_search_wolfe1(self.f,
      +                                                                 self.df,
      +                                                                 xi,
      +                                                                 si, gi,
      +                                                                 fi, fi_old)
      +            if alphai is None:
      +                alphai, _, _, fi2, fi_old2, gfi = \
      +                         line_search_wolfe2(self.f, self.df,
      +                                            xi, si, gi,
      +                                            fi, fi_old)
      +                if alphai is None:
      +                    # This line search also failed to find a better solution.
      +                    status = LINE_SEARCH
      +                    break
      +            if fi2 < fi:
      +                fi, fi_old = fi2, fi_old2
      +            if gfi is not None:
      +                gi = gfi
      +
      +            if numpy.isnan(fi) or fi_old < fi:
      +                gi, ur, si = self.reset(xi, *a, **kw)
      +
      +            else:
      +                xi += numpy.dot(alphai, si)
      +                if self.messages:
      +                    sys.stdout.write("\r")
      +                    sys.stdout.flush()
      +                    sys.stdout.write("iteration: {0:> 6g}  f:{1:> 12e}  |g|:{2:> 12e}".format(it, fi, numpy.dot(gi.T, gi)))
      +
      +            if it % self.report_every == 0:
      +                self.callback(xi, fi, gi, it, self.f_call.value, self.df_call.value, status)
      +            it += 1
      +        else:
      +            status = MAXITER
      +        self.callback_return(xi, fi, gi, it, self.f_call.value, self.df_call.value, status)
      +        self.result = [xi, fi, gi, it, self.f_call.value, self.df_call.value, status]
      +
      +
      [docs]class Async_Optimize(object): + callback = lambda *x: None + runsignal = Event() + SENTINEL = "SENTINEL" + +
      [docs] def async_callback_collect(self, q): + while self.runsignal.is_set(): + try: + for ret in iter(lambda: q.get(timeout=1), self.SENTINEL): + self.callback(*ret) + self.runsignal.clear() + except Empty: + pass +
      +
      [docs] def opt_async(self, f, df, x0, callback, update_rule=PolakRibiere, + messages=0, maxiter=5e3, max_f_eval=15e3, gtol=1e-6, + report_every=10, *args, **kwargs): + self.runsignal.set() + c = None + outqueue = None + if callback: + outqueue = Queue() + self.callback = callback + c = Thread(target=self.async_callback_collect, args=(outqueue,)) + c.start() + p = _CGDAsync(f, df, x0, update_rule, self.runsignal, self.SENTINEL, + report_every=report_every, messages=messages, maxiter=maxiter, + max_f_eval=max_f_eval, gtol=gtol, outqueue=outqueue, *args, **kwargs) + p.start() + return p, c +
      +
      [docs] def opt(self, f, df, x0, callback=None, update_rule=FletcherReeves, + messages=0, maxiter=5e3, max_f_eval=15e3, gtol=1e-6, + report_every=10, *args, **kwargs): + p, c = self.opt_async(f, df, x0, callback, update_rule, messages, + maxiter, max_f_eval, gtol, + report_every, *args, **kwargs) + while self.runsignal.is_set(): + try: + p.join(1) + if c: c.join(1) + except KeyboardInterrupt: + # print "^C" + self.runsignal.clear() + p.join() + if c: c.join() + if c and c.is_alive(): +# self.runsignal.set() +# while self.runsignal.is_set(): +# try: +# c.join(.1) +# except KeyboardInterrupt: +# # print "^C" +# self.runsignal.clear() +# c.join() + print "WARNING: callback still running, optimisation done!" + return p.result +
      +
      [docs]class CGD(Async_Optimize): + ''' + Conjugate gradient descent algorithm to minimize + function f with gradients df, starting at x0 + with update rule update_rule + + if df returns tuple (grad, natgrad) it will optimize according + to natural gradient rules + ''' + opt_name = "Conjugate Gradient Descent" + +
      [docs] def opt_async(self, *a, **kw): + """ + opt_async(self, f, df, x0, callback, update_rule=FletcherReeves, + messages=0, maxiter=5e3, max_f_eval=15e3, gtol=1e-6, + report_every=10, \*args, \*\*kwargs) + + callback gets called every `report_every` iterations + + callback(xi, fi, gi, iteration, function_calls, gradient_calls, status_message) + + if df returns tuple (grad, natgrad) it will optimize according + to natural gradient rules + + f, and df will be called with + + f(xi, \*args, \*\*kwargs) + df(xi, \*args, \*\*kwargs) + + **Returns:** + + Started `Process` object, optimizing asynchronously + + **Calls:** + + callback(x_opt, f_opt, g_opt, iteration, function_calls, gradient_calls, status_message) + + at end of optimization! + """ + return super(CGD, self).opt_async(*a, **kw) +
      +
      [docs] def opt(self, *a, **kw): + """ + opt(self, f, df, x0, callback=None, update_rule=FletcherReeves, + messages=0, maxiter=5e3, max_f_eval=15e3, gtol=1e-6, + report_every=10, \*args, \*\*kwargs) + + Minimize f, calling callback every `report_every` iterations with following syntax: + + callback(xi, fi, gi, iteration, function_calls, gradient_calls, status_message) + + if df returns tuple (grad, natgrad) it will optimize according + to natural gradient rules + + f, and df will be called with + + f(xi, \*args, \*\*kwargs) + df(xi, \*args, \*\*kwargs) + + **returns** + + x_opt, f_opt, g_opt, iteration, function_calls, gradient_calls, status_message + + at end of optimization + """ + return super(CGD, self).opt(*a, **kw) +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/optimization/gradient_descent_update_rules.html b/doc/_build/html/_modules/GPy/inference/optimization/gradient_descent_update_rules.html new file mode 100644 index 00000000..ee11770d --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/optimization/gradient_descent_update_rules.html @@ -0,0 +1,145 @@ + + + + + + + + GPy.inference.optimization.gradient_descent_update_rules — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.optimization.gradient_descent_update_rules

      +# Copyright (c) 2012-2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy
      +
      +
      [docs]class GDUpdateRule(): + _gradnat = None + _gradnatold = None + def __init__(self, initgrad, initgradnat=None): + self.grad = initgrad + if initgradnat: + self.gradnat = initgradnat + else: + self.gradnat = initgrad + # self.grad, self.gradnat + def _gamma(self): + raise NotImplemented("""Implement gamma update rule here, + you can use self.grad and self.gradold for parameters, as well as + self.gradnat and self.gradnatold for natural gradients.""") + def __call__(self, grad, gradnat=None, si=None, *args, **kw): + """ + Return gamma for given gradients and optional natural gradients + """ + if not gradnat: + gradnat = grad + self.gradold = self.grad + self.gradnatold = self.gradnat + self.grad = grad + self.gradnat = gradnat + self.si = si + return self._gamma(*args, **kw) +
      +
      [docs]class FletcherReeves(GDUpdateRule): + ''' + Fletcher Reeves update rule for gamma + ''' + def _gamma(self, *a, **kw): + tmp = numpy.dot(self.grad.T, self.gradnat) + if tmp: + return tmp / numpy.dot(self.gradold.T, self.gradnatold) + return tmp +
      +
      [docs]class PolakRibiere(GDUpdateRule): + ''' + Fletcher Reeves update rule for gamma + ''' + def _gamma(self, *a, **kw): + tmp = numpy.dot((self.grad - self.gradold).T, self.gradnat) + if tmp: + return tmp / numpy.dot(self.gradold.T, self.gradnatold) + return tmp
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/optimization/optimization.html b/doc/_build/html/_modules/GPy/inference/optimization/optimization.html new file mode 100644 index 00000000..311a0745 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/optimization/optimization.html @@ -0,0 +1,335 @@ + + + + + + + + GPy.inference.optimization.optimization — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.optimization.optimization

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import datetime as dt
      +from scipy import optimize
      +from warnings import warn
      +
      +try:
      +    import rasmussens_minimize as rasm
      +    rasm_available = True
      +except ImportError:
      +    rasm_available = False
      +from scg import SCG
      +
      +
      [docs]class Optimizer(): + """ + Superclass for all the optimizers. + + :param x_init: initial set of parameters + :param f_fp: function that returns the function AND the gradients at the same time + :param f: function to optimize + :param fp: gradients + :param messages: print messages from the optimizer? + :type messages: (True | False) + :param max_f_eval: maximum number of function evaluations + + :rtype: optimizer object. + + """ + def __init__(self, x_init, messages=False, model=None, max_f_eval=1e4, max_iters=1e3, + ftol=None, gtol=None, xtol=None, bfgs_factor=None): + self.opt_name = None + self.x_init = x_init + self.messages = messages + self.f_opt = None + self.x_opt = None + self.funct_eval = None + self.status = None + self.max_f_eval = int(max_f_eval) + self.max_iters = int(max_iters) + self.bfgs_factor = bfgs_factor + self.trace = None + self.time = "Not available" + self.xtol = xtol + self.gtol = gtol + self.ftol = ftol + self.model = model + +
      [docs] def run(self, **kwargs): + start = dt.datetime.now() + self.opt(**kwargs) + end = dt.datetime.now() + self.time = str(end - start) +
      +
      [docs] def opt(self, f_fp=None, f=None, fp=None): + raise NotImplementedError, "this needs to be implemented to use the optimizer class" +
      +
      [docs] def plot(self): + """ + See GPy.plotting.matplot_dep.inference_plots + """ + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ...plotting.matplot_dep import inference_plots + inference_plots.plot_optimizer(self) + +
      + def __str__(self): + diagnostics = "Optimizer: \t\t\t\t %s\n" % self.opt_name + diagnostics += "f(x_opt): \t\t\t\t %.3f\n" % self.f_opt + diagnostics += "Number of function evaluations: \t %d\n" % self.funct_eval + diagnostics += "Optimization status: \t\t\t %s\n" % self.status + diagnostics += "Time elapsed: \t\t\t\t %s\n" % self.time + return diagnostics +
      +
      [docs]class opt_tnc(Optimizer): + def __init__(self, *args, **kwargs): + Optimizer.__init__(self, *args, **kwargs) + self.opt_name = "TNC (Scipy implementation)" + +
      [docs] def opt(self, f_fp=None, f=None, fp=None): + """ + Run the TNC optimizer + + """ + tnc_rcstrings = ['Local minimum', 'Converged', 'XConverged', 'Maximum number of f evaluations reached', + 'Line search failed', 'Function is constant'] + + assert f_fp != None, "TNC requires f_fp" + + opt_dict = {} + if self.xtol is not None: + opt_dict['xtol'] = self.xtol + if self.ftol is not None: + opt_dict['ftol'] = self.ftol + if self.gtol is not None: + opt_dict['pgtol'] = self.gtol + + opt_result = optimize.fmin_tnc(f_fp, self.x_init, messages=self.messages, + maxfun=self.max_f_eval, **opt_dict) + self.x_opt = opt_result[0] + self.f_opt = f_fp(self.x_opt)[0] + self.funct_eval = opt_result[1] + self.status = tnc_rcstrings[opt_result[2]] +
      +
      [docs]class opt_lbfgsb(Optimizer): + def __init__(self, *args, **kwargs): + Optimizer.__init__(self, *args, **kwargs) + self.opt_name = "L-BFGS-B (Scipy implementation)" + +
      [docs] def opt(self, f_fp=None, f=None, fp=None): + """ + Run the optimizer + + """ + rcstrings = ['Converged', 'Maximum number of f evaluations reached', 'Error'] + + assert f_fp != None, "BFGS requires f_fp" + + if self.messages: + iprint = 1 + else: + iprint = -1 + + opt_dict = {} + if self.xtol is not None: + print "WARNING: l-bfgs-b doesn't have an xtol arg, so I'm going to ignore it" + if self.ftol is not None: + print "WARNING: l-bfgs-b doesn't have an ftol arg, so I'm going to ignore it" + if self.gtol is not None: + opt_dict['pgtol'] = self.gtol + if self.bfgs_factor is not None: + opt_dict['factr'] = self.bfgs_factor + + opt_result = optimize.fmin_l_bfgs_b(f_fp, self.x_init, iprint=iprint, + maxfun=self.max_iters, **opt_dict) + self.x_opt = opt_result[0] + self.f_opt = f_fp(self.x_opt)[0] + self.funct_eval = opt_result[2]['funcalls'] + self.status = rcstrings[opt_result[2]['warnflag']] +
      +
      [docs]class opt_simplex(Optimizer): + def __init__(self, *args, **kwargs): + Optimizer.__init__(self, *args, **kwargs) + self.opt_name = "Nelder-Mead simplex routine (via Scipy)" + +
      [docs] def opt(self, f_fp=None, f=None, fp=None): + """ + The simplex optimizer does not require gradients. + """ + + statuses = ['Converged', 'Maximum number of function evaluations made', 'Maximum number of iterations reached'] + + opt_dict = {} + if self.xtol is not None: + opt_dict['xtol'] = self.xtol + if self.ftol is not None: + opt_dict['ftol'] = self.ftol + if self.gtol is not None: + print "WARNING: simplex doesn't have an gtol arg, so I'm going to ignore it" + + opt_result = optimize.fmin(f, self.x_init, (), disp=self.messages, + maxfun=self.max_f_eval, full_output=True, **opt_dict) + + self.x_opt = opt_result[0] + self.f_opt = opt_result[1] + self.funct_eval = opt_result[3] + self.status = statuses[opt_result[4]] + self.trace = None + +
      +
      [docs]class opt_rasm(Optimizer): + def __init__(self, *args, **kwargs): + Optimizer.__init__(self, *args, **kwargs) + self.opt_name = "Rasmussen's Conjugate Gradient" + +
      [docs] def opt(self, f_fp=None, f=None, fp=None): + """ + Run Rasmussen's Conjugate Gradient optimizer + """ + + assert f_fp != None, "Rasmussen's minimizer requires f_fp" + statuses = ['Converged', 'Line search failed', 'Maximum number of f evaluations reached', + 'NaNs in optimization'] + + opt_dict = {} + if self.xtol is not None: + print "WARNING: minimize doesn't have an xtol arg, so I'm going to ignore it" + if self.ftol is not None: + print "WARNING: minimize doesn't have an ftol arg, so I'm going to ignore it" + if self.gtol is not None: + print "WARNING: minimize doesn't have an gtol arg, so I'm going to ignore it" + + opt_result = rasm.minimize(self.x_init, f_fp, (), messages=self.messages, + maxnumfuneval=self.max_f_eval) + self.x_opt = opt_result[0] + self.f_opt = opt_result[1][-1] + self.funct_eval = opt_result[2] + self.status = statuses[opt_result[3]] + + self.trace = opt_result[1] +
      +
      [docs]class opt_SCG(Optimizer): + def __init__(self, *args, **kwargs): + if 'max_f_eval' in kwargs: + warn("max_f_eval deprecated for SCG optimizer: use max_iters instead!\nIgnoring max_f_eval!", FutureWarning) + Optimizer.__init__(self, *args, **kwargs) + + self.opt_name = "Scaled Conjugate Gradients" + +
      [docs] def opt(self, f_fp=None, f=None, fp=None): + assert not f is None + assert not fp is None + + opt_result = SCG(f, fp, self.x_init, display=self.messages, + maxiters=self.max_iters, + max_f_eval=self.max_f_eval, + xtol=self.xtol, ftol=self.ftol, + gtol=self.gtol) + + self.x_opt = opt_result[0] + self.trace = opt_result[1] + self.f_opt = self.trace[-1] + self.funct_eval = opt_result[2] + self.status = opt_result[3] +
      +
      [docs]def get_optimizer(f_min): + + optimizers = {'fmin_tnc': opt_tnc, + 'simplex': opt_simplex, + 'lbfgsb': opt_lbfgsb, + 'scg': opt_SCG} + + if rasm_available: + optimizers['rasmussen'] = opt_rasm + + for opt_name in optimizers.keys(): + if opt_name.lower().find(f_min.lower()) != -1: + return optimizers[opt_name] + + raise KeyError('No optimizer was found matching the name: %s' % f_min)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/optimization/scg.html b/doc/_build/html/_modules/GPy/inference/optimization/scg.html new file mode 100644 index 00000000..39e5f7c2 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/optimization/scg.html @@ -0,0 +1,285 @@ + + + + + + + + GPy.inference.optimization.scg — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.optimization.scg

      +# Copyright I. Nabney, N.Lawrence and James Hensman (1996 - 2014)
      +
      +# Scaled Conjuagte Gradients, originally in Matlab as part of the Netlab toolbox by I. Nabney, converted to python N. Lawrence and given a pythonic interface by James Hensman
      +
      +#      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
      +#      HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
      +#      EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
      +#      NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      +#      MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      +#      PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
      +#      REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
      +#      DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      +#      EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      +#      (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
      +#      OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      +#      DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      +#      HOWEVER CAUSED AND ON ANY THEORY OF
      +#      LIABILITY, WHETHER IN CONTRACT, STRICT
      +#      LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      +#      OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      +#      OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      +#      POSSIBILITY OF SUCH DAMAGE.
      +
      +
      +import numpy as np
      +import sys
      +
      +
      +
      +
      [docs]def exponents(fnow, current_grad): + exps = [np.abs(np.float(fnow)), current_grad] + return np.sign(exps) * np.log10(exps).astype(int) +
      +
      [docs]def SCG(f, gradf, x, optargs=(), maxiters=500, max_f_eval=np.inf, display=True, xtol=None, ftol=None, gtol=None): + """ + Optimisation through Scaled Conjugate Gradients (SCG) + + f: the objective function + gradf : the gradient function (should return a 1D np.ndarray) + x : the initial condition + + Returns + x the optimal value for x + flog : a list of all the objective values + function_eval number of fn evaluations + status: string describing convergence status + """ + if xtol is None: + xtol = 1e-6 + if ftol is None: + ftol = 1e-6 + if gtol is None: + gtol = 1e-5 + + sigma0 = 1.0e-7 + fold = f(x, *optargs) # Initial function value. + function_eval = 1 + fnow = fold + gradnew = gradf(x, *optargs) # Initial gradient. + #if any(np.isnan(gradnew)): + # raise UnexpectedInfOrNan, "Gradient contribution resulted in a NaN value" + current_grad = np.dot(gradnew, gradnew) + gradold = gradnew.copy() + d = -gradnew # Initial search direction. + success = True # Force calculation of directional derivs. + nsuccess = 0 # nsuccess counts number of successes. + beta = 1.0 # Initial scale parameter. + betamin = 1.0e-15 # Lower bound on scale. + betamax = 1.0e15 # Upper bound on scale. + status = "Not converged" + + flog = [fold] + + iteration = 0 + + len_maxiters = len(str(maxiters)) + if display: + print ' {0:{mi}s} {1:11s} {2:11s} {3:11s}'.format("I", "F", "Scale", "|g|", mi=len_maxiters) + exps = exponents(fnow, current_grad) + p_iter = iteration + + # Main optimization loop. + while iteration < maxiters: + + # Calculate first and second directional derivatives. + if success: + mu = np.dot(d, gradnew) + if mu >= 0: + d = -gradnew + mu = np.dot(d, gradnew) + kappa = np.dot(d, d) + sigma = sigma0 / np.sqrt(kappa) + xplus = x + sigma * d + gplus = gradf(xplus, *optargs) + theta = np.dot(d, (gplus - gradnew)) / sigma + + # Increase effective curvature and evaluate step size alpha. + delta = theta + beta * kappa + if delta <= 0: + delta = beta * kappa + beta = beta - theta / kappa + + alpha = -mu / delta + + # Calculate the comparison ratio. + xnew = x + alpha * d + fnew = f(xnew, *optargs) + function_eval += 1 + +# if function_eval >= max_f_eval: +# status = "maximum number of function evaluations exceeded" +# break +# return x, flog, function_eval, status + + Delta = 2.*(fnew - fold) / (alpha * mu) + if Delta >= 0.: + success = True + nsuccess += 1 + x = xnew + fnow = fnew + else: + success = False + fnow = fold + + # Store relevant variables + flog.append(fnow) # Current function value + + iteration += 1 + if display: + print_out(len_maxiters, fnow, current_grad, beta, iteration) + n_exps = exponents(fnow, current_grad) + if iteration - p_iter >= 20 * np.random.rand(): + a = iteration >= p_iter * 2.78 + b = np.any(n_exps < exps) + if a or b: + p_iter = iteration + print '' + if b: + exps = n_exps + + if success: + # Test for termination + + if (np.abs(fnew - fold) < ftol): + status = 'converged - relative reduction in objective' + break +# return x, flog, function_eval, status + elif (np.max(np.abs(alpha * d)) < xtol): + status = 'converged - relative stepsize' + break + else: + # Update variables for new position + gradold = gradnew + gradnew = gradf(x, *optargs) + current_grad = np.dot(gradnew, gradnew) + fold = fnew + # If the gradient is zero then we are done. + if current_grad <= gtol: + status = 'converged - relative reduction in gradient' + break + # return x, flog, function_eval, status + + # Adjust beta according to comparison ratio. + if Delta < 0.25: + beta = min(4.0 * beta, betamax) + if Delta > 0.75: + beta = max(0.25 * beta, betamin) + + # Update search direction using Polak-Ribiere formula, or re-start + # in direction of negative gradient after nparams steps. + if nsuccess == x.size: + d = -gradnew + beta = 1. # This is not in the original paper + nsuccess = 0 + elif success: + Gamma = np.dot(gradold - gradnew, gradnew) / (mu) + d = Gamma * d - gradnew + else: + # If we get here, then we haven't terminated in the given number of + # iterations. + status = "maxiter exceeded" + + if display: + print_out(len_maxiters, fnow, current_grad, beta, iteration) + print "" + print status + return x, flog, function_eval, status
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/inference/optimization/stochastics.html b/doc/_build/html/_modules/GPy/inference/optimization/stochastics.html new file mode 100644 index 00000000..6f5292f8 --- /dev/null +++ b/doc/_build/html/_modules/GPy/inference/optimization/stochastics.html @@ -0,0 +1,150 @@ + + + + + + + + GPy.inference.optimization.stochastics — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.inference.optimization.stochastics

      +# Copyright (c) 2012-2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      [docs]class StochasticStorage(object): + ''' + This is a container for holding the stochastic parameters, + such as subset indices or step length and so on. + ''' + def __init__(self, model): + """ + Initialize this stochastic container using the given model + """ + +
      [docs] def do_stochastics(self): + """ + Update the internal state to the next batch of the stochastic + descent algorithm. + """ + pass +
      +
      [docs] def reset(self): + """ + Reset the state of this stochastics generator. + """ +
      +
      [docs]class SparseGPMissing(StochasticStorage): + def __init__(self, model, batchsize=1): + """ + Here we want to loop over all dimensions everytime. + Thus, we can just make sure the loop goes over self.d every + time. + """ + self.d = xrange(model.Y_normalized.shape[1]) +
      +
      [docs]class SparseGPStochastics(StochasticStorage): + """ + For the sparse gp we need to store the dimension we are in, + and the indices corresponding to those + """ + def __init__(self, model, batchsize=1): + self.batchsize = batchsize + self.output_dim = model.Y.shape[1] + self.reset() + self.do_stochastics() + +
      [docs] def do_stochastics(self): + if self.batchsize == 1: + self.current_dim = (self.current_dim+1)%self.output_dim + self.d = [self.current_dim] + else: + import numpy as np + self.d = np.random.choice(self.output_dim, size=self.batchsize, replace=False) +
      +
      [docs] def reset(self): + self.current_dim = -1 + self.d = None
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/ODE_UY.html b/doc/_build/html/_modules/GPy/kern/_src/ODE_UY.html new file mode 100644 index 00000000..98849cda --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/ODE_UY.html @@ -0,0 +1,375 @@ + + + + + + + + GPy.kern._src.ODE_UY — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.ODE_UY

      +# Copyright (c) 2013, GPy authors (see AUTHORS.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
      +import numpy as np
      +from independent_outputs import index_to_slices
      +
      +
      [docs]class ODE_UY(Kern): + def __init__(self, input_dim, variance_U=3., variance_Y=1., lengthscale_U=1., lengthscale_Y=1., active_dims=None, name='ode_uy'): + assert input_dim ==2, "only defined for 2 input dims" + super(ODE_UY, self).__init__(input_dim, active_dims, name) + + self.variance_Y = Param('variance_Y', variance_Y, Logexp()) + self.variance_U = Param('variance_U', variance_Y, Logexp()) + self.lengthscale_Y = Param('lengthscale_Y', lengthscale_Y, Logexp()) + self.lengthscale_U = Param('lengthscale_U', lengthscale_Y, Logexp()) + + self.link_parameters(self.variance_Y, self.variance_U, self.lengthscale_Y, self.lengthscale_U) + +
      [docs] def K(self, X, X2=None): + # model : a * dy/dt + b * y = U + #lu=sqrt(3)/theta1 ly=1/theta2 theta2= a/b :thetay sigma2=1/(2ab) :sigmay + + X,slices = X[:,:-1],index_to_slices(X[:,-1]) + if X2 is None: + X2,slices2 = X,slices + K = np.zeros((X.shape[0], X.shape[0])) + else: + X2,slices2 = X2[:,:-1],index_to_slices(X2[:,-1]) + K = np.zeros((X.shape[0], X2.shape[0])) + + + #rdist = X[:,0][:,None] - X2[:,0][:,None].T + rdist = X - X2.T + ly=1/self.lengthscale_Y + lu=np.sqrt(3)/self.lengthscale_U + #iu=self.input_lengthU #dimention of U + Vu=self.variance_U + Vy=self.variance_Y + #Vy=ly/2 + #stop + + + # kernel for kuu matern3/2 + kuu = lambda dist:Vu * (1 + lu* np.abs(dist)) * np.exp(-lu * np.abs(dist)) + + # kernel for kyy + k1 = lambda dist:np.exp(-ly*np.abs(dist))*(2*lu+ly)/(lu+ly)**2 + k2 = lambda dist:(np.exp(-lu*dist)*(ly-2*lu+lu*ly*dist-lu**2*dist) + np.exp(-ly*dist)*(2*lu-ly) ) / (ly-lu)**2 + k3 = lambda dist:np.exp(-lu*dist) * ( (1+lu*dist)/(lu+ly) + (lu)/(lu+ly)**2 ) + kyy = lambda dist:Vu*Vy*(k1(dist) + k2(dist) + k3(dist)) + + + # cross covariance function + kyu3 = lambda dist:np.exp(-lu*dist)/(lu+ly)*(1+lu*(dist+1/(lu+ly))) + #kyu3 = lambda dist: 0 + + k1cros = lambda dist:np.exp(ly*dist)/(lu-ly) * ( 1- np.exp( (lu-ly)*dist) + lu* ( dist*np.exp( (lu-ly)*dist ) + (1- np.exp( (lu-ly)*dist ) ) /(lu-ly) ) ) + #k1cros = lambda dist:0 + + k2cros = lambda dist:np.exp(ly*dist)*( 1/(lu+ly) + lu/(lu+ly)**2 ) + #k2cros = lambda dist:0 + + Vyu=np.sqrt(Vy*ly*2) + + # cross covariance kuy + kuyp = lambda dist:Vu*Vyu*(kyu3(dist)) #t>0 kuy + kuyn = lambda dist:Vu*Vyu*(k1cros(dist)+k2cros(dist)) #t<0 kuy + # cross covariance kyu + kyup = lambda dist:Vu*Vyu*(k1cros(-dist)+k2cros(-dist)) #t>0 kyu + kyun = lambda dist:Vu*Vyu*(kyu3(-dist)) #t<0 kyu + + + for i, s1 in enumerate(slices): + for j, s2 in enumerate(slices2): + for ss1 in s1: + for ss2 in s2: + if i==0 and j==0: + K[ss1,ss2] = kuu(np.abs(rdist[ss1,ss2])) + elif i==0 and j==1: + #K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kuyp(np.abs(rdist[ss1,ss2])), kuyn(np.abs(rdist[ss1,ss2]) ) ) + K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kuyp(rdist[ss1,ss2]), kuyn(rdist[ss1,ss2] ) ) + elif i==1 and j==1: + K[ss1,ss2] = kyy(np.abs(rdist[ss1,ss2])) + else: + #K[ss1,ss2]= 0 + #K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kyup(np.abs(rdist[ss1,ss2])), kyun(np.abs(rdist[ss1,ss2]) ) ) + K[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , kyup(rdist[ss1,ss2]), kyun(rdist[ss1,ss2] ) ) + return K + + +
      +
      [docs] def Kdiag(self, X): + """Compute the diagonal of the covariance matrix associated to X.""" + Kdiag = np.zeros(X.shape[0]) + ly=1/self.lengthscale_Y + lu=np.sqrt(3)/self.lengthscale_U + + Vu = self.variance_U + Vy=self.variance_Y + + k1 = (2*lu+ly)/(lu+ly)**2 + k2 = (ly-2*lu + 2*lu-ly ) / (ly-lu)**2 + k3 = 1/(lu+ly) + (lu)/(lu+ly)**2 + + slices = index_to_slices(X[:,-1]) + + for i, ss1 in enumerate(slices): + for s1 in ss1: + if i==0: + Kdiag[s1]+= self.variance_U + elif i==1: + Kdiag[s1]+= Vu*Vy*(k1+k2+k3) + else: + raise ValueError, "invalid input/output index" + #Kdiag[slices[0][0]]+= self.variance_U #matern32 diag + #Kdiag[slices[1][0]]+= self.variance_U*self.variance_Y*(k1+k2+k3) # diag + return Kdiag + +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + """derivative of the covariance matrix with respect to the parameters.""" + X,slices = X[:,:-1],index_to_slices(X[:,-1]) + if X2 is None: + X2,slices2 = X,slices + else: + X2,slices2 = X2[:,:-1],index_to_slices(X2[:,-1]) + #rdist = X[:,0][:,None] - X2[:,0][:,None].T + + rdist = X - X2.T + ly=1/self.lengthscale_Y + lu=np.sqrt(3)/self.lengthscale_U + + Vu=self.variance_U + Vy=self.variance_Y + Vyu = np.sqrt(Vy*ly*2) + dVdly = 0.5/np.sqrt(ly)*np.sqrt(2*Vy) + dVdVy = 0.5/np.sqrt(Vy)*np.sqrt(2*ly) + + rd=rdist.shape + dktheta1 = np.zeros(rd) + dktheta2 = np.zeros(rd) + dkUdvar = np.zeros(rd) + dkYdvar = np.zeros(rd) + + # dk dtheta for UU + UUdtheta1 = lambda dist: np.exp(-lu* dist)*dist + (-dist)*np.exp(-lu* dist)*(1+lu*dist) + UUdtheta2 = lambda dist: 0 + #UUdvar = lambda dist: (1 + lu*dist)*np.exp(-lu*dist) + UUdvar = lambda dist: (1 + lu* np.abs(dist)) * np.exp(-lu * np.abs(dist)) + + # dk dtheta for YY + + dk1theta1 = lambda dist: np.exp(-ly*dist)*2*(-lu)/(lu+ly)**3 + + dk2theta1 = lambda dist: (1.0)*( + np.exp(-lu*dist)*dist*(-ly+2*lu-lu*ly*dist+dist*lu**2)*(ly-lu)**(-2) + np.exp(-lu*dist)*(-2+ly*dist-2*dist*lu)*(ly-lu)**(-2) + +np.exp(-dist*lu)*(ly-2*lu+ly*lu*dist-dist*lu**2)*2*(ly-lu)**(-3) + +np.exp(-dist*ly)*2*(ly-lu)**(-2) + +np.exp(-dist*ly)*2*(2*lu-ly)*(ly-lu)**(-3) + ) + + dk3theta1 = lambda dist: np.exp(-dist*lu)*(lu+ly)**(-2)*((2*lu+ly+dist*lu**2+lu*ly*dist)*(-dist-2/(lu+ly))+2+2*lu*dist+ly*dist) + + #dktheta1 = lambda dist: self.variance_U*self.variance_Y*(dk1theta1+dk2theta1+dk3theta1) + + + + + dk1theta2 = lambda dist: np.exp(-ly*dist) * ((lu+ly)**(-2)) * ( (-dist)*(2*lu+ly) + 1 + (-2)*(2*lu+ly)/(lu+ly) ) + + dk2theta2 =lambda dist: 1*( + np.exp(-dist*lu)*(ly-lu)**(-2) * ( 1+lu*dist+(-2)*(ly-2*lu+lu*ly*dist-dist*lu**2)*(ly-lu)**(-1) ) + +np.exp(-dist*ly)*(ly-lu)**(-2) * ( (-dist)*(2*lu-ly) -1+(2*lu-ly)*(-2)*(ly-lu)**(-1) ) + ) + + dk3theta2 = lambda dist: np.exp(-dist*lu) * (-3*lu-ly-dist*lu**2-lu*ly*dist)/(lu+ly)**3 + + #dktheta2 = lambda dist: self.variance_U*self.variance_Y*(dk1theta2 + dk2theta2 +dk3theta2) + + # kyy kernel + + k1 = lambda dist: np.exp(-ly*dist)*(2*lu+ly)/(lu+ly)**2 + k2 = lambda dist: (np.exp(-lu*dist)*(ly-2*lu+lu*ly*dist-lu**2*dist) + np.exp(-ly*dist)*(2*lu-ly) ) / (ly-lu)**2 + k3 = lambda dist: np.exp(-lu*dist) * ( (1+lu*dist)/(lu+ly) + (lu)/(lu+ly)**2 ) + #dkdvar = k1+k2+k3 + + + + # cross covariance function + kyu3 = lambda dist:np.exp(-lu*dist)/(lu+ly)*(1+lu*(dist+1/(lu+ly))) + + k1cros = lambda dist:np.exp(ly*dist)/(lu-ly) * ( 1- np.exp( (lu-ly)*dist) + lu* ( dist*np.exp( (lu-ly)*dist ) + (1- np.exp( (lu-ly)*dist ) ) /(lu-ly) ) ) + + k2cros = lambda dist:np.exp(ly*dist)*( 1/(lu+ly) + lu/(lu+ly)**2 ) + # cross covariance kuy + kuyp = lambda dist:(kyu3(dist)) #t>0 kuy + kuyn = lambda dist:(k1cros(dist)+k2cros(dist)) #t<0 kuy + # cross covariance kyu + kyup = lambda dist:(k1cros(-dist)+k2cros(-dist)) #t>0 kyu + kyun = lambda dist:(kyu3(-dist)) #t<0 kyu + + # dk dtheta for UY + + + dkyu3dtheta2 = lambda dist: np.exp(-lu*dist) * ( (-1)*(lu+ly)**(-2)*(1+lu*dist+lu*(lu+ly)**(-1)) + (lu+ly)**(-1)*(-lu)*(lu+ly)**(-2) ) + dkyu3dtheta1 = lambda dist: np.exp(-lu*dist)*(lu+ly)**(-1)* ( (-dist)*(1+dist*lu+lu*(lu+ly)**(-1)) -\ + (lu+ly)**(-1)*(1+dist*lu+lu*(lu+ly)**(-1)) +dist+(lu+ly)**(-1)-lu*(lu+ly)**(-2) ) + + dkcros2dtheta1 = lambda dist: np.exp(ly*dist)* ( -(ly+lu)**(-2) + (ly+lu)**(-2) + (-2)*lu*(lu+ly)**(-3) ) + dkcros2dtheta2 = lambda dist: np.exp(ly*dist)*dist* ( (ly+lu)**(-1) + lu*(lu+ly)**(-2) ) + \ + np.exp(ly*dist)*( -(lu+ly)**(-2) + lu*(-2)*(lu+ly)**(-3) ) + + dkcros1dtheta1 = lambda dist: np.exp(ly*dist)*( -(lu-ly)**(-2)*( 1-np.exp((lu-ly)*dist) + lu*dist*np.exp((lu-ly)*dist)+ \ + lu*(1-np.exp((lu-ly)*dist))/(lu-ly) ) + (lu-ly)**(-1)*( -np.exp( (lu-ly)*dist )*dist + dist*np.exp( (lu-ly)*dist)+\ + lu*dist**2*np.exp((lu-ly)*dist)+(1-np.exp((lu-ly)*dist))/(lu-ly) - lu*np.exp((lu-ly)*dist)*dist/(lu-ly) -\ + lu*(1-np.exp((lu-ly)*dist))/(lu-ly)**2 ) ) + + dkcros1dtheta2 = lambda t: np.exp(ly*t)*t/(lu-ly)*( 1-np.exp((lu-ly)*t) +lu*t*np.exp((lu-ly)*t)+\ + lu*(1-np.exp((lu-ly)*t))/(lu-ly) )+\ + np.exp(ly*t)/(lu-ly)**2* ( 1-np.exp((lu-ly)*t) +lu*t*np.exp((lu-ly)*t) + lu*( 1-np.exp((lu-ly)*t) )/(lu-ly) )+\ + np.exp(ly*t)/(lu-ly)*( np.exp((lu-ly)*t)*t -lu*t*t*np.exp((lu-ly)*t) +lu*t*np.exp((lu-ly)*t)/(lu-ly)+\ + lu*( 1-np.exp((lu-ly)*t) )/(lu-ly)**2 ) + + dkuypdtheta1 = lambda dist:(dkyu3dtheta1(dist)) #t>0 kuy + dkuyndtheta1 = lambda dist:(dkcros1dtheta1(dist)+dkcros2dtheta1(dist)) #t<0 kuy + # cross covariance kyu + dkyupdtheta1 = lambda dist:(dkcros1dtheta1(-dist)+dkcros2dtheta1(-dist)) #t>0 kyu + dkyundtheta1 = lambda dist:(dkyu3dtheta1(-dist)) #t<0 kyu + + dkuypdtheta2 = lambda dist:(dkyu3dtheta2(dist)) #t>0 kuy + dkuyndtheta2 = lambda dist:(dkcros1dtheta2(dist)+dkcros2dtheta2(dist)) #t<0 kuy + # cross covariance kyu + dkyupdtheta2 = lambda dist:(dkcros1dtheta2(-dist)+dkcros2dtheta2(-dist)) #t>0 kyu + dkyundtheta2 = lambda dist:(dkyu3dtheta2(-dist)) #t<0 kyu + + + for i, s1 in enumerate(slices): + for j, s2 in enumerate(slices2): + for ss1 in s1: + for ss2 in s2: + if i==0 and j==0: + #target[ss1,ss2] = kuu(np.abs(rdist[ss1,ss2])) + dktheta1[ss1,ss2] = Vu*UUdtheta1(np.abs(rdist[ss1,ss2])) + dktheta2[ss1,ss2] = 0 + dkUdvar[ss1,ss2] = UUdvar(np.abs(rdist[ss1,ss2])) + dkYdvar[ss1,ss2] = 0 + elif i==0 and j==1: + ########target[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , kuyp(np.abs(rdist[ss1,ss2])), kuyn(np.abs(rdist[s1[0],s2[0]]) ) ) + #np.where( rdist[ss1,ss2]>0 , kuyp(np.abs(rdist[ss1,ss2])), kuyn(np.abs(rdist[s1[0],s2[0]]) ) ) + #dktheta1[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , self.variance_U*self.variance_Y*dkcrtheta1(np.abs(rdist[ss1,ss2])) ,self.variance_U*self.variance_Y*(dk1theta1(np.abs(rdist[ss1,ss2]))+dk2theta1(np.abs(rdist[ss1,ss2]))) ) + #dktheta2[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , self.variance_U*self.variance_Y*dkcrtheta2(np.abs(rdist[ss1,ss2])) ,self.variance_U*self.variance_Y*(dk1theta2(np.abs(rdist[ss1,ss2]))+dk2theta2(np.abs(rdist[ss1,ss2]))) ) + dktheta1[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*Vyu*dkuypdtheta1(rdist[ss1,ss2]),Vu*Vyu*dkuyndtheta1(rdist[ss1,ss2]) ) + dkUdvar[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vyu*kuyp(rdist[ss1,ss2]), Vyu* kuyn(rdist[ss1,ss2]) ) + dktheta2[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*Vyu*dkuypdtheta2(rdist[ss1,ss2])+Vu*dVdly*kuyp(rdist[ss1,ss2]),Vu*Vyu*dkuyndtheta2(rdist[ss1,ss2])+Vu*dVdly*kuyn(rdist[ss1,ss2]) ) + dkYdvar[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*dVdVy*kuyp(rdist[ss1,ss2]), Vu*dVdVy* kuyn(rdist[ss1,ss2]) ) + elif i==1 and j==1: + #target[ss1,ss2] = kyy(np.abs(rdist[ss1,ss2])) + dktheta1[ss1,ss2] = self.variance_U*self.variance_Y*(dk1theta1(np.abs(rdist[ss1,ss2]))+dk2theta1(np.abs(rdist[ss1,ss2]))+dk3theta1(np.abs(rdist[ss1,ss2]))) + dktheta2[ss1,ss2] = self.variance_U*self.variance_Y*(dk1theta2(np.abs(rdist[ss1,ss2])) + dk2theta2(np.abs(rdist[ss1,ss2])) +dk3theta2(np.abs(rdist[ss1,ss2]))) + dkUdvar[ss1,ss2] = self.variance_Y*(k1(np.abs(rdist[ss1,ss2]))+k2(np.abs(rdist[ss1,ss2]))+k3(np.abs(rdist[ss1,ss2])) ) + dkYdvar[ss1,ss2] = self.variance_U*(k1(np.abs(rdist[ss1,ss2]))+k2(np.abs(rdist[ss1,ss2]))+k3(np.abs(rdist[ss1,ss2])) ) + else: + #######target[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , kyup(np.abs(rdist[ss1,ss2])), kyun(np.abs(rdist[s1[0],s2[0]]) ) ) + #dktheta1[ss1,ss2] = np.where( rdist[ss1,ss2]>0 ,self.variance_U*self.variance_Y*(dk1theta1(np.abs(rdist[ss1,ss2]))+dk2theta1(np.abs(rdist[ss1,ss2]))) , self.variance_U*self.variance_Y*dkcrtheta1(np.abs(rdist[ss1,ss2])) ) + #dktheta2[ss1,ss2] = np.where( rdist[ss1,ss2]>0 ,self.variance_U*self.variance_Y*(dk1theta2(np.abs(rdist[ss1,ss2]))+dk2theta2(np.abs(rdist[ss1,ss2]))) , self.variance_U*self.variance_Y*dkcrtheta2(np.abs(rdist[ss1,ss2])) ) + dktheta1[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*Vyu*dkyupdtheta1(rdist[ss1,ss2]),Vu*Vyu*dkyundtheta1(rdist[ss1,ss2]) ) + dkUdvar[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vyu*kyup(rdist[ss1,ss2]),Vyu*kyun(rdist[ss1,ss2])) + dktheta2[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*Vyu*dkyupdtheta2(rdist[ss1,ss2])+Vu*dVdly*kyup(rdist[ss1,ss2]),Vu*Vyu*dkyundtheta2(rdist[ss1,ss2])+Vu*dVdly*kyun(rdist[ss1,ss2]) ) + dkYdvar[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*dVdVy*kyup(rdist[ss1,ss2]), Vu*dVdVy*kyun(rdist[ss1,ss2])) + + #stop + self.variance_U.gradient = np.sum(dkUdvar * dL_dK) # Vu + + self.variance_Y.gradient = np.sum(dkYdvar * dL_dK) # Vy + + self.lengthscale_U.gradient = np.sum(dktheta1*(-np.sqrt(3)*self.lengthscale_U**(-2))* dL_dK) #lu + + self.lengthscale_Y.gradient = np.sum(dktheta2*(-self.lengthscale_Y**(-2)) * dL_dK) #ly +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/ODE_UYC.html b/doc/_build/html/_modules/GPy/kern/_src/ODE_UYC.html new file mode 100644 index 00000000..9f32a651 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/ODE_UYC.html @@ -0,0 +1,383 @@ + + + + + + + + GPy.kern._src.ODE_UYC — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.ODE_UYC

      +# Copyright (c) 2013, GPy authors (see AUTHORS.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
      +import numpy as np
      +from independent_outputs import index_to_slices
      +
      +
      [docs]class ODE_UYC(Kern): + def __init__(self, input_dim, variance_U=3., variance_Y=1., lengthscale_U=1., lengthscale_Y=1., ubias =1. ,active_dims=None, name='ode_uyc'): + assert input_dim ==2, "only defined for 2 input dims" + super(ODE_UYC, self).__init__(input_dim, active_dims, name) + + self.variance_Y = Param('variance_Y', variance_Y, Logexp()) + self.variance_U = Param('variance_U', variance_U, Logexp()) + self.lengthscale_Y = Param('lengthscale_Y', lengthscale_Y, Logexp()) + self.lengthscale_U = Param('lengthscale_U', lengthscale_U, Logexp()) + self.ubias = Param('ubias', ubias, Logexp()) + + self.add_parameters(self.variance_Y, self.variance_U, self.lengthscale_Y, self.lengthscale_U, self.ubias) + +
      [docs] def K(self, X, X2=None): + # model : a * dy/dt + b * y = U + #lu=sqrt(3)/theta1 ly=1/theta2 theta2= a/b :thetay sigma2=1/(2ab) :sigmay + + X,slices = X[:,:-1],index_to_slices(X[:,-1]) + if X2 is None: + X2,slices2 = X,slices + K = np.zeros((X.shape[0], X.shape[0])) + else: + X2,slices2 = X2[:,:-1],index_to_slices(X2[:,-1]) + K = np.zeros((X.shape[0], X2.shape[0])) + + #stop + #rdist = X[:,0][:,None] - X2[:,0][:,None].T + rdist = X - X2.T + ly=1/self.lengthscale_Y + lu=np.sqrt(3)/self.lengthscale_U + #iu=self.input_lengthU #dimention of U + Vu=self.variance_U + Vy=self.variance_Y + #Vy=ly/2 + #stop + + + # kernel for kuu matern3/2 + kuu = lambda dist:Vu * (1 + lu* np.abs(dist)) * np.exp(-lu * np.abs(dist)) +self.ubias + + # kernel for kyy + k1 = lambda dist:np.exp(-ly*np.abs(dist))*(2*lu+ly)/(lu+ly)**2 + k2 = lambda dist:(np.exp(-lu*dist)*(ly-2*lu+lu*ly*dist-lu**2*dist) + np.exp(-ly*dist)*(2*lu-ly) ) / (ly-lu)**2 + k3 = lambda dist:np.exp(-lu*dist) * ( (1+lu*dist)/(lu+ly) + (lu)/(lu+ly)**2 ) + kyy = lambda dist:Vu*Vy*(k1(dist) + k2(dist) + k3(dist)) + + + # cross covariance function + kyu3 = lambda dist:np.exp(-lu*dist)/(lu+ly)*(1+lu*(dist+1/(lu+ly))) + #kyu3 = lambda dist: 0 + + k1cros = lambda dist:np.exp(ly*dist)/(lu-ly) * ( 1- np.exp( (lu-ly)*dist) + lu* ( dist*np.exp( (lu-ly)*dist ) + (1- np.exp( (lu-ly)*dist ) ) /(lu-ly) ) ) + #k1cros = lambda dist:0 + + k2cros = lambda dist:np.exp(ly*dist)*( 1/(lu+ly) + lu/(lu+ly)**2 ) + #k2cros = lambda dist:0 + + Vyu=np.sqrt(Vy*ly*2) + + # cross covariance kuy + kuyp = lambda dist:Vu*Vyu*(kyu3(dist)) #t>0 kuy + kuyn = lambda dist:Vu*Vyu*(k1cros(dist)+k2cros(dist)) #t<0 kuy + # cross covariance kyu + kyup = lambda dist:Vu*Vyu*(k1cros(-dist)+k2cros(-dist)) #t>0 kyu + kyun = lambda dist:Vu*Vyu*(kyu3(-dist)) #t<0 kyu + + + for i, s1 in enumerate(slices): + for j, s2 in enumerate(slices2): + for ss1 in s1: + for ss2 in s2: + if i==0 and j==0: + K[ss1,ss2] = kuu(np.abs(rdist[ss1,ss2])) + elif i==0 and j==1: + #K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kuyp(np.abs(rdist[ss1,ss2])), kuyn(np.abs(rdist[ss1,ss2]) ) ) + K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kuyp(rdist[ss1,ss2]), kuyn(rdist[ss1,ss2] ) ) + elif i==1 and j==1: + K[ss1,ss2] = kyy(np.abs(rdist[ss1,ss2])) + else: + #K[ss1,ss2]= 0 + #K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kyup(np.abs(rdist[ss1,ss2])), kyun(np.abs(rdist[ss1,ss2]) ) ) + K[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , kyup(rdist[ss1,ss2]), kyun(rdist[ss1,ss2] ) ) + return K + + +
      +
      [docs] def Kdiag(self, X): + """Compute the diagonal of the covariance matrix associated to X.""" + Kdiag = np.zeros(X.shape[0]) + ly=1/self.lengthscale_Y + lu=np.sqrt(3)/self.lengthscale_U + + Vu = self.variance_U + Vy=self.variance_Y + + k1 = (2*lu+ly)/(lu+ly)**2 + k2 = (ly-2*lu + 2*lu-ly ) / (ly-lu)**2 + k3 = 1/(lu+ly) + (lu)/(lu+ly)**2 + + slices = index_to_slices(X[:,-1]) + + for i, ss1 in enumerate(slices): + for s1 in ss1: + if i==0: + Kdiag[s1]+= self.variance_U + self.ubias + elif i==1: + Kdiag[s1]+= Vu*Vy*(k1+k2+k3) + else: + raise ValueError, "invalid input/output index" + #Kdiag[slices[0][0]]+= self.variance_U #matern32 diag + #Kdiag[slices[1][0]]+= self.variance_U*self.variance_Y*(k1+k2+k3) # diag + return Kdiag + +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + """derivative of the covariance matrix with respect to the parameters.""" + X,slices = X[:,:-1],index_to_slices(X[:,-1]) + if X2 is None: + X2,slices2 = X,slices + else: + X2,slices2 = X2[:,:-1],index_to_slices(X2[:,-1]) + #rdist = X[:,0][:,None] - X2[:,0][:,None].T + + rdist = X - X2.T + ly=1/self.lengthscale_Y + lu=np.sqrt(3)/self.lengthscale_U + + Vu=self.variance_U + Vy=self.variance_Y + Vyu = np.sqrt(Vy*ly*2) + dVdly = 0.5/np.sqrt(ly)*np.sqrt(2*Vy) + dVdVy = 0.5/np.sqrt(Vy)*np.sqrt(2*ly) + + rd=rdist.shape[0] + dktheta1 = np.zeros([rd,rd]) + dktheta2 = np.zeros([rd,rd]) + dkUdvar = np.zeros([rd,rd]) + dkYdvar = np.zeros([rd,rd]) + + dkdubias = np.zeros([rd,rd]) + + # dk dtheta for UU + UUdtheta1 = lambda dist: np.exp(-lu* dist)*dist + (-dist)*np.exp(-lu* dist)*(1+lu*dist) + UUdtheta2 = lambda dist: 0 + #UUdvar = lambda dist: (1 + lu*dist)*np.exp(-lu*dist) + UUdvar = lambda dist: (1 + lu* np.abs(dist)) * np.exp(-lu * np.abs(dist)) + + # dk dtheta for YY + + dk1theta1 = lambda dist: np.exp(-ly*dist)*2*(-lu)/(lu+ly)**3 + + dk2theta1 = lambda dist: (1.0)*( + np.exp(-lu*dist)*dist*(-ly+2*lu-lu*ly*dist+dist*lu**2)*(ly-lu)**(-2) + np.exp(-lu*dist)*(-2+ly*dist-2*dist*lu)*(ly-lu)**(-2) + +np.exp(-dist*lu)*(ly-2*lu+ly*lu*dist-dist*lu**2)*2*(ly-lu)**(-3) + +np.exp(-dist*ly)*2*(ly-lu)**(-2) + +np.exp(-dist*ly)*2*(2*lu-ly)*(ly-lu)**(-3) + ) + + dk3theta1 = lambda dist: np.exp(-dist*lu)*(lu+ly)**(-2)*((2*lu+ly+dist*lu**2+lu*ly*dist)*(-dist-2/(lu+ly))+2+2*lu*dist+ly*dist) + + #dktheta1 = lambda dist: self.variance_U*self.variance_Y*(dk1theta1+dk2theta1+dk3theta1) + + + + + dk1theta2 = lambda dist: np.exp(-ly*dist) * ((lu+ly)**(-2)) * ( (-dist)*(2*lu+ly) + 1 + (-2)*(2*lu+ly)/(lu+ly) ) + + dk2theta2 =lambda dist: 1*( + np.exp(-dist*lu)*(ly-lu)**(-2) * ( 1+lu*dist+(-2)*(ly-2*lu+lu*ly*dist-dist*lu**2)*(ly-lu)**(-1) ) + +np.exp(-dist*ly)*(ly-lu)**(-2) * ( (-dist)*(2*lu-ly) -1+(2*lu-ly)*(-2)*(ly-lu)**(-1) ) + ) + + dk3theta2 = lambda dist: np.exp(-dist*lu) * (-3*lu-ly-dist*lu**2-lu*ly*dist)/(lu+ly)**3 + + #dktheta2 = lambda dist: self.variance_U*self.variance_Y*(dk1theta2 + dk2theta2 +dk3theta2) + + # kyy kernel + + k1 = lambda dist: np.exp(-ly*dist)*(2*lu+ly)/(lu+ly)**2 + k2 = lambda dist: (np.exp(-lu*dist)*(ly-2*lu+lu*ly*dist-lu**2*dist) + np.exp(-ly*dist)*(2*lu-ly) ) / (ly-lu)**2 + k3 = lambda dist: np.exp(-lu*dist) * ( (1+lu*dist)/(lu+ly) + (lu)/(lu+ly)**2 ) + #dkdvar = k1+k2+k3 + + + + # cross covariance function + kyu3 = lambda dist:np.exp(-lu*dist)/(lu+ly)*(1+lu*(dist+1/(lu+ly))) + + k1cros = lambda dist:np.exp(ly*dist)/(lu-ly) * ( 1- np.exp( (lu-ly)*dist) + lu* ( dist*np.exp( (lu-ly)*dist ) + (1- np.exp( (lu-ly)*dist ) ) /(lu-ly) ) ) + + k2cros = lambda dist:np.exp(ly*dist)*( 1/(lu+ly) + lu/(lu+ly)**2 ) + # cross covariance kuy + kuyp = lambda dist:(kyu3(dist)) #t>0 kuy + kuyn = lambda dist:(k1cros(dist)+k2cros(dist)) #t<0 kuy + # cross covariance kyu + kyup = lambda dist:(k1cros(-dist)+k2cros(-dist)) #t>0 kyu + kyun = lambda dist:(kyu3(-dist)) #t<0 kyu + + # dk dtheta for UY + + + dkyu3dtheta2 = lambda dist: np.exp(-lu*dist) * ( (-1)*(lu+ly)**(-2)*(1+lu*dist+lu*(lu+ly)**(-1)) + (lu+ly)**(-1)*(-lu)*(lu+ly)**(-2) ) + dkyu3dtheta1 = lambda dist: np.exp(-lu*dist)*(lu+ly)**(-1)* ( (-dist)*(1+dist*lu+lu*(lu+ly)**(-1)) -\ + (lu+ly)**(-1)*(1+dist*lu+lu*(lu+ly)**(-1)) +dist+(lu+ly)**(-1)-lu*(lu+ly)**(-2) ) + + dkcros2dtheta1 = lambda dist: np.exp(ly*dist)* ( -(ly+lu)**(-2) + (ly+lu)**(-2) + (-2)*lu*(lu+ly)**(-3) ) + dkcros2dtheta2 = lambda dist: np.exp(ly*dist)*dist* ( (ly+lu)**(-1) + lu*(lu+ly)**(-2) ) + \ + np.exp(ly*dist)*( -(lu+ly)**(-2) + lu*(-2)*(lu+ly)**(-3) ) + + dkcros1dtheta1 = lambda dist: np.exp(ly*dist)*( -(lu-ly)**(-2)*( 1-np.exp((lu-ly)*dist) + lu*dist*np.exp((lu-ly)*dist)+ \ + lu*(1-np.exp((lu-ly)*dist))/(lu-ly) ) + (lu-ly)**(-1)*( -np.exp( (lu-ly)*dist )*dist + dist*np.exp( (lu-ly)*dist)+\ + lu*dist**2*np.exp((lu-ly)*dist)+(1-np.exp((lu-ly)*dist))/(lu-ly) - lu*np.exp((lu-ly)*dist)*dist/(lu-ly) -\ + lu*(1-np.exp((lu-ly)*dist))/(lu-ly)**2 ) ) + + dkcros1dtheta2 = lambda t: np.exp(ly*t)*t/(lu-ly)*( 1-np.exp((lu-ly)*t) +lu*t*np.exp((lu-ly)*t)+\ + lu*(1-np.exp((lu-ly)*t))/(lu-ly) )+\ + np.exp(ly*t)/(lu-ly)**2* ( 1-np.exp((lu-ly)*t) +lu*t*np.exp((lu-ly)*t) + lu*( 1-np.exp((lu-ly)*t) )/(lu-ly) )+\ + np.exp(ly*t)/(lu-ly)*( np.exp((lu-ly)*t)*t -lu*t*t*np.exp((lu-ly)*t) +lu*t*np.exp((lu-ly)*t)/(lu-ly)+\ + lu*( 1-np.exp((lu-ly)*t) )/(lu-ly)**2 ) + + dkuypdtheta1 = lambda dist:(dkyu3dtheta1(dist)) #t>0 kuy + dkuyndtheta1 = lambda dist:(dkcros1dtheta1(dist)+dkcros2dtheta1(dist)) #t<0 kuy + # cross covariance kyu + dkyupdtheta1 = lambda dist:(dkcros1dtheta1(-dist)+dkcros2dtheta1(-dist)) #t>0 kyu + dkyundtheta1 = lambda dist:(dkyu3dtheta1(-dist)) #t<0 kyu + + dkuypdtheta2 = lambda dist:(dkyu3dtheta2(dist)) #t>0 kuy + dkuyndtheta2 = lambda dist:(dkcros1dtheta2(dist)+dkcros2dtheta2(dist)) #t<0 kuy + # cross covariance kyu + dkyupdtheta2 = lambda dist:(dkcros1dtheta2(-dist)+dkcros2dtheta2(-dist)) #t>0 kyu + dkyundtheta2 = lambda dist:(dkyu3dtheta2(-dist)) #t<0 kyu + + + for i, s1 in enumerate(slices): + for j, s2 in enumerate(slices2): + for ss1 in s1: + for ss2 in s2: + if i==0 and j==0: + #target[ss1,ss2] = kuu(np.abs(rdist[ss1,ss2])) + dktheta1[ss1,ss2] = Vu*UUdtheta1(np.abs(rdist[ss1,ss2])) + dktheta2[ss1,ss2] = 0 + dkUdvar[ss1,ss2] = UUdvar(np.abs(rdist[ss1,ss2])) + dkYdvar[ss1,ss2] = 0 + dkdubias[ss1,ss2] = 1 + elif i==0 and j==1: + ########target[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , kuyp(np.abs(rdist[ss1,ss2])), kuyn(np.abs(rdist[s1[0],s2[0]]) ) ) + #np.where( rdist[ss1,ss2]>0 , kuyp(np.abs(rdist[ss1,ss2])), kuyn(np.abs(rdist[s1[0],s2[0]]) ) ) + #dktheta1[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , self.variance_U*self.variance_Y*dkcrtheta1(np.abs(rdist[ss1,ss2])) ,self.variance_U*self.variance_Y*(dk1theta1(np.abs(rdist[ss1,ss2]))+dk2theta1(np.abs(rdist[ss1,ss2]))) ) + #dktheta2[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , self.variance_U*self.variance_Y*dkcrtheta2(np.abs(rdist[ss1,ss2])) ,self.variance_U*self.variance_Y*(dk1theta2(np.abs(rdist[ss1,ss2]))+dk2theta2(np.abs(rdist[ss1,ss2]))) ) + dktheta1[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*Vyu*dkuypdtheta1(rdist[ss1,ss2]),Vu*Vyu*dkuyndtheta1(rdist[ss1,ss2]) ) + dkUdvar[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vyu*kuyp(rdist[ss1,ss2]), Vyu* kuyn(rdist[ss1,ss2]) ) + dktheta2[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*Vyu*dkuypdtheta2(rdist[ss1,ss2])+Vu*dVdly*kuyp(rdist[ss1,ss2]),Vu*Vyu*dkuyndtheta2(rdist[ss1,ss2])+Vu*dVdly*kuyn(rdist[ss1,ss2]) ) + dkYdvar[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*dVdVy*kuyp(rdist[ss1,ss2]), Vu*dVdVy* kuyn(rdist[ss1,ss2]) ) + dkdubias[ss1,ss2] = 0 + elif i==1 and j==1: + #target[ss1,ss2] = kyy(np.abs(rdist[ss1,ss2])) + dktheta1[ss1,ss2] = self.variance_U*self.variance_Y*(dk1theta1(np.abs(rdist[ss1,ss2]))+dk2theta1(np.abs(rdist[ss1,ss2]))+dk3theta1(np.abs(rdist[ss1,ss2]))) + dktheta2[ss1,ss2] = self.variance_U*self.variance_Y*(dk1theta2(np.abs(rdist[ss1,ss2])) + dk2theta2(np.abs(rdist[ss1,ss2])) +dk3theta2(np.abs(rdist[ss1,ss2]))) + dkUdvar[ss1,ss2] = self.variance_Y*(k1(np.abs(rdist[ss1,ss2]))+k2(np.abs(rdist[ss1,ss2]))+k3(np.abs(rdist[ss1,ss2])) ) + dkYdvar[ss1,ss2] = self.variance_U*(k1(np.abs(rdist[ss1,ss2]))+k2(np.abs(rdist[ss1,ss2]))+k3(np.abs(rdist[ss1,ss2])) ) + dkdubias[ss1,ss2] = 0 + else: + #######target[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , kyup(np.abs(rdist[ss1,ss2])), kyun(np.abs(rdist[s1[0],s2[0]]) ) ) + #dktheta1[ss1,ss2] = np.where( rdist[ss1,ss2]>0 ,self.variance_U*self.variance_Y*(dk1theta1(np.abs(rdist[ss1,ss2]))+dk2theta1(np.abs(rdist[ss1,ss2]))) , self.variance_U*self.variance_Y*dkcrtheta1(np.abs(rdist[ss1,ss2])) ) + #dktheta2[ss1,ss2] = np.where( rdist[ss1,ss2]>0 ,self.variance_U*self.variance_Y*(dk1theta2(np.abs(rdist[ss1,ss2]))+dk2theta2(np.abs(rdist[ss1,ss2]))) , self.variance_U*self.variance_Y*dkcrtheta2(np.abs(rdist[ss1,ss2])) ) + dktheta1[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*Vyu*dkyupdtheta1(rdist[ss1,ss2]),Vu*Vyu*dkyundtheta1(rdist[ss1,ss2]) ) + dkUdvar[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vyu*kyup(rdist[ss1,ss2]),Vyu*kyun(rdist[ss1,ss2])) + dktheta2[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*Vyu*dkyupdtheta2(rdist[ss1,ss2])+Vu*dVdly*kyup(rdist[ss1,ss2]),Vu*Vyu*dkyundtheta2(rdist[ss1,ss2])+Vu*dVdly*kyun(rdist[ss1,ss2]) ) + dkYdvar[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , Vu*dVdVy*kyup(rdist[ss1,ss2]), Vu*dVdVy*kyun(rdist[ss1,ss2])) + dkdubias[ss1,ss2] = 0 + #stop + self.variance_U.gradient = np.sum(dkUdvar * dL_dK) # Vu + + self.variance_Y.gradient = np.sum(dkYdvar * dL_dK) # Vy + + self.lengthscale_U.gradient = np.sum(dktheta1*(-np.sqrt(3)*self.lengthscale_U**(-2))* dL_dK) #lu + + self.lengthscale_Y.gradient = np.sum(dktheta2*(-self.lengthscale_Y**(-2)) * dL_dK) #ly + + self.ubias.gradient = np.sum(dkdubias * dL_dK) +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/ODE_st.html b/doc/_build/html/_modules/GPy/kern/_src/ODE_st.html new file mode 100644 index 00000000..290f8980 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/ODE_st.html @@ -0,0 +1,360 @@ + + + + + + + + GPy.kern._src.ODE_st — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.ODE_st

      +# Copyright (c) 2012, GPy authors (see AUTHORS.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
      +import numpy as np
      +from independent_outputs import index_to_slices
      +
      +
      +
      [docs]class ODE_st(Kern): + """ + kernel resultiong from a first order ODE with OU driving GP + + :param input_dim: the number of input dimension, has to be equal to one + :type input_dim: int + :param varianceU: variance of the driving GP + :type varianceU: float + :param lengthscaleU: lengthscale of the driving GP (sqrt(3)/lengthscaleU) + :type lengthscaleU: float + :param varianceY: 'variance' of the transfer function + :type varianceY: float + :param lengthscaleY: 'lengthscale' of the transfer function (1/lengthscaleY) + :type lengthscaleY: float + :rtype: kernel object + + """ + + def __init__(self, input_dim, a=1.,b=1., c=1.,variance_Yx=3.,variance_Yt=1.5, lengthscale_Yx=1.5, lengthscale_Yt=1.5, active_dims=None, name='ode_st'): + assert input_dim ==3, "only defined for 3 input dims" + super(ODE_st, self).__init__(input_dim, active_dims, name) + + self.variance_Yt = Param('variance_Yt', variance_Yt, Logexp()) + self.variance_Yx = Param('variance_Yx', variance_Yx, Logexp()) + self.lengthscale_Yt = Param('lengthscale_Yt', lengthscale_Yt, Logexp()) + self.lengthscale_Yx = Param('lengthscale_Yx', lengthscale_Yx, Logexp()) + + self.a= Param('a', a, Logexp()) + self.b = Param('b', b, Logexp()) + self.c = Param('c', c, Logexp()) + + self.add_parameters(self.a, self.b, self.c, self.variance_Yt, self.variance_Yx, self.lengthscale_Yt,self.lengthscale_Yx) + + +
      [docs] def K(self, X, X2=None): + # model : -a d^2y/dx^2 + b dy/dt + c * y = U + # kernel Kyy rbf spatiol temporal + # vyt Y temporal variance vyx Y spatiol variance lyt Y temporal lengthscale lyx Y spatiol lengthscale + # kernel Kuu doper( doper(Kyy)) + # a b c lyt lyx vyx*vyt + """Compute the covariance matrix between X and X2.""" + X,slices = X[:,:-1],index_to_slices(X[:,-1]) + if X2 is None: + X2,slices2 = X,slices + K = np.zeros((X.shape[0], X.shape[0])) + else: + X2,slices2 = X2[:,:-1],index_to_slices(X2[:,-1]) + K = np.zeros((X.shape[0], X2.shape[0])) + + + tdist = (X[:,0][:,None] - X2[:,0][None,:])**2 + xdist = (X[:,1][:,None] - X2[:,1][None,:])**2 + + ttdist = (X[:,0][:,None] - X2[:,0][None,:]) + #rdist = [tdist,xdist] + #dist = np.abs(X - X2.T) + vyt = self.variance_Yt + vyx = self.variance_Yx + + lyt=1/(2*self.lengthscale_Yt) + lyx=1/(2*self.lengthscale_Yx) + + a = self.a ## -a is used in the model, negtive diffusion + b = self.b + c = self.c + + kyy = lambda tdist,xdist: np.exp(-lyt*(tdist) -lyx*(xdist)) + + k1 = lambda tdist: (2*lyt - 4*lyt**2 * (tdist) ) + + k2 = lambda xdist: ( 4*lyx**2 * (xdist) - 2*lyx ) + + k3 = lambda xdist: ( 3*4*lyx**2 - 6*8*xdist*lyx**3 + 16*xdist**2*lyx**4 ) + + k4 = lambda ttdist: 2*lyt*(ttdist) + + for i, s1 in enumerate(slices): + for j, s2 in enumerate(slices2): + for ss1 in s1: + for ss2 in s2: + if i==0 and j==0: + K[ss1,ss2] = vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + elif i==0 and j==1: + K[ss1,ss2] = (-a*k2(xdist[ss1,ss2]) + b*k4(ttdist[ss1,ss2]) + c)*vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + #K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kuyp(np.abs(rdist[ss1,ss2])), kuyn(np.abs(rdist[ss1,ss2]) ) ) + #K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kuyp(rdist[ss1,ss2]), kuyn(rdist[ss1,ss2] ) ) + elif i==1 and j==1: + K[ss1,ss2] = ( b**2*k1(tdist[ss1,ss2]) - 2*a*c*k2(xdist[ss1,ss2]) + a**2*k3(xdist[ss1,ss2]) + c**2 )* vyt*vyx* kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + else: + K[ss1,ss2] = (-a*k2(xdist[ss1,ss2]) - b*k4(ttdist[ss1,ss2]) + c)*vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + #K[ss1,ss2]= np.where( rdist[ss1,ss2]>0 , kyup(np.abs(rdist[ss1,ss2])), kyun(np.abs(rdist[ss1,ss2]) ) ) + #K[ss1,ss2] = np.where( rdist[ss1,ss2]>0 , kyup(rdist[ss1,ss2]), kyun(rdist[ss1,ss2] ) ) + + #stop + return K +
      +
      [docs] def Kdiag(self, X): + """Compute the diagonal of the covariance matrix associated to X.""" + vyt = self.variance_Yt + vyx = self.variance_Yx + + lyt = 1./(2*self.lengthscale_Yt) + lyx = 1./(2*self.lengthscale_Yx) + + a = self.a + b = self.b + c = self.c + + ## dk^2/dtdt' + k1 = (2*lyt )*vyt*vyx + ## dk^2/dx^2 + k2 = ( - 2*lyx )*vyt*vyx + ## dk^4/dx^2dx'^2 + k3 = ( 4*3*lyx**2 )*vyt*vyx + + + Kdiag = np.zeros(X.shape[0]) + slices = index_to_slices(X[:,-1]) + + for i, ss1 in enumerate(slices): + for s1 in ss1: + if i==0: + Kdiag[s1]+= vyt*vyx + elif i==1: + #i=1 + Kdiag[s1]+= b**2*k1 - 2*a*c*k2 + a**2*k3 + c**2*vyt*vyx + #Kdiag[s1]+= Vu*Vy*(k1+k2+k3) + else: + raise ValueError, "invalid input/output index" + + return Kdiag + +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + #def dK_dtheta(self, dL_dK, X, X2, target): + """derivative of the covariance matrix with respect to the parameters.""" + X,slices = X[:,:-1],index_to_slices(X[:,-1]) + if X2 is None: + X2,slices2 = X,slices + K = np.zeros((X.shape[0], X.shape[0])) + else: + X2,slices2 = X2[:,:-1],index_to_slices(X2[:,-1]) + + vyt = self.variance_Yt + vyx = self.variance_Yx + + lyt = 1./(2*self.lengthscale_Yt) + lyx = 1./(2*self.lengthscale_Yx) + + a = self.a + b = self.b + c = self.c + + tdist = (X[:,0][:,None] - X2[:,0][None,:])**2 + xdist = (X[:,1][:,None] - X2[:,1][None,:])**2 + #rdist = [tdist,xdist] + ttdist = (X[:,0][:,None] - X2[:,0][None,:]) + + rd=tdist.shape[0] + + dka = np.zeros([rd,rd]) + dkb = np.zeros([rd,rd]) + dkc = np.zeros([rd,rd]) + dkYdvart = np.zeros([rd,rd]) + dkYdvarx = np.zeros([rd,rd]) + dkYdlent = np.zeros([rd,rd]) + dkYdlenx = np.zeros([rd,rd]) + + + kyy = lambda tdist,xdist: np.exp(-lyt*(tdist) -lyx*(xdist)) + #k1 = lambda tdist: (lyt - lyt**2 * (tdist) ) + #k2 = lambda xdist: ( lyx**2 * (xdist) - lyx ) + #k3 = lambda xdist: ( 3*lyx**2 - 6*xdist*lyx**3 + xdist**2*lyx**4 ) + #k4 = lambda tdist: -lyt*np.sqrt(tdist) + + k1 = lambda tdist: (2*lyt - 4*lyt**2 * (tdist) ) + + k2 = lambda xdist: ( 4*lyx**2 * (xdist) - 2*lyx ) + + k3 = lambda xdist: ( 3*4*lyx**2 - 6*8*xdist*lyx**3 + 16*xdist**2*lyx**4 ) + + k4 = lambda ttdist: 2*lyt*(ttdist) + + dkyydlyx = lambda tdist,xdist: kyy(tdist,xdist)*(-xdist) + dkyydlyt = lambda tdist,xdist: kyy(tdist,xdist)*(-tdist) + + dk1dlyt = lambda tdist: 2. - 4*2.*lyt*tdist + dk2dlyx = lambda xdist: (4.*2.*lyx*xdist -2.) + dk3dlyx = lambda xdist: (6.*4.*lyx - 18.*8*xdist*lyx**2 + 4*16*xdist**2*lyx**3) + + dk4dlyt = lambda ttdist: 2*(ttdist) + + for i, s1 in enumerate(slices): + for j, s2 in enumerate(slices2): + for ss1 in s1: + for ss2 in s2: + if i==0 and j==0: + dka[ss1,ss2] = 0 + dkb[ss1,ss2] = 0 + dkc[ss1,ss2] = 0 + dkYdvart[ss1,ss2] = vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdvarx[ss1,ss2] = vyt*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdlenx[ss1,ss2] = vyt*vyx*dkyydlyx(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdlent[ss1,ss2] = vyt*vyx*dkyydlyt(tdist[ss1,ss2],xdist[ss1,ss2]) + elif i==0 and j==1: + dka[ss1,ss2] = -k2(xdist[ss1,ss2])*vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkb[ss1,ss2] = k4(ttdist[ss1,ss2])*vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkc[ss1,ss2] = vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + #dkYdvart[ss1,ss2] = 0 + #dkYdvarx[ss1,ss2] = 0 + #dkYdlent[ss1,ss2] = 0 + #dkYdlenx[ss1,ss2] = 0 + dkYdvart[ss1,ss2] = (-a*k2(xdist[ss1,ss2])+b*k4(ttdist[ss1,ss2])+c)*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdvarx[ss1,ss2] = (-a*k2(xdist[ss1,ss2])+b*k4(ttdist[ss1,ss2])+c)*vyt*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdlent[ss1,ss2] = vyt*vyx*dkyydlyt(tdist[ss1,ss2],xdist[ss1,ss2])* (-a*k2(xdist[ss1,ss2])+b*k4(ttdist[ss1,ss2])+c)+\ + vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2])*b*dk4dlyt(ttdist[ss1,ss2]) + dkYdlenx[ss1,ss2] = vyt*vyx*dkyydlyx(tdist[ss1,ss2],xdist[ss1,ss2])*(-a*k2(xdist[ss1,ss2])+b*k4(ttdist[ss1,ss2])+c)+\ + vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2])*(-a*dk2dlyx(xdist[ss1,ss2])) + elif i==1 and j==1: + dka[ss1,ss2] = (2*a*k3(xdist[ss1,ss2]) - 2*c*k2(xdist[ss1,ss2]))*vyt*vyx* kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkb[ss1,ss2] = 2*b*k1(tdist[ss1,ss2])*vyt*vyx* kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkc[ss1,ss2] = (-2*a*k2(xdist[ss1,ss2]) + 2*c )*vyt*vyx* kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdvart[ss1,ss2] = ( b**2*k1(tdist[ss1,ss2]) - 2*a*c*k2(xdist[ss1,ss2]) + a**2*k3(xdist[ss1,ss2]) + c**2 )*vyx* kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdvarx[ss1,ss2] = ( b**2*k1(tdist[ss1,ss2]) - 2*a*c*k2(xdist[ss1,ss2]) + a**2*k3(xdist[ss1,ss2]) + c**2 )*vyt* kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdlent[ss1,ss2] = vyt*vyx*dkyydlyt(tdist[ss1,ss2],xdist[ss1,ss2])*( b**2*k1(tdist[ss1,ss2]) - 2*a*c*k2(xdist[ss1,ss2]) + a**2*k3(xdist[ss1,ss2]) + c**2 ) +\ + vyx*vyt*kyy(tdist[ss1,ss2],xdist[ss1,ss2])*b**2*dk1dlyt(tdist[ss1,ss2]) + dkYdlenx[ss1,ss2] = vyt*vyx*dkyydlyx(tdist[ss1,ss2],xdist[ss1,ss2])*( b**2*k1(tdist[ss1,ss2]) - 2*a*c*k2(xdist[ss1,ss2]) + a**2*k3(xdist[ss1,ss2]) + c**2 ) +\ + vyx*vyt*kyy(tdist[ss1,ss2],xdist[ss1,ss2])* (-2*a*c*dk2dlyx(xdist[ss1,ss2]) + a**2*dk3dlyx(xdist[ss1,ss2]) ) + else: + dka[ss1,ss2] = -k2(xdist[ss1,ss2])*vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkb[ss1,ss2] = -k4(ttdist[ss1,ss2])*vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkc[ss1,ss2] = vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + #dkYdvart[ss1,ss2] = 0 + #dkYdvarx[ss1,ss2] = 0 + #dkYdlent[ss1,ss2] = 0 + #dkYdlenx[ss1,ss2] = 0 + dkYdvart[ss1,ss2] = (-a*k2(xdist[ss1,ss2])-b*k4(ttdist[ss1,ss2])+c)*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdvarx[ss1,ss2] = (-a*k2(xdist[ss1,ss2])-b*k4(ttdist[ss1,ss2])+c)*vyt*kyy(tdist[ss1,ss2],xdist[ss1,ss2]) + dkYdlent[ss1,ss2] = vyt*vyx*dkyydlyt(tdist[ss1,ss2],xdist[ss1,ss2])* (-a*k2(xdist[ss1,ss2])-b*k4(ttdist[ss1,ss2])+c)+\ + vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2])*(-1)*b*dk4dlyt(ttdist[ss1,ss2]) + dkYdlenx[ss1,ss2] = vyt*vyx*dkyydlyx(tdist[ss1,ss2],xdist[ss1,ss2])*(-a*k2(xdist[ss1,ss2])-b*k4(ttdist[ss1,ss2])+c)+\ + vyt*vyx*kyy(tdist[ss1,ss2],xdist[ss1,ss2])*(-a*dk2dlyx(xdist[ss1,ss2])) + + self.a.gradient = np.sum(dka * dL_dK) + + self.b.gradient = np.sum(dkb * dL_dK) + + self.c.gradient = np.sum(dkc * dL_dK) + + + self.variance_Yt.gradient = np.sum(dkYdvart * dL_dK) # Vy + + self.variance_Yx.gradient = np.sum(dkYdvarx * dL_dK) + + self.lengthscale_Yt.gradient = np.sum(dkYdlent*(-0.5*self.lengthscale_Yt**(-2)) * dL_dK) #ly np.sum(dktheta2*(-self.lengthscale_Y**(-2)) * dL_dK) + + self.lengthscale_Yx.gradient = np.sum(dkYdlenx*(-0.5*self.lengthscale_Yx**(-2)) * dL_dK) +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/ODE_t.html b/doc/_build/html/_modules/GPy/kern/_src/ODE_t.html new file mode 100644 index 00000000..67173a47 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/ODE_t.html @@ -0,0 +1,259 @@ + + + + + + + + GPy.kern._src.ODE_t — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.ODE_t

      +from kern import Kern
      +from ...core.parameterization import Param
      +from ...core.parameterization.transformations import Logexp
      +import numpy as np
      +from independent_outputs import index_to_slices
      +
      +
      +
      [docs]class ODE_t(Kern): + + def __init__(self, input_dim, a=1., c=1.,variance_Yt=3., lengthscale_Yt=1.5,ubias =1., active_dims=None, name='ode_st'): + assert input_dim ==2, "only defined for 2 input dims" + super(ODE_t, self).__init__(input_dim, active_dims, name) + + self.variance_Yt = Param('variance_Yt', variance_Yt, Logexp()) + self.lengthscale_Yt = Param('lengthscale_Yt', lengthscale_Yt, Logexp()) + + self.a= Param('a', a, Logexp()) + self.c = Param('c', c, Logexp()) + self.ubias = Param('ubias', ubias, Logexp()) + self.add_parameters(self.a, self.c, self.variance_Yt, self.lengthscale_Yt,self.ubias) + +
      [docs] def K(self, X, X2=None): + """Compute the covariance matrix between X and X2.""" + X,slices = X[:,:-1],index_to_slices(X[:,-1]) + if X2 is None: + X2,slices2 = X,slices + K = np.zeros((X.shape[0], X.shape[0])) + else: + X2,slices2 = X2[:,:-1],index_to_slices(X2[:,-1]) + K = np.zeros((X.shape[0], X2.shape[0])) + + tdist = (X[:,0][:,None] - X2[:,0][None,:])**2 + ttdist = (X[:,0][:,None] - X2[:,0][None,:]) + + vyt = self.variance_Yt + + lyt=1/(2*self.lengthscale_Yt) + + a = -self.a + c = self.c + + kyy = lambda tdist: np.exp(-lyt*(tdist)) + + k1 = lambda tdist: (2*lyt - 4*lyt**2 *(tdist) ) + + k4 = lambda tdist: 2*lyt*(tdist) + + for i, s1 in enumerate(slices): + for j, s2 in enumerate(slices2): + for ss1 in s1: + for ss2 in s2: + if i==0 and j==0: + K[ss1,ss2] = vyt*kyy(tdist[ss1,ss2]) + elif i==0 and j==1: + K[ss1,ss2] = (k4(ttdist[ss1,ss2])+1)*vyt*kyy(tdist[ss1,ss2]) + #K[ss1,ss2] = (2*lyt*(ttdist[ss1,ss2])+1)*vyt*kyy(tdist[ss1,ss2]) + elif i==1 and j==1: + K[ss1,ss2] = ( k1(tdist[ss1,ss2]) + 1. )*vyt* kyy(tdist[ss1,ss2])+self.ubias + else: + K[ss1,ss2] = (-k4(ttdist[ss1,ss2])+1)*vyt*kyy(tdist[ss1,ss2]) + #K[ss1,ss2] = (-2*lyt*(ttdist[ss1,ss2])+1)*vyt*kyy(tdist[ss1,ss2]) + #stop + return K + +
      +
      [docs] def Kdiag(self, X): + + vyt = self.variance_Yt + lyt = 1./(2*self.lengthscale_Yt) + + a = -self.a + c = self.c + + k1 = (2*lyt )*vyt + + Kdiag = np.zeros(X.shape[0]) + slices = index_to_slices(X[:,-1]) + + for i, ss1 in enumerate(slices): + for s1 in ss1: + if i==0: + Kdiag[s1]+= vyt + elif i==1: + #i=1 + Kdiag[s1]+= k1 + vyt+self.ubias + #Kdiag[s1]+= Vu*Vy*(k1+k2+k3) + else: + raise ValueError, "invalid input/output index" + + return Kdiag +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + """derivative of the covariance matrix with respect to the parameters.""" + X,slices = X[:,:-1],index_to_slices(X[:,-1]) + if X2 is None: + X2,slices2 = X,slices + K = np.zeros((X.shape[0], X.shape[0])) + else: + X2,slices2 = X2[:,:-1],index_to_slices(X2[:,-1]) + + + vyt = self.variance_Yt + + lyt = 1./(2*self.lengthscale_Yt) + + tdist = (X[:,0][:,None] - X2[:,0][None,:])**2 + ttdist = (X[:,0][:,None] - X2[:,0][None,:]) + #rdist = [tdist,xdist] + + rd=tdist.shape[0] + + dka = np.zeros([rd,rd]) + dkc = np.zeros([rd,rd]) + dkYdvart = np.zeros([rd,rd]) + dkYdlent = np.zeros([rd,rd]) + + dkdubias = np.zeros([rd,rd]) + + kyy = lambda tdist: np.exp(-lyt*(tdist)) + dkyydlyt = lambda tdist: kyy(tdist)*(-tdist) + + k1 = lambda tdist: (2*lyt - 4*lyt**2 * (tdist) ) + + k4 = lambda ttdist: 2*lyt*(ttdist) + + dk1dlyt = lambda tdist: 2. - 4*2.*lyt*tdist + + dk4dlyt = lambda ttdist: 2*(ttdist) + + for i, s1 in enumerate(slices): + for j, s2 in enumerate(slices2): + for ss1 in s1: + for ss2 in s2: + if i==0 and j==0: + dkYdvart[ss1,ss2] = kyy(tdist[ss1,ss2]) + dkYdlent[ss1,ss2] = vyt*dkyydlyt(tdist[ss1,ss2]) + dkdubias[ss1,ss2] = 0 + elif i==0 and j==1: + dkYdvart[ss1,ss2] = (k4(ttdist[ss1,ss2])+1)*kyy(tdist[ss1,ss2]) + #dkYdvart[ss1,ss2] = ((2*lyt*ttdist[ss1,ss2])+1)*kyy(tdist[ss1,ss2]) + dkYdlent[ss1,ss2] = vyt*dkyydlyt(tdist[ss1,ss2])* (k4(ttdist[ss1,ss2])+1.)+\ + vyt*kyy(tdist[ss1,ss2])*(dk4dlyt(ttdist[ss1,ss2])) + #dkYdlent[ss1,ss2] = vyt*dkyydlyt(tdist[ss1,ss2])* (2*lyt*(ttdist[ss1,ss2])+1.)+\ + #vyt*kyy(tdist[ss1,ss2])*(2*ttdist[ss1,ss2]) + dkdubias[ss1,ss2] = 0 + elif i==1 and j==1: + dkYdvart[ss1,ss2] = (k1(tdist[ss1,ss2]) + 1. )* kyy(tdist[ss1,ss2]) + dkYdlent[ss1,ss2] = vyt*dkyydlyt(tdist[ss1,ss2])*( k1(tdist[ss1,ss2]) + 1. ) +\ + vyt*kyy(tdist[ss1,ss2])*dk1dlyt(tdist[ss1,ss2]) + dkdubias[ss1,ss2] = 1 + else: + dkYdvart[ss1,ss2] = (-k4(ttdist[ss1,ss2])+1)*kyy(tdist[ss1,ss2]) + #dkYdvart[ss1,ss2] = (-2*lyt*(ttdist[ss1,ss2])+1)*kyy(tdist[ss1,ss2]) + dkYdlent[ss1,ss2] = vyt*dkyydlyt(tdist[ss1,ss2])* (-k4(ttdist[ss1,ss2])+1.)+\ + vyt*kyy(tdist[ss1,ss2])*(-dk4dlyt(ttdist[ss1,ss2]) ) + dkdubias[ss1,ss2] = 0 + #dkYdlent[ss1,ss2] = vyt*dkyydlyt(tdist[ss1,ss2])* (-2*lyt*(ttdist[ss1,ss2])+1.)+\ + #vyt*kyy(tdist[ss1,ss2])*(-2)*(ttdist[ss1,ss2]) + + + self.variance_Yt.gradient = np.sum(dkYdvart * dL_dK) + + self.lengthscale_Yt.gradient = np.sum(dkYdlent*(-0.5*self.lengthscale_Yt**(-2)) * dL_dK) + + self.ubias.gradient = np.sum(dkdubias * dL_dK)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/add.html b/doc/_build/html/_modules/GPy/kern/_src/add.html new file mode 100644 index 00000000..146487ac --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/add.html @@ -0,0 +1,282 @@ + + + + + + + + GPy.kern._src.add — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.add

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +import itertools
      +from ...util.caching import Cache_this
      +from kern import CombinationKernel
      +
      +
      [docs]class Add(CombinationKernel): + """ + Add given list of kernels together. + propagates gradients through. + + This kernel will take over the active dims of it's subkernels passed in. + """ + def __init__(self, subkerns, name='add'): + for i, kern in enumerate(subkerns[:]): + if isinstance(kern, Add): + del subkerns[i] + for part in kern.parts[::-1]: + kern.unlink_parameter(part) + subkerns.insert(i, part) + + super(Add, self).__init__(subkerns, name) + + @Cache_this(limit=2, force_kwargs=['which_parts']) +
      [docs] def K(self, X, X2=None, which_parts=None): + """ + Add all kernels together. + If a list of parts (of this kernel!) `which_parts` is given, only + the parts of the list are taken to compute the covariance. + """ + if which_parts is None: + which_parts = self.parts + elif not isinstance(which_parts, (list, tuple)): + # if only one part is given + which_parts = [which_parts] + return reduce(np.add, (p.K(X, X2) for p in which_parts)) +
      + @Cache_this(limit=2, force_kwargs=['which_parts']) +
      [docs] def Kdiag(self, X, which_parts=None): + if which_parts is None: + which_parts = self.parts + elif not isinstance(which_parts, (list, tuple)): + # if only one part is given + which_parts = [which_parts] + return reduce(np.add, (p.Kdiag(X) for p in which_parts)) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + [p.update_gradients_full(dL_dK, X, X2) for p in self.parts if not p.is_fixed] +
      +
      [docs] def update_gradients_diag(self, dL_dK, X): + [p.update_gradients_diag(dL_dK, X) for p in self.parts] +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + """Compute the gradient of the objective function with respect to X. + + :param dL_dK: An array of gradients of the objective function with respect to the covariance function. + :type dL_dK: np.ndarray (num_samples x num_inducing) + :param X: Observed data inputs + :type X: np.ndarray (num_samples x input_dim) + :param X2: Observed data inputs (optional, defaults to X) + :type X2: np.ndarray (num_inducing x input_dim)""" + + target = np.zeros(X.shape) + [target.__iadd__(p.gradients_X(dL_dK, X, X2)) for p in self.parts] + return target +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + target = np.zeros(X.shape) + [target.__iadd__(p.gradients_X_diag(dL_dKdiag, X)) for p in self.parts] + return target +
      + @Cache_this(limit=2, force_kwargs=['which_parts']) +
      [docs] def psi0(self, Z, variational_posterior): + return reduce(np.add, (p.psi0(Z, variational_posterior) for p in self.parts)) +
      + @Cache_this(limit=2, force_kwargs=['which_parts']) +
      [docs] def psi1(self, Z, variational_posterior): + return reduce(np.add, (p.psi1(Z, variational_posterior) for p in self.parts)) +
      + @Cache_this(limit=2, force_kwargs=['which_parts']) +
      [docs] def psi2(self, Z, variational_posterior): + psi2 = reduce(np.add, (p.psi2(Z, variational_posterior) for p in self.parts)) + #return psi2 + # compute the "cross" terms + from static import White, Bias + from rbf import RBF + #from rbf_inv import RBFInv + from linear import Linear + #ffrom fixed import Fixed + + for p1, p2 in itertools.combinations(self.parts, 2): + # i1, i2 = p1.active_dims, p2.active_dims + # white doesn;t combine with anything + if isinstance(p1, White) or isinstance(p2, White): + pass + # rbf X bias + #elif isinstance(p1, (Bias, Fixed)) and isinstance(p2, (RBF, RBFInv)): + elif isinstance(p1, Bias) and isinstance(p2, (RBF, Linear)): + tmp = p2.psi1(Z, variational_posterior).sum(axis=0) + psi2 += p1.variance * (tmp[:,None]+tmp[None,:]) #(tmp[:, :, None] + tmp[:, None, :]) + #elif isinstance(p2, (Bias, Fixed)) and isinstance(p1, (RBF, RBFInv)): + elif isinstance(p2, Bias) and isinstance(p1, (RBF, Linear)): + tmp = p1.psi1(Z, variational_posterior).sum(axis=0) + psi2 += p2.variance * (tmp[:,None]+tmp[None,:]) #(tmp[:, :, None] + tmp[:, None, :]) + elif isinstance(p2, (RBF, Linear)) and isinstance(p1, (RBF, Linear)): + assert np.intersect1d(p1.active_dims, p2.active_dims).size == 0, "only non overlapping kernel dimensions allowed so far" + tmp1 = p1.psi1(Z, variational_posterior) + tmp2 = p2.psi1(Z, variational_posterior) + psi2 += np.einsum('nm,no->mo',tmp1,tmp2)+np.einsum('nm,no->mo',tmp2,tmp1) + #(tmp1[:, :, None] * tmp2[:, None, :]) + (tmp2[:, :, None] * tmp1[:, None, :]) + else: + raise NotImplementedError, "psi2 cannot be computed for this kernel" + return psi2 +
      +
      [docs] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + from static import White, Bias + for p1 in self.parts: + #compute the effective dL_dpsi1. Extra terms appear becaue of the cross terms in psi2! + eff_dL_dpsi1 = dL_dpsi1.copy() + for p2 in self.parts: + if p2 is p1: + continue + if isinstance(p2, White): + continue + elif isinstance(p2, Bias): + eff_dL_dpsi1 += dL_dpsi2.sum(0) * p2.variance * 2. + else:# np.setdiff1d(p1.active_dims, ar2, assume_unique): # TODO: Careful, not correct for overlapping active_dims + eff_dL_dpsi1 += dL_dpsi2.sum(0) * p2.psi1(Z, variational_posterior) * 2. + p1.update_gradients_expectations(dL_dpsi0, eff_dL_dpsi1, dL_dpsi2, Z, variational_posterior) +
      +
      [docs] def gradients_Z_expectations(self, dL_psi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + from static import White, Bias + target = np.zeros(Z.shape) + for p1 in self.parts: + #compute the effective dL_dpsi1. extra terms appear becaue of the cross terms in psi2! + eff_dL_dpsi1 = dL_dpsi1.copy() + for p2 in self.parts: + if p2 is p1: + continue + if isinstance(p2, White): + continue + elif isinstance(p2, Bias): + eff_dL_dpsi1 += dL_dpsi2.sum(0) * p2.variance * 2. + else: + eff_dL_dpsi1 += dL_dpsi2.sum(0) * p2.psi1(Z, variational_posterior) * 2. + target += p1.gradients_Z_expectations(dL_psi0, eff_dL_dpsi1, dL_dpsi2, Z, variational_posterior) + return target +
      +
      [docs] def gradients_qX_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + from static import White, Bias + target_grads = [np.zeros(v.shape) for v in variational_posterior.parameters] + for p1 in self.parameters: + #compute the effective dL_dpsi1. extra terms appear becaue of the cross terms in psi2! + eff_dL_dpsi1 = dL_dpsi1.copy() + for p2 in self.parameters: + if p2 is p1: + continue + if isinstance(p2, White): + continue + elif isinstance(p2, Bias): + eff_dL_dpsi1 += dL_dpsi2.sum(0) * p2.variance * 2. + else: + eff_dL_dpsi1 += dL_dpsi2.sum(0) * p2.psi1(Z, variational_posterior) * 2. + grads = p1.gradients_qX_expectations(dL_dpsi0, eff_dL_dpsi1, dL_dpsi2, Z, variational_posterior) + [np.add(target_grads[i],grads[i],target_grads[i]) for i in xrange(len(grads))] + return target_grads +
      +
      [docs] def add(self, other): + if isinstance(other, Add): + other_params = other.parameters[:] + for p in other_params: + other.unlink_parameter(p) + self.link_parameters(*other_params) + else: + self.link_parameter(other) + self.input_dim, self.active_dims = self.get_input_dim_active_dims(self.parts) + return self +
      +
      [docs] def input_sensitivity(self, summarize=True): + if summarize: + return reduce(np.add, [k.input_sensitivity(summarize) for k in self.parts]) + else: + i_s = np.zeros((len(self.parts), self.input_dim)) + from operator import setitem + [setitem(i_s, (i, Ellipsis), k.input_sensitivity(summarize)) for i, k in enumerate(self.parts)] + return i_s
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/brownian.html b/doc/_build/html/_modules/GPy/kern/_src/brownian.html new file mode 100644 index 00000000..6662beb3 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/brownian.html @@ -0,0 +1,141 @@ + + + + + + + + GPy.kern._src.brownian — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.brownian

      +# Copyright (c) 2012, GPy authors (see AUTHORS.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
      +import numpy as np
      +
      +
      [docs]class Brownian(Kern): + """ + Brownian motion in 1D only. + + Negative times are treated as a separate (backwards!) Brownian motion. + + :param input_dim: the number of input dimensions + :type input_dim: int + :param variance: + :type variance: float + """ + def __init__(self, input_dim=1, variance=1., active_dims=None, name='Brownian'): + assert input_dim==1, "Brownian motion in 1D only" + super(Brownian, self).__init__(input_dim, active_dims, name) + + self.variance = Param('variance', variance, Logexp()) + self.link_parameters(self.variance) + +
      [docs] def K(self,X,X2=None): + if X2 is None: + X2 = X + return self.variance*np.where(np.sign(X)==np.sign(X2.T),np.fmin(np.abs(X),np.abs(X2.T)), 0.) +
      +
      [docs] def Kdiag(self,X): + return self.variance*np.abs(X.flatten()) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + if X2 is None: + X2 = X + self.variance.gradient = np.sum(dL_dK * np.where(np.sign(X)==np.sign(X2.T),np.fmin(np.abs(X),np.abs(X2.T)), 0.)) + + #def update_gradients_diag(self, dL_dKdiag, X): + #self.variance.gradient = np.dot(np.abs(X.flatten()), dL_dKdiag) + + #def gradients_X(self, dL_dK, X, X2=None): + #if X2 is None: + #return np.sum(self.variance*dL_dK*np.abs(X),1)[:,None] + #else: + #return np.sum(np.where(np.logical_and(np.abs(X)<np.abs(X2.T), np.sign(X)==np.sign(X2)), self.variance*dL_dK,0.),1)[:,None] +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/coregionalize.html b/doc/_build/html/_modules/GPy/kern/_src/coregionalize.html new file mode 100644 index 00000000..5a9ccbb8 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/coregionalize.html @@ -0,0 +1,267 @@ + + + + + + + + GPy.kern._src.coregionalize — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.coregionalize

      +# Copyright (c) 2012, James Hensman and Ricardo Andrade
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from kern import Kern
      +import numpy as np
      +from scipy import weave
      +from ...core.parameterization import Param
      +from ...core.parameterization.transformations import Logexp
      +from ...util.config import config # for assesing whether to use weave
      +
      +
      [docs]class Coregionalize(Kern): + """ + Covariance function for intrinsic/linear coregionalization models + + This covariance has the form: + .. math:: + \mathbf{B} = \mathbf{W}\mathbf{W}^\top + \text{diag}(kappa) + + An intrinsic/linear coregionalization covariance function of the form: + .. math:: + + k_2(x, y)=\mathbf{B} k(x, y) + + it is obtained as the tensor product between a covariance function + k(x, y) and B. + + :param output_dim: number of outputs to coregionalize + :type output_dim: int + :param rank: number of columns of the W matrix (this parameter is ignored if parameter W is not None) + :type rank: int + :param W: a low rank matrix that determines the correlations between the different outputs, together with kappa it forms the coregionalization matrix B + :type W: numpy array of dimensionality (num_outpus, W_columns) + :param kappa: a vector which allows the outputs to behave independently + :type kappa: numpy array of dimensionality (output_dim, ) + + .. note: see coregionalization examples in GPy.examples.regression for some usage. + """ + def __init__(self, input_dim, output_dim, rank=1, W=None, kappa=None, active_dims=None, name='coregion'): + super(Coregionalize, self).__init__(input_dim, active_dims, name=name) + self.output_dim = output_dim + self.rank = rank + if self.rank>output_dim: + print("Warning: Unusual choice of rank, it should normally be less than the output_dim.") + if W is None: + W = 0.5*np.random.randn(self.output_dim, self.rank)/np.sqrt(self.rank) + else: + assert W.shape==(self.output_dim, self.rank) + self.W = Param('W', W) + if kappa is None: + kappa = 0.5*np.ones(self.output_dim) + else: + assert kappa.shape==(self.output_dim, ) + self.kappa = Param('kappa', kappa, Logexp()) + self.link_parameters(self.W, self.kappa) + +
      [docs] def parameters_changed(self): + self.B = np.dot(self.W, self.W.T) + np.diag(self.kappa) +
      +
      [docs] def K(self, X, X2=None): + if config.getboolean('weave', 'working'): + try: + return self._K_weave(X, X2) + except: + print "\n Weave compilation failed. Falling back to (slower) numpy implementation\n" + config.set('weave', 'working', 'False') + return self._K_numpy(X, X2) + else: + return self._K_numpy(X, X2) + +
      + def _K_numpy(self, X, X2=None): + index = np.asarray(X, dtype=np.int) + if X2 is None: + return self.B[index,index.T] + else: + index2 = np.asarray(X2, dtype=np.int) + return self.B[index,index2.T] + + def _K_weave(self, X, X2=None): + """compute the kernel function using scipy.weave""" + index = np.asarray(X, dtype=np.int) + + if X2 is None: + target = np.empty((X.shape[0], X.shape[0]), dtype=np.float64) + code=""" + for(int i=0;i<N; i++){ + target[i+i*N] = B[index[i]+output_dim*index[i]]; + for(int j=0; j<i; j++){ + target[j+i*N] = B[index[i]+output_dim*index[j]]; + target[i+j*N] = target[j+i*N]; + } + } + """ + N, B, output_dim = index.size, self.B, self.output_dim + weave.inline(code, ['target', 'index', 'N', 'B', 'output_dim']) + else: + index2 = np.asarray(X2, dtype=np.int) + target = np.empty((X.shape[0], X2.shape[0]), dtype=np.float64) + code=""" + for(int i=0;i<num_inducing; i++){ + for(int j=0; j<N; j++){ + target[i+j*num_inducing] = B[output_dim*index[j]+index2[i]]; + } + } + """ + N, num_inducing, B, output_dim = index.size, index2.size, self.B, self.output_dim + weave.inline(code, ['target', 'index', 'index2', 'N', 'num_inducing', 'B', 'output_dim']) + return target + + +
      [docs] def Kdiag(self, X): + return np.diag(self.B)[np.asarray(X, dtype=np.int).flatten()] +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + index = np.asarray(X, dtype=np.int) + if X2 is None: + index2 = index + else: + index2 = np.asarray(X2, dtype=np.int) + + #attempt to use weave for a nasty double indexing loop: fall back to numpy + if config.getboolean('weave', 'working'): + try: + dL_dK_small = self._gradient_reduce_weave(dL_dK, index, index2) + except: + print "\n Weave compilation failed. Falling back to (slower) numpy implementation\n" + config.set('weave', 'working', 'False') + dL_dK_small = self._gradient_reduce_weave(dL_dK, index, index2) + else: + dL_dK_small = self._gradient_reduce_weave(dL_dK, index, index2) + + + + dkappa = np.diag(dL_dK_small) + dL_dK_small += dL_dK_small.T + dW = (self.W[:, None, :]*dL_dK_small[:, :, None]).sum(0) + + self.W.gradient = dW + self.kappa.gradient = dkappa +
      + def _gradient_reduce_weave(self, dL_dK, index, index2): + dL_dK_small = np.zeros_like(self.B) + code=""" + for(int i=0; i<num_inducing; i++){ + for(int j=0; j<N; j++){ + dL_dK_small[index[j] + output_dim*index2[i]] += dL_dK[i+j*num_inducing]; + } + } + """ + N, num_inducing, output_dim = index.size, index2.size, self.output_dim + weave.inline(code, ['N', 'num_inducing', 'output_dim', 'dL_dK', 'dL_dK_small', 'index', 'index2']) + return dL_dK_small + + def _gradient_reduce_numpy(self, dL_dK, index, index2): + index, index2 = index[:,0], index2[:,0] + dL_dK_small = np.zeros_like(self.B) + for i in range(k.output_dim): + tmp1 = dL_dK[index==i] + for j in range(k.output_dim): + dL_dK_small[j,i] = tmp1[:,index2==j].sum() + return dL_dK_small + +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + index = np.asarray(X, dtype=np.int).flatten() + dL_dKdiag_small = np.array([dL_dKdiag[index==i].sum() for i in xrange(self.output_dim)]) + self.W.gradient = 2.*self.W*dL_dKdiag_small[:, None] + self.kappa.gradient = dL_dKdiag_small +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + return np.zeros(X.shape) +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + return np.zeros(X.shape) +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/independent_outputs.html b/doc/_build/html/_modules/GPy/kern/_src/independent_outputs.html new file mode 100644 index 00000000..759a0d28 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/independent_outputs.html @@ -0,0 +1,294 @@ + + + + + + + + GPy.kern._src.independent_outputs — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.independent_outputs

      +# Copyright (c) 2012, James Hesnsman
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +from kern import Kern, CombinationKernel
      +import numpy as np
      +import itertools
      +
      +
      [docs]def index_to_slices(index): + """ + take a numpy array of integers (index) and return a nested list of slices such that the slices describe the start, stop points for each integer in the index. + + e.g. + >>> index = np.asarray([0,0,0,1,1,1,2,2,2]) + returns + >>> [[slice(0,3,None)],[slice(3,6,None)],[slice(6,9,None)]] + + or, a more complicated example + >>> index = np.asarray([0,0,1,1,0,2,2,2,1,1]) + returns + >>> [[slice(0,2,None),slice(4,5,None)],[slice(2,4,None),slice(8,10,None)],[slice(5,8,None)]] + """ + if len(index)==0: + return[] + + #contruct the return structure + ind = np.asarray(index,dtype=np.int) + ret = [[] for i in range(ind.max()+1)] + + #find the switchpoints + ind_ = np.hstack((ind,ind[0]+ind[-1]+1)) + switchpoints = np.nonzero(ind_ - np.roll(ind_,+1))[0] + + [ret[ind_i].append(slice(*indexes_i)) for ind_i,indexes_i in zip(ind[switchpoints[:-1]],zip(switchpoints,switchpoints[1:]))] + return ret +
      +
      [docs]class IndependentOutputs(CombinationKernel): + """ + A kernel which can represent several independent functions. this kernel + 'switches off' parts of the matrix where the output indexes are different. + + The index of the functions is given by the last column in the input X the + rest of the columns of X are passed to the underlying kernel for + computation (in blocks). + + :param kernels: either a kernel, or list of kernels to work with. If it is + a list of kernels the indices in the index_dim, index the kernels you gave! + """ + def __init__(self, kernels, index_dim=-1, name='independ'): + assert isinstance(index_dim, int), "IndependentOutputs kernel is only defined with one input dimension being the index" + if not isinstance(kernels, list): + self.single_kern = True + self.kern = kernels + kernels = [kernels] + else: + self.single_kern = False + self.kern = kernels + super(IndependentOutputs, self).__init__(kernels=kernels, extra_dims=[index_dim], name=name) + self.index_dim = index_dim + +
      [docs] def K(self,X ,X2=None): + slices = index_to_slices(X[:,self.index_dim]) + kerns = itertools.repeat(self.kern) if self.single_kern else self.kern + if X2 is None: + target = np.zeros((X.shape[0], X.shape[0])) + [[target.__setitem__((s,ss), kern.K(X[s,:], X[ss,:])) for s,ss in itertools.product(slices_i, slices_i)] for kern, slices_i in zip(kerns, slices)] + else: + slices2 = index_to_slices(X2[:,self.index_dim]) + target = np.zeros((X.shape[0], X2.shape[0])) + [[target.__setitem__((s,s2), kern.K(X[s,:],X2[s2,:])) for s,s2 in itertools.product(slices_i, slices_j)] for kern, slices_i,slices_j in zip(kerns, slices,slices2)] + return target +
      +
      [docs] def Kdiag(self,X): + slices = index_to_slices(X[:,self.index_dim]) + kerns = itertools.repeat(self.kern) if self.single_kern else self.kern + target = np.zeros(X.shape[0]) + [[np.copyto(target[s], kern.Kdiag(X[s])) for s in slices_i] for kern, slices_i in zip(kerns, slices)] + return target +
      +
      [docs] def update_gradients_full(self,dL_dK,X,X2=None): + slices = index_to_slices(X[:,self.index_dim]) + if self.single_kern: + target = np.zeros(self.kern.size) + kerns = itertools.repeat(self.kern) + else: + kerns = self.kern + target = [np.zeros(kern.size) for kern, _ in zip(kerns, slices)] + def collate_grads(kern, i, dL, X, X2): + kern.update_gradients_full(dL,X,X2) + if self.single_kern: target[:] += kern.gradient + else: target[i][:] += kern.gradient + if X2 is None: + [[collate_grads(kern, i, dL_dK[s,ss], X[s], X[ss]) for s,ss in itertools.product(slices_i, slices_i)] for i,(kern,slices_i) in enumerate(zip(kerns,slices))] + else: + slices2 = index_to_slices(X2[:,self.index_dim]) + [[[collate_grads(kern, i, dL_dK[s,s2],X[s],X2[s2]) for s in slices_i] for s2 in slices_j] for i,(kern,slices_i,slices_j) in enumerate(zip(kerns,slices,slices2))] + if self.single_kern: kern.gradient = target + else:[kern.gradient.__setitem__(Ellipsis, target[i]) for i, [kern, _] in enumerate(zip(kerns, slices))] +
      +
      [docs] def gradients_X(self,dL_dK, X, X2=None): + target = np.zeros(X.shape) + kerns = itertools.repeat(self.kern) if self.single_kern else self.kern + if X2 is None: + # TODO: make use of index_to_slices + values = np.unique(X[:,self.index_dim]) + slices = [X[:,self.index_dim]==i for i in values] + [target.__setitem__(s, kern.gradients_X(dL_dK[s,s],X[s],None)) + for kern, s in zip(kerns, slices)] + #slices = index_to_slices(X[:,self.index_dim]) + #[[np.add(target[s], kern.gradients_X(dL_dK[s,s], X[s]), out=target[s]) + # for s in slices_i] for kern, slices_i in zip(kerns, slices)] + #import ipdb;ipdb.set_trace() + #[[(np.add(target[s ], kern.gradients_X(dL_dK[s ,ss],X[s ], X[ss]), out=target[s ]), + # np.add(target[ss], kern.gradients_X(dL_dK[ss,s ],X[ss], X[s ]), out=target[ss])) + # for s, ss in itertools.combinations(slices_i, 2)] for kern, slices_i in zip(kerns, slices)] + else: + values = np.unique(X[:,self.index_dim]) + slices = [X[:,self.index_dim]==i for i in values] + slices2 = [X2[:,self.index_dim]==i for i in values] + [target.__setitem__(s, kern.gradients_X(dL_dK[s, :][:, s2],X[s],X2[s2])) + for kern, s, s2 in zip(kerns, slices, slices2)] + # TODO: make work with index_to_slices + #slices = index_to_slices(X[:,self.index_dim]) + #slices2 = index_to_slices(X2[:,self.index_dim]) + #[[target.__setitem__(s, target[s] + kern.gradients_X(dL_dK[s,s2], X[s], X2[s2])) for s, s2 in itertools.product(slices_i, slices_j)] for kern, slices_i,slices_j in zip(kerns, slices,slices2)] + return target +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + slices = index_to_slices(X[:,self.index_dim]) + kerns = itertools.repeat(self.kern) if self.single_kern else self.kern + target = np.zeros(X.shape) + [[target.__setitem__(s, kern.gradients_X_diag(dL_dKdiag[s],X[s])) for s in slices_i] for kern, slices_i in zip(kerns, slices)] + return target +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + slices = index_to_slices(X[:,self.index_dim]) + kerns = itertools.repeat(self.kern) if self.single_kern else self.kern + if self.single_kern: target = np.zeros(self.kern.size) + else: target = [np.zeros(kern.size) for kern, _ in zip(kerns, slices)] + def collate_grads(kern, i, dL, X): + kern.update_gradients_diag(dL,X) + if self.single_kern: target[:] += kern.gradient + else: target[i][:] += kern.gradient + [[collate_grads(kern, i, dL_dKdiag[s], X[s,:]) for s in slices_i] for i, (kern, slices_i) in enumerate(zip(kerns, slices))] + if self.single_kern: kern.gradient = target + else:[kern.gradient.__setitem__(Ellipsis, target[i]) for i, [kern, _] in enumerate(zip(kerns, slices))] +
      +
      [docs]class Hierarchical(CombinationKernel): + """ + A kernel which can represent a simple hierarchical model. + + See Hensman et al 2013, "Hierarchical Bayesian modelling of gene expression time + series across irregularly sampled replicates and clusters" + http://www.biomedcentral.com/1471-2105/14/252 + + To construct this kernel, you must pass a list of kernels. the first kernel + will be assumed to be the 'base' kernel, and will be computed everywhere. + For every additional kernel, we assume another layer in the hierachy, with + a corresponding column of the input matrix which indexes which function the + data are in at that level. + + For more, see the ipython notebook documentation on Hierarchical + covariances. + """ + def __init__(self, kernels, name='hierarchy'): + assert all([k.input_dim==kernels[0].input_dim for k in kernels]) + assert len(kernels) > 1 + self.levels = len(kernels) -1 + input_max = max([k.input_dim for k in kernels]) + super(Hierarchical, self).__init__(kernels=kernels, extra_dims = range(input_max, input_max + len(kernels)-1), name=name) + +
      [docs] def K(self,X ,X2=None): + K = self.parts[0].K(X, X2) # compute 'base' kern everywhere + slices = [index_to_slices(X[:,i]) for i in self.extra_dims] + if X2 is None: + [[[np.add(K[s,s], k.K(X[s], None), K[s, s]) for s in slices_i] for slices_i in slices_k] for k, slices_k in zip(self.parts[1:], slices)] + else: + slices2 = [index_to_slices(X2[:,i]) for i in self.extra_dims] + [[[np.add(K[s,ss], k.K(X[s], X2[ss]), K[s, ss]) for s,ss in zip(slices_i, slices_j)] for slices_i, slices_j in zip(slices_k1, slices_k2)] for k, slices_k1, slices_k2 in zip(self.parts[1:], slices, slices2)] + return K +
      +
      [docs] def Kdiag(self,X): + return np.diag(self.K(X)) +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + raise NotImplementedError +
      +
      [docs] def update_gradients_full(self,dL_dK,X,X2=None): + slices = [index_to_slices(X[:,i]) for i in self.extra_dims] + if X2 is None: + self.parts[0].update_gradients_full(dL_dK, X, None) + for k, slices_k in zip(self.parts[1:], slices): + target = np.zeros(k.size) + def collate_grads(dL, X, X2, target): + k.update_gradients_full(dL,X,X2) + target += k.gradient + [[collate_grads(dL_dK[s,s], X[s], None, target) for s in slices_i] for slices_i in slices_k] + k.gradient[:] = target + else: + raise NotImplementedError +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/kern.html b/doc/_build/html/_modules/GPy/kern/_src/kern.html new file mode 100644 index 00000000..3ea1b0f9 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/kern.html @@ -0,0 +1,374 @@ + + + + + + + + GPy.kern._src.kern — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.kern

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import sys
      +import numpy as np
      +from ...core.parameterization.parameterized import Parameterized
      +from kernel_slice_operations import KernCallsViaSlicerMeta
      +from ...util.caching import Cache_this
      +from GPy.core.parameterization.observable_array import ObsAr
      +
      +
      +
      +
      [docs]class Kern(Parameterized): + #=========================================================================== + # This adds input slice support. The rather ugly code for slicing can be + # found in kernel_slice_operations + __metaclass__ = KernCallsViaSlicerMeta + #=========================================================================== + _support_GPU=False + def __init__(self, input_dim, active_dims, name, useGPU=False, *a, **kw): + """ + The base class for a kernel: a positive definite function + which forms of a covariance function (kernel). + + input_dim: + + is the number of dimensions to work on. Make sure to give the + tight dimensionality of inputs. + You most likely want this to be the integer telling the number of + 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 (!). + + active_dims: + + is the active_dimensions of inputs X we will work on. + All kernels will get sliced Xes as inputs, if active_dims is not None + Only positive integers are allowed in active_dims! + 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 array-like|None active_dims: list of indices on which dimensions this kernel works on, or none if no slicing + + Do not instantiate. + """ + super(Kern, self).__init__(name=name, *a, **kw) + self.input_dim = int(input_dim) + + if active_dims is None: + active_dims = np.arange(input_dim) + + self.active_dims = np.atleast_1d(active_dims).astype(int) + + assert self.active_dims.size == self.input_dim, "input_dim={} does not match len(active_dim)={}, active_dims={}".format(self.input_dim, self.active_dims.size, self.active_dims) + + self._sliced_X = 0 + self.useGPU = self._support_GPU and useGPU + self._return_psi2_n_flag = ObsAr(np.zeros(1)).astype(bool) + + @property + def return_psi2_n(self): + """ + Flag whether to pass back psi2 as NxMxM or MxM, by summing out N. + """ + return self._return_psi2_n_flag[0] + @return_psi2_n.setter + def return_psi2_n(self, val): + def visit(self): + if isinstance(self, Kern): + self._return_psi2_n_flag[0]=val + self.traverse(visit) + + @Cache_this(limit=20) + def _slice_X(self, X): + return X[:, self.active_dims] + +
      [docs] def K(self, X, X2): + """ + Compute the kernel function. + + :param X: the first set of inputs to the kernel + :param X2: (optional) the second set of arguments to the kernel. If X2 + is None, this is passed throgh to the 'part' object, which + handLes this as X2 == X. + """ + raise NotImplementedError
      +
      [docs] def Kdiag(self, X): + raise NotImplementedError
      +
      [docs] def psi0(self, Z, variational_posterior): + raise NotImplementedError
      +
      [docs] def psi1(self, Z, variational_posterior): + raise NotImplementedError
      +
      [docs] def psi2(self, Z, variational_posterior): + raise NotImplementedError
      +
      [docs] def gradients_X(self, dL_dK, X, X2): + raise NotImplementedError
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + raise NotImplementedError +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + """ update the gradients of all parameters when using only the diagonal elements of the covariance matrix""" + raise NotImplementedError +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2): + """Set the gradients of all parameters when doing full (N) inference.""" + raise NotImplementedError +
      +
      [docs] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + """ + Set the gradients of all parameters when doing inference with + uncertain inputs, using expectations of the kernel. + + The esential maths is + + dL_d{theta_i} = dL_dpsi0 * dpsi0_d{theta_i} + + dL_dpsi1 * dpsi1_d{theta_i} + + dL_dpsi2 * dpsi2_d{theta_i} + """ + raise NotImplementedError +
      +
      [docs] def gradients_Z_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + """ + Returns the derivative of the objective wrt Z, using the chain rule + through the expectation variables. + """ + raise NotImplementedError +
      +
      [docs] def gradients_qX_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + """ + Compute the gradients wrt the parameters of the variational + distruibution q(X), chain-ruling via the expectations of the kernel + """ + raise NotImplementedError +
      +
      [docs] def plot(self, x=None, fignum=None, ax=None, title=None, plot_limits=None, resolution=None, **mpl_kwargs): + """ + plot this kernel. + :param x: the value to use for the other kernel argument (kernels are a function of two variables!) + :param fignum: figure number of the plot + :param ax: matplotlib axis to plot on + :param title: the matplotlib title + :param plot_limits: the range over which to plot the kernel + :resolution: the resolution of the lines used in plotting + :mpl_kwargs avalid keyword arguments to pass through to matplotlib (e.g. lw=7) + """ + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ...plotting.matplot_dep import kernel_plots + kernel_plots.plot(self, x, fignum, ax, title, plot_limits, resolution, **mpl_kwargs) +
      +
      [docs] def plot_ARD(self, *args, **kw): + """ + See :class:`~GPy.plotting.matplot_dep.kernel_plots` + """ + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ...plotting.matplot_dep import kernel_plots + return kernel_plots.plot_ARD(self,*args,**kw) +
      +
      [docs] def input_sensitivity(self, summarize=True): + """ + Returns the sensitivity for each dimension of this kernel. + """ + return np.zeros(self.input_dim) +
      + def __add__(self, other): + """ Overloading of the '+' operator. for more control, see self.add """ + return self.add(other) + + def __iadd__(self, other): + return self.add(other) + +
      [docs] def add(self, other, name='add'): + """ + Add another kernel to this one. + + :param other: the other kernel to be added + :type other: GPy.kern + + """ + assert isinstance(other, Kern), "only kernels can be added to kernels..." + from add import Add + return Add([self, other], name=name) +
      + def __mul__(self, other): + """ Here we overload the '*' operator. See self.prod for more information""" + return self.prod(other) + + def __imul__(self, other): + """ Here we overload the '*' operator. See self.prod for more information""" + return self.prod(other) + + def __pow__(self, other): + """ + Shortcut for tensor `prod`. + """ + assert np.all(self.active_dims == range(self.input_dim)), "Can only use kernels, which have their input_dims defined from 0" + assert np.all(other.active_dims == range(other.input_dim)), "Can only use kernels, which have their input_dims defined from 0" + other.active_dims += self.input_dim + return self.prod(other) + +
      [docs] def prod(self, other, name='mul'): + """ + Multiply two kernels (either on the same space, or on the tensor + product of the input space). + + :param other: the other kernel to be added + :type other: GPy.kern + :param tensor: whether or not to use the tensor space (default is false). + :type tensor: bool + + """ + assert isinstance(other, Kern), "only kernels can be multiplied to kernels..." + from prod import Prod + #kernels = [] + #if isinstance(self, Prod): kernels.extend(self.parameters) + #else: kernels.append(self) + #if isinstance(other, Prod): kernels.extend(other.parameters) + #else: kernels.append(other) + return Prod([self, other], name) +
      + def _check_input_dim(self, X): + assert X.shape[1] == self.input_dim, "{} did not specify active_dims and X has wrong shape: X_dim={}, whereas input_dim={}".format(self.name, X.shape[1], self.input_dim) + + def _check_active_dims(self, X): + assert X.shape[1] >= len(self.active_dims), "At least {} dimensional X needed, X.shape={!s}".format(len(self.active_dims), X.shape) + +
      +
      [docs]class CombinationKernel(Kern): + """ + Abstract super class for combination kernels. + A combination kernel combines (a list of) kernels and works on those. + Examples are the HierarchicalKernel or Add and Prod kernels. + """ + def __init__(self, kernels, name, extra_dims=[]): + """ + Abstract super class for combination kernels. + A combination kernel combines (a list of) kernels and works on those. + Examples are the HierarchicalKernel or Add and Prod kernels. + + :param list kernels: List of kernels to combine (can be only one element) + :param str name: name of the combination kernel + :param array-like extra_dims: if needed extra dimensions for the combination kernel to work on + """ + assert all([isinstance(k, Kern) for k in kernels]) + extra_dims = np.array(extra_dims, dtype=int) + input_dim, active_dims = self.get_input_dim_active_dims(kernels, extra_dims) + # initialize the kernel with the full input_dim + super(CombinationKernel, self).__init__(input_dim, active_dims, name) + self.extra_dims = extra_dims + self.link_parameters(*kernels) + + @property + def parts(self): + return self.parameters + +
      [docs] def get_input_dim_active_dims(self, kernels, extra_dims = None): + #active_dims = reduce(np.union1d, (np.r_[x.active_dims] for x in kernels), np.array([], dtype=int)) + #active_dims = np.array(np.concatenate((active_dims, extra_dims if extra_dims is not None else [])), dtype=int) + input_dim = reduce(max, (k.active_dims.max() for k in kernels)) + 1 + + if extra_dims is not None: + input_dim += extra_dims.size + + active_dims = np.arange(input_dim) + return input_dim, active_dims +
      +
      [docs] def input_sensitivity(self, summarize=True): + """ + If summize is true, we want to get the summerized view of the sensitivities, + otherwise put everything into an array with shape (#kernels, input_dim) + in the order of appearance of the kernels in the parameterized object. + """ + raise NotImplementedError("Choose the kernel you want to get the sensitivity for. You need to override the default behaviour for getting the input sensitivity to be able to get the input sensitivity. For sum kernel it is the sum of all sensitivities, TODO: product kernel? Other kernels?, also TODO: shall we return all the sensitivities here in the combination kernel? So we can combine them however we want? This could lead to just plot all the sensitivities here...") +
      + def _check_active_dims(self, X): + return + + def _check_input_dim(self, X): + # As combination kernels cannot always know, what their inner kernels have as input dims, the check will be done inside them, respectively + return
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/kernel_slice_operations.html b/doc/_build/html/_modules/GPy/kern/_src/kernel_slice_operations.html new file mode 100644 index 00000000..77ca8b56 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/kernel_slice_operations.html @@ -0,0 +1,237 @@ + + + + + + + + GPy.kern._src.kernel_slice_operations — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.kernel_slice_operations

      +'''
      +Created on 11 Mar 2014
      +
      +@author: maxz
      +'''
      +from ...core.parameterization.parameterized import ParametersChangedMeta
      +import numpy as np
      +from functools import wraps
      +
      +
      [docs]def put_clean(dct, name, func): + if name in dct: + dct['_clean_{}'.format(name)] = dct[name] + dct[name] = func(dct[name]) +
      +
      [docs]class KernCallsViaSlicerMeta(ParametersChangedMeta): + def __new__(cls, name, bases, dct): + put_clean(dct, 'K', _slice_K) + put_clean(dct, 'Kdiag', _slice_Kdiag) + put_clean(dct, 'update_gradients_full', _slice_update_gradients_full) + put_clean(dct, 'update_gradients_diag', _slice_update_gradients_diag) + put_clean(dct, 'gradients_X', _slice_gradients_X) + put_clean(dct, 'gradients_X_diag', _slice_gradients_X_diag) + + put_clean(dct, 'psi0', _slice_psi) + put_clean(dct, 'psi1', _slice_psi) + put_clean(dct, 'psi2', _slice_psi) + put_clean(dct, 'update_gradients_expectations', _slice_update_gradients_expectations) + put_clean(dct, 'gradients_Z_expectations', _slice_gradients_Z_expectations) + put_clean(dct, 'gradients_qX_expectations', _slice_gradients_qX_expectations) + return super(KernCallsViaSlicerMeta, cls).__new__(cls, name, bases, dct) +
      +class _Slice_wrap(object): + def __init__(self, k, X, X2=None): + self.k = k + self.shape = X.shape + assert X.ndim == 2, "only matrices are allowed as inputs to kernels for now, given X.shape={!s}".format(X.shape) + if X2 is not None: + assert X2.ndim == 2, "only matrices are allowed as inputs to kernels for now, given X2.shape={!s}".format(X2.shape) + if (self.k.active_dims is not None) and (self.k._sliced_X == 0): + self.k._check_active_dims(X) + self.X = self.k._slice_X(X) + self.X2 = self.k._slice_X(X2) if X2 is not None else X2 + self.ret = True + else: + self.k._check_input_dim(X) + self.X = X + self.X2 = X2 + self.ret = False + def __enter__(self): + self.k._sliced_X += 1 + return self + def __exit__(self, *a): + self.k._sliced_X -= 1 + def handle_return_array(self, return_val): + if self.ret: + ret = np.zeros(self.shape) + ret[:, self.k.active_dims] = return_val + return ret + return return_val + +def _slice_K(f): + @wraps(f) + def wrap(self, X, X2 = None, *a, **kw): + with _Slice_wrap(self, X, X2) as s: + ret = f(self, s.X, s.X2, *a, **kw) + return ret + return wrap + +def _slice_Kdiag(f): + @wraps(f) + def wrap(self, X, *a, **kw): + with _Slice_wrap(self, X, None) as s: + ret = f(self, s.X, *a, **kw) + return ret + return wrap + +def _slice_update_gradients_full(f): + @wraps(f) + def wrap(self, dL_dK, X, X2=None): + with _Slice_wrap(self, X, X2) as s: + ret = f(self, dL_dK, s.X, s.X2) + return ret + return wrap + +def _slice_update_gradients_diag(f): + @wraps(f) + def wrap(self, dL_dKdiag, X): + with _Slice_wrap(self, X, None) as s: + ret = f(self, dL_dKdiag, s.X) + return ret + return wrap + +def _slice_gradients_X(f): + @wraps(f) + def wrap(self, dL_dK, X, X2=None): + with _Slice_wrap(self, X, X2) as s: + ret = s.handle_return_array(f(self, dL_dK, s.X, s.X2)) + return ret + return wrap + +def _slice_gradients_X_diag(f): + @wraps(f) + def wrap(self, dL_dKdiag, X): + with _Slice_wrap(self, X, None) as s: + ret = s.handle_return_array(f(self, dL_dKdiag, s.X)) + return ret + return wrap + +def _slice_psi(f): + @wraps(f) + def wrap(self, Z, variational_posterior): + with _Slice_wrap(self, Z, variational_posterior) as s: + ret = f(self, s.X, s.X2) + return ret + return wrap + +def _slice_update_gradients_expectations(f): + @wraps(f) + def wrap(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + with _Slice_wrap(self, Z, variational_posterior) as s: + ret = f(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, s.X, s.X2) + return ret + return wrap + +def _slice_gradients_Z_expectations(f): + @wraps(f) + def wrap(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + with _Slice_wrap(self, Z, variational_posterior) as s: + ret = s.handle_return_array(f(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, s.X, s.X2)) + return ret + return wrap + +def _slice_gradients_qX_expectations(f): + @wraps(f) + def wrap(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + with _Slice_wrap(self, variational_posterior, Z) as s: + ret = list(f(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, s.X2, s.X)) + r2 = ret[:2] + ret[0] = s.handle_return_array(r2[0]) + ret[1] = s.handle_return_array(r2[1]) + del r2 + return ret + return wrap +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/linear.html b/doc/_build/html/_modules/GPy/kern/_src/linear.html new file mode 100644 index 00000000..8ed9a433 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/linear.html @@ -0,0 +1,269 @@ + + + + + + + + GPy.kern._src.linear — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.linear

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from kern import Kern
      +from ...util.linalg import tdot
      +from ...core.parameterization import Param
      +from ...core.parameterization.transformations import Logexp
      +from ...util.caching import Cache_this
      +from ...util.config import *
      +from .psi_comp import PSICOMP_Linear
      +
      +
      [docs]class Linear(Kern): + """ + Linear kernel + + .. math:: + + k(x,y) = \sum_{i=1}^input_dim \sigma^2_i x_iy_i + + :param input_dim: the number of input dimensions + :type input_dim: int + :param variances: the vector of variances :math:`\sigma^2_i` + :type variances: array or list of the appropriate size (or float if there + is only one variance parameter) + :param ARD: Auto Relevance Determination. If False, the kernel has only one + variance parameter \sigma^2, otherwise there is one variance + parameter per dimension. + :type ARD: Boolean + :rtype: kernel object + + """ + + def __init__(self, input_dim, variances=None, ARD=False, active_dims=None, name='linear'): + super(Linear, self).__init__(input_dim, active_dims, name) + self.ARD = ARD + if not ARD: + if variances is not None: + variances = np.asarray(variances) + assert variances.size == 1, "Only one variance needed for non-ARD kernel" + else: + variances = np.ones(1) + else: + if variances is not None: + variances = np.asarray(variances) + assert variances.size == self.input_dim, "bad number of variances, need one ARD variance per input_dim" + else: + variances = np.ones(self.input_dim) + + self.variances = Param('variances', variances, Logexp()) + self.link_parameter(self.variances) + self.psicomp = PSICOMP_Linear() + + @Cache_this(limit=2) +
      [docs] def K(self, X, X2=None): + if self.ARD: + if X2 is None: + return tdot(X*np.sqrt(self.variances)) + else: + rv = np.sqrt(self.variances) + return np.dot(X*rv, (X2*rv).T) + else: + return self._dot_product(X, X2) * self.variances +
      + @Cache_this(limit=1, ignore_args=(0,)) + def _dot_product(self, X, X2=None): + if X2 is None: + return tdot(X) + else: + return np.dot(X, X2.T) + +
      [docs] def Kdiag(self, X): + return np.sum(self.variances * np.square(X), -1) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + if self.ARD: + if X2 is None: + #self.variances.gradient = np.array([np.sum(dL_dK * tdot(X[:, i:i + 1])) for i in range(self.input_dim)]) + self.variances.gradient = np.einsum('ij,iq,jq->q', dL_dK, X, X) + else: + #product = X[:, None, :] * X2[None, :, :] + #self.variances.gradient = (dL_dK[:, :, None] * product).sum(0).sum(0) + self.variances.gradient = np.einsum('ij,iq,jq->q', dL_dK, X, X2) + else: + self.variances.gradient = np.sum(self._dot_product(X, X2) * dL_dK) +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + tmp = dL_dKdiag[:, None] * X ** 2 + if self.ARD: + self.variances.gradient = tmp.sum(0) + else: + self.variances.gradient = np.atleast_1d(tmp.sum()) + +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + if X2 is None: + return np.einsum('jq,q,ij->iq', X, 2*self.variances, dL_dK) + else: + #return (((X2[None,:, :] * self.variances)) * dL_dK[:, :, None]).sum(1) + return np.einsum('jq,q,ij->iq', X2, self.variances, dL_dK) +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + return 2.*self.variances*dL_dKdiag[:,None]*X +
      +
      [docs] def input_sensitivity(self, summarize=True): + return np.ones(self.input_dim) * self.variances + + #---------------------------------------# + # PSI statistics # + #---------------------------------------# +
      +
      [docs] def psi0(self, Z, variational_posterior): + return self.psicomp.psicomputations(self.variances, Z, variational_posterior)[0] +
      +
      [docs] def psi1(self, Z, variational_posterior): + return self.psicomp.psicomputations(self.variances, Z, variational_posterior)[1] +
      +
      [docs] def psi2(self, Z, variational_posterior): + return self.psicomp.psicomputations(self.variances, Z, variational_posterior)[2] +
      +
      [docs] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + dL_dvar = self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variances, Z, variational_posterior)[0] + if self.ARD: + self.variances.gradient = dL_dvar + else: + self.variances.gradient = dL_dvar.sum() +
      +
      [docs] def gradients_Z_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + return self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variances, Z, variational_posterior)[1] +
      +
      [docs] def gradients_qX_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + return self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variances, Z, variational_posterior)[2:] +
      +
      [docs]class LinearFull(Kern): + def __init__(self, input_dim, rank, W=None, kappa=None, active_dims=None, name='linear_full'): + super(LinearFull, self).__init__(input_dim, active_dims, name) + if W is None: + W = np.ones((input_dim, rank)) + if kappa is None: + kappa = np.ones(input_dim) + assert W.shape == (input_dim, rank) + assert kappa.shape == (input_dim,) + + self.W = Param('W', W) + self.kappa = Param('kappa', kappa, Logexp()) + self.link_parameters(self.W, self.kappa) + +
      [docs] def K(self, X, X2=None): + P = np.dot(self.W, self.W.T) + np.diag(self.kappa) + return np.einsum('ij,jk,lk->il', X, P, X if X2 is None else X2) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + self.kappa.gradient = np.einsum('ij,ik,kj->j', X, dL_dK, X if X2 is None else X2) + self.W.gradient = np.einsum('ij,kl,ik,lm->jm', X, X if X2 is None else X2, dL_dK, self.W) + self.W.gradient += np.einsum('ij,kl,ik,jm->lm', X, X if X2 is None else X2, dL_dK, self.W) +
      +
      [docs] def Kdiag(self, X): + P = np.dot(self.W, self.W.T) + np.diag(self.kappa) + return np.einsum('ij,jk,ik->i', X, P, X) +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + self.kappa.gradient = np.einsum('ij,i->j', np.square(X), dL_dKdiag) + self.W.gradient = 2.*np.einsum('ij,ik,jl,i->kl', X, X, self.W, dL_dKdiag) +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + P = np.dot(self.W, self.W.T) + np.diag(self.kappa) + if X2 is None: + return 2.*np.einsum('ij,jk,kl->il', dL_dK, X, P) + else: + return np.einsum('ij,jk,kl->il', dL_dK, X2, P) +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + P = np.dot(self.W, self.W.T) + np.diag(self.kappa) + return 2.*np.einsum('jk,i,ij->ik', P, dL_dKdiag, X) +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/mlp.html b/doc/_build/html/_modules/GPy/kern/_src/mlp.html new file mode 100644 index 00000000..76a31a8e --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/mlp.html @@ -0,0 +1,223 @@ + + + + + + + + GPy.kern._src.mlp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.mlp

      +# Copyright (c) 2013, GPy authors (see AUTHORS.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
      +import numpy as np
      +four_over_tau = 2./np.pi
      +
      +
      [docs]class MLP(Kern): + """ + + Multi layer perceptron kernel (also known as arc sine kernel or neural network kernel) + + .. math:: + + k(x,y) = \\sigma^{2}\\frac{2}{\\pi } \\text{asin} \\left ( \\frac{ \\sigma_w^2 x^\\top y+\\sigma_b^2}{\\sqrt{\\sigma_w^2x^\\top x + \\sigma_b^2 + 1}\\sqrt{\\sigma_w^2 y^\\top y \\sigma_b^2 +1}} \\right ) + + + :param input_dim: the number of input dimensions + :type input_dim: int + :param variance: the variance :math:`\sigma^2` + :type variance: float + :param weight_variance: the vector of the variances of the prior over input weights in the neural network :math:`\sigma^2_w` + :type weight_variance: array or list of the appropriate size (or float if there is only one weight variance parameter) + :param bias_variance: the variance of the prior over bias parameters :math:`\sigma^2_b` + :param ARD: Auto Relevance Determination. If equal to "False", the kernel is isotropic (ie. one weight variance parameter \sigma^2_w), otherwise there is one weight variance parameter per dimension. + :type ARD: Boolean + :rtype: Kernpart object + + + """ + + def __init__(self, input_dim, variance=1., weight_variance=1., bias_variance=100., active_dims=None, name='mlp'): + super(MLP, self).__init__(input_dim, active_dims, name) + self.variance = Param('variance', variance, Logexp()) + self.weight_variance = Param('weight_variance', weight_variance, Logexp()) + self.bias_variance = Param('bias_variance', bias_variance, Logexp()) + self.link_parameters(self.variance, self.weight_variance, self.bias_variance) + + +
      [docs] def K(self, X, X2=None): + self._K_computations(X, X2) + return self.variance*self._K_dvar +
      +
      [docs] def Kdiag(self, X): + """Compute the diagonal of the covariance matrix for X.""" + self._K_diag_computations(X) + return self.variance*self._K_diag_dvar +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + """Derivative of the covariance with respect to the parameters.""" + self._K_computations(X, X2) + self.variance.gradient = np.sum(self._K_dvar*dL_dK) + + denom3 = self._K_denom**3 + base = four_over_tau*self.variance/np.sqrt(1-self._K_asin_arg*self._K_asin_arg) + base_cov_grad = base*dL_dK + + if X2 is None: + vec = np.diag(self._K_inner_prod) + self.weight_variance.gradient = ((self._K_inner_prod/self._K_denom + -.5*self._K_numer/denom3 + *(np.outer((self.weight_variance*vec+self.bias_variance+1.), vec) + +np.outer(vec,(self.weight_variance*vec+self.bias_variance+1.))))*base_cov_grad).sum() + self.bias_variance.gradient = ((1./self._K_denom + -.5*self._K_numer/denom3 + *((vec[None, :]+vec[:, None])*self.weight_variance + +2.*self.bias_variance + 2.))*base_cov_grad).sum() + else: + vec1 = (X*X).sum(1) + vec2 = (X2*X2).sum(1) + self.weight_variance.gradient = ((self._K_inner_prod/self._K_denom + -.5*self._K_numer/denom3 + *(np.outer((self.weight_variance*vec1+self.bias_variance+1.), vec2) + np.outer(vec1, self.weight_variance*vec2 + self.bias_variance+1.)))*base_cov_grad).sum() + self.bias_variance.gradient = ((1./self._K_denom + -.5*self._K_numer/denom3 + *((vec1[:, None]+vec2[None, :])*self.weight_variance + + 2*self.bias_variance + 2.))*base_cov_grad).sum() +
      +
      [docs] def update_gradients_diag(self, X): + raise NotImplementedError, "TODO" + +
      +
      [docs] def gradients_X(self, dL_dK, X, X2): + """Derivative of the covariance matrix with respect to X""" + self._K_computations(X, X2) + arg = self._K_asin_arg + numer = self._K_numer + denom = self._K_denom + denom3 = denom*denom*denom + if X2 is not None: + vec2 = (X2*X2).sum(1)*self.weight_variance+self.bias_variance + 1. + return four_over_tau*self.weight_variance*self.variance*((X2[None, :, :]/denom[:, :, None] - vec2[None, :, None]*X[:, None, :]*(numer/denom3)[:, :, None])*(dL_dK/np.sqrt(1-arg*arg))[:, :, None]).sum(1) + else: + vec = (X*X).sum(1)*self.weight_variance+self.bias_variance + 1. + return 2*four_over_tau*self.weight_variance*self.variance*((X[None, :, :]/denom[:, :, None] - vec[None, :, None]*X[:, None, :]*(numer/denom3)[:, :, None])*(dL_dK/np.sqrt(1-arg*arg))[:, :, None]).sum(1) +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + """Gradient of diagonal of covariance with respect to X""" + self._K_diag_computations(X) + arg = self._K_diag_asin_arg + denom = self._K_diag_denom + #numer = self._K_diag_numer + return four_over_tau*2.*self.weight_variance*self.variance*X*(1./denom*(1. - arg)*dL_dKdiag/(np.sqrt(1-arg*arg)))[:, None] + +
      + def _K_computations(self, X, X2): + """Pre-computations for the covariance matrix (used for computing the covariance and its gradients.""" + if X2 is None: + self._K_inner_prod = np.dot(X,X.T) + self._K_numer = self._K_inner_prod*self.weight_variance + self.bias_variance + vec = np.diag(self._K_numer) + 1. + self._K_denom = np.sqrt(np.outer(vec,vec)) + else: + self._K_inner_prod = np.dot(X,X2.T) + self._K_numer = self._K_inner_prod*self.weight_variance + self.bias_variance + vec1 = (X*X).sum(1)*self.weight_variance + self.bias_variance + 1. + vec2 = (X2*X2).sum(1)*self.weight_variance + self.bias_variance + 1. + self._K_denom = np.sqrt(np.outer(vec1,vec2)) + self._K_asin_arg = self._K_numer/self._K_denom + self._K_dvar = four_over_tau*np.arcsin(self._K_asin_arg) + + def _K_diag_computations(self, X): + """Pre-computations concerning the diagonal terms (used for computation of diagonal and its gradients).""" + self._K_diag_numer = (X*X).sum(1)*self.weight_variance + self.bias_variance + self._K_diag_denom = self._K_diag_numer+1. + self._K_diag_asin_arg = self._K_diag_numer/self._K_diag_denom + self._K_diag_dvar = four_over_tau*np.arcsin(self._K_diag_asin_arg)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/periodic.html b/doc/_build/html/_modules/GPy/kern/_src/periodic.html new file mode 100644 index 00000000..f5c13619 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/periodic.html @@ -0,0 +1,498 @@ + + + + + + + + GPy.kern._src.periodic — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.periodic

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from kern import Kern
      +from ...util.linalg import mdot
      +from ...util.decorators import silence_errors
      +from ...core.parameterization.param import Param
      +from ...core.parameterization.transformations import Logexp
      +
      +
      [docs]class Periodic(Kern): + def __init__(self, input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name): + """ + :type input_dim: int + :param variance: the variance of the Matern kernel + :type variance: float + :param lengthscale: the lengthscale of the Matern kernel + :type lengthscale: np.ndarray of size (input_dim,) + :param period: the period + :type period: float + :param n_freq: the number of frequencies considered for the periodic subspace + :type n_freq: int + :rtype: kernel object + """ + + assert input_dim==1, "Periodic kernels are only defined for input_dim=1" + super(Periodic, self).__init__(input_dim, active_dims, name) + self.input_dim = input_dim + self.lower,self.upper = lower, upper + self.n_freq = n_freq + self.n_basis = 2*n_freq + self.variance = Param('variance', np.float64(variance), Logexp()) + self.lengthscale = Param('lengthscale', np.float64(lengthscale), Logexp()) + self.period = Param('period', np.float64(period), Logexp()) + self.link_parameters(self.variance, self.lengthscale, self.period) + + def _cos(self, alpha, omega, phase): + def f(x): + return alpha*np.cos(omega*x + phase) + return f + + @silence_errors + def _cos_factorization(self, alpha, omega, phase): + r1 = np.sum(alpha*np.cos(phase),axis=1)[:,None] + r2 = np.sum(alpha*np.sin(phase),axis=1)[:,None] + r = np.sqrt(r1**2 + r2**2) + psi = np.where(r1 != 0, (np.arctan(r2/r1) + (r1<0.)*np.pi),np.arcsin(r2)) + return r,omega[:,0:1], psi + + @silence_errors + def _int_computation(self,r1,omega1,phi1,r2,omega2,phi2): + Gint1 = 1./(omega1+omega2.T)*( np.sin((omega1+omega2.T)*self.upper+phi1+phi2.T) - np.sin((omega1+omega2.T)*self.lower+phi1+phi2.T)) + 1./(omega1-omega2.T)*( np.sin((omega1-omega2.T)*self.upper+phi1-phi2.T) - np.sin((omega1-omega2.T)*self.lower+phi1-phi2.T) ) + Gint2 = 1./(omega1+omega2.T)*( np.sin((omega1+omega2.T)*self.upper+phi1+phi2.T) - np.sin((omega1+omega2.T)*self.lower+phi1+phi2.T)) + np.cos(phi1-phi2.T)*(self.upper-self.lower) + Gint = np.dot(r1,r2.T)/2 * np.where(np.isnan(Gint1),Gint2,Gint1) + return Gint + +
      [docs] def K(self, X, X2=None): + FX = self._cos(self.basis_alpha[None,:],self.basis_omega[None,:],self.basis_phi[None,:])(X) + if X2 is None: + FX2 = FX + else: + FX2 = self._cos(self.basis_alpha[None,:],self.basis_omega[None,:],self.basis_phi[None,:])(X2) + return mdot(FX,self.Gi,FX2.T) +
      +
      [docs] def Kdiag(self,X): + return np.diag(self.K(X)) + + + +
      +
      [docs]class PeriodicExponential(Periodic): + """ + Kernel of the periodic subspace (up to a given frequency) of a exponential + (Matern 1/2) RKHS. + + Only defined for input_dim=1. + """ + + def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, active_dims=None, name='periodic_exponential'): + super(PeriodicExponential, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name) + +
      [docs] def parameters_changed(self): + self.a = [1./self.lengthscale, 1.] + self.b = [1] + + self.basis_alpha = np.ones((self.n_basis,)) + self.basis_omega = (2*np.pi*np.arange(1,self.n_freq+1)/self.period).repeat(2) + self.basis_phi = np.zeros(self.n_freq * 2) + self.basis_phi[::2] = -np.pi/2 + + self.G = self.Gram_matrix() + self.Gi = np.linalg.inv(self.G) +
      +
      [docs] def Gram_matrix(self): + La = np.column_stack((self.a[0]*np.ones((self.n_basis,1)),self.a[1]*self.basis_omega)) + Lo = np.column_stack((self.basis_omega,self.basis_omega)) + Lp = np.column_stack((self.basis_phi,self.basis_phi+np.pi/2)) + r,omega,phi = self._cos_factorization(La,Lo,Lp) + Gint = self._int_computation( r,omega,phi, r,omega,phi) + Flower = np.array(self._cos(self.basis_alpha,self.basis_omega,self.basis_phi)(self.lower))[:,None] + return(self.lengthscale/(2*self.variance) * Gint + 1./self.variance*np.dot(Flower,Flower.T)) +
      + @silence_errors +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + """derivative of the covariance matrix with respect to the parameters (shape is N x num_inducing x num_params)""" + if X2 is None: X2 = X + FX = self._cos(self.basis_alpha[None,:],self.basis_omega[None,:],self.basis_phi[None,:])(X) + FX2 = self._cos(self.basis_alpha[None,:],self.basis_omega[None,:],self.basis_phi[None,:])(X2) + + La = np.column_stack((self.a[0]*np.ones((self.n_basis,1)),self.a[1]*self.basis_omega)) + Lo = np.column_stack((self.basis_omega,self.basis_omega)) + Lp = np.column_stack((self.basis_phi,self.basis_phi+np.pi/2)) + r,omega,phi = self._cos_factorization(La,Lo,Lp) + Gint = self._int_computation( r,omega,phi, r,omega,phi) + + Flower = np.array(self._cos(self.basis_alpha,self.basis_omega,self.basis_phi)(self.lower))[:,None] + + #dK_dvar + dK_dvar = 1./self.variance*mdot(FX,self.Gi,FX2.T) + + #dK_dlen + da_dlen = [-1./self.lengthscale**2,0.] + dLa_dlen = np.column_stack((da_dlen[0]*np.ones((self.n_basis,1)),da_dlen[1]*self.basis_omega)) + r1,omega1,phi1 = self._cos_factorization(dLa_dlen,Lo,Lp) + dGint_dlen = self._int_computation(r1,omega1,phi1, r,omega,phi) + dGint_dlen = dGint_dlen + dGint_dlen.T + dG_dlen = 1./2*Gint + self.lengthscale/2*dGint_dlen + dK_dlen = -mdot(FX,self.Gi,dG_dlen/self.variance,self.Gi,FX2.T) + + #dK_dper + dFX_dper = self._cos(-self.basis_alpha[None,:]*self.basis_omega[None,:]/self.period*X ,self.basis_omega[None,:],self.basis_phi[None,:]+np.pi/2)(X) + dFX2_dper = self._cos(-self.basis_alpha[None,:]*self.basis_omega[None,:]/self.period*X2,self.basis_omega[None,:],self.basis_phi[None,:]+np.pi/2)(X2) + + dLa_dper = np.column_stack((-self.a[0]*self.basis_omega/self.period, -self.a[1]*self.basis_omega**2/self.period)) + dLp_dper = np.column_stack((self.basis_phi+np.pi/2,self.basis_phi+np.pi)) + r1,omega1,phi1 = self._cos_factorization(dLa_dper,Lo,dLp_dper) + + IPPprim1 = self.upper*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi/2) + 1./(omega-omega1.T)*np.cos((omega-omega1.T)*self.upper+phi-phi1.T-np.pi/2)) + IPPprim1 -= self.lower*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi/2) + 1./(omega-omega1.T)*np.cos((omega-omega1.T)*self.lower+phi-phi1.T-np.pi/2)) + # SIMPLIFY!!! IPPprim1 = (self.upper - self.lower)*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi/2) + 1./(omega-omega1.T)*np.cos((omega-omega1.T)*self.upper+phi-phi1.T-np.pi/2)) + IPPprim2 = self.upper*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi/2) + self.upper*np.cos(phi-phi1.T)) + IPPprim2 -= self.lower*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi/2) + self.lower*np.cos(phi-phi1.T)) + IPPprim = np.where(np.logical_or(np.isnan(IPPprim1), np.isinf(IPPprim1)), IPPprim2, IPPprim1) + + + IPPint1 = 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi) + 1./(omega-omega1.T)**2*np.cos((omega-omega1.T)*self.upper+phi-phi1.T-np.pi) + IPPint1 -= 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi) + 1./(omega-omega1.T)**2*np.cos((omega-omega1.T)*self.lower+phi-phi1.T-np.pi) + IPPint2 = 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi) + 1./2*self.upper**2*np.cos(phi-phi1.T) + IPPint2 -= 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi) + 1./2*self.lower**2*np.cos(phi-phi1.T) + #IPPint2[0,0] = (self.upper**2 - self.lower**2)*np.cos(phi[0,0])*np.cos(phi1[0,0]) + IPPint = np.where(np.isnan(IPPint1),IPPint2,IPPint1) + + dLa_dper2 = np.column_stack((-self.a[1]*self.basis_omega/self.period)) + dLp_dper2 = np.column_stack((self.basis_phi+np.pi/2)) + r2,omega2,phi2 = dLa_dper2.T,Lo[:,0:1],dLp_dper2.T + + dGint_dper = np.dot(r,r1.T)/2 * (IPPprim - IPPint) + self._int_computation(r2,omega2,phi2, r,omega,phi) + dGint_dper = dGint_dper + dGint_dper.T + + dFlower_dper = np.array(self._cos(-self.lower*self.basis_alpha*self.basis_omega/self.period,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + + dG_dper = 1./self.variance*(self.lengthscale/2*dGint_dper + self.b[0]*(np.dot(dFlower_dper,Flower.T)+np.dot(Flower,dFlower_dper.T))) + + dK_dper = mdot(dFX_dper,self.Gi,FX2.T) - mdot(FX,self.Gi,dG_dper,self.Gi,FX2.T) + mdot(FX,self.Gi,dFX2_dper.T) + + self.variance.gradient = np.sum(dK_dvar*dL_dK) + self.lengthscale.gradient = np.sum(dK_dlen*dL_dK) + self.period.gradient = np.sum(dK_dper*dL_dK) + + +
      +
      [docs]class PeriodicMatern32(Periodic): + """ + Kernel of the periodic subspace (up to a given frequency) of a Matern 3/2 RKHS. Only defined for input_dim=1. + + :param input_dim: the number of input dimensions + :type input_dim: int + :param variance: the variance of the Matern kernel + :type variance: float + :param lengthscale: the lengthscale of the Matern kernel + :type lengthscale: np.ndarray of size (input_dim,) + :param period: the period + :type period: float + :param n_freq: the number of frequencies considered for the periodic subspace + :type n_freq: int + :rtype: kernel object + + """ + + def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, active_dims=None, name='periodic_Matern32'): + super(PeriodicMatern32, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name) +
      [docs] def parameters_changed(self): + self.a = [3./self.lengthscale**2, 2*np.sqrt(3)/self.lengthscale, 1.] + self.b = [1,self.lengthscale**2/3] + + self.basis_alpha = np.ones((self.n_basis,)) + self.basis_omega = (2*np.pi*np.arange(1,self.n_freq+1)/self.period).repeat(2) + self.basis_phi = np.zeros(self.n_freq * 2) + self.basis_phi[::2] = -np.pi/2 + + self.G = self.Gram_matrix() + self.Gi = np.linalg.inv(self.G) +
      +
      [docs] def Gram_matrix(self): + La = np.column_stack((self.a[0]*np.ones((self.n_basis,1)),self.a[1]*self.basis_omega,self.a[2]*self.basis_omega**2)) + Lo = np.column_stack((self.basis_omega,self.basis_omega,self.basis_omega)) + Lp = np.column_stack((self.basis_phi,self.basis_phi+np.pi/2,self.basis_phi+np.pi)) + r,omega,phi = self._cos_factorization(La,Lo,Lp) + Gint = self._int_computation( r,omega,phi, r,omega,phi) + + Flower = np.array(self._cos(self.basis_alpha,self.basis_omega,self.basis_phi)(self.lower))[:,None] + F1lower = np.array(self._cos(self.basis_alpha*self.basis_omega,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + return(self.lengthscale**3/(12*np.sqrt(3)*self.variance) * Gint + 1./self.variance*np.dot(Flower,Flower.T) + self.lengthscale**2/(3.*self.variance)*np.dot(F1lower,F1lower.T)) + +
      + @silence_errors +
      [docs] def update_gradients_full(self,dL_dK,X,X2): + """derivative of the covariance matrix with respect to the parameters (shape is num_data x num_inducing x num_params)""" + if X2 is None: X2 = X + FX = self._cos(self.basis_alpha[None,:],self.basis_omega[None,:],self.basis_phi[None,:])(X) + FX2 = self._cos(self.basis_alpha[None,:],self.basis_omega[None,:],self.basis_phi[None,:])(X2) + + La = np.column_stack((self.a[0]*np.ones((self.n_basis,1)),self.a[1]*self.basis_omega,self.a[2]*self.basis_omega**2)) + Lo = np.column_stack((self.basis_omega,self.basis_omega,self.basis_omega)) + Lp = np.column_stack((self.basis_phi,self.basis_phi+np.pi/2,self.basis_phi+np.pi)) + r,omega,phi = self._cos_factorization(La,Lo,Lp) + Gint = self._int_computation( r,omega,phi, r,omega,phi) + + Flower = np.array(self._cos(self.basis_alpha,self.basis_omega,self.basis_phi)(self.lower))[:,None] + F1lower = np.array(self._cos(self.basis_alpha*self.basis_omega,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + + #dK_dvar + dK_dvar = 1./self.variance*mdot(FX,self.Gi,FX2.T) + + #dK_dlen + da_dlen = [-6/self.lengthscale**3,-2*np.sqrt(3)/self.lengthscale**2,0.] + db_dlen = [0.,2*self.lengthscale/3.] + dLa_dlen = np.column_stack((da_dlen[0]*np.ones((self.n_basis,1)),da_dlen[1]*self.basis_omega,da_dlen[2]*self.basis_omega**2)) + r1,omega1,phi1 = self._cos_factorization(dLa_dlen,Lo,Lp) + dGint_dlen = self._int_computation(r1,omega1,phi1, r,omega,phi) + dGint_dlen = dGint_dlen + dGint_dlen.T + dG_dlen = self.lengthscale**2/(4*np.sqrt(3))*Gint + self.lengthscale**3/(12*np.sqrt(3))*dGint_dlen + db_dlen[0]*np.dot(Flower,Flower.T) + db_dlen[1]*np.dot(F1lower,F1lower.T) + dK_dlen = -mdot(FX,self.Gi,dG_dlen/self.variance,self.Gi,FX2.T) + + #dK_dper + dFX_dper = self._cos(-self.basis_alpha[None,:]*self.basis_omega[None,:]/self.period*X ,self.basis_omega[None,:],self.basis_phi[None,:]+np.pi/2)(X) + dFX2_dper = self._cos(-self.basis_alpha[None,:]*self.basis_omega[None,:]/self.period*X2,self.basis_omega[None,:],self.basis_phi[None,:]+np.pi/2)(X2) + + dLa_dper = np.column_stack((-self.a[0]*self.basis_omega/self.period, -self.a[1]*self.basis_omega**2/self.period, -self.a[2]*self.basis_omega**3/self.period)) + dLp_dper = np.column_stack((self.basis_phi+np.pi/2,self.basis_phi+np.pi,self.basis_phi+np.pi*3/2)) + r1,omega1,phi1 = self._cos_factorization(dLa_dper,Lo,dLp_dper) + + IPPprim1 = self.upper*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi/2) + 1./(omega-omega1.T)*np.cos((omega-omega1.T)*self.upper+phi-phi1.T-np.pi/2)) + IPPprim1 -= self.lower*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi/2) + 1./(omega-omega1.T)*np.cos((omega-omega1.T)*self.lower+phi-phi1.T-np.pi/2)) + IPPprim2 = self.upper*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi/2) + self.upper*np.cos(phi-phi1.T)) + IPPprim2 -= self.lower*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi/2) + self.lower*np.cos(phi-phi1.T)) + IPPprim = np.where(np.isnan(IPPprim1),IPPprim2,IPPprim1) + + IPPint1 = 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi) + 1./(omega-omega1.T)**2*np.cos((omega-omega1.T)*self.upper+phi-phi1.T-np.pi) + IPPint1 -= 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi) + 1./(omega-omega1.T)**2*np.cos((omega-omega1.T)*self.lower+phi-phi1.T-np.pi) + IPPint2 = 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi) + 1./2*self.upper**2*np.cos(phi-phi1.T) + IPPint2 -= 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi) + 1./2*self.lower**2*np.cos(phi-phi1.T) + IPPint = np.where(np.isnan(IPPint1),IPPint2,IPPint1) + + dLa_dper2 = np.column_stack((-self.a[1]*self.basis_omega/self.period, -2*self.a[2]*self.basis_omega**2/self.period)) + dLp_dper2 = np.column_stack((self.basis_phi+np.pi/2,self.basis_phi+np.pi)) + r2,omega2,phi2 = self._cos_factorization(dLa_dper2,Lo[:,0:2],dLp_dper2) + + dGint_dper = np.dot(r,r1.T)/2 * (IPPprim - IPPint) + self._int_computation(r2,omega2,phi2, r,omega,phi) + dGint_dper = dGint_dper + dGint_dper.T + + dFlower_dper = np.array(self._cos(-self.lower*self.basis_alpha*self.basis_omega/self.period,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + dF1lower_dper = np.array(self._cos(-self.lower*self.basis_alpha*self.basis_omega**2/self.period,self.basis_omega,self.basis_phi+np.pi)(self.lower)+self._cos(-self.basis_alpha*self.basis_omega/self.period,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + + dG_dper = 1./self.variance*(self.lengthscale**3/(12*np.sqrt(3))*dGint_dper + self.b[0]*(np.dot(dFlower_dper,Flower.T)+np.dot(Flower,dFlower_dper.T)) + self.b[1]*(np.dot(dF1lower_dper,F1lower.T)+np.dot(F1lower,dF1lower_dper.T))) + + dK_dper = mdot(dFX_dper,self.Gi,FX2.T) - mdot(FX,self.Gi,dG_dper,self.Gi,FX2.T) + mdot(FX,self.Gi,dFX2_dper.T) + + self.variance.gradient = np.sum(dK_dvar*dL_dK) + self.lengthscale.gradient = np.sum(dK_dlen*dL_dK) + self.period.gradient = np.sum(dK_dper*dL_dK) + + +
      +
      [docs]class PeriodicMatern52(Periodic): + """ + Kernel of the periodic subspace (up to a given frequency) of a Matern 5/2 RKHS. Only defined for input_dim=1. + + :param input_dim: the number of input dimensions + :type input_dim: int + :param variance: the variance of the Matern kernel + :type variance: float + :param lengthscale: the lengthscale of the Matern kernel + :type lengthscale: np.ndarray of size (input_dim,) + :param period: the period + :type period: float + :param n_freq: the number of frequencies considered for the periodic subspace + :type n_freq: int + :rtype: kernel object + + """ + + def __init__(self, input_dim=1, variance=1., lengthscale=1., period=2.*np.pi, n_freq=10, lower=0., upper=4*np.pi, active_dims=None, name='periodic_Matern52'): + super(PeriodicMatern52, self).__init__(input_dim, variance, lengthscale, period, n_freq, lower, upper, active_dims, name) + +
      [docs] def parameters_changed(self): + self.a = [5*np.sqrt(5)/self.lengthscale**3, 15./self.lengthscale**2,3*np.sqrt(5)/self.lengthscale, 1.] + self.b = [9./8, 9*self.lengthscale**4/200., 3*self.lengthscale**2/5., 3*self.lengthscale**2/(5*8.), 3*self.lengthscale**2/(5*8.)] + + self.basis_alpha = np.ones((2*self.n_freq,)) + self.basis_omega = (2*np.pi*np.arange(1,self.n_freq+1)/self.period).repeat(2) + self.basis_phi = np.zeros(self.n_freq * 2) + self.basis_phi[::2] = -np.pi/2 + + self.G = self.Gram_matrix() + self.Gi = np.linalg.inv(self.G) +
      +
      [docs] def Gram_matrix(self): + La = np.column_stack((self.a[0]*np.ones((self.n_basis,1)), self.a[1]*self.basis_omega, self.a[2]*self.basis_omega**2, self.a[3]*self.basis_omega**3)) + Lo = np.column_stack((self.basis_omega, self.basis_omega, self.basis_omega, self.basis_omega)) + Lp = np.column_stack((self.basis_phi, self.basis_phi+np.pi/2, self.basis_phi+np.pi, self.basis_phi+np.pi*3/2)) + r,omega,phi = self._cos_factorization(La,Lo,Lp) + Gint = self._int_computation( r,omega,phi, r,omega,phi) + + Flower = np.array(self._cos(self.basis_alpha,self.basis_omega,self.basis_phi)(self.lower))[:,None] + F1lower = np.array(self._cos(self.basis_alpha*self.basis_omega,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + F2lower = np.array(self._cos(self.basis_alpha*self.basis_omega**2,self.basis_omega,self.basis_phi+np.pi)(self.lower))[:,None] + lower_terms = self.b[0]*np.dot(Flower,Flower.T) + self.b[1]*np.dot(F2lower,F2lower.T) + self.b[2]*np.dot(F1lower,F1lower.T) + self.b[3]*np.dot(F2lower,Flower.T) + self.b[4]*np.dot(Flower,F2lower.T) + return(3*self.lengthscale**5/(400*np.sqrt(5)*self.variance) * Gint + 1./self.variance*lower_terms) +
      + @silence_errors +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + if X2 is None: X2 = X + FX = self._cos(self.basis_alpha[None,:],self.basis_omega[None,:],self.basis_phi[None,:])(X) + FX2 = self._cos(self.basis_alpha[None,:],self.basis_omega[None,:],self.basis_phi[None,:])(X2) + + La = np.column_stack((self.a[0]*np.ones((self.n_basis,1)), self.a[1]*self.basis_omega, self.a[2]*self.basis_omega**2, self.a[3]*self.basis_omega**3)) + Lo = np.column_stack((self.basis_omega, self.basis_omega, self.basis_omega, self.basis_omega)) + Lp = np.column_stack((self.basis_phi, self.basis_phi+np.pi/2, self.basis_phi+np.pi, self.basis_phi+np.pi*3/2)) + r,omega,phi = self._cos_factorization(La,Lo,Lp) + Gint = self._int_computation( r,omega,phi, r,omega,phi) + + Flower = np.array(self._cos(self.basis_alpha,self.basis_omega,self.basis_phi)(self.lower))[:,None] + F1lower = np.array(self._cos(self.basis_alpha*self.basis_omega,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + F2lower = np.array(self._cos(self.basis_alpha*self.basis_omega**2,self.basis_omega,self.basis_phi+np.pi)(self.lower))[:,None] + + #dK_dvar + dK_dvar = 1./self.variance*mdot(FX,self.Gi,FX2.T) + + #dK_dlen + da_dlen = [-3*self.a[0]/self.lengthscale, -2*self.a[1]/self.lengthscale, -self.a[2]/self.lengthscale, 0.] + db_dlen = [0., 4*self.b[1]/self.lengthscale, 2*self.b[2]/self.lengthscale, 2*self.b[3]/self.lengthscale, 2*self.b[4]/self.lengthscale] + dLa_dlen = np.column_stack((da_dlen[0]*np.ones((self.n_basis,1)), da_dlen[1]*self.basis_omega, da_dlen[2]*self.basis_omega**2, da_dlen[3]*self.basis_omega**3)) + r1,omega1,phi1 = self._cos_factorization(dLa_dlen,Lo,Lp) + dGint_dlen = self._int_computation(r1,omega1,phi1, r,omega,phi) + dGint_dlen = dGint_dlen + dGint_dlen.T + dlower_terms_dlen = db_dlen[0]*np.dot(Flower,Flower.T) + db_dlen[1]*np.dot(F2lower,F2lower.T) + db_dlen[2]*np.dot(F1lower,F1lower.T) + db_dlen[3]*np.dot(F2lower,Flower.T) + db_dlen[4]*np.dot(Flower,F2lower.T) + dG_dlen = 15*self.lengthscale**4/(400*np.sqrt(5))*Gint + 3*self.lengthscale**5/(400*np.sqrt(5))*dGint_dlen + dlower_terms_dlen + dK_dlen = -mdot(FX,self.Gi,dG_dlen/self.variance,self.Gi,FX2.T) + + #dK_dper + dFX_dper = self._cos(-self.basis_alpha[None,:]*self.basis_omega[None,:]/self.period*X ,self.basis_omega[None,:],self.basis_phi[None,:]+np.pi/2)(X) + dFX2_dper = self._cos(-self.basis_alpha[None,:]*self.basis_omega[None,:]/self.period*X2,self.basis_omega[None,:],self.basis_phi[None,:]+np.pi/2)(X2) + + dLa_dper = np.column_stack((-self.a[0]*self.basis_omega/self.period, -self.a[1]*self.basis_omega**2/self.period, -self.a[2]*self.basis_omega**3/self.period, -self.a[3]*self.basis_omega**4/self.period)) + dLp_dper = np.column_stack((self.basis_phi+np.pi/2,self.basis_phi+np.pi,self.basis_phi+np.pi*3/2,self.basis_phi)) + r1,omega1,phi1 = self._cos_factorization(dLa_dper,Lo,dLp_dper) + + IPPprim1 = self.upper*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi/2) + 1./(omega-omega1.T)*np.cos((omega-omega1.T)*self.upper+phi-phi1.T-np.pi/2)) + IPPprim1 -= self.lower*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi/2) + 1./(omega-omega1.T)*np.cos((omega-omega1.T)*self.lower+phi-phi1.T-np.pi/2)) + IPPprim2 = self.upper*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi/2) + self.upper*np.cos(phi-phi1.T)) + IPPprim2 -= self.lower*(1./(omega+omega1.T)*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi/2) + self.lower*np.cos(phi-phi1.T)) + IPPprim = np.where(np.isnan(IPPprim1),IPPprim2,IPPprim1) + + IPPint1 = 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi) + 1./(omega-omega1.T)**2*np.cos((omega-omega1.T)*self.upper+phi-phi1.T-np.pi) + IPPint1 -= 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi) + 1./(omega-omega1.T)**2*np.cos((omega-omega1.T)*self.lower+phi-phi1.T-np.pi) + IPPint2 = 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.upper+phi+phi1.T-np.pi) + 1./2*self.upper**2*np.cos(phi-phi1.T) + IPPint2 -= 1./(omega+omega1.T)**2*np.cos((omega+omega1.T)*self.lower+phi+phi1.T-np.pi) + 1./2*self.lower**2*np.cos(phi-phi1.T) + IPPint = np.where(np.isnan(IPPint1),IPPint2,IPPint1) + + dLa_dper2 = np.column_stack((-self.a[1]*self.basis_omega/self.period, -2*self.a[2]*self.basis_omega**2/self.period, -3*self.a[3]*self.basis_omega**3/self.period)) + dLp_dper2 = np.column_stack((self.basis_phi+np.pi/2, self.basis_phi+np.pi, self.basis_phi+np.pi*3/2)) + r2,omega2,phi2 = self._cos_factorization(dLa_dper2,Lo[:,0:2],dLp_dper2) + + dGint_dper = np.dot(r,r1.T)/2 * (IPPprim - IPPint) + self._int_computation(r2,omega2,phi2, r,omega,phi) + dGint_dper = dGint_dper + dGint_dper.T + + dFlower_dper = np.array(self._cos(-self.lower*self.basis_alpha*self.basis_omega/self.period,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + dF1lower_dper = np.array(self._cos(-self.lower*self.basis_alpha*self.basis_omega**2/self.period,self.basis_omega,self.basis_phi+np.pi)(self.lower)+self._cos(-self.basis_alpha*self.basis_omega/self.period,self.basis_omega,self.basis_phi+np.pi/2)(self.lower))[:,None] + dF2lower_dper = np.array(self._cos(-self.lower*self.basis_alpha*self.basis_omega**3/self.period,self.basis_omega,self.basis_phi+np.pi*3/2)(self.lower) + self._cos(-2*self.basis_alpha*self.basis_omega**2/self.period,self.basis_omega,self.basis_phi+np.pi)(self.lower))[:,None] + + dlower_terms_dper = self.b[0] * (np.dot(dFlower_dper,Flower.T) + np.dot(Flower.T,dFlower_dper)) + dlower_terms_dper += self.b[1] * (np.dot(dF2lower_dper,F2lower.T) + np.dot(F2lower,dF2lower_dper.T)) - 4*self.b[1]/self.period*np.dot(F2lower,F2lower.T) + dlower_terms_dper += self.b[2] * (np.dot(dF1lower_dper,F1lower.T) + np.dot(F1lower,dF1lower_dper.T)) - 2*self.b[2]/self.period*np.dot(F1lower,F1lower.T) + dlower_terms_dper += self.b[3] * (np.dot(dF2lower_dper,Flower.T) + np.dot(F2lower,dFlower_dper.T)) - 2*self.b[3]/self.period*np.dot(F2lower,Flower.T) + dlower_terms_dper += self.b[4] * (np.dot(dFlower_dper,F2lower.T) + np.dot(Flower,dF2lower_dper.T)) - 2*self.b[4]/self.period*np.dot(Flower,F2lower.T) + + dG_dper = 1./self.variance*(3*self.lengthscale**5/(400*np.sqrt(5))*dGint_dper + 0.5*dlower_terms_dper) + dK_dper = mdot(dFX_dper,self.Gi,FX2.T) - mdot(FX,self.Gi,dG_dper,self.Gi,FX2.T) + mdot(FX,self.Gi,dFX2_dper.T) + + self.variance.gradient = np.sum(dK_dvar*dL_dK) + self.lengthscale.gradient = np.sum(dK_dlen*dL_dK) + self.period.gradient = np.sum(dK_dper*dL_dK) +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/poly.html b/doc/_build/html/_modules/GPy/kern/_src/poly.html new file mode 100644 index 00000000..9d77898f --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/poly.html @@ -0,0 +1,135 @@ + + + + + + + + GPy.kern._src.poly — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.poly

      +# Copyright (c) 2014, James Hensman
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from kern import Kern
      +from ...core.parameterization import Param
      +from ...core.parameterization.transformations import Logexp
      +
      [docs]class Poly(Kern): + """ + Polynomial kernel + """ + + def __init__(self, input_dim, variance=1., order=3., active_dims=None, name='poly'): + super(Poly, self).__init__(input_dim, active_dims, name) + self.variance = Param('variance', variance, Logexp()) + self.link_parameter(self.variance) + self.order=order + +
      [docs] def K(self, X, X2=None): + return (self._dot_product(X, X2) + 1.)**self.order * self.variance +
      + def _dot_product(self, X, X2=None): + if X2 is None: + return np.dot(X, X.T) + else: + return np.dot(X, X2.T) + +
      [docs] def Kdiag(self, X): + return self.variance*(np.square(X).sum(1) + 1.)**self.order +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + self.variance.gradient = np.sum(dL_dK * (self._dot_product(X, X2) + 1.)**self.order) +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + raise NotImplementedError +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + raise NotImplementedError +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + raise NotImplementedError
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/prod.html b/doc/_build/html/_modules/GPy/kern/_src/prod.html new file mode 100644 index 00000000..1988b28c --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/prod.html @@ -0,0 +1,160 @@ + + + + + + + + GPy.kern._src.prod — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.prod

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from kern import CombinationKernel
      +from ...util.caching import Cache_this
      +import itertools
      +
      +
      [docs]class Prod(CombinationKernel): + """ + Computes the product of 2 kernels + + :param k1, k2: the kernels to multiply + :type k1, k2: Kern + :param tensor: The kernels are either multiply as functions defined on the same input space (default) or on the product of the input spaces + :type tensor: Boolean + :rtype: kernel object + + """ + def __init__(self, kernels, name='mul'): + for i, kern in enumerate(kernels[:]): + if isinstance(kern, Prod): + del kernels[i] + for part in kern.parts[::-1]: + kern.unlink_parameter(part) + kernels.insert(i, part) + super(Prod, self).__init__(kernels, name) + + @Cache_this(limit=2, force_kwargs=['which_parts']) +
      [docs] def K(self, X, X2=None, which_parts=None): + if which_parts is None: + which_parts = self.parts + elif not isinstance(which_parts, (list, tuple)): + # if only one part is given + which_parts = [which_parts] + return reduce(np.multiply, (p.K(X, X2) for p in which_parts)) +
      + @Cache_this(limit=2, force_kwargs=['which_parts']) +
      [docs] def Kdiag(self, X, which_parts=None): + if which_parts is None: + which_parts = self.parts + return reduce(np.multiply, (p.Kdiag(X) for p in which_parts)) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + k = self.K(X,X2)*dL_dK + for p in self.parts: + p.update_gradients_full(k/p.K(X,X2),X,X2) +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + k = self.Kdiag(X)*dL_dKdiag + for p in self.parts: + p.update_gradients_diag(k/p.Kdiag(X),X) +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + target = np.zeros(X.shape) + k = self.K(X,X2)*dL_dK + for p in self.parts: + target += p.gradients_X(k/p.K(X,X2),X,X2) + return target +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + target = np.zeros(X.shape) + k = self.Kdiag(X)*dL_dKdiag + for p in self.parts: + target += p.gradients_X_diag(k/p.Kdiag(X),X) + return target
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/psi_comp.html b/doc/_build/html/_modules/GPy/kern/_src/psi_comp.html new file mode 100644 index 00000000..21672469 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/psi_comp.html @@ -0,0 +1,149 @@ + + + + + + + + GPy.kern._src.psi_comp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.psi_comp

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from ....core.parameterization.parameter_core import Pickleable
      +from GPy.util.caching import Cache_this
      +from ....core.parameterization import variational
      +import rbf_psi_comp
      +import ssrbf_psi_comp
      +import sslinear_psi_comp
      +import linear_psi_comp
      +
      +
      [docs]class PSICOMP_RBF(Pickleable): + @Cache_this(limit=2, ignore_args=(0,)) + def psicomputations(self, variance, lengthscale, Z, variational_posterior): + if isinstance(variational_posterior, variational.NormalPosterior): + return rbf_psi_comp.psicomputations(variance, lengthscale, Z, variational_posterior) + elif isinstance(variational_posterior, variational.SpikeAndSlabPosterior): + return ssrbf_psi_comp.psicomputations(variance, lengthscale, Z, variational_posterior) + else: + raise ValueError, "unknown distriubtion received for psi-statistics" + + @Cache_this(limit=2, ignore_args=(0,1,2,3)) + def psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior): + if isinstance(variational_posterior, variational.NormalPosterior): + return rbf_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior) + elif isinstance(variational_posterior, variational.SpikeAndSlabPosterior): + return ssrbf_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior) + else: + raise ValueError, "unknown distriubtion received for psi-statistics" + + def _setup_observers(self): + pass +
      +
      [docs]class PSICOMP_Linear(Pickleable): + + @Cache_this(limit=2, ignore_args=(0,)) + def psicomputations(self, variance, Z, variational_posterior): + if isinstance(variational_posterior, variational.NormalPosterior): + return linear_psi_comp.psicomputations(variance, Z, variational_posterior) + elif isinstance(variational_posterior, variational.SpikeAndSlabPosterior): + return sslinear_psi_comp.psicomputations(variance, Z, variational_posterior) + else: + raise ValueError, "unknown distriubtion received for psi-statistics" + + @Cache_this(limit=2, ignore_args=(0,1,2,3)) + def psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior): + if isinstance(variational_posterior, variational.NormalPosterior): + return linear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior) + elif isinstance(variational_posterior, variational.SpikeAndSlabPosterior): + return sslinear_psi_comp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior) + else: + raise ValueError, "unknown distriubtion received for psi-statistics" + + def _setup_observers(self): + pass
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/psi_comp/linear_psi_comp.html b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/linear_psi_comp.html new file mode 100644 index 00000000..bfd33eb2 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/linear_psi_comp.html @@ -0,0 +1,173 @@ + + + + + + + + GPy.kern._src.psi_comp.linear_psi_comp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.psi_comp.linear_psi_comp

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +"""
      +The package for the Psi statistics computation of the linear kernel for Bayesian GPLVM
      +"""
      +
      +import numpy as np
      +from ....util.linalg import tdot
      +
      +
      [docs]def psicomputations(variance, Z, variational_posterior): + """ + Compute psi-statistics for ss-linear kernel + """ + # here are the "statistics" for psi0, psi1 and psi2 + # Produced intermediate results: + # psi0 N + # psi1 NxM + # psi2 MxM + mu = variational_posterior.mean + S = variational_posterior.variance + + psi0 = (variance*(np.square(mu)+S)).sum(axis=1) + psi1 = np.dot(mu,(variance*Z).T) + psi2 = np.dot(S.sum(axis=0)*np.square(variance)*Z,Z.T)+ tdot(psi1.T) + + return psi0, psi1, psi2 +
      +
      [docs]def psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior): + mu = variational_posterior.mean + S = variational_posterior.variance + + dL_dvar, dL_dmu, dL_dS, dL_dZ = _psi2computations(dL_dpsi2, variance, Z, mu, S) + + # Compute for psi0 and psi1 + mu2S = np.square(mu)+S + dL_dpsi0_var = dL_dpsi0[:,None]*variance[None,:] + dL_dpsi1_mu = np.dot(dL_dpsi1.T,mu) + dL_dvar += (dL_dpsi0[:,None]*mu2S).sum(axis=0)+ (dL_dpsi1_mu*Z).sum(axis=0) + dL_dmu += 2.*dL_dpsi0_var*mu+np.dot(dL_dpsi1,Z)*variance + dL_dS += dL_dpsi0_var + dL_dZ += dL_dpsi1_mu*variance + + return dL_dvar, dL_dZ, dL_dmu, dL_dS +
      +def _psi2computations(dL_dpsi2, variance, Z, mu, S): + """ + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + """ + # here are the "statistics" for psi1 and psi2 + # Produced intermediate results: + # _psi2_dvariance Q + # _psi2_dZ MxQ + # _psi2_dmu NxQ + # _psi2_dS NxQ + + variance2 = np.square(variance) + common_sum = np.dot(mu,(variance*Z).T) + Z_expect = (np.dot(dL_dpsi2,Z)*Z).sum(axis=0) + dL_dpsi2T = dL_dpsi2+dL_dpsi2.T + common_expect = np.dot(common_sum,np.dot(dL_dpsi2T,Z)) + Z2_expect = np.inner(common_sum,dL_dpsi2T) + Z1_expect = np.dot(dL_dpsi2T,Z) + + dL_dvar = 2.*S.sum(axis=0)*variance*Z_expect+(common_expect*mu).sum(axis=0) + + dL_dmu = common_expect*variance + + dL_dS = np.empty(S.shape) + dL_dS[:] = Z_expect*variance2 + + dL_dZ = variance2*S.sum(axis=0)*Z1_expect+np.dot(Z2_expect.T,variance*mu) + + return dL_dvar, dL_dmu, dL_dS, dL_dZ +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/psi_comp/rbf_psi_comp.html b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/rbf_psi_comp.html new file mode 100644 index 00000000..5d746f8d --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/rbf_psi_comp.html @@ -0,0 +1,257 @@ + + + + + + + + GPy.kern._src.psi_comp.rbf_psi_comp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.psi_comp.rbf_psi_comp

      +"""
      +The module for psi-statistics for RBF kernel
      +"""
      +
      +import numpy as np
      +from GPy.util.caching import Cacher
      +
      +
      [docs]def psicomputations(variance, lengthscale, Z, variational_posterior): + """ + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + """ + # here are the "statistics" for psi0, psi1 and psi2 + # Produced intermediate results: + # _psi1 NxM + mu = variational_posterior.mean + S = variational_posterior.variance + + psi0 = np.empty(mu.shape[0]) + psi0[:] = variance + psi1 = _psi1computations(variance, lengthscale, Z, mu, S) + psi2 = _psi2computations(variance, lengthscale, Z, mu, S).sum(axis=0) + return psi0, psi1, psi2 +
      +def __psi1computations(variance, lengthscale, Z, mu, S): + """ + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + """ + # here are the "statistics" for psi1 + # Produced intermediate results: + # _psi1 NxM + + lengthscale2 = np.square(lengthscale) + + # psi1 + _psi1_logdenom = np.log(S/lengthscale2+1.).sum(axis=-1) # N + _psi1_log = (_psi1_logdenom[:,None]+np.einsum('nmq,nq->nm',np.square(mu[:,None,:]-Z[None,:,:]),1./(S+lengthscale2)))/(-2.) + _psi1 = variance*np.exp(_psi1_log) + + return _psi1 + +def __psi2computations(variance, lengthscale, Z, mu, S): + """ + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + """ + # here are the "statistics" for psi2 + # Produced intermediate results: + # _psi2 MxM + + lengthscale2 = np.square(lengthscale) + + _psi2_logdenom = np.log(2.*S/lengthscale2+1.).sum(axis=-1)/(-2.) # N + _psi2_exp1 = (np.square(Z[:,None,:]-Z[None,:,:])/lengthscale2).sum(axis=-1)/(-4.) #MxM + Z_hat = (Z[:,None,:]+Z[None,:,:])/2. #MxMxQ + denom = 1./(2.*S+lengthscale2) + _psi2_exp2 = -(np.square(mu)*denom).sum(axis=-1)[:,None,None]+2.*np.einsum('nq,moq,nq->nmo',mu,Z_hat,denom)-np.einsum('moq,nq->nmo',np.square(Z_hat),denom) + _psi2 = variance*variance*np.exp(_psi2_logdenom[:,None,None]+_psi2_exp1[None,:,:]+_psi2_exp2) + + + return _psi2 + +
      [docs]def psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior): + ARD = (len(lengthscale)!=1) + + dvar_psi1, dl_psi1, dZ_psi1, dmu_psi1, dS_psi1 = _psi1compDer(dL_dpsi1, variance, lengthscale, Z, variational_posterior.mean, variational_posterior.variance) + dvar_psi2, dl_psi2, dZ_psi2, dmu_psi2, dS_psi2 = _psi2compDer(dL_dpsi2, variance, lengthscale, Z, variational_posterior.mean, variational_posterior.variance) + + dL_dvar = np.sum(dL_dpsi0) + dvar_psi1 + dvar_psi2 + + dL_dlengscale = dl_psi1 + dl_psi2 + if not ARD: + dL_dlengscale = dL_dlengscale.sum() + + dL_dmu = dmu_psi1 + dmu_psi2 + dL_dS = dS_psi1 + dS_psi2 + dL_dZ = dZ_psi1 + dZ_psi2 + + return dL_dvar, dL_dlengscale, dL_dZ, dL_dmu, dL_dS +
      +def _psi1compDer(dL_dpsi1, variance, lengthscale, Z, mu, S): + """ + dL_dpsi1 - NxM + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + """ + # here are the "statistics" for psi1 + # Produced intermediate results: dL_dparams w.r.t. psi1 + # _dL_dvariance 1 + # _dL_dlengthscale Q + # _dL_dZ MxQ + # _dL_dgamma NxQ + # _dL_dmu NxQ + # _dL_dS NxQ + + lengthscale2 = np.square(lengthscale) + + _psi1 = _psi1computations(variance, lengthscale, Z, mu, S) + Lpsi1 = dL_dpsi1*_psi1 + Zmu = Z[None,:,:]-mu[:,None,:] # NxMxQ + denom = 1./(S+lengthscale2) + Zmu2_denom = np.square(Zmu)*denom[:,None,:] #NxMxQ + _dL_dvar = Lpsi1.sum()/variance + _dL_dmu = np.einsum('nm,nmq,nq->nq',Lpsi1,Zmu,denom) + _dL_dS = np.einsum('nm,nmq,nq->nq',Lpsi1,(Zmu2_denom-1.),denom)/2. + _dL_dZ = -np.einsum('nm,nmq,nq->mq',Lpsi1,Zmu,denom) + _dL_dl = np.einsum('nm,nmq,nq->q',Lpsi1,(Zmu2_denom+(S/lengthscale2)[:,None,:]),denom*lengthscale) + + return _dL_dvar, _dL_dl, _dL_dZ, _dL_dmu, _dL_dS + +def _psi2compDer(dL_dpsi2, variance, lengthscale, Z, mu, S): + """ + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + dL_dpsi2 - MxM + """ + # here are the "statistics" for psi2 + # Produced the derivatives w.r.t. psi2: + # _dL_dvariance 1 + # _dL_dlengthscale Q + # _dL_dZ MxQ + # _dL_dgamma NxQ + # _dL_dmu NxQ + # _dL_dS NxQ + + lengthscale2 = np.square(lengthscale) + denom = 1./(2*S+lengthscale2) + denom2 = np.square(denom) + + _psi2 = _psi2computations(variance, lengthscale, Z, mu, S) # NxMxM + Lpsi2 = dL_dpsi2*_psi2 # dL_dpsi2 is MxM, using broadcast to multiply N out + Lpsi2sum = np.einsum('nmo->n',Lpsi2) #N + Lpsi2Z = np.einsum('nmo,oq->nq',Lpsi2,Z) #NxQ + Lpsi2Z2 = np.einsum('nmo,oq,oq->nq',Lpsi2,Z,Z) #NxQ + Lpsi2Z2p = np.einsum('nmo,mq,oq->nq',Lpsi2,Z,Z) #NxQ + Lpsi2Zhat = Lpsi2Z + Lpsi2Zhat2 = (Lpsi2Z2+Lpsi2Z2p)/2 + + _dL_dvar = Lpsi2sum.sum()*2/variance + _dL_dmu = (-2*denom) * (mu*Lpsi2sum[:,None]-Lpsi2Zhat) + _dL_dS = (2*np.square(denom))*(np.square(mu)*Lpsi2sum[:,None]-2*mu*Lpsi2Zhat+Lpsi2Zhat2) - denom*Lpsi2sum[:,None] + _dL_dZ = -np.einsum('nmo,oq->oq',Lpsi2,Z)/lengthscale2+np.einsum('nmo,oq->mq',Lpsi2,Z)/lengthscale2+ \ + 2*np.einsum('nmo,nq,nq->mq',Lpsi2,mu,denom) - np.einsum('nmo,nq,mq->mq',Lpsi2,denom,Z) - np.einsum('nmo,oq,nq->mq',Lpsi2,Z,denom) + _dL_dl = 2*lengthscale* ((S/lengthscale2*denom+np.square(mu*denom))*Lpsi2sum[:,None]+(Lpsi2Z2-Lpsi2Z2p)/(2*np.square(lengthscale2))- + (2*mu*denom2)*Lpsi2Zhat+denom2*Lpsi2Zhat2).sum(axis=0) + + return _dL_dvar, _dL_dl, _dL_dZ, _dL_dmu, _dL_dS + +_psi1computations = Cacher(__psi1computations, limit=1) +_psi2computations = Cacher(__psi2computations, limit=1) +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/psi_comp/rbf_psi_gpucomp.html b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/rbf_psi_gpucomp.html new file mode 100644 index 00000000..520fe9e3 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/rbf_psi_gpucomp.html @@ -0,0 +1,506 @@ + + + + + + + + GPy.kern._src.psi_comp.rbf_psi_gpucomp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.psi_comp.rbf_psi_gpucomp

      +"""
      +The module for psi-statistics for RBF kernel
      +"""
      +
      +import numpy as np
      +from ....util.caching import Cache_this
      +from . import PSICOMP_RBF
      +from ....util import gpu_init
      +
      +try:
      +    import pycuda.gpuarray as gpuarray
      +    from pycuda.compiler import SourceModule
      +    from ....util.linalg_gpu import sum_axis
      +except:
      +    pass    
      +
      +gpu_code = """
      +    // define THREADNUM
      +
      +    #define IDX_NMQ(n,m,q) ((q*M+m)*N+n)
      +    #define IDX_NMM(n,m1,m2) ((m2*M+m1)*N+n)
      +    #define IDX_NQ(n,q) (q*N+n)
      +    #define IDX_NM(n,m) (m*N+n)
      +    #define IDX_MQ(m,q) (q*M+m)
      +    #define IDX_MM(m1,m2) (m2*M+m1)
      +    #define IDX_NQB(n,q,b) ((b*Q+q)*N+n)
      +    #define IDX_QB(q,b) (b*Q+q)
      +
      +    // Divide data evenly
      +    __device__ void divide_data(int total_data, int psize, int pidx, int *start, int *end) {
      +        int residue = (total_data)%psize;
      +        if(pidx<residue) {
      +            int size = total_data/psize+1;
      +            *start = size*pidx;
      +            *end = *start+size;
      +        } else {
      +            int size = total_data/psize;
      +            *start = size*pidx+residue;
      +            *end = *start+size;
      +        }
      +    }
      +    
      +    __device__ void reduce_sum(double* array, int array_size) {
      +        int s;
      +        if(array_size >= blockDim.x) {
      +            for(int i=blockDim.x+threadIdx.x; i<array_size; i+= blockDim.x) {
      +                array[threadIdx.x] += array[i];
      +            }
      +            array_size = blockDim.x;
      +        }
      +        __syncthreads();
      +        for(int i=1; i<=array_size;i*=2) {s=i;}
      +        if(threadIdx.x < array_size-s) {array[threadIdx.x] += array[s+threadIdx.x];}
      +        __syncthreads();
      +        for(s=s/2;s>=1;s=s/2) {
      +            if(threadIdx.x < s) {array[threadIdx.x] += array[s+threadIdx.x];}
      +            __syncthreads();
      +        }
      +    }
      +
      +    __global__ void compDenom(double *log_denom1, double *log_denom2, double *l, double *S, int N, int Q)
      +    {
      +        int n_start, n_end;
      +        divide_data(N, gridDim.x, blockIdx.x, &n_start, &n_end);
      +        
      +        for(int i=n_start*Q+threadIdx.x; i<n_end*Q; i+=blockDim.x) {
      +            int n=i/Q;
      +            int q=i%Q;
      +
      +            double Snq = S[IDX_NQ(n,q)];
      +            double lq = l[q]*l[q];
      +            log_denom1[IDX_NQ(n,q)] = log(Snq/lq+1.);
      +            log_denom2[IDX_NQ(n,q)] = log(2.*Snq/lq+1.);
      +        }
      +    }
      +
      +    __global__ void psi1computations(double *psi1, double *log_denom1, double var, double *l, double *Z, double *mu, double *S, int N, int M, int Q)
      +    {
      +        int m_start, m_end;
      +        divide_data(M, gridDim.x, blockIdx.x, &m_start, &m_end);
      +        
      +        for(int m=m_start; m<m_end; m++) {
      +            for(int n=threadIdx.x; n<N; n+= blockDim.x) {            
      +                double log_psi1 = 0;
      +                for(int q=0;q<Q;q++) {
      +                    double muZ = mu[IDX_NQ(n,q)]-Z[IDX_MQ(m,q)];
      +                    double Snq = S[IDX_NQ(n,q)];
      +                    double lq = l[q]*l[q];
      +                    log_psi1 += (muZ*muZ/(Snq+lq)+log_denom1[IDX_NQ(n,q)])/(-2.);
      +                }
      +                psi1[IDX_NM(n,m)] = var*exp(log_psi1);
      +            }
      +        }
      +    }
      +    
      +    __global__ void psi2computations(double *psi2, double *psi2n, double *log_denom2, double var, double *l, double *Z, double *mu, double *S, int N, int M, int Q)
      +    {
      +        int psi2_idx_start, psi2_idx_end;
      +        __shared__ double psi2_local[THREADNUM];
      +        divide_data((M+1)*M/2, gridDim.x, blockIdx.x, &psi2_idx_start, &psi2_idx_end);
      +        
      +        for(int psi2_idx=psi2_idx_start; psi2_idx<psi2_idx_end; psi2_idx++) {
      +            int m1 = int((sqrt(8.*psi2_idx+1.)-1.)/2.);
      +            int m2 = psi2_idx - (m1+1)*m1/2;
      +            
      +            psi2_local[threadIdx.x] = 0;
      +            for(int n=threadIdx.x;n<N;n+=blockDim.x) {
      +                double log_psi2_n = 0;
      +                for(int q=0;q<Q;q++) {
      +                    double dZ = Z[IDX_MQ(m1,q)] - Z[IDX_MQ(m2,q)];
      +                    double muZhat = mu[IDX_NQ(n,q)]- (Z[IDX_MQ(m1,q)]+Z[IDX_MQ(m2,q)])/2.;
      +                    double Snq = S[IDX_NQ(n,q)];
      +                    double lq = l[q]*l[q];
      +                    log_psi2_n += dZ*dZ/(-4.*lq)-muZhat*muZhat/(2.*Snq+lq) + log_denom2[IDX_NQ(n,q)]/(-2.);
      +                }
      +                double exp_psi2_n = exp(log_psi2_n);
      +                psi2n[IDX_NMM(n,m1,m2)] = var*var*exp_psi2_n;
      +                if(m1!=m2) { psi2n[IDX_NMM(n,m2,m1)] = var*var*exp_psi2_n;}
      +                psi2_local[threadIdx.x] += exp_psi2_n;
      +            }
      +            __syncthreads();
      +            reduce_sum(psi2_local, THREADNUM);
      +            if(threadIdx.x==0) {
      +                psi2[IDX_MM(m1,m2)] = var*var*psi2_local[0];
      +                if(m1!=m2) { psi2[IDX_MM(m2,m1)] = var*var*psi2_local[0]; }
      +            }
      +            __syncthreads();
      +        }
      +    }
      +    
      +    __global__ void psi1compDer(double *dvar, double *dl, double *dZ, double *dmu, double *dS, double *dL_dpsi1, double *psi1, double var, double *l, double *Z, double *mu, double *S, int N, int M, int Q)
      +    {
      +        int m_start, m_end;
      +        __shared__ double g_local[THREADNUM];
      +        divide_data(M, gridDim.x, blockIdx.x, &m_start, &m_end);
      +        int P = int(ceil(double(N)/THREADNUM));
      +
      +        double dvar_local = 0;
      +        for(int q=0;q<Q;q++) {
      +            double lq_sqrt = l[q];
      +            double lq = lq_sqrt*lq_sqrt;
      +            double dl_local = 0;
      +            for(int p=0;p<P;p++) {
      +                int n = p*THREADNUM + threadIdx.x;
      +                double dmu_local = 0;
      +                double dS_local = 0;
      +                double Snq,mu_nq;
      +                if(n<N) {Snq = S[IDX_NQ(n,q)]; mu_nq=mu[IDX_NQ(n,q)];}
      +                for(int m=m_start; m<m_end; m++) {
      +                    if(n<N) {
      +                        double lpsi1 = psi1[IDX_NM(n,m)]*dL_dpsi1[IDX_NM(n,m)];
      +                        if(q==0) {dvar_local += lpsi1;}
      +                        
      +                        double Zmu = Z[IDX_MQ(m,q)] - mu_nq;
      +                        double denom = Snq+lq;
      +                        double Zmu2_denom = Zmu*Zmu/denom;
      +                        
      +                        dmu_local += lpsi1*Zmu/denom;
      +                        dS_local += lpsi1*(Zmu2_denom-1.)/denom;
      +                        dl_local += lpsi1*(Zmu2_denom+Snq/lq)/denom;
      +                        g_local[threadIdx.x] = -lpsi1*Zmu/denom;
      +                    }
      +                    __syncthreads();
      +                    reduce_sum(g_local, p<P-1?THREADNUM:N-(P-1)*THREADNUM);
      +                    if(threadIdx.x==0) {dZ[IDX_MQ(m,q)] += g_local[0];}
      +                }
      +                if(n<N) {
      +                    dmu[IDX_NQB(n,q,blockIdx.x)] += dmu_local;
      +                    dS[IDX_NQB(n,q,blockIdx.x)] += dS_local/2.;
      +                }
      +                __threadfence_block();
      +            }
      +            g_local[threadIdx.x] = dl_local*lq_sqrt;
      +            __syncthreads();
      +            reduce_sum(g_local, THREADNUM);
      +            if(threadIdx.x==0) {dl[IDX_QB(q,blockIdx.x)] += g_local[0];}
      +        }
      +        g_local[threadIdx.x] = dvar_local;
      +        __syncthreads();
      +        reduce_sum(g_local, THREADNUM);
      +        if(threadIdx.x==0) {dvar[blockIdx.x] += g_local[0]/var;}        
      +    }
      +    
      +    __global__ void psi2compDer(double *dvar, double *dl, double *dZ, double *dmu, double *dS, double *dL_dpsi2, double *psi2n, double var, double *l, double *Z, double *mu, double *S, int N, int M, int Q)
      +    {
      +        int m_start, m_end;
      +        __shared__ double g_local[THREADNUM];
      +        divide_data(M, gridDim.x, blockIdx.x, &m_start, &m_end);
      +        int P = int(ceil(double(N)/THREADNUM));
      +
      +        double dvar_local = 0;
      +        for(int q=0;q<Q;q++) {
      +            double lq_sqrt = l[q];
      +            double lq = lq_sqrt*lq_sqrt;
      +            double dl_local = 0;
      +            for(int p=0;p<P;p++) {
      +                int n = p*THREADNUM + threadIdx.x;
      +                double dmu_local = 0;
      +                double dS_local = 0;
      +                double Snq,mu_nq;
      +                if(n<N) {Snq = S[IDX_NQ(n,q)]; mu_nq=mu[IDX_NQ(n,q)];}
      +                for(int m1=m_start; m1<m_end; m1++) {
      +                    g_local[threadIdx.x] = 0;
      +                    for(int m2=0;m2<M;m2++) {
      +                        if(n<N) {
      +                            double lpsi2 = psi2n[IDX_NMM(n,m1,m2)]*dL_dpsi2[IDX_MM(m1,m2)];
      +                            if(q==0) {dvar_local += lpsi2;}
      +                            
      +                            double dZ = Z[IDX_MQ(m1,q)] - Z[IDX_MQ(m2,q)];
      +                            double muZhat =  mu_nq - (Z[IDX_MQ(m1,q)] + Z[IDX_MQ(m2,q)])/2.;
      +                            double denom = 2.*Snq+lq;
      +                            double muZhat2_denom = muZhat*muZhat/denom;
      +                            
      +                            dmu_local += lpsi2*muZhat/denom;
      +                            dS_local += lpsi2*(2.*muZhat2_denom-1.)/denom;
      +                            dl_local += lpsi2*((Snq/lq+muZhat2_denom)/denom+dZ*dZ/(4.*lq*lq));
      +                            g_local[threadIdx.x] += 2.*lpsi2*(muZhat/denom-dZ/(2*lq));
      +                        }
      +                    }
      +                    __syncthreads();
      +                    reduce_sum(g_local, p<P-1?THREADNUM:N-(P-1)*THREADNUM);
      +                    if(threadIdx.x==0) {dZ[IDX_MQ(m1,q)] += g_local[0];}
      +                }
      +                if(n<N) {
      +                    dmu[IDX_NQB(n,q,blockIdx.x)] += -2.*dmu_local;
      +                    dS[IDX_NQB(n,q,blockIdx.x)] += dS_local;
      +                }
      +                __threadfence_block();
      +            }
      +            g_local[threadIdx.x] = dl_local*2.*lq_sqrt;
      +            __syncthreads();
      +            reduce_sum(g_local, THREADNUM);
      +            if(threadIdx.x==0) {dl[IDX_QB(q,blockIdx.x)] += g_local[0];}
      +        }
      +        g_local[threadIdx.x] = dvar_local;
      +        __syncthreads();
      +        reduce_sum(g_local, THREADNUM);
      +        if(threadIdx.x==0) {dvar[blockIdx.x] += g_local[0]*2/var;}
      +    }
      +    """
      +
      +
      [docs]class PSICOMP_RBF_GPU(PSICOMP_RBF): + + def __init__(self, threadnum=128, blocknum=15, GPU_direct=False): + self.GPU_direct = GPU_direct + self.gpuCache = None + + self.threadnum = threadnum + self.blocknum = blocknum + module = SourceModule("#define THREADNUM "+str(self.threadnum)+"\n"+gpu_code) + self.g_psi1computations = module.get_function('psi1computations') + self.g_psi1computations.prepare('PPdPPPPiii') + self.g_psi2computations = module.get_function('psi2computations') + self.g_psi2computations.prepare('PPPdPPPPiii') + self.g_psi1compDer = module.get_function('psi1compDer') + self.g_psi1compDer.prepare('PPPPPPPdPPPPiii') + self.g_psi2compDer = module.get_function('psi2compDer') + self.g_psi2compDer.prepare('PPPPPPPdPPPPiii') + self.g_compDenom = module.get_function('compDenom') + self.g_compDenom.prepare('PPPPii') + + def __deepcopy__(self, memo): + s = PSICOMP_RBF_GPU(threadnum=self.threadnum, blocknum=self.blocknum, GPU_direct=self.GPU_direct) + memo[id(self)] = s + return s + + def _initGPUCache(self, N, M, Q): + if self.gpuCache == None: + self.gpuCache = { + 'l_gpu' :gpuarray.empty((Q,),np.float64,order='F'), + 'Z_gpu' :gpuarray.empty((M,Q),np.float64,order='F'), + 'mu_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'S_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'psi1_gpu' :gpuarray.empty((N,M),np.float64,order='F'), + 'psi2_gpu' :gpuarray.empty((M,M),np.float64,order='F'), + 'psi2n_gpu' :gpuarray.empty((N,M,M),np.float64,order='F'), + 'dL_dpsi1_gpu' :gpuarray.empty((N,M),np.float64,order='F'), + 'dL_dpsi2_gpu' :gpuarray.empty((M,M),np.float64,order='F'), + 'log_denom1_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'log_denom2_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + # derivatives + 'dvar_gpu' :gpuarray.empty((self.blocknum,),np.float64, order='F'), + 'dl_gpu' :gpuarray.empty((Q,self.blocknum),np.float64, order='F'), + 'dZ_gpu' :gpuarray.empty((M,Q),np.float64, order='F'), + 'dmu_gpu' :gpuarray.empty((N,Q,self.blocknum),np.float64, order='F'), + 'dS_gpu' :gpuarray.empty((N,Q,self.blocknum),np.float64, order='F'), + # grad + 'grad_l_gpu' :gpuarray.empty((Q,),np.float64, order='F'), + 'grad_mu_gpu' :gpuarray.empty((N,Q,),np.float64, order='F'), + 'grad_S_gpu' :gpuarray.empty((N,Q,),np.float64, order='F'), + } + else: + assert N==self.gpuCache['mu_gpu'].shape[0] + assert M==self.gpuCache['Z_gpu'].shape[0] + assert Q==self.gpuCache['l_gpu'].shape[0] + +
      [docs] def sync_params(self, lengthscale, Z, mu, S): + if len(lengthscale)==1: + self.gpuCache['l_gpu'].fill(lengthscale) + else: + self.gpuCache['l_gpu'].set(np.asfortranarray(lengthscale)) + self.gpuCache['Z_gpu'].set(np.asfortranarray(Z)) + self.gpuCache['mu_gpu'].set(np.asfortranarray(mu)) + self.gpuCache['S_gpu'].set(np.asfortranarray(S)) + N,Q = self.gpuCache['S_gpu'].shape + # t=self.g_compDenom(self.gpuCache['log_denom1_gpu'],self.gpuCache['log_denom2_gpu'],self.gpuCache['l_gpu'],self.gpuCache['S_gpu'], np.int32(N), np.int32(Q), block=(self.threadnum,1,1), grid=(self.blocknum,1),time_kernel=True) + # print 'g_compDenom '+str(t) + self.g_compDenom.prepared_call((self.blocknum,1),(self.threadnum,1,1), self.gpuCache['log_denom1_gpu'].gpudata,self.gpuCache['log_denom2_gpu'].gpudata,self.gpuCache['l_gpu'].gpudata,self.gpuCache['S_gpu'].gpudata, np.int32(N), np.int32(Q)) +
      +
      [docs] def reset_derivative(self): + self.gpuCache['dvar_gpu'].fill(0.) + self.gpuCache['dl_gpu'].fill(0.) + self.gpuCache['dZ_gpu'].fill(0.) + self.gpuCache['dmu_gpu'].fill(0.) + self.gpuCache['dS_gpu'].fill(0.) + self.gpuCache['grad_l_gpu'].fill(0.) + self.gpuCache['grad_mu_gpu'].fill(0.) + self.gpuCache['grad_S_gpu'].fill(0.) +
      +
      [docs] def get_dimensions(self, Z, variational_posterior): + return variational_posterior.mean.shape[0], Z.shape[0], Z.shape[1] +
      + @Cache_this(limit=1, ignore_args=(0,)) + def psicomputations(self, variance, lengthscale, Z, variational_posterior): + """ + Z - MxQ + mu - NxQ + S - NxQ + """ + N,M,Q = self.get_dimensions(Z, variational_posterior) + self._initGPUCache(N,M,Q) + self.sync_params(lengthscale, Z, variational_posterior.mean, variational_posterior.variance) + + psi1_gpu = self.gpuCache['psi1_gpu'] + psi2_gpu = self.gpuCache['psi2_gpu'] + psi2n_gpu = self.gpuCache['psi2n_gpu'] + l_gpu = self.gpuCache['l_gpu'] + Z_gpu = self.gpuCache['Z_gpu'] + mu_gpu = self.gpuCache['mu_gpu'] + S_gpu = self.gpuCache['S_gpu'] + log_denom1_gpu = self.gpuCache['log_denom1_gpu'] + log_denom2_gpu = self.gpuCache['log_denom2_gpu'] + + psi0 = np.empty((N,)) + psi0[:] = variance + self.g_psi1computations.prepared_call((self.blocknum,1),(self.threadnum,1,1),psi1_gpu.gpudata, log_denom1_gpu.gpudata, np.float64(variance),l_gpu.gpudata,Z_gpu.gpudata,mu_gpu.gpudata,S_gpu.gpudata, np.int32(N), np.int32(M), np.int32(Q)) + self.g_psi2computations.prepared_call((self.blocknum,1),(self.threadnum,1,1),psi2_gpu.gpudata, psi2n_gpu.gpudata, log_denom2_gpu.gpudata, np.float64(variance),l_gpu.gpudata,Z_gpu.gpudata,mu_gpu.gpudata,S_gpu.gpudata, np.int32(N), np.int32(M), np.int32(Q)) + # t = self.g_psi1computations(psi1_gpu, log_denom1_gpu, np.float64(variance),l_gpu,Z_gpu,mu_gpu,S_gpu, np.int32(N), np.int32(M), np.int32(Q), block=(self.threadnum,1,1), grid=(self.blocknum,1),time_kernel=True) + # print 'g_psi1computations '+str(t) + # t = self.g_psi2computations(psi2_gpu, psi2n_gpu, log_denom2_gpu, np.float64(variance),l_gpu,Z_gpu,mu_gpu,S_gpu, np.int32(N), np.int32(M), np.int32(Q), block=(self.threadnum,1,1), grid=(self.blocknum,1),time_kernel=True) + # print 'g_psi2computations '+str(t) + + if self.GPU_direct: + return psi0, psi1_gpu, psi2_gpu + else: + return psi0, psi1_gpu.get(), psi2_gpu.get() + + @Cache_this(limit=1, ignore_args=(0,1,2,3)) + def psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior): + ARD = (len(lengthscale)!=1) + + N,M,Q = self.get_dimensions(Z, variational_posterior) + psi1_gpu = self.gpuCache['psi1_gpu'] + psi2n_gpu = self.gpuCache['psi2n_gpu'] + l_gpu = self.gpuCache['l_gpu'] + Z_gpu = self.gpuCache['Z_gpu'] + mu_gpu = self.gpuCache['mu_gpu'] + S_gpu = self.gpuCache['S_gpu'] + dvar_gpu = self.gpuCache['dvar_gpu'] + dl_gpu = self.gpuCache['dl_gpu'] + dZ_gpu = self.gpuCache['dZ_gpu'] + dmu_gpu = self.gpuCache['dmu_gpu'] + dS_gpu = self.gpuCache['dS_gpu'] + grad_l_gpu = self.gpuCache['grad_l_gpu'] + grad_mu_gpu = self.gpuCache['grad_mu_gpu'] + grad_S_gpu = self.gpuCache['grad_S_gpu'] + + if self.GPU_direct: + dL_dpsi1_gpu = dL_dpsi1 + dL_dpsi2_gpu = dL_dpsi2 + dL_dpsi0_sum = dL_dpsi0.get().sum() #gpuarray.sum(dL_dpsi0).get() + else: + dL_dpsi1_gpu = self.gpuCache['dL_dpsi1_gpu'] + dL_dpsi2_gpu = self.gpuCache['dL_dpsi2_gpu'] + dL_dpsi1_gpu.set(np.asfortranarray(dL_dpsi1)) + dL_dpsi2_gpu.set(np.asfortranarray(dL_dpsi2)) + dL_dpsi0_sum = dL_dpsi0.sum() + + self.reset_derivative() + # t=self.g_psi1compDer(dvar_gpu,dl_gpu,dZ_gpu,dmu_gpu,dS_gpu,dL_dpsi1_gpu,psi1_gpu, np.float64(variance),l_gpu,Z_gpu,mu_gpu,S_gpu, np.int32(N), np.int32(M), np.int32(Q), block=(self.threadnum,1,1), grid=(self.blocknum,1),time_kernel=True) + # print 'g_psi1compDer '+str(t) + # t=self.g_psi2compDer(dvar_gpu,dl_gpu,dZ_gpu,dmu_gpu,dS_gpu,dL_dpsi2_gpu,psi2n_gpu, np.float64(variance),l_gpu,Z_gpu,mu_gpu,S_gpu, np.int32(N), np.int32(M), np.int32(Q), block=(self.threadnum,1,1), grid=(self.blocknum,1),time_kernel=True) + # print 'g_psi2compDer '+str(t) + self.g_psi1compDer.prepared_call((self.blocknum,1),(self.threadnum,1,1),dvar_gpu.gpudata,dl_gpu.gpudata,dZ_gpu.gpudata,dmu_gpu.gpudata,dS_gpu.gpudata,dL_dpsi1_gpu.gpudata,psi1_gpu.gpudata, np.float64(variance),l_gpu.gpudata,Z_gpu.gpudata,mu_gpu.gpudata,S_gpu.gpudata, np.int32(N), np.int32(M), np.int32(Q)) + self.g_psi2compDer.prepared_call((self.blocknum,1),(self.threadnum,1,1),dvar_gpu.gpudata,dl_gpu.gpudata,dZ_gpu.gpudata,dmu_gpu.gpudata,dS_gpu.gpudata,dL_dpsi2_gpu.gpudata,psi2n_gpu.gpudata, np.float64(variance),l_gpu.gpudata,Z_gpu.gpudata,mu_gpu.gpudata,S_gpu.gpudata, np.int32(N), np.int32(M), np.int32(Q)) + + dL_dvar = dL_dpsi0_sum + dvar_gpu.get().sum()#gpuarray.sum(dvar_gpu).get() + sum_axis(grad_mu_gpu,dmu_gpu,N*Q,self.blocknum) + dL_dmu = grad_mu_gpu.get() + sum_axis(grad_S_gpu,dS_gpu,N*Q,self.blocknum) + dL_dS = grad_S_gpu.get() + dL_dZ = dZ_gpu.get() + if ARD: + sum_axis(grad_l_gpu,dl_gpu,Q,self.blocknum) + dL_dlengscale = grad_l_gpu.get() + else: + dL_dlengscale = dl_gpu.get().sum() #gpuarray.sum(dl_gpu).get() + + return dL_dvar, dL_dlengscale, dL_dZ, dL_dmu, dL_dS + +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/psi_comp/sslinear_psi_comp.html b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/sslinear_psi_comp.html new file mode 100644 index 00000000..32632cb9 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/sslinear_psi_comp.html @@ -0,0 +1,188 @@ + + + + + + + + GPy.kern._src.psi_comp.sslinear_psi_comp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.psi_comp.sslinear_psi_comp

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +"""
      +The package for the Psi statistics computation of the linear kernel for SSGPLVM
      +"""
      +
      +from ....util.linalg import tdot
      +
      +import numpy as np
      +
      +
      [docs]def psicomputations(variance, Z, variational_posterior): + """ + Compute psi-statistics for ss-linear kernel + """ + # here are the "statistics" for psi0, psi1 and psi2 + # Produced intermediate results: + # psi0 N + # psi1 NxM + # psi2 MxM + mu = variational_posterior.mean + S = variational_posterior.variance + gamma = variational_posterior.binary_prob + + psi0 = (gamma*(np.square(mu)+S)*variance).sum(axis=-1) + psi1 = np.inner(variance*gamma*mu,Z) + psi2 = np.inner(np.square(variance)*(gamma*((1-gamma)*np.square(mu)+S)).sum(axis=0)*Z,Z)+tdot(psi1.T) + + return psi0, psi1, psi2 +
      +
      [docs]def psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, Z, variational_posterior): + mu = variational_posterior.mean + S = variational_posterior.variance + gamma = variational_posterior.binary_prob + + dL_dvar, dL_dgamma, dL_dmu, dL_dS, dL_dZ = _psi2computations(dL_dpsi2, variance, Z, mu, S, gamma) + + # Compute for psi0 and psi1 + mu2S = np.square(mu)+S + dL_dvar += np.einsum('n,nq,nq->q',dL_dpsi0,gamma,mu2S) + np.einsum('nm,nq,mq,nq->q',dL_dpsi1,gamma,Z,mu) + dL_dgamma += np.einsum('n,q,nq->nq',dL_dpsi0,variance,mu2S) + np.einsum('nm,q,mq,nq->nq',dL_dpsi1,variance,Z,mu) + dL_dmu += np.einsum('n,nq,q,nq->nq',dL_dpsi0,gamma,2.*variance,mu) + np.einsum('nm,nq,q,mq->nq',dL_dpsi1,gamma,variance,Z) + dL_dS += np.einsum('n,nq,q->nq',dL_dpsi0,gamma,variance) + dL_dZ += np.einsum('nm,nq,q,nq->mq',dL_dpsi1,gamma, variance,mu) + + return dL_dvar, dL_dZ, dL_dmu, dL_dS, dL_dgamma +
      +def _psi2computations(dL_dpsi2, variance, Z, mu, S, gamma): + """ + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + """ + # here are the "statistics" for psi1 and psi2 + # Produced intermediate results: + # _psi2_dvariance Q + # _psi2_dZ MxQ + # _psi2_dgamma NxQ + # _psi2_dmu NxQ + # _psi2_dS NxQ + + mu2 = np.square(mu) + gamma2 = np.square(gamma) + variance2 = np.square(variance) + mu2S = mu2+S # NxQ + gvm = np.einsum('nq,nq,q->nq',gamma,mu,variance) + common_sum = np.einsum('nq,mq->nm',gvm,Z) +# common_sum = np.einsum('nq,q,mq,nq->nm',gamma,variance,Z,mu) # NxM + Z_expect = np.einsum('mo,mq,oq->q',dL_dpsi2,Z,Z) + dL_dpsi2T = dL_dpsi2+dL_dpsi2.T + tmp = np.einsum('mo,oq->mq',dL_dpsi2T,Z) + common_expect = np.einsum('mq,nm->nq',tmp,common_sum) +# common_expect = np.einsum('mo,mq,no->nq',dL_dpsi2+dL_dpsi2.T,Z,common_sum) + Z2_expect = np.einsum('om,nm->no',dL_dpsi2T,common_sum) + Z1_expect = np.einsum('om,mq->oq',dL_dpsi2T,Z) + + dL_dvar = np.einsum('nq,q,q->q',2.*(gamma*mu2S-gamma2*mu2),variance,Z_expect)+\ + np.einsum('nq,nq,nq->q',common_expect,gamma,mu) + + dL_dgamma = np.einsum('q,q,nq->nq',Z_expect,variance2,(mu2S-2.*gamma*mu2))+\ + np.einsum('nq,q,nq->nq',common_expect,variance,mu) + + dL_dmu = np.einsum('q,q,nq,nq->nq',Z_expect,variance2,mu,2.*(gamma-gamma2))+\ + np.einsum('nq,nq,q->nq',common_expect,gamma,variance) + + dL_dS = np.einsum('q,nq,q->nq',Z_expect,gamma,variance2) + +# dL_dZ = 2.*(np.einsum('om,nq,q,mq,nq->oq',dL_dpsi2,gamma,variance2,Z,(mu2S-gamma*mu2))+np.einsum('om,nq,q,nq,nm->oq',dL_dpsi2,gamma,variance,mu,common_sum)) + dL_dZ = Z1_expect*np.einsum('nq,q,nq->q',gamma,variance2,(mu2S-gamma*mu2))+np.einsum('nq,q,nq,nm->mq',gamma,variance,mu,Z2_expect) + + return dL_dvar, dL_dgamma, dL_dmu, dL_dS, dL_dZ +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/psi_comp/ssrbf_psi_comp.html b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/ssrbf_psi_comp.html new file mode 100644 index 00000000..1fbc74ce --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/ssrbf_psi_comp.html @@ -0,0 +1,490 @@ + + + + + + + + GPy.kern._src.psi_comp.ssrbf_psi_comp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.psi_comp.ssrbf_psi_comp

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +"""
      +The package for the psi statistics computation
      +"""
      +
      +import numpy as np
      +
      +try:
      +    from scipy import weave
      +     
      +    def _psicomputations(variance, lengthscale, Z, variational_posterior):
      +        """
      +        Z - MxQ
      +        mu - NxQ
      +        S - NxQ
      +        gamma - NxQ
      +        """
      +        # here are the "statistics" for psi0, psi1 and psi2
      +        # Produced intermediate results:
      +        # _psi1                NxM
      +        mu = variational_posterior.mean
      +        S = variational_posterior.variance
      +         
      +        N,M,Q = mu.shape[0],Z.shape[0],mu.shape[1]
      +        l2 = np.square(lengthscale)
      +        log_denom1 = np.log(S/l2+1)
      +        log_denom2 = np.log(2*S/l2+1)
      +        log_gamma,log_gamma1 = variational_posterior.gamma_log_prob()
      +        variance = float(variance)
      +        psi0 = np.empty(N)
      +        psi0[:] = variance
      +        psi1 = np.empty((N,M))
      +        psi2n = np.empty((N,M,M))
      +         
      +        from ....util.misc import param_to_array
      +        S = param_to_array(S)
      +        mu = param_to_array(mu)
      +        Z = param_to_array(Z)
      +         
      +        support_code = """
      +        #include <math.h>
      +        """
      +        code = """
      +        for(int n=0; n<N; n++) {
      +            for(int m1=0;m1<M;m1++) {
      +                double log_psi1=0;
      +                for(int m2=0;m2<=m1;m2++) {
      +                    double log_psi2_n=0;
      +                    for(int q=0;q<Q;q++) {
      +                        double Snq = S(n,q);
      +                        double lq = l2(q);
      +                        double Zm1q = Z(m1,q);
      +                        double Zm2q = Z(m2,q);
      +                         
      +                        if(m2==0) {
      +                            // Compute Psi_1
      +                            double muZ = mu(n,q)-Z(m1,q);
      +                             
      +                            double psi1_exp1 = log_gamma(n,q) - (muZ*muZ/(Snq+lq) +log_denom1(n,q))/2.;
      +                            double psi1_exp2 = log_gamma1(n,q) -Zm1q*Zm1q/(2.*lq);
      +                            log_psi1 += (psi1_exp1>psi1_exp2)?psi1_exp1+log1p(exp(psi1_exp2-psi1_exp1)):psi1_exp2+log1p(exp(psi1_exp1-psi1_exp2));
      +                        }
      +                        // Compute Psi_2
      +                        double muZhat = mu(n,q) - (Zm1q+Zm2q)/2.;
      +                        double Z2 = Zm1q*Zm1q+ Zm2q*Zm2q;
      +                        double dZ = Zm1q - Zm2q;
      +                         
      +                        double psi2_exp1 = dZ*dZ/(-4.*lq)-muZhat*muZhat/(2.*Snq+lq) - log_denom2(n,q)/2. + log_gamma(n,q);
      +                        double psi2_exp2 = log_gamma1(n,q) - Z2/(2.*lq);
      +                        log_psi2_n += (psi2_exp1>psi2_exp2)?psi2_exp1+log1p(exp(psi2_exp2-psi2_exp1)):psi2_exp2+log1p(exp(psi2_exp1-psi2_exp2));                    
      +                    }
      +                    double exp_psi2_n = exp(log_psi2_n);
      +                    psi2n(n,m1,m2) = variance*variance*exp_psi2_n;
      +                    if(m1!=m2) { psi2n(n,m2,m1) = variance*variance*exp_psi2_n;}
      +                }
      +                psi1(n,m1) = variance*exp(log_psi1);
      +            }
      +        }
      +        """
      +        weave.inline(code, support_code=support_code, arg_names=['psi1','psi2n','N','M','Q','variance','l2','Z','mu','S','log_denom1','log_denom2','log_gamma','log_gamma1'], type_converters=weave.converters.blitz)
      +     
      +        psi2 = psi2n.sum(axis=0)
      +        return psi0,psi1,psi2,psi2n
      +     
      +    from GPy.util.caching import Cacher
      +    psicomputations = Cacher(_psicomputations, limit=1)
      +     
      +    def psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior):
      +        ARD = (len(lengthscale)!=1)
      +         
      +        _,psi1,_,psi2n = psicomputations(variance, lengthscale, Z, variational_posterior)
      +     
      +        mu = variational_posterior.mean
      +        S = variational_posterior.variance
      +        N,M,Q = mu.shape[0],Z.shape[0],mu.shape[1]
      +        l2 = np.square(lengthscale)
      +        log_denom1 = np.log(S/l2+1)
      +        log_denom2 = np.log(2*S/l2+1)
      +        log_gamma,log_gamma1 = variational_posterior.gamma_log_prob()
      +        gamma, gamma1 = variational_posterior.gamma_probabilities()
      +        variance = float(variance)
      +     
      +        dvar = np.zeros(1)
      +        dmu = np.zeros((N,Q))
      +        dS = np.zeros((N,Q))
      +        dgamma = np.zeros((N,Q))
      +        dl = np.zeros(Q)
      +        dZ = np.zeros((M,Q))
      +        dvar += np.sum(dL_dpsi0)
      +         
      +        from ....util.misc import param_to_array
      +        S = param_to_array(S)
      +        mu = param_to_array(mu)
      +        Z = param_to_array(Z)
      +         
      +        support_code = """
      +        #include <math.h>
      +        """
      +        code = """
      +        for(int n=0; n<N; n++) {
      +            for(int m1=0;m1<M;m1++) {
      +                double log_psi1=0;
      +                for(int m2=0;m2<M;m2++) {
      +                    double log_psi2_n=0;
      +                    for(int q=0;q<Q;q++) {
      +                        double Snq = S(n,q);
      +                        double lq = l2(q);
      +                        double Zm1q = Z(m1,q);
      +                        double Zm2q = Z(m2,q);
      +                        double gnq = gamma(n,q);
      +                        double g1nq = gamma1(n,q);
      +                        double mu_nq = mu(n,q);
      +                         
      +                        if(m2==0) {
      +                            // Compute Psi_1                        
      +                            double lpsi1 = psi1(n,m1)*dL_dpsi1(n,m1);
      +                            if(q==0) {dvar(0) += lpsi1/variance;}
      +                             
      +                            double Zmu = Zm1q - mu_nq;
      +                            double denom = Snq+lq;
      +                            double Zmu2_denom = Zmu*Zmu/denom;
      +                             
      +                            double exp1 = log_gamma(n,q)-(Zmu*Zmu/(Snq+lq)+log_denom1(n,q))/(2.);
      +                            double exp2 = log_gamma1(n,q)-Zm1q*Zm1q/(2.*lq);
      +                            double d_exp1,d_exp2;
      +                            if(exp1>exp2) {
      +                                d_exp1 = 1.;
      +                                d_exp2 = exp(exp2-exp1);
      +                            } else {
      +                                d_exp1 = exp(exp1-exp2);
      +                                d_exp2 = 1.;
      +                            }
      +                            double exp_sum = d_exp1+d_exp2;
      +                             
      +                            dmu(n,q) += lpsi1*Zmu*d_exp1/(denom*exp_sum);
      +                            dS(n,q) += lpsi1*(Zmu2_denom-1.)*d_exp1/(denom*exp_sum)/2.;
      +                            dgamma(n,q) += lpsi1*(d_exp1*g1nq-d_exp2*gnq)/exp_sum;
      +                            dl(q) += lpsi1*((Zmu2_denom+Snq/lq)/denom*d_exp1+Zm1q*Zm1q/(lq*lq)*d_exp2)/(2.*exp_sum);
      +                            dZ(m1,q) += lpsi1*(-Zmu/denom*d_exp1-Zm1q/lq*d_exp2)/exp_sum;
      +                        }
      +                        // Compute Psi_2
      +                        double lpsi2 = psi2n(n,m1,m2)*dL_dpsi2(m1,m2);
      +                        if(q==0) {dvar(0) += lpsi2*2/variance;}
      +                         
      +                        double dZm1m2 = Zm1q - Zm2q;
      +                        double Z2 = Zm1q*Zm1q+Zm2q*Zm2q;
      +                        double muZhat =  mu_nq - (Zm1q + Zm2q)/2.;
      +                        double denom = 2.*Snq+lq;
      +                        double muZhat2_denom = muZhat*muZhat/denom;
      +                         
      +                        double exp1 = dZm1m2*dZm1m2/(-4.*lq)-muZhat*muZhat/(2.*Snq+lq) - log_denom2(n,q)/2. + log_gamma(n,q);
      +                        double exp2 = log_gamma1(n,q) - Z2/(2.*lq);
      +                        double d_exp1,d_exp2;
      +                        if(exp1>exp2) {
      +                            d_exp1 = 1.;
      +                            d_exp2 = exp(exp2-exp1);
      +                        } else {
      +                            d_exp1 = exp(exp1-exp2);
      +                            d_exp2 = 1.;
      +                        }
      +                        double exp_sum = d_exp1+d_exp2;
      +                         
      +                        dmu(n,q) += -2.*lpsi2*muZhat/denom*d_exp1/exp_sum;
      +                        dS(n,q) += lpsi2*(2.*muZhat2_denom-1.)/denom*d_exp1/exp_sum;
      +                        dgamma(n,q) += lpsi2*(d_exp1*g1nq-d_exp2*gnq)/exp_sum;
      +                        dl(q) += lpsi2*(((Snq/lq+muZhat2_denom)/denom+dZm1m2*dZm1m2/(4.*lq*lq))*d_exp1+Z2/(2.*lq*lq)*d_exp2)/exp_sum;
      +                        dZ(m1,q) += 2.*lpsi2*((muZhat/denom-dZm1m2/(2*lq))*d_exp1-Zm1q/lq*d_exp2)/exp_sum;                   
      +                    }
      +                }
      +            }
      +        }
      +        """
      +        weave.inline(code, support_code=support_code, arg_names=['dL_dpsi1','dL_dpsi2','psi1','psi2n','N','M','Q','variance','l2','Z','mu','S','gamma','gamma1','log_denom1','log_denom2','log_gamma','log_gamma1','dvar','dl','dmu','dS','dgamma','dZ'], type_converters=weave.converters.blitz)
      +     
      +        dl *= 2.*lengthscale
      +        if not ARD:
      +            dl = dl.sum()
      +         
      +        return dvar, dl, dZ, dmu, dS, dgamma
      +
      +except:
      +
      +    def psicomputations(variance, lengthscale, Z, variational_posterior):
      +        """
      +        Z - MxQ
      +        mu - NxQ
      +        S - NxQ
      +        gamma - NxQ
      +        """
      +        # here are the "statistics" for psi0, psi1 and psi2
      +        # Produced intermediate results:
      +        # _psi1                NxM
      +        mu = variational_posterior.mean
      +        S = variational_posterior.variance
      +        gamma = variational_posterior.binary_prob
      +         
      +        psi0 = np.empty(mu.shape[0])
      +        psi0[:] = variance
      +        psi1 = _psi1computations(variance, lengthscale, Z, mu, S, gamma)
      +        psi2 = _psi2computations(variance, lengthscale, Z, mu, S, gamma)
      +        return psi0, psi1, psi2
      +    
      +    def _psi1computations(variance, lengthscale, Z, mu, S, gamma):
      +        """
      +        Z - MxQ
      +        mu - NxQ
      +        S - NxQ
      +        gamma - NxQ
      +        """
      +        # here are the "statistics" for psi1
      +        # Produced intermediate results:
      +        # _psi1                NxM
      +    
      +        lengthscale2 = np.square(lengthscale)
      +    
      +        # psi1
      +        _psi1_denom = S[:, None, :] / lengthscale2 + 1.  # Nx1xQ
      +        _psi1_denom_sqrt = np.sqrt(_psi1_denom) #Nx1xQ
      +        _psi1_dist = Z[None, :, :] - mu[:, None, :]  # NxMxQ
      +        _psi1_dist_sq = np.square(_psi1_dist) / (lengthscale2 * _psi1_denom) # NxMxQ
      +        _psi1_common = gamma[:,None,:] / (lengthscale2*_psi1_denom*_psi1_denom_sqrt) #Nx1xQ
      +        _psi1_exponent1 = np.log(gamma[:,None,:]) - (_psi1_dist_sq + np.log(_psi1_denom))/2. # NxMxQ
      +        _psi1_exponent2 = np.log(1.-gamma[:,None,:]) - (np.square(Z[None,:,:])/lengthscale2)/2. # NxMxQ
      +        _psi1_exponent_max = np.maximum(_psi1_exponent1,_psi1_exponent2)
      +        _psi1_exponent = _psi1_exponent_max+np.log(np.exp(_psi1_exponent1-_psi1_exponent_max) + np.exp(_psi1_exponent2-_psi1_exponent_max)) #NxMxQ
      +        _psi1_exp_sum = _psi1_exponent.sum(axis=-1) #NxM
      +        _psi1 = variance * np.exp(_psi1_exp_sum) # NxM
      +    
      +        return _psi1
      +    
      +    def _psi2computations(variance, lengthscale, Z, mu, S, gamma):
      +        """
      +        Z - MxQ
      +        mu - NxQ
      +        S - NxQ
      +        gamma - NxQ
      +        """
      +        # here are the "statistics" for psi2
      +        # Produced intermediate results:
      +        # _psi2                MxM
      +        
      +        lengthscale2 = np.square(lengthscale)
      +        
      +        _psi2_Zhat = 0.5 * (Z[:, None, :] + Z[None, :, :]) # M,M,Q
      +        _psi2_Zdist = 0.5 * (Z[:, None, :] - Z[None, :, :]) # M,M,Q
      +        _psi2_Zdist_sq = np.square(_psi2_Zdist / lengthscale) # M,M,Q
      +        _psi2_Z_sq_sum = (np.square(Z[:,None,:])+np.square(Z[None,:,:]))/lengthscale2 # MxMxQ
      +    
      +        # psi2
      +        _psi2_denom = 2.*S[:, None, None, :] / lengthscale2 + 1. # Nx1x1xQ
      +        _psi2_denom_sqrt = np.sqrt(_psi2_denom)
      +        _psi2_mudist = mu[:,None,None,:]-_psi2_Zhat #N,M,M,Q
      +        _psi2_mudist_sq = np.square(_psi2_mudist)/(lengthscale2*_psi2_denom)
      +        _psi2_common = gamma[:,None,None,:]/(lengthscale2 * _psi2_denom * _psi2_denom_sqrt) # Nx1x1xQ
      +        _psi2_exponent1 = -_psi2_Zdist_sq -_psi2_mudist_sq -0.5*np.log(_psi2_denom)+np.log(gamma[:,None,None,:]) #N,M,M,Q
      +        _psi2_exponent2 = np.log(1.-gamma[:,None,None,:]) - 0.5*(_psi2_Z_sq_sum) # NxMxMxQ
      +        _psi2_exponent_max = np.maximum(_psi2_exponent1, _psi2_exponent2)
      +        _psi2_exponent = _psi2_exponent_max+np.log(np.exp(_psi2_exponent1-_psi2_exponent_max) + np.exp(_psi2_exponent2-_psi2_exponent_max))
      +        _psi2_exp_sum = _psi2_exponent.sum(axis=-1) #NxM
      +        _psi2 = variance*variance * (np.exp(_psi2_exp_sum).sum(axis=0)) # MxM
      +    
      +        return _psi2
      +    
      +
      [docs] def psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior): + ARD = (len(lengthscale)!=1) + + dvar_psi1, dl_psi1, dZ_psi1, dmu_psi1, dS_psi1, dgamma_psi1 = _psi1compDer(dL_dpsi1, variance, lengthscale, Z, variational_posterior.mean, variational_posterior.variance, variational_posterior.binary_prob) + dvar_psi2, dl_psi2, dZ_psi2, dmu_psi2, dS_psi2, dgamma_psi2 = _psi2compDer(dL_dpsi2, variance, lengthscale, Z, variational_posterior.mean, variational_posterior.variance, variational_posterior.binary_prob) + + dL_dvar = np.sum(dL_dpsi0) + dvar_psi1 + dvar_psi2 + + dL_dlengscale = dl_psi1 + dl_psi2 + if not ARD: + dL_dlengscale = dL_dlengscale.sum() + + dL_dgamma = dgamma_psi1 + dgamma_psi2 + dL_dmu = dmu_psi1 + dmu_psi2 + dL_dS = dS_psi1 + dS_psi2 + dL_dZ = dZ_psi1 + dZ_psi2 + + return dL_dvar, dL_dlengscale, dL_dZ, dL_dmu, dL_dS, dL_dgamma +
      + def _psi1compDer(dL_dpsi1, variance, lengthscale, Z, mu, S, gamma): + """ + dL_dpsi1 - NxM + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + """ + # here are the "statistics" for psi1 + # Produced intermediate results: dL_dparams w.r.t. psi1 + # _dL_dvariance 1 + # _dL_dlengthscale Q + # _dL_dZ MxQ + # _dL_dgamma NxQ + # _dL_dmu NxQ + # _dL_dS NxQ + + lengthscale2 = np.square(lengthscale) + + # psi1 + _psi1_denom = S / lengthscale2 + 1. # NxQ + _psi1_denom_sqrt = np.sqrt(_psi1_denom) #NxQ + _psi1_dist = Z[None, :, :] - mu[:, None, :] # NxMxQ + _psi1_dist_sq = np.square(_psi1_dist) / (lengthscale2 * _psi1_denom[:,None,:]) # NxMxQ + _psi1_common = gamma / (lengthscale2*_psi1_denom*_psi1_denom_sqrt) #NxQ + _psi1_exponent1 = np.log(gamma[:,None,:]) -0.5 * (_psi1_dist_sq + np.log(_psi1_denom[:, None,:])) # NxMxQ + _psi1_exponent2 = np.log(1.-gamma[:,None,:]) -0.5 * (np.square(Z[None,:,:])/lengthscale2) # NxMxQ + _psi1_exponent_max = np.maximum(_psi1_exponent1,_psi1_exponent2) + _psi1_exponent = _psi1_exponent_max+np.log(np.exp(_psi1_exponent1-_psi1_exponent_max) + np.exp(_psi1_exponent2-_psi1_exponent_max)) #NxMxQ + _psi1_exp_sum = _psi1_exponent.sum(axis=-1) #NxM + _psi1_exp_dist_sq = np.exp(-0.5*_psi1_dist_sq) # NxMxQ + _psi1_exp_Z = np.exp(-0.5*np.square(Z[None,:,:])/lengthscale2) # 1xMxQ + _psi1_q = variance * np.exp(_psi1_exp_sum[:,:,None] - _psi1_exponent) # NxMxQ + _psi1 = variance * np.exp(_psi1_exp_sum) # NxM + _dL_dvariance = np.einsum('nm,nm->',dL_dpsi1, _psi1)/variance # 1 + _dL_dgamma = np.einsum('nm,nmq,nmq->nq',dL_dpsi1, _psi1_q, (_psi1_exp_dist_sq/_psi1_denom_sqrt[:,None,:]-_psi1_exp_Z)) # NxQ + _dL_dmu = np.einsum('nm, nmq, nmq, nmq, nq->nq',dL_dpsi1,_psi1_q,_psi1_exp_dist_sq,_psi1_dist,_psi1_common) # NxQ + _dL_dS = np.einsum('nm,nmq,nmq,nq,nmq->nq',dL_dpsi1,_psi1_q,_psi1_exp_dist_sq,_psi1_common,(_psi1_dist_sq-1.))/2. # NxQ + _dL_dZ = np.einsum('nm,nmq,nmq->mq',dL_dpsi1,_psi1_q, (- _psi1_common[:,None,:] * _psi1_dist * _psi1_exp_dist_sq - (1-gamma[:,None,:])/lengthscale2*Z[None,:,:]*_psi1_exp_Z)) + _dL_dlengthscale = lengthscale* np.einsum('nm,nmq,nmq->q',dL_dpsi1,_psi1_q,(_psi1_common[:,None,:]*(S[:,None,:]/lengthscale2+_psi1_dist_sq)*_psi1_exp_dist_sq + (1-gamma[:,None,:])*np.square(Z[None,:,:]/lengthscale2)*_psi1_exp_Z)) + + return _dL_dvariance, _dL_dlengthscale, _dL_dZ, _dL_dmu, _dL_dS, _dL_dgamma + + def _psi2compDer(dL_dpsi2, variance, lengthscale, Z, mu, S, gamma): + """ + Z - MxQ + mu - NxQ + S - NxQ + gamma - NxQ + dL_dpsi2 - MxM + """ + # here are the "statistics" for psi2 + # Produced the derivatives w.r.t. psi2: + # _dL_dvariance 1 + # _dL_dlengthscale Q + # _dL_dZ MxQ + # _dL_dgamma NxQ + # _dL_dmu NxQ + # _dL_dS NxQ + + lengthscale2 = np.square(lengthscale) + + _psi2_Zhat = 0.5 * (Z[:, None, :] + Z[None, :, :]) # M,M,Q + _psi2_Zdist = 0.5 * (Z[:, None, :] - Z[None, :, :]) # M,M,Q + _psi2_Zdist_sq = np.square(_psi2_Zdist / lengthscale) # M,M,Q + _psi2_Z_sq_sum = (np.square(Z[:,None,:])+np.square(Z[None,:,:]))/lengthscale2 # MxMxQ + + # psi2 + _psi2_denom = 2.*S / lengthscale2 + 1. # NxQ + _psi2_denom_sqrt = np.sqrt(_psi2_denom) + _psi2_mudist = mu[:,None,None,:]-_psi2_Zhat #N,M,M,Q + _psi2_mudist_sq = np.square(_psi2_mudist)/(lengthscale2*_psi2_denom[:,None,None,:]) + _psi2_common = gamma/(lengthscale2 * _psi2_denom * _psi2_denom_sqrt) # NxQ + _psi2_exponent1 = -_psi2_Zdist_sq -_psi2_mudist_sq -0.5*np.log(_psi2_denom[:,None,None,:])+np.log(gamma[:,None,None,:]) #N,M,M,Q + _psi2_exponent2 = np.log(1.-gamma[:,None,None,:]) - 0.5*(_psi2_Z_sq_sum) # NxMxMxQ + _psi2_exponent_max = np.maximum(_psi2_exponent1, _psi2_exponent2) + _psi2_exponent = _psi2_exponent_max+np.log(np.exp(_psi2_exponent1-_psi2_exponent_max) + np.exp(_psi2_exponent2-_psi2_exponent_max)) + _psi2_exp_sum = _psi2_exponent.sum(axis=-1) #NxM + _psi2_q = variance*variance * np.exp(_psi2_exp_sum[:,:,:,None]-_psi2_exponent) # NxMxMxQ + _psi2_exp_dist_sq = np.exp(-_psi2_Zdist_sq -_psi2_mudist_sq) # NxMxMxQ + _psi2_exp_Z = np.exp(-0.5*_psi2_Z_sq_sum) # MxMxQ + _psi2 = variance*variance * (np.exp(_psi2_exp_sum).sum(axis=0)) # MxM + _dL_dvariance = np.einsum('mo,mo->',dL_dpsi2,_psi2)*2./variance + _dL_dgamma = np.einsum('mo,nmoq,nmoq->nq',dL_dpsi2,_psi2_q,(_psi2_exp_dist_sq/_psi2_denom_sqrt[:,None,None,:] - _psi2_exp_Z)) + _dL_dmu = -2.*np.einsum('mo,nmoq,nq,nmoq,nmoq->nq',dL_dpsi2,_psi2_q,_psi2_common,_psi2_mudist,_psi2_exp_dist_sq) + _dL_dS = np.einsum('mo,nmoq,nq,nmoq,nmoq->nq',dL_dpsi2,_psi2_q, _psi2_common, (2.*_psi2_mudist_sq-1.), _psi2_exp_dist_sq) + _dL_dZ = 2.*np.einsum('mo,nmoq,nmoq->mq',dL_dpsi2,_psi2_q,(_psi2_common[:,None,None,:]*(-_psi2_Zdist*_psi2_denom[:,None,None,:]+_psi2_mudist)*_psi2_exp_dist_sq - (1-gamma[:,None,None,:])*Z[:,None,:]/lengthscale2*_psi2_exp_Z)) + _dL_dlengthscale = 2.*lengthscale* np.einsum('mo,nmoq,nmoq->q',dL_dpsi2,_psi2_q,(_psi2_common[:,None,None,:]*(S[:,None,None,:]/lengthscale2+_psi2_Zdist_sq*_psi2_denom[:,None,None,:]+_psi2_mudist_sq)*_psi2_exp_dist_sq+(1-gamma[:,None,None,:])*_psi2_Z_sq_sum*0.5/lengthscale2*_psi2_exp_Z)) + + return _dL_dvariance, _dL_dlengthscale, _dL_dZ, _dL_dmu, _dL_dS, _dL_dgamma +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/psi_comp/ssrbf_psi_gpucomp.html b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/ssrbf_psi_gpucomp.html new file mode 100644 index 00000000..2a32598f --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/psi_comp/ssrbf_psi_gpucomp.html @@ -0,0 +1,568 @@ + + + + + + + + GPy.kern._src.psi_comp.ssrbf_psi_gpucomp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.psi_comp.ssrbf_psi_gpucomp

      +"""
      +The module for psi-statistics for RBF kernel for Spike-and-Slab GPLVM
      +"""
      +
      +import numpy as np
      +from ....util.caching import Cache_this
      +from . import PSICOMP_RBF
      +from ....util import gpu_init
      +
      +try:
      +    import pycuda.gpuarray as gpuarray
      +    from pycuda.compiler import SourceModule
      +    from ....util.linalg_gpu import sum_axis
      +except:
      +    pass    
      +
      +gpu_code = """
      +    // define THREADNUM
      +
      +    #define IDX_NMQ(n,m,q) ((q*M+m)*N+n)
      +    #define IDX_NMM(n,m1,m2) ((m2*M+m1)*N+n)
      +    #define IDX_NQ(n,q) (q*N+n)
      +    #define IDX_NM(n,m) (m*N+n)
      +    #define IDX_MQ(m,q) (q*M+m)
      +    #define IDX_MM(m1,m2) (m2*M+m1)
      +    #define IDX_NQB(n,q,b) ((b*Q+q)*N+n)
      +    #define IDX_QB(q,b) (b*Q+q)
      +
      +    // Divide data evenly
      +    __device__ void divide_data(int total_data, int psize, int pidx, int *start, int *end) {
      +        int residue = (total_data)%psize;
      +        if(pidx<residue) {
      +            int size = total_data/psize+1;
      +            *start = size*pidx;
      +            *end = *start+size;
      +        } else {
      +            int size = total_data/psize;
      +            *start = size*pidx+residue;
      +            *end = *start+size;
      +        }
      +    }
      +    
      +    __device__ void reduce_sum(double* array, int array_size) {
      +        int s;
      +        if(array_size >= blockDim.x) {
      +            for(int i=blockDim.x+threadIdx.x; i<array_size; i+= blockDim.x) {
      +                array[threadIdx.x] += array[i];
      +            }
      +            array_size = blockDim.x;
      +        }
      +        __syncthreads();
      +        for(int i=1; i<=array_size;i*=2) {s=i;}
      +        if(threadIdx.x < array_size-s) {array[threadIdx.x] += array[s+threadIdx.x];}
      +        __syncthreads();
      +        for(s=s/2;s>=1;s=s/2) {
      +            if(threadIdx.x < s) {array[threadIdx.x] += array[s+threadIdx.x];}
      +            __syncthreads();
      +        }
      +    }
      +
      +    __global__ void compDenom(double *log_denom1, double *log_denom2, double *log_gamma, double*log_gamma1, double *gamma, double *l, double *S, int N, int Q)
      +    {
      +        int n_start, n_end;
      +        divide_data(N, gridDim.x, blockIdx.x, &n_start, &n_end);
      +        
      +        for(int i=n_start*Q+threadIdx.x; i<n_end*Q; i+=blockDim.x) {
      +            int n=i/Q;
      +            int q=i%Q;
      +
      +            double Snq = S[IDX_NQ(n,q)];
      +            double lq = l[q]*l[q];
      +            double gnq = gamma[IDX_NQ(n,q)];
      +            log_denom1[IDX_NQ(n,q)] = log(Snq/lq+1.);
      +            log_denom2[IDX_NQ(n,q)] = log(2.*Snq/lq+1.);
      +            log_gamma[IDX_NQ(n,q)] = log(gnq);
      +            log_gamma1[IDX_NQ(n,q)] = log(1.-gnq);
      +        }
      +    }
      +
      +    __global__ void psi1computations(double *psi1, double *log_denom1, double *log_gamma, double*log_gamma1, double var, double *l, double *Z, double *mu, double *S, int N, int M, int Q)
      +    {
      +        int m_start, m_end;
      +        divide_data(M, gridDim.x, blockIdx.x, &m_start, &m_end);
      +        
      +        for(int m=m_start; m<m_end; m++) {
      +            for(int n=threadIdx.x; n<N; n+= blockDim.x) {            
      +                double log_psi1 = 0;
      +                for(int q=0;q<Q;q++) {
      +                    double Zmq = Z[IDX_MQ(m,q)];
      +                    double muZ = mu[IDX_NQ(n,q)]-Zmq;
      +                    double Snq = S[IDX_NQ(n,q)];
      +                    double lq = l[q]*l[q];
      +                    double exp1 = log_gamma[IDX_NQ(n,q)]-(muZ*muZ/(Snq+lq)+log_denom1[IDX_NQ(n,q)])/(2.);
      +                    double exp2 = log_gamma1[IDX_NQ(n,q)]-Zmq*Zmq/(2.*lq);
      +                    log_psi1 += (exp1>exp2)?exp1+log1p(exp(exp2-exp1)):exp2+log1p(exp(exp1-exp2));
      +                }
      +                psi1[IDX_NM(n,m)] = var*exp(log_psi1);
      +            }
      +        }
      +    }
      +    
      +    __global__ void psi2computations(double *psi2, double *psi2n, double *log_denom2, double *log_gamma, double*log_gamma1, double var, double *l, double *Z, double *mu, double *S, int N, int M, int Q)
      +    {
      +        int psi2_idx_start, psi2_idx_end;
      +        __shared__ double psi2_local[THREADNUM];
      +        divide_data((M+1)*M/2, gridDim.x, blockIdx.x, &psi2_idx_start, &psi2_idx_end);
      +        
      +        for(int psi2_idx=psi2_idx_start; psi2_idx<psi2_idx_end; psi2_idx++) {
      +            int m1 = int((sqrt(8.*psi2_idx+1.)-1.)/2.);
      +            int m2 = psi2_idx - (m1+1)*m1/2;
      +            
      +            psi2_local[threadIdx.x] = 0;
      +            for(int n=threadIdx.x;n<N;n+=blockDim.x) {
      +                double log_psi2_n = 0;
      +                for(int q=0;q<Q;q++) {
      +                    double Zm1q = Z[IDX_MQ(m1,q)];
      +                    double Zm2q = Z[IDX_MQ(m2,q)];
      +                    double dZ = Zm1q - Zm2q;
      +                    double muZhat = mu[IDX_NQ(n,q)]- (Zm1q+Zm2q)/2.;
      +                    double Z2 = Zm1q*Zm1q+Zm2q*Zm2q;
      +                    double Snq = S[IDX_NQ(n,q)];
      +                    double lq = l[q]*l[q];
      +                    double exp1 = dZ*dZ/(-4.*lq)-muZhat*muZhat/(2.*Snq+lq) - log_denom2[IDX_NQ(n,q)]/2. + log_gamma[IDX_NQ(n,q)];
      +                    double exp2 = log_gamma1[IDX_NQ(n,q)] - Z2/(2.*lq);
      +                    log_psi2_n += (exp1>exp2)?exp1+log1p(exp(exp2-exp1)):exp2+log1p(exp(exp1-exp2));
      +                }
      +                double exp_psi2_n = exp(log_psi2_n);
      +                psi2n[IDX_NMM(n,m1,m2)] = var*var*exp_psi2_n;
      +                if(m1!=m2) { psi2n[IDX_NMM(n,m2,m1)] = var*var*exp_psi2_n;}
      +                psi2_local[threadIdx.x] += exp_psi2_n;
      +            }
      +            __syncthreads();
      +            reduce_sum(psi2_local, THREADNUM);
      +            if(threadIdx.x==0) {
      +                psi2[IDX_MM(m1,m2)] = var*var*psi2_local[0];
      +                if(m1!=m2) { psi2[IDX_MM(m2,m1)] = var*var*psi2_local[0]; }
      +            }
      +            __syncthreads();
      +        }
      +    }
      +    
      +    __global__ void psi1compDer(double *dvar, double *dl, double *dZ, double *dmu, double *dS, double *dgamma, double *dL_dpsi1, double *psi1, double *log_denom1, double *log_gamma, double*log_gamma1, double var, double *l, double *Z, double *mu, double *S, double *gamma, int N, int M, int Q)
      +    {
      +        int m_start, m_end;
      +        __shared__ double g_local[THREADNUM];
      +        divide_data(M, gridDim.x, blockIdx.x, &m_start, &m_end);
      +        int P = int(ceil(double(N)/THREADNUM));
      +
      +        double dvar_local = 0;
      +        for(int q=0;q<Q;q++) {
      +            double lq_sqrt = l[q];
      +            double lq = lq_sqrt*lq_sqrt;
      +            double dl_local = 0;
      +            for(int p=0;p<P;p++) {
      +                int n = p*THREADNUM + threadIdx.x;
      +                double dmu_local = 0;
      +                double dS_local = 0;
      +                double dgamma_local = 0;
      +                double Snq,mu_nq,gnq,log_gnq,log_gnq1,log_de;
      +                if(n<N) {Snq = S[IDX_NQ(n,q)]; mu_nq=mu[IDX_NQ(n,q)]; gnq = gamma[IDX_NQ(n,q)];
      +                        log_gnq = log_gamma[IDX_NQ(n,q)]; log_gnq1 = log_gamma1[IDX_NQ(n,q)];
      +                        log_de = log_denom1[IDX_NQ(n,q)];}
      +                for(int m=m_start; m<m_end; m++) {
      +                    if(n<N) {
      +                        double lpsi1 = psi1[IDX_NM(n,m)]*dL_dpsi1[IDX_NM(n,m)];
      +                        if(q==0) {dvar_local += lpsi1;}
      +                        
      +                        double Zmq = Z[IDX_MQ(m,q)];
      +                        double Zmu = Zmq - mu_nq;
      +                        double denom = Snq+lq;
      +                        double Zmu2_denom = Zmu*Zmu/denom;
      +                        
      +                        double exp1 = log_gnq-(Zmu*Zmu/(Snq+lq)+log_de)/(2.);
      +                        double exp2 = log_gnq1-Zmq*Zmq/(2.*lq);
      +                        double d_exp1,d_exp2;
      +                        if(exp1>exp2) {
      +                            d_exp1 = 1.;
      +                            d_exp2 = exp(exp2-exp1);
      +                        } else {
      +                            d_exp1 = exp(exp1-exp2);
      +                            d_exp2 = 1.;
      +                        }
      +                        double exp_sum = d_exp1+d_exp2;
      +                        
      +                        dmu_local += lpsi1*Zmu*d_exp1/(denom*exp_sum);
      +                        dS_local += lpsi1*(Zmu2_denom-1.)*d_exp1/(denom*exp_sum);
      +                        dgamma_local += lpsi1*(d_exp1/gnq-d_exp2/(1.-gnq))/exp_sum;
      +                        dl_local += lpsi1*((Zmu2_denom+Snq/lq)/denom*d_exp1+Zmq*Zmq/(lq*lq)*d_exp2)/(2.*exp_sum);
      +                        g_local[threadIdx.x] = lpsi1*(-Zmu/denom*d_exp1-Zmq/lq*d_exp2)/exp_sum;
      +                    }
      +                    __syncthreads();
      +                    reduce_sum(g_local, p<P-1?THREADNUM:N-(P-1)*THREADNUM);
      +                    if(threadIdx.x==0) {dZ[IDX_MQ(m,q)] += g_local[0];}
      +                }
      +                if(n<N) {
      +                    dmu[IDX_NQB(n,q,blockIdx.x)] += dmu_local;
      +                    dS[IDX_NQB(n,q,blockIdx.x)] += dS_local/2.;
      +                    dgamma[IDX_NQB(n,q,blockIdx.x)] += dgamma_local;
      +                }
      +                __threadfence_block();
      +            }
      +            g_local[threadIdx.x] = dl_local*2.*lq_sqrt;
      +            __syncthreads();
      +            reduce_sum(g_local, THREADNUM);
      +            if(threadIdx.x==0) {dl[IDX_QB(q,blockIdx.x)] += g_local[0];}
      +        }
      +        g_local[threadIdx.x] = dvar_local;
      +        __syncthreads();
      +        reduce_sum(g_local, THREADNUM);
      +        if(threadIdx.x==0) {dvar[blockIdx.x] += g_local[0]/var;}
      +    }
      +    
      +    __global__ void psi2compDer(double *dvar, double *dl, double *dZ, double *dmu, double *dS, double *dgamma, double *dL_dpsi2, double *psi2n, double *log_denom2, double *log_gamma, double*log_gamma1, double var, double *l, double *Z, double *mu, double *S, double *gamma, int N, int M, int Q)
      +    {
      +        int m_start, m_end;
      +        __shared__ double g_local[THREADNUM];
      +        divide_data(M, gridDim.x, blockIdx.x, &m_start, &m_end);
      +        int P = int(ceil(double(N)/THREADNUM));
      +
      +        double dvar_local = 0;
      +        for(int q=0;q<Q;q++) {
      +            double lq_sqrt = l[q];
      +            double lq = lq_sqrt*lq_sqrt;
      +            double dl_local = 0;
      +            for(int p=0;p<P;p++) {
      +                int n = p*THREADNUM + threadIdx.x;
      +                double dmu_local = 0;
      +                double dS_local = 0;
      +                double dgamma_local = 0;
      +                double Snq,mu_nq,gnq,log_gnq,log_gnq1,log_de;
      +                if(n<N) {Snq = S[IDX_NQ(n,q)]; mu_nq=mu[IDX_NQ(n,q)]; gnq = gamma[IDX_NQ(n,q)];
      +                        log_gnq = log_gamma[IDX_NQ(n,q)]; log_gnq1 = log_gamma1[IDX_NQ(n,q)];
      +                        log_de = log_denom2[IDX_NQ(n,q)];}
      +                for(int m1=m_start; m1<m_end; m1++) {
      +                    g_local[threadIdx.x] = 0;
      +                    for(int m2=0;m2<M;m2++) {
      +                        if(n<N) {
      +                            double lpsi2 = psi2n[IDX_NMM(n,m1,m2)]*dL_dpsi2[IDX_MM(m1,m2)];
      +                            if(q==0) {dvar_local += lpsi2;}
      +                            
      +                            double Zm1q = Z[IDX_MQ(m1,q)];
      +                            double Zm2q = Z[IDX_MQ(m2,q)];
      +                            double dZ = Zm1q - Zm2q;
      +                            double Z2 = Zm1q*Zm1q+Zm2q*Zm2q;
      +                            double muZhat =  mu_nq - (Zm1q + Zm2q)/2.;
      +                            double denom = 2.*Snq+lq;
      +                            double muZhat2_denom = muZhat*muZhat/denom;
      +                            
      +                            double exp1 = dZ*dZ/(-4.*lq)-muZhat*muZhat/(2.*Snq+lq) - log_de/2. + log_gnq;
      +                            double exp2 = log_gnq1 - Z2/(2.*lq);
      +                            double d_exp1,d_exp2;
      +                            if(exp1>exp2) {
      +                                d_exp1 = 1.;
      +                                d_exp2 = exp(exp2-exp1);
      +                            } else {
      +                                d_exp1 = exp(exp1-exp2);
      +                                d_exp2 = 1.;
      +                            }
      +                            double exp_sum = d_exp1+d_exp2;
      +                            
      +                            dmu_local += lpsi2*muZhat/denom*d_exp1/exp_sum;
      +                            dS_local += lpsi2*(2.*muZhat2_denom-1.)/denom*d_exp1/exp_sum;
      +                            dgamma_local += lpsi2*(d_exp1/gnq-d_exp2/(1.-gnq))/exp_sum;
      +                            dl_local += lpsi2*(((Snq/lq+muZhat2_denom)/denom+dZ*dZ/(4.*lq*lq))*d_exp1+Z2/(2.*lq*lq)*d_exp2)/exp_sum;
      +                            g_local[threadIdx.x] += 2.*lpsi2*((muZhat/denom-dZ/(2*lq))*d_exp1-Zm1q/lq*d_exp2)/exp_sum;
      +                        }
      +                    }
      +                    __syncthreads();
      +                    reduce_sum(g_local, p<P-1?THREADNUM:N-(P-1)*THREADNUM);
      +                    if(threadIdx.x==0) {dZ[IDX_MQ(m1,q)] += g_local[0];}
      +                }
      +                if(n<N) {
      +                    dmu[IDX_NQB(n,q,blockIdx.x)] += -2.*dmu_local;
      +                    dS[IDX_NQB(n,q,blockIdx.x)] += dS_local;
      +                    dgamma[IDX_NQB(n,q,blockIdx.x)] += dgamma_local;
      +                }
      +                __threadfence_block();
      +            }
      +            g_local[threadIdx.x] = dl_local*2.*lq_sqrt;
      +            __syncthreads();
      +            reduce_sum(g_local, THREADNUM);
      +            if(threadIdx.x==0) {dl[IDX_QB(q,blockIdx.x)] += g_local[0];}
      +        }
      +        g_local[threadIdx.x] = dvar_local;
      +        __syncthreads();
      +        reduce_sum(g_local, THREADNUM);
      +        if(threadIdx.x==0) {dvar[blockIdx.x] += g_local[0]*2/var;}
      +    }
      +    """
      +
      +class PSICOMP_SSRBF_GPU(PSICOMP_RBF):
      +
      [docs] + def __init__(self, threadnum=128, blocknum=15, GPU_direct=False): + self.GPU_direct = GPU_direct + self.gpuCache = None + + self.threadnum = threadnum + self.blocknum = blocknum + module = SourceModule("#define THREADNUM "+str(self.threadnum)+"\n"+gpu_code) + self.g_psi1computations = module.get_function('psi1computations') + self.g_psi1computations.prepare('PPPPdPPPPiii') + self.g_psi2computations = module.get_function('psi2computations') + self.g_psi2computations.prepare('PPPPPdPPPPiii') + self.g_psi1compDer = module.get_function('psi1compDer') + self.g_psi1compDer.prepare('PPPPPPPPPPPdPPPPPiii') + self.g_psi2compDer = module.get_function('psi2compDer') + self.g_psi2compDer.prepare('PPPPPPPPPPPdPPPPPiii') + self.g_compDenom = module.get_function('compDenom') + self.g_compDenom.prepare('PPPPPPPii') + + def __deepcopy__(self, memo): + s = PSICOMP_SSRBF_GPU(threadnum=self.threadnum, blocknum=self.blocknum, GPU_direct=self.GPU_direct) + memo[id(self)] = s + return s + + def _initGPUCache(self, N, M, Q): + if self.gpuCache == None: + self.gpuCache = { + 'l_gpu' :gpuarray.empty((Q,),np.float64,order='F'), + 'Z_gpu' :gpuarray.empty((M,Q),np.float64,order='F'), + 'mu_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'S_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'gamma_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'psi1_gpu' :gpuarray.empty((N,M),np.float64,order='F'), + 'psi2_gpu' :gpuarray.empty((M,M),np.float64,order='F'), + 'psi2n_gpu' :gpuarray.empty((N,M,M),np.float64,order='F'), + 'dL_dpsi1_gpu' :gpuarray.empty((N,M),np.float64,order='F'), + 'dL_dpsi2_gpu' :gpuarray.empty((M,M),np.float64,order='F'), + 'log_denom1_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'log_denom2_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'log_gamma_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + 'log_gamma1_gpu' :gpuarray.empty((N,Q),np.float64,order='F'), + # derivatives + 'dvar_gpu' :gpuarray.empty((self.blocknum,),np.float64, order='F'), + 'dl_gpu' :gpuarray.empty((Q,self.blocknum),np.float64, order='F'), + 'dZ_gpu' :gpuarray.empty((M,Q),np.float64, order='F'), + 'dmu_gpu' :gpuarray.empty((N,Q,self.blocknum),np.float64, order='F'), + 'dS_gpu' :gpuarray.empty((N,Q,self.blocknum),np.float64, order='F'), + 'dgamma_gpu' :gpuarray.empty((N,Q,self.blocknum),np.float64, order='F'), + # grad + 'grad_l_gpu' :gpuarray.empty((Q,),np.float64, order='F'), + 'grad_mu_gpu' :gpuarray.empty((N,Q,),np.float64, order='F'), + 'grad_S_gpu' :gpuarray.empty((N,Q,),np.float64, order='F'), + 'grad_gamma_gpu' :gpuarray.empty((N,Q,),np.float64, order='F'), + } + else: + assert N==self.gpuCache['mu_gpu'].shape[0] + assert M==self.gpuCache['Z_gpu'].shape[0] + assert Q==self.gpuCache['l_gpu'].shape[0] + + def sync_params(self, lengthscale, Z, mu, S, gamma): +
      [docs] if len(lengthscale)==1: + self.gpuCache['l_gpu'].fill(lengthscale) + else: + self.gpuCache['l_gpu'].set(np.asfortranarray(lengthscale)) + self.gpuCache['Z_gpu'].set(np.asfortranarray(Z)) + self.gpuCache['mu_gpu'].set(np.asfortranarray(mu)) + self.gpuCache['S_gpu'].set(np.asfortranarray(S)) + self.gpuCache['gamma_gpu'].set(np.asfortranarray(gamma)) + N,Q = self.gpuCache['S_gpu'].shape + self.g_compDenom.prepared_call((self.blocknum,1),(self.threadnum,1,1), self.gpuCache['log_denom1_gpu'].gpudata,self.gpuCache['log_denom2_gpu'].gpudata,self.gpuCache['log_gamma_gpu'].gpudata,self.gpuCache['log_gamma1_gpu'].gpudata,self.gpuCache['gamma_gpu'].gpudata,self.gpuCache['l_gpu'].gpudata,self.gpuCache['S_gpu'].gpudata, np.int32(N), np.int32(Q)) + + def reset_derivative(self):
      +
      [docs] self.gpuCache['dvar_gpu'].fill(0.) + self.gpuCache['dl_gpu'].fill(0.) + self.gpuCache['dZ_gpu'].fill(0.) + self.gpuCache['dmu_gpu'].fill(0.) + self.gpuCache['dS_gpu'].fill(0.) + self.gpuCache['dgamma_gpu'].fill(0.) + self.gpuCache['grad_l_gpu'].fill(0.) + self.gpuCache['grad_mu_gpu'].fill(0.) + self.gpuCache['grad_S_gpu'].fill(0.) + self.gpuCache['grad_gamma_gpu'].fill(0.) + + def get_dimensions(self, Z, variational_posterior):
      +
      [docs] return variational_posterior.mean.shape[0], Z.shape[0], Z.shape[1] + + @Cache_this(limit=1, ignore_args=(0,))
      + def psicomputations(self, variance, lengthscale, Z, variational_posterior): + """ + Z - MxQ + mu - NxQ + S - NxQ + """ + N,M,Q = self.get_dimensions(Z, variational_posterior) + self._initGPUCache(N,M,Q) + self.sync_params(lengthscale, Z, variational_posterior.mean, variational_posterior.variance, variational_posterior.binary_prob) + + psi1_gpu = self.gpuCache['psi1_gpu'] + psi2_gpu = self.gpuCache['psi2_gpu'] + psi2n_gpu = self.gpuCache['psi2n_gpu'] + l_gpu = self.gpuCache['l_gpu'] + Z_gpu = self.gpuCache['Z_gpu'] + mu_gpu = self.gpuCache['mu_gpu'] + S_gpu = self.gpuCache['S_gpu'] + log_denom1_gpu = self.gpuCache['log_denom1_gpu'] + log_denom2_gpu = self.gpuCache['log_denom2_gpu'] + log_gamma_gpu = self.gpuCache['log_gamma_gpu'] + log_gamma1_gpu = self.gpuCache['log_gamma1_gpu'] + + psi0 = np.empty((N,)) + psi0[:] = variance + self.g_psi1computations.prepared_call((self.blocknum,1),(self.threadnum,1,1),psi1_gpu.gpudata, log_denom1_gpu.gpudata, log_gamma_gpu.gpudata, log_gamma1_gpu.gpudata, np.float64(variance),l_gpu.gpudata,Z_gpu.gpudata,mu_gpu.gpudata,S_gpu.gpudata, np.int32(N), np.int32(M), np.int32(Q)) + self.g_psi2computations.prepared_call((self.blocknum,1),(self.threadnum,1,1),psi2_gpu.gpudata, psi2n_gpu.gpudata, log_denom2_gpu.gpudata, log_gamma_gpu.gpudata, log_gamma1_gpu.gpudata, np.float64(variance),l_gpu.gpudata,Z_gpu.gpudata,mu_gpu.gpudata,S_gpu.gpudata, np.int32(N), np.int32(M), np.int32(Q)) + + if self.GPU_direct: + return psi0, psi1_gpu, psi2_gpu + else: + return psi0, psi1_gpu.get(), psi2_gpu.get() + + @Cache_this(limit=1, ignore_args=(0,1,2,3)) + def psiDerivativecomputations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, variance, lengthscale, Z, variational_posterior): + ARD = (len(lengthscale)!=1) + + N,M,Q = self.get_dimensions(Z, variational_posterior) + psi1_gpu = self.gpuCache['psi1_gpu'] + psi2n_gpu = self.gpuCache['psi2n_gpu'] + l_gpu = self.gpuCache['l_gpu'] + Z_gpu = self.gpuCache['Z_gpu'] + mu_gpu = self.gpuCache['mu_gpu'] + S_gpu = self.gpuCache['S_gpu'] + gamma_gpu = self.gpuCache['gamma_gpu'] + dvar_gpu = self.gpuCache['dvar_gpu'] + dl_gpu = self.gpuCache['dl_gpu'] + dZ_gpu = self.gpuCache['dZ_gpu'] + dmu_gpu = self.gpuCache['dmu_gpu'] + dS_gpu = self.gpuCache['dS_gpu'] + dgamma_gpu = self.gpuCache['dgamma_gpu'] + grad_l_gpu = self.gpuCache['grad_l_gpu'] + grad_mu_gpu = self.gpuCache['grad_mu_gpu'] + grad_S_gpu = self.gpuCache['grad_S_gpu'] + grad_gamma_gpu = self.gpuCache['grad_gamma_gpu'] + log_denom1_gpu = self.gpuCache['log_denom1_gpu'] + log_denom2_gpu = self.gpuCache['log_denom2_gpu'] + log_gamma_gpu = self.gpuCache['log_gamma_gpu'] + log_gamma1_gpu = self.gpuCache['log_gamma1_gpu'] + + if self.GPU_direct: + dL_dpsi1_gpu = dL_dpsi1 + dL_dpsi2_gpu = dL_dpsi2 + dL_dpsi0_sum = gpuarray.sum(dL_dpsi0).get() + else: + dL_dpsi1_gpu = self.gpuCache['dL_dpsi1_gpu'] + dL_dpsi2_gpu = self.gpuCache['dL_dpsi2_gpu'] + dL_dpsi1_gpu.set(np.asfortranarray(dL_dpsi1)) + dL_dpsi2_gpu.set(np.asfortranarray(dL_dpsi2)) + dL_dpsi0_sum = dL_dpsi0.sum() + + self.reset_derivative() + # t=self.g_psi1compDer(dvar_gpu,dl_gpu,dZ_gpu,dmu_gpu,dS_gpu,dL_dpsi1_gpu,psi1_gpu, np.float64(variance),l_gpu,Z_gpu,mu_gpu,S_gpu, np.int32(N), np.int32(M), np.int32(Q), block=(self.threadnum,1,1), grid=(self.blocknum,1),time_kernel=True) + # print 'g_psi1compDer '+str(t) + # t=self.g_psi2compDer(dvar_gpu,dl_gpu,dZ_gpu,dmu_gpu,dS_gpu,dL_dpsi2_gpu,psi2n_gpu, np.float64(variance),l_gpu,Z_gpu,mu_gpu,S_gpu, np.int32(N), np.int32(M), np.int32(Q), block=(self.threadnum,1,1), grid=(self.blocknum,1),time_kernel=True) + # print 'g_psi2compDer '+str(t) + self.g_psi1compDer.prepared_call((self.blocknum,1),(self.threadnum,1,1),dvar_gpu.gpudata,dl_gpu.gpudata,dZ_gpu.gpudata,dmu_gpu.gpudata,dS_gpu.gpudata,dgamma_gpu.gpudata,dL_dpsi1_gpu.gpudata,psi1_gpu.gpudata, log_denom1_gpu.gpudata, log_gamma_gpu.gpudata, log_gamma1_gpu.gpudata, np.float64(variance),l_gpu.gpudata,Z_gpu.gpudata,mu_gpu.gpudata,S_gpu.gpudata,gamma_gpu.gpudata,np.int32(N), np.int32(M), np.int32(Q)) + self.g_psi2compDer.prepared_call((self.blocknum,1),(self.threadnum,1,1),dvar_gpu.gpudata,dl_gpu.gpudata,dZ_gpu.gpudata,dmu_gpu.gpudata,dS_gpu.gpudata,dgamma_gpu.gpudata,dL_dpsi2_gpu.gpudata,psi2n_gpu.gpudata, log_denom2_gpu.gpudata, log_gamma_gpu.gpudata, log_gamma1_gpu.gpudata, np.float64(variance),l_gpu.gpudata,Z_gpu.gpudata,mu_gpu.gpudata,S_gpu.gpudata,gamma_gpu.gpudata,np.int32(N), np.int32(M), np.int32(Q)) + + dL_dvar = dL_dpsi0_sum + gpuarray.sum(dvar_gpu).get() + sum_axis(grad_mu_gpu,dmu_gpu,N*Q,self.blocknum) + dL_dmu = grad_mu_gpu.get() + sum_axis(grad_S_gpu,dS_gpu,N*Q,self.blocknum) + dL_dS = grad_S_gpu.get() + sum_axis(grad_gamma_gpu,dgamma_gpu,N*Q,self.blocknum) + dL_dgamma = grad_gamma_gpu.get() + dL_dZ = dZ_gpu.get() + if ARD: + sum_axis(grad_l_gpu,dl_gpu,Q,self.blocknum) + dL_dlengscale = grad_l_gpu.get() + else: + dL_dlengscale = gpuarray.sum(dl_gpu).get() + + return dL_dvar, dL_dlengscale, dL_dZ, dL_dmu, dL_dS, dL_dgamma + +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/rbf.html b/doc/_build/html/_modules/GPy/kern/_src/rbf.html new file mode 100644 index 00000000..67c0212a --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/rbf.html @@ -0,0 +1,164 @@ + + + + + + + + GPy.kern._src.rbf — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.rbf

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from stationary import Stationary
      +from psi_comp import PSICOMP_RBF
      +from psi_comp.rbf_psi_gpucomp import PSICOMP_RBF_GPU
      +from ...util.config import *
      +
      +
      [docs]class RBF(Stationary): + """ + Radial Basis Function kernel, aka squared-exponential, exponentiated quadratic or Gaussian kernel: + + .. math:: + + k(r) = \sigma^2 \exp \\bigg(- \\frac{1}{2} r^2 \\bigg) + + """ + _support_GPU = True + def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='rbf', useGPU=False): + super(RBF, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name, useGPU=useGPU) + self.psicomp = PSICOMP_RBF() + if self.useGPU: + self.psicomp = PSICOMP_RBF_GPU() + else: + self.psicomp = PSICOMP_RBF() + +
      [docs] def K_of_r(self, r): + return self.variance * np.exp(-0.5 * r**2) +
      +
      [docs] def dK_dr(self, r): + return -r*self.K_of_r(r) +
      + def __getstate__(self): + dc = super(RBF, self).__getstate__() + if self.useGPU: + dc['psicomp'] = PSICOMP_RBF() + return dc + + def __setstate__(self, state): + return super(RBF, self).__setstate__(state) + +
      [docs] def spectrum(self, omega): + assert self.input_dim == 1 #TODO: higher dim spectra? + return self.variance*np.sqrt(2*np.pi)*self.lengthscale*np.exp(-self.lengthscale*2*omega**2/2) + + #---------------------------------------# + # PSI statistics # + #---------------------------------------# +
      +
      [docs] def psi0(self, Z, variational_posterior): + return self.psicomp.psicomputations(self.variance, self.lengthscale, Z, variational_posterior)[0] +
      +
      [docs] def psi1(self, Z, variational_posterior): + return self.psicomp.psicomputations(self.variance, self.lengthscale, Z, variational_posterior)[1] +
      +
      [docs] def psi2(self, Z, variational_posterior): + return self.psicomp.psicomputations(self.variance, self.lengthscale, Z, variational_posterior)[2] +
      +
      [docs] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + dL_dvar, dL_dlengscale = self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variance, self.lengthscale, Z, variational_posterior)[:2] + self.variance.gradient = dL_dvar + self.lengthscale.gradient = dL_dlengscale +
      +
      [docs] def gradients_Z_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + return self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variance, self.lengthscale, Z, variational_posterior)[2] +
      +
      [docs] def gradients_qX_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + return self.psicomp.psiDerivativecomputations(dL_dpsi0, dL_dpsi1, dL_dpsi2, self.variance, self.lengthscale, Z, variational_posterior)[3:] +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/splitKern.html b/doc/_build/html/_modules/GPy/kern/_src/splitKern.html new file mode 100644 index 00000000..33937492 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/splitKern.html @@ -0,0 +1,297 @@ + + + + + + + + GPy.kern._src.splitKern — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.splitKern

      +"""
      +A new kernel
      +"""
      +
      +import numpy as np
      +from kern import Kern,CombinationKernel
      +from .independent_outputs import index_to_slices
      +import itertools
      +
      +
      [docs]class DiffGenomeKern(Kern): + + def __init__(self, kernel, idx_p, Xp, index_dim=-1, name='DiffGenomeKern'): + self.idx_p = idx_p + self.index_dim=index_dim + self.kern = SplitKern(kernel,Xp, index_dim=index_dim) + super(DiffGenomeKern, self).__init__(input_dim=kernel.input_dim+1, active_dims=None, name=name) + self.add_parameter(self.kern) + +
      [docs] def K(self, X, X2=None): + assert X2==None + K = self.kern.K(X,X2) + + if self.idx_p<=0 or self.idx_p>X.shape[0]/2: + return K + + slices = index_to_slices(X[:,self.index_dim]) + idx_start = slices[1][0].start + idx_end = idx_start+self.idx_p + K_c = K[idx_start:idx_end,idx_start:idx_end].copy() + K[idx_start:idx_end,:] = K[:self.idx_p,:] + K[:,idx_start:idx_end] = K[:,:self.idx_p] + K[idx_start:idx_end,idx_start:idx_end] = K_c + + return K +
      +
      [docs] def Kdiag(self,X): + Kdiag = self.kern.Kdiag(X) + + if self.idx_p<=0 or self.idx_p>X.shape[0]/2: + return Kdiag + + slices = index_to_slices(X[:,self.index_dim]) + idx_start = slices[1][0].start + idx_end = idx_start+self.idx_p + Kdiag[idx_start:idx_end] = Kdiag[:self.idx_p] + + return Kdiag +
      +
      [docs] def update_gradients_full(self,dL_dK,X,X2=None): + assert X2==None + if self.idx_p<=0 or self.idx_p>X.shape[0]/2: + self.kern.update_gradients_full(dL_dK, X) + return + + slices = index_to_slices(X[:,self.index_dim]) + idx_start = slices[1][0].start + idx_end = idx_start+self.idx_p + + self.kern.update_gradients_full(dL_dK[idx_start:idx_end,:], X[:self.idx_p],X) + grad_p1 = self.kern.gradient.copy() + self.kern.update_gradients_full(dL_dK[:,idx_start:idx_end], X, X[:self.idx_p]) + grad_p2 = self.kern.gradient.copy() + self.kern.update_gradients_full(dL_dK[idx_start:idx_end,idx_start:idx_end], X[:self.idx_p],X[idx_start:idx_end]) + grad_p3 = self.kern.gradient.copy() + self.kern.update_gradients_full(dL_dK[idx_start:idx_end,idx_start:idx_end], X[idx_start:idx_end], X[:self.idx_p]) + grad_p4 = self.kern.gradient.copy() + + self.kern.update_gradients_full(dL_dK[idx_start:idx_end,:], X[idx_start:idx_end],X) + grad_n1 = self.kern.gradient.copy() + self.kern.update_gradients_full(dL_dK[:,idx_start:idx_end], X, X[idx_start:idx_end]) + grad_n2 = self.kern.gradient.copy() + self.kern.update_gradients_full(dL_dK[idx_start:idx_end,idx_start:idx_end], X[idx_start:idx_end], X[idx_start:idx_end]) + grad_n3 = self.kern.gradient.copy() + + self.kern.update_gradients_full(dL_dK, X) + self.kern.gradient += grad_p1+grad_p2-grad_p3-grad_p4-grad_n1-grad_n2+2*grad_n3 +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + pass +
      +
      [docs]class SplitKern(CombinationKernel): + + def __init__(self, kernel, Xp, index_dim=-1, name='SplitKern'): + assert isinstance(index_dim, int), "The index dimension must be an integer!" + self.kern = kernel + self.kern_cross = SplitKern_cross(kernel,Xp) + super(SplitKern, self).__init__(kernels=[self.kern, self.kern_cross], extra_dims=[index_dim], name=name) + self.index_dim = index_dim + +
      [docs] def K(self,X ,X2=None): + slices = index_to_slices(X[:,self.index_dim]) + assert len(slices)<=2, 'The Split kernel only support two different indices' + if X2 is None: + target = np.zeros((X.shape[0], X.shape[0])) + # diagonal blocks + [[target.__setitem__((s,ss), self.kern.K(X[s,:], X[ss,:])) for s,ss in itertools.product(slices_i, slices_i)] for slices_i in slices] + if len(slices)>1: + # cross blocks + [target.__setitem__((s,ss), self.kern_cross.K(X[s,:], X[ss,:])) for s,ss in itertools.product(slices[0], slices[1])] + # cross blocks + [target.__setitem__((s,ss), self.kern_cross.K(X[s,:], X[ss,:])) for s,ss in itertools.product(slices[1], slices[0])] + else: + slices2 = index_to_slices(X2[:,self.index_dim]) + assert len(slices2)<=2, 'The Split kernel only support two different indices' + target = np.zeros((X.shape[0], X2.shape[0])) + # diagonal blocks + [[target.__setitem__((s,s2), self.kern.K(X[s,:],X2[s2,:])) for s,s2 in itertools.product(slices[i], slices2[i])] for i in xrange(min(len(slices),len(slices2)))] + if len(slices)>1: + [target.__setitem__((s,s2), self.kern_cross.K(X[s,:],X2[s2,:])) for s,s2 in itertools.product(slices[1], slices2[0])] + if len(slices2)>1: + [target.__setitem__((s,s2), self.kern_cross.K(X[s,:],X2[s2,:])) for s,s2 in itertools.product(slices[0], slices2[1])] + return target +
      +
      [docs] def Kdiag(self,X): + return self.kern.Kdiag(X) +
      +
      [docs] def update_gradients_full(self,dL_dK,X,X2=None): + slices = index_to_slices(X[:,self.index_dim]) + target = np.zeros(self.kern.size) + + def collate_grads(dL, X, X2, cross=False): + if cross: + self.kern_cross.update_gradients_full(dL,X,X2) + target[:] += self.kern_cross.kern.gradient + else: + self.kern.update_gradients_full(dL,X,X2) + target[:] += self.kern.gradient + + if X2 is None: + assert dL_dK.shape==(X.shape[0],X.shape[0]) + [[collate_grads(dL_dK[s,ss], X[s], X[ss]) for s,ss in itertools.product(slices_i, slices_i)] for slices_i in slices] + if len(slices)>1: + [collate_grads(dL_dK[s,ss], X[s], X[ss], True) for s,ss in itertools.product(slices[0], slices[1])] + [collate_grads(dL_dK[s,ss], X[s], X[ss], True) for s,ss in itertools.product(slices[1], slices[0])] + else: + assert dL_dK.shape==(X.shape[0],X2.shape[0]) + slices2 = index_to_slices(X2[:,self.index_dim]) + [[collate_grads(dL_dK[s,s2],X[s],X2[s2]) for s,s2 in itertools.product(slices[i], slices2[i])] for i in xrange(min(len(slices),len(slices2)))] + if len(slices)>1: + [collate_grads(dL_dK[s,s2], X[s], X2[s2], True) for s,s2 in itertools.product(slices[1], slices2[0])] + if len(slices2)>1: + [collate_grads(dL_dK[s,s2], X[s], X2[s2], True) for s,s2 in itertools.product(slices[0], slices2[1])] + self.kern.gradient = target +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + self.kern.update_gradients_diag(self, dL_dKdiag, X) +
      +
      [docs]class SplitKern_cross(Kern): + + def __init__(self, kernel, Xp, name='SplitKern_cross'): + assert isinstance(kernel, Kern) + self.kern = kernel + if not isinstance(Xp,np.ndarray): + Xp = np.array([[Xp]]) + self.Xp = Xp + super(SplitKern_cross, self).__init__(input_dim=kernel.input_dim, active_dims=None, name=name) + +
      [docs] def K(self, X, X2=None): + if X2 is None: + return np.dot(self.kern.K(X,self.Xp),self.kern.K(self.Xp,X))/self.kern.K(self.Xp,self.Xp) + else: + return np.dot(self.kern.K(X,self.Xp),self.kern.K(self.Xp,X2))/self.kern.K(self.Xp,self.Xp) +
      +
      [docs] def Kdiag(self, X): + return np.inner(self.kern.K(X,self.Xp),self.kern.K(self.Xp,X).T)/self.kern.K(self.Xp,self.Xp) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + if X2 is None: + X2 = X + + k1 = self.kern.K(X,self.Xp) + k2 = self.kern.K(self.Xp,X2) + k3 = self.kern.K(self.Xp,self.Xp) + dL_dk1 = np.einsum('ij,j->i',dL_dK,k2[0])/k3[0,0] + dL_dk2 = np.einsum('ij,i->j',dL_dK,k1[:,0])/k3[0,0] + dL_dk3 = np.einsum('ij,ij->',dL_dK,-np.dot(k1,k2)/(k3[0,0]*k3[0,0])) + + self.kern.update_gradients_full(dL_dk1[:,None],X,self.Xp) + grad = self.kern.gradient.copy() + self.kern.update_gradients_full(dL_dk2[None,:],self.Xp,X2) + grad += self.kern.gradient.copy() + self.kern.update_gradients_full(np.array([[dL_dk3]]),self.Xp,self.Xp) + grad += self.kern.gradient.copy() + + self.kern.gradient = grad +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + k1 = self.kern.K(X,self.Xp) + k2 = self.kern.K(self.Xp,X) + k3 = self.kern.K(self.Xp,self.Xp) + dL_dk1 = dL_dKdiag*k2[0]/k3 + dL_dk2 = dL_dKdiag*k1[:,0]/k3 + dL_dk3 = -dL_dKdiag*(k1[:,0]*k2[0]).sum()/(k3*k3) + + self.kern.update_gradients_full(dL_dk1[:,None],X,self.Xp) + grad1 = self.kern.gradient.copy() + self.kern.update_gradients_full(dL_dk2[None,:],self.Xp,X) + grad2 = self.kern.gradient.copy() + self.kern.update_gradients_full(np.array([[dL_dk3]]),self.Xp,self.Xp) + grad3 = self.kern.gradient.copy() + + self.kern.gradient = grad1+grad2+grad3 + +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/static.html b/doc/_build/html/_modules/GPy/kern/_src/static.html new file mode 100644 index 00000000..a2cefe60 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/static.html @@ -0,0 +1,215 @@ + + + + + + + + GPy.kern._src.static — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.static

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +from kern import Kern
      +import numpy as np
      +from ...core.parameterization import Param
      +from ...core.parameterization.transformations import Logexp
      +
      +
      [docs]class Static(Kern): + def __init__(self, input_dim, variance, active_dims, name): + super(Static, self).__init__(input_dim, active_dims, name) + self.variance = Param('variance', variance, Logexp()) + self.link_parameters(self.variance) + +
      [docs] def Kdiag(self, X): + ret = np.empty((X.shape[0],), dtype=np.float64) + ret[:] = self.variance + return ret +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + return np.zeros(X.shape) +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + return np.zeros(X.shape) +
      +
      [docs] def gradients_Z_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + return np.zeros(Z.shape) +
      +
      [docs] def gradients_qX_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + return np.zeros(variational_posterior.shape), np.zeros(variational_posterior.shape) +
      +
      [docs] def psi0(self, Z, variational_posterior): + return self.Kdiag(variational_posterior.mean) +
      +
      [docs] def psi1(self, Z, variational_posterior): + return self.K(variational_posterior.mean, Z) +
      +
      [docs] def psi2(self, Z, variational_posterior): + K = self.K(variational_posterior.mean, Z) + return np.einsum('ij,ik->jk',K,K) #K[:,:,None]*K[:,None,:] # NB. more efficient implementations on inherriting classes +
      +
      [docs] def input_sensitivity(self, summarize=True): + if summarize: + return super(Static, self).input_sensitivity(summarize=summarize) + else: + return np.ones(self.input_dim) * self.variance +
      +
      [docs]class White(Static): + def __init__(self, input_dim, variance=1., active_dims=None, name='white'): + super(White, self).__init__(input_dim, variance, active_dims, name) + +
      [docs] def K(self, X, X2=None): + if X2 is None: + return np.eye(X.shape[0])*self.variance + else: + return np.zeros((X.shape[0], X2.shape[0])) +
      +
      [docs] def psi2(self, Z, variational_posterior): + return np.zeros((Z.shape[0], Z.shape[0]), dtype=np.float64) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + self.variance.gradient = np.trace(dL_dK) +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + self.variance.gradient = dL_dKdiag.sum() +
      +
      [docs] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + self.variance.gradient = dL_dpsi0.sum() +
      +
      [docs]class Bias(Static): + def __init__(self, input_dim, variance=1., active_dims=None, name='bias'): + super(Bias, self).__init__(input_dim, variance, active_dims, name) + +
      [docs] def K(self, X, X2=None): + shape = (X.shape[0], X.shape[0] if X2 is None else X2.shape[0]) + ret = np.empty(shape, dtype=np.float64) + ret[:] = self.variance + return ret +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + self.variance.gradient = dL_dK.sum() +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + self.variance.gradient = dL_dKdiag.sum() +
      +
      [docs] def psi2(self, Z, variational_posterior): + ret = np.empty((Z.shape[0], Z.shape[0]), dtype=np.float64) + ret[:] = self.variance*self.variance*variational_posterior.shape[0] + return ret +
      +
      [docs] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + self.variance.gradient = dL_dpsi0.sum() + dL_dpsi1.sum() + 2.*self.variance*dL_dpsi2.sum()*variational_posterior.shape[0] +
      +
      [docs]class Fixed(Static): + def __init__(self, input_dim, covariance_matrix, variance=1., active_dims=None, name='fixed'): + """ + :param input_dim: the number of input dimensions + :type input_dim: int + :param variance: the variance of the kernel + :type variance: float + """ + super(Fixed, self).__init__(input_dim, variance, active_dims, name) + self.fixed_K = covariance_matrix +
      [docs] def K(self, X, X2): + return self.variance * self.fixed_K +
      +
      [docs] def Kdiag(self, X): + return self.variance * self.fixed_K.diag() +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + self.variance.gradient = np.einsum('ij,ij', dL_dK, self.fixed_K) +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + self.variance.gradient = np.einsum('i,i', dL_dKdiag, self.fixed_K) +
      +
      [docs] def psi2(self, Z, variational_posterior): + return np.zeros((Z.shape[0], Z.shape[0]), dtype=np.float64) +
      +
      [docs] def update_gradients_expectations(self, dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, variational_posterior): + self.variance.gradient = dL_dpsi0.sum() +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/stationary.html b/doc/_build/html/_modules/GPy/kern/_src/stationary.html new file mode 100644 index 00000000..a86b8e93 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/stationary.html @@ -0,0 +1,576 @@ + + + + + + + + GPy.kern._src.stationary — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.stationary

      +# Copyright (c) 2012, GPy authors (see AUTHORS.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
      +from scipy import integrate, weave
      +from ...util.config import config # for assesing whether to use weave
      +from ...util.caching import Cache_this
      +
      +
      [docs]class Stationary(Kern): + """ + Stationary kernels (covariance functions). + + Stationary covariance fucntion depend only on r, where r is defined as + + r = \sqrt{ \sum_{q=1}^Q (x_q - x'_q)^2 } + + The covariance function k(x, x' can then be written k(r). + + In this implementation, r is scaled by the lengthscales parameter(s): + + r = \sqrt{ \sum_{q=1}^Q \frac{(x_q - x'_q)^2}{\ell_q^2} }. + + By default, there's only one lengthscale: seaprate lengthscales for each + dimension can be enables by setting ARD=True. + + To implement a stationary covariance function using this class, one need + only define the covariance function k(r), and it derivative. + + ... + def K_of_r(self, r): + return foo + def dK_dr(self, r): + return bar + + The lengthscale(s) and variance parameters are added to the structure automatically. + + """ + + def __init__(self, input_dim, variance, lengthscale, ARD, active_dims, name, useGPU=False): + super(Stationary, self).__init__(input_dim, active_dims, name,useGPU=useGPU) + self.ARD = ARD + if not ARD: + if lengthscale is None: + lengthscale = np.ones(1) + else: + lengthscale = np.asarray(lengthscale) + assert lengthscale.size == 1, "Only 1 lengthscale needed for non-ARD kernel" + else: + if lengthscale is not None: + lengthscale = np.asarray(lengthscale) + assert lengthscale.size in [1, input_dim], "Bad number of lengthscales" + if lengthscale.size != input_dim: + lengthscale = np.ones(input_dim)*lengthscale + else: + lengthscale = np.ones(self.input_dim) + self.lengthscale = Param('lengthscale', lengthscale, Logexp()) + self.variance = Param('variance', variance, Logexp()) + assert self.variance.size==1 + self.link_parameters(self.variance, self.lengthscale) + +
      [docs] def K_of_r(self, r): + raise NotImplementedError, "implement the covariance function as a fn of r to use this class" +
      +
      [docs] def dK_dr(self, r): + raise NotImplementedError, "implement derivative of the covariance function wrt r to use this class" +
      + @Cache_this(limit=5, ignore_args=()) +
      [docs] def K(self, X, X2=None): + """ + Kernel function applied on inputs X and X2. + In the stationary case there is an inner function depending on the + distances from X to X2, called r. + + K(X, X2) = K_of_r((X-X2)**2) + """ + r = self._scaled_dist(X, X2) + return self.K_of_r(r) +
      + @Cache_this(limit=3, ignore_args=()) + def dK_dr_via_X(self, X, X2): + #a convenience function, so we can cache dK_dr + return self.dK_dr(self._scaled_dist(X, X2)) + + def _unscaled_dist(self, X, X2=None): + """ + Compute the Euclidean distance between each row of X and X2, or between + each pair of rows of X if X2 is None. + """ + #X, = self._slice_X(X) + if X2 is None: + Xsq = np.sum(np.square(X),1) + r2 = -2.*tdot(X) + (Xsq[:,None] + Xsq[None,:]) + util.diag.view(r2)[:,]= 0. # force diagnoal to be zero: sometime numerically a little negative + r2 = np.clip(r2, 0, np.inf) + return np.sqrt(r2) + else: + #X2, = self._slice_X(X2) + X1sq = np.sum(np.square(X),1) + X2sq = np.sum(np.square(X2),1) + r2 = -2.*np.dot(X, X2.T) + X1sq[:,None] + X2sq[None,:] + r2 = np.clip(r2, 0, np.inf) + return np.sqrt(r2) + + @Cache_this(limit=5, ignore_args=()) + def _scaled_dist(self, X, X2=None): + """ + Efficiently compute the scaled distance, r. + + r = \sqrt( \sum_{q=1}^Q (x_q - x'q)^2/l_q^2 ) + + Note that if thre is only one lengthscale, l comes outside the sum. In + this case we compute the unscaled distance first (in a separate + function for caching) and divide by lengthscale afterwards + + """ + if self.ARD: + if X2 is not None: + X2 = X2 / self.lengthscale + return self._unscaled_dist(X/self.lengthscale, X2) + else: + return self._unscaled_dist(X, X2)/self.lengthscale + +
      [docs] def Kdiag(self, X): + ret = np.empty(X.shape[0]) + ret[:] = self.variance + return ret +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + """ + Given the derivative of the objective with respect to the diagonal of + the covariance matrix, compute the derivative wrt the parameters of + this kernel and stor in the <parameter>.gradient field. + + See also update_gradients_full + """ + self.variance.gradient = np.sum(dL_dKdiag) + self.lengthscale.gradient = 0. +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + """ + Given the derivative of the objective wrt the covariance matrix + (dL_dK), compute the gradient wrt the parameters of this kernel, + and store in the parameters object as e.g. self.variance.gradient + """ + self.variance.gradient = np.einsum('ij,ij,i', self.K(X, X2), dL_dK, 1./self.variance) + + #now the lengthscale gradient(s) + dL_dr = self.dK_dr_via_X(X, X2) * dL_dK + if self.ARD: + #rinv = self._inv_dis# this is rather high memory? Should we loop instead?t(X, X2) + #d = X[:, None, :] - X2[None, :, :] + #x_xl3 = np.square(d) + #self.lengthscale.gradient = -((dL_dr*rinv)[:,:,None]*x_xl3).sum(0).sum(0)/self.lengthscale**3 + tmp = dL_dr*self._inv_dist(X, X2) + if X2 is None: X2 = X + + + if config.getboolean('weave', 'working'): + try: + self.lengthscale.gradient = self.weave_lengthscale_grads(tmp, X, X2) + except: + print "\n Weave compilation failed. Falling back to (slower) numpy implementation\n" + config.set('weave', 'working', 'False') + self.lengthscale.gradient = np.array([np.einsum('ij,ij,...', tmp, np.square(X[:,q:q+1] - X2[:,q:q+1].T), -1./self.lengthscale[q]**3) for q in xrange(self.input_dim)]) + else: + self.lengthscale.gradient = np.array([np.einsum('ij,ij,...', tmp, np.square(X[:,q:q+1] - X2[:,q:q+1].T), -1./self.lengthscale[q]**3) for q in xrange(self.input_dim)]) + else: + r = self._scaled_dist(X, X2) + self.lengthscale.gradient = -np.sum(dL_dr*r)/self.lengthscale + +
      + def _inv_dist(self, X, X2=None): + """ + Compute the elementwise inverse of the distance matrix, expecpt on the + diagonal, where we return zero (the distance on the diagonal is zero). + This term appears in derviatives. + """ + dist = self._scaled_dist(X, X2).copy() + return 1./np.where(dist != 0., dist, np.inf) + +
      [docs] def weave_lengthscale_grads(self, tmp, X, X2): + """Use scipy.weave to compute derivatives wrt the lengthscales""" + N,M = tmp.shape + Q = X.shape[1] + if hasattr(X, 'values'):X = X.values + if hasattr(X2, 'values'):X2 = X2.values + grads = np.zeros(self.input_dim) + code = """ + double gradq; + for(int q=0; q<Q; q++){ + gradq = 0; + for(int n=0; n<N; n++){ + for(int m=0; m<M; m++){ + gradq += tmp(n,m)*(X(n,q)-X2(m,q))*(X(n,q)-X2(m,q)); + } + } + grads(q) = gradq; + } + """ + weave.inline(code, ['tmp', 'X', 'X2', 'grads', 'N', 'M', 'Q'], type_converters=weave.converters.blitz, support_code="#include <math.h>") + return -grads/self.lengthscale**3 +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + """ + Given the derivative of the objective wrt K (dL_dK), compute the derivative wrt X + """ + if config.getboolean('weave', 'working'): + try: + return self.gradients_X_weave(dL_dK, X, X2) + except: + print "\n Weave compilation failed. Falling back to (slower) numpy implementation\n" + config.set('weave', 'working', 'False') + return self.gradients_X_(dL_dK, X, X2) + else: + return self.gradients_X_(dL_dK, X, X2) +
      +
      [docs] def gradients_X_(self, dL_dK, X, X2=None): + invdist = self._inv_dist(X, X2) + dL_dr = self.dK_dr_via_X(X, X2) * dL_dK + tmp = invdist*dL_dr + if X2 is None: + tmp = tmp + tmp.T + X2 = X + + #The high-memory numpy way: + #d = X[:, None, :] - X2[None, :, :] + #ret = np.sum(tmp[:,:,None]*d,1)/self.lengthscale**2 + + #the lower memory way with a loop + ret = np.empty(X.shape, dtype=np.float64) + for q in xrange(self.input_dim): + np.sum(tmp*(X[:,q][:,None]-X2[:,q][None,:]), axis=1, out=ret[:,q]) + ret /= self.lengthscale**2 + + return ret +
      +
      [docs] def gradients_X_weave(self, dL_dK, X, X2=None): + invdist = self._inv_dist(X, X2) + dL_dr = self.dK_dr_via_X(X, X2) * dL_dK + tmp = invdist*dL_dr + if X2 is None: + tmp = tmp + tmp.T + X2 = X + + code = """ + int n,m,d; + double retnd; + #pragma omp parallel for private(n,d, retnd, m) + for(d=0;d<D;d++){ + for(n=0;n<N;n++){ + retnd = 0.0; + for(m=0;m<M;m++){ + retnd += tmp(n,m)*(X(n,d)-X2(m,d)); + } + ret(n,d) = retnd; + } + } + + """ + if hasattr(X, 'values'):X = X.values #remove the GPy wrapping to make passing into weave safe + if hasattr(X2, 'values'):X2 = X2.values + ret = np.zeros(X.shape) + N,D = X.shape + N,M = tmp.shape + from scipy import weave + support_code = """ + #include <omp.h> + #include <stdio.h> + """ + weave_options = {'headers' : ['<omp.h>'], + 'extra_compile_args': ['-fopenmp -O3'], # -march=native'], + 'extra_link_args' : ['-lgomp']} + weave.inline(code, ['ret', 'N', 'D', 'M', 'tmp', 'X', 'X2'], type_converters=weave.converters.blitz, support_code=support_code, **weave_options) + return ret/self.lengthscale**2 +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + return np.zeros(X.shape) +
      +
      [docs] def input_sensitivity(self, summarize=True): + return np.ones(self.input_dim)/self.lengthscale**2 +
      +
      [docs]class Exponential(Stationary): + def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Exponential'): + super(Exponential, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) + +
      [docs] def K_of_r(self, r): + return self.variance * np.exp(-0.5 * r) +
      +
      [docs] def dK_dr(self, r): + return -0.5*self.K_of_r(r) + +
      +
      [docs]class OU(Stationary): + """ + OU kernel: + + .. math:: + + k(r) = \\sigma^2 \exp(- r) \\ \\ \\ \\ \\text{ where } r = \sqrt{\sum_{i=1}^input_dim \\frac{(x_i-y_i)^2}{\ell_i^2} } + + """ + + def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='OU'): + super(OU, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) + +
      [docs] def K_of_r(self, r): + return self.variance * np.exp(-r) +
      +
      [docs] def dK_dr(self,r): + return -1.*self.variance*np.exp(-r) + +
      +
      [docs]class Matern32(Stationary): + """ + Matern 3/2 kernel: + + .. math:: + + k(r) = \\sigma^2 (1 + \\sqrt{3} r) \exp(- \sqrt{3} r) \\ \\ \\ \\ \\text{ where } r = \sqrt{\sum_{i=1}^input_dim \\frac{(x_i-y_i)^2}{\ell_i^2} } + + """ + + def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Mat32'): + super(Matern32, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) + +
      [docs] def K_of_r(self, r): + return self.variance * (1. + np.sqrt(3.) * r) * np.exp(-np.sqrt(3.) * r) +
      +
      [docs] def dK_dr(self,r): + return -3.*self.variance*r*np.exp(-np.sqrt(3.)*r) +
      +
      [docs] def Gram_matrix(self, F, F1, F2, lower, upper): + """ + Return the Gram matrix of the vector of functions F with respect to the + RKHS norm. The use of this function is limited to input_dim=1. + + :param F: vector of functions + :type F: np.array + :param F1: vector of derivatives of F + :type F1: np.array + :param F2: vector of second derivatives of F + :type F2: np.array + :param lower,upper: boundaries of the input domain + :type lower,upper: floats + """ + assert self.input_dim == 1 + def L(x, i): + return(3. / self.lengthscale ** 2 * F[i](x) + 2 * np.sqrt(3) / self.lengthscale * F1[i](x) + F2[i](x)) + n = F.shape[0] + G = np.zeros((n, n)) + for i in range(n): + for j in range(i, n): + G[i, j] = G[j, i] = integrate.quad(lambda x : L(x, i) * L(x, j), lower, upper)[0] + Flower = np.array([f(lower) for f in F])[:, None] + F1lower = np.array([f(lower) for f in F1])[:, None] + return(self.lengthscale ** 3 / (12.*np.sqrt(3) * self.variance) * G + 1. / self.variance * np.dot(Flower, Flower.T) + self.lengthscale ** 2 / (3.*self.variance) * np.dot(F1lower, F1lower.T)) + +
      +
      [docs]class Matern52(Stationary): + """ + Matern 5/2 kernel: + + .. math:: + + k(r) = \sigma^2 (1 + \sqrt{5} r + \\frac53 r^2) \exp(- \sqrt{5} r) + """ + def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Mat52'): + super(Matern52, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) + +
      [docs] def K_of_r(self, r): + return self.variance*(1+np.sqrt(5.)*r+5./3*r**2)*np.exp(-np.sqrt(5.)*r) +
      +
      [docs] def dK_dr(self, r): + return self.variance*(10./3*r -5.*r -5.*np.sqrt(5.)/3*r**2)*np.exp(-np.sqrt(5.)*r) +
      +
      [docs] def Gram_matrix(self, F, F1, F2, F3, lower, upper): + """ + Return the Gram matrix of the vector of functions F with respect to the RKHS norm. The use of this function is limited to input_dim=1. + + :param F: vector of functions + :type F: np.array + :param F1: vector of derivatives of F + :type F1: np.array + :param F2: vector of second derivatives of F + :type F2: np.array + :param F3: vector of third derivatives of F + :type F3: np.array + :param lower,upper: boundaries of the input domain + :type lower,upper: floats + """ + assert self.input_dim == 1 + def L(x,i): + return(5*np.sqrt(5)/self.lengthscale**3*F[i](x) + 15./self.lengthscale**2*F1[i](x)+ 3*np.sqrt(5)/self.lengthscale*F2[i](x) + F3[i](x)) + n = F.shape[0] + G = np.zeros((n,n)) + for i in range(n): + for j in range(i,n): + G[i,j] = G[j,i] = integrate.quad(lambda x : L(x,i)*L(x,j),lower,upper)[0] + G_coef = 3.*self.lengthscale**5/(400*np.sqrt(5)) + Flower = np.array([f(lower) for f in F])[:,None] + F1lower = np.array([f(lower) for f in F1])[:,None] + F2lower = np.array([f(lower) for f in F2])[:,None] + orig = 9./8*np.dot(Flower,Flower.T) + 9.*self.lengthscale**4/200*np.dot(F2lower,F2lower.T) + orig2 = 3./5*self.lengthscale**2 * ( np.dot(F1lower,F1lower.T) + 1./8*np.dot(Flower,F2lower.T) + 1./8*np.dot(F2lower,Flower.T)) + return(1./self.variance* (G_coef*G + orig + orig2)) + +
      +
      [docs]class ExpQuad(Stationary): + """ + The Exponentiated quadratic covariance function. + + .. math:: + + k(r) = \sigma^2 (1 + \sqrt{5} r + \\frac53 r^2) \exp(- \sqrt{5} r) + + notes:: + - Yes, this is exactly the same as the RBF covariance function, but the + RBF implementation also has some features for doing variational kernels + (the psi-statistics). + + """ + def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='ExpQuad'): + super(ExpQuad, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) + +
      [docs] def K_of_r(self, r): + return self.variance * np.exp(-0.5 * r**2) +
      +
      [docs] def dK_dr(self, r): + return -r*self.K_of_r(r) +
      +
      [docs]class Cosine(Stationary): + def __init__(self, input_dim, variance=1., lengthscale=None, ARD=False, active_dims=None, name='Cosine'): + super(Cosine, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) + +
      [docs] def K_of_r(self, r): + return self.variance * np.cos(r) +
      +
      [docs] def dK_dr(self, r): + return -self.variance * np.sin(r) + +
      +
      [docs]class RatQuad(Stationary): + """ + Rational Quadratic Kernel + + .. math:: + + k(r) = \sigma^2 \\bigg( 1 + \\frac{r^2}{2} \\bigg)^{- \\alpha} + + """ + + + def __init__(self, input_dim, variance=1., lengthscale=None, power=2., ARD=False, active_dims=None, name='RatQuad'): + super(RatQuad, self).__init__(input_dim, variance, lengthscale, ARD, active_dims, name) + self.power = Param('power', power, Logexp()) + self.link_parameters(self.power) + +
      [docs] def K_of_r(self, r): + r2 = np.power(r, 2.) + return self.variance*np.power(1. + r2/2., -self.power) +
      +
      [docs] def dK_dr(self, r): + r2 = np.power(r, 2.) + return -self.variance*self.power*r*np.power(1. + r2/2., - self.power - 1.) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + super(RatQuad, self).update_gradients_full(dL_dK, X, X2) + r = self._scaled_dist(X, X2) + r2 = np.power(r, 2.) + dK_dpow = -self.variance * np.power(2., self.power) * np.power(r2 + 2., -self.power) * np.log(0.5*(r2+2.)) + grad = np.sum(dL_dK*dK_dpow) + self.power.gradient = grad +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + super(RatQuad, self).update_gradients_diag(dL_dKdiag, X) + self.power.gradient = 0. +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/kern/_src/trunclinear.html b/doc/_build/html/_modules/GPy/kern/_src/trunclinear.html new file mode 100644 index 00000000..fed71196 --- /dev/null +++ b/doc/_build/html/_modules/GPy/kern/_src/trunclinear.html @@ -0,0 +1,296 @@ + + + + + + + + GPy.kern._src.trunclinear — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.kern._src.trunclinear

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from kern import Kern
      +from ...core.parameterization import Param
      +from ...core.parameterization.transformations import Logexp
      +from ...util.caching import Cache_this
      +from ...util.config import *
      +
      +
      [docs]class TruncLinear(Kern): + """ + Truncated Linear kernel + + .. math:: + + k(x,y) = \sum_{i=1}^input_dim \sigma^2_i \max(0, x_iy_i - \simga_q) + + :param input_dim: the number of input dimensions + :type input_dim: int + :param variances: the vector of variances :math:`\sigma^2_i` + :type variances: array or list of the appropriate size (or float if there + is only one variance parameter) + :param ARD: Auto Relevance Determination. If False, the kernel has only one + variance parameter \sigma^2, otherwise there is one variance + parameter per dimension. + :type ARD: Boolean + :rtype: kernel object + + """ + + def __init__(self, input_dim, variances=None, delta=None, ARD=False, active_dims=None, name='linear'): + super(TruncLinear, self).__init__(input_dim, active_dims, name) + self.ARD = ARD + if not ARD: + if variances is not None: + variances = np.asarray(variances) + delta = np.asarray(delta) + assert variances.size == 1, "Only one variance needed for non-ARD kernel" + else: + variances = np.ones(1) + delta = np.zeros(1) + else: + if variances is not None: + variances = np.asarray(variances) + delta = np.asarray(delta) + assert variances.size == self.input_dim, "bad number of variances, need one ARD variance per input_dim" + else: + variances = np.ones(self.input_dim) + delta = np.zeros(self.input_dim) + + self.variances = Param('variances', variances, Logexp()) + self.delta = Param('delta', delta) + self.add_parameter(self.variances) + self.add_parameter(self.delta) + + @Cache_this(limit=2) +
      [docs] def K(self, X, X2=None): + XX = self.variances*self._product(X, X2) + return XX.sum(axis=-1) +
      + @Cache_this(limit=2) + def _product(self, X, X2=None): + if X2 is None: + X2 = X + XX = np.einsum('nq,mq->nmq',X-self.delta,X2-self.delta) + XX[XX<0] = 0 + return XX + +
      [docs] def Kdiag(self, X): + return (self.variances*np.square(X-self.delta)).sum(axis=-1) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + dK_dvar = self._product(X, X2) + if X2 is None: + X2=X + dK_ddelta = self.variances*(2*self.delta-X[:,None,:]-X2[None,:,:])*(dK_dvar>0) + if self.ARD: + self.variances.gradient[:] = np.einsum('nmq,nm->q',dK_dvar,dL_dK) + self.delta.gradient[:] = np.einsum('nmq,nm->q',dK_ddelta,dL_dK) + else: + self.variances.gradient[:] = np.einsum('nmq,nm->',dK_dvar,dL_dK) + self.delta.gradient[:] = np.einsum('nmq,nm->',dK_ddelta,dL_dK) +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + if self.ARD: + self.variances.gradient[:] = np.einsum('nq,n->q',np.square(X-self.delta),dL_dKdiag) + self.delta.gradient[:] = np.einsum('nq,n->q',2*self.variances*(self.delta-X),dL_dKdiag) + else: + self.variances.gradient[:] = np.einsum('nq,n->',np.square(X-self.delta),dL_dKdiag) + self.delta.gradient[:] = np.einsum('nq,n->',2*self.variances*(self.delta-X),dL_dKdiag) +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + XX = self._product(X, X2) + if X2 is None: + Xp = (self.variances*(X-self.delta))*(XX>0) + else: + Xp = (self.variances*(X2-self.delta))*(XX>0) + if X2 is None: + return np.einsum('nmq,nm->nq',Xp,dL_dK)+np.einsum('mnq,nm->mq',Xp,dL_dK) + else: + return np.einsum('nmq,nm->nq',Xp,dL_dK) +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + return 2.*self.variances*dL_dKdiag[:,None]*(X-self.delta) +
      +
      [docs] def input_sensitivity(self): + return np.ones(self.input_dim) * self.variances +
      +
      [docs]class TruncLinear_inf(Kern): + """ + Truncated Linear kernel + + .. math:: + + k(x,y) = \sum_{i=1}^input_dim \sigma^2_i \max(0, x_iy_i - \simga_q) + + :param input_dim: the number of input dimensions + :type input_dim: int + :param variances: the vector of variances :math:`\sigma^2_i` + :type variances: array or list of the appropriate size (or float if there + is only one variance parameter) + :param ARD: Auto Relevance Determination. If False, the kernel has only one + variance parameter \sigma^2, otherwise there is one variance + parameter per dimension. + :type ARD: Boolean + :rtype: kernel object + + """ + + def __init__(self, input_dim, interval, variances=None, ARD=False, active_dims=None, name='linear'): + super(TruncLinear_inf, self).__init__(input_dim, active_dims, name) + self.interval = interval + self.ARD = ARD + if not ARD: + if variances is not None: + variances = np.asarray(variances) + assert variances.size == 1, "Only one variance needed for non-ARD kernel" + else: + variances = np.ones(1) + else: + if variances is not None: + variances = np.asarray(variances) + assert variances.size == self.input_dim, "bad number of variances, need one ARD variance per input_dim" + else: + variances = np.ones(self.input_dim) + + self.variances = Param('variances', variances, Logexp()) + self.add_parameter(self.variances) + + +# @Cache_this(limit=2) +
      [docs] def K(self, X, X2=None): + tmp = self._product(X, X2) + return (self.variances*tmp).sum(axis=-1) + +# @Cache_this(limit=2)
      + def _product(self, X, X2=None): + if X2 is None: + X2 = X + X_X2 = X[:,None,:]-X2[None,:,:] + tmp = np.abs(X_X2**3)/6+np.einsum('nq,mq->nmq',X,X2)*(self.interval[1]-self.interval[0]) \ + -(X[:,None,:]+X2[None,:,:])*(self.interval[1]*self.interval[1]-self.interval[0]*self.interval[0])/2+(self.interval[1]**3-self.interval[0]**3)/3. + return tmp + +
      [docs] def Kdiag(self, X): + tmp = np.square(X)*(self.interval[1]-self.interval[0]) \ + -X*(self.interval[1]*self.interval[1]-self.interval[0]*self.interval[0])+(self.interval[1]**3-self.interval[0]**3)/3 + return (self.variances*tmp).sum(axis=-1) +
      +
      [docs] def update_gradients_full(self, dL_dK, X, X2=None): + dK_dvar = self._product(X, X2) + if self.ARD: + self.variances.gradient[:] = np.einsum('nmq,nm->q',dK_dvar,dL_dK) + else: + self.variances.gradient[:] = np.einsum('nmq,nm->',dK_dvar,dL_dK) +
      +
      [docs] def update_gradients_diag(self, dL_dKdiag, X): + tmp = np.square(X)*(self.interval[1]-self.interval[0]) \ + -X*(self.interval[1]*self.interval[1]-self.interval[0]*self.interval[0])+(self.interval[1]**3-self.interval[0]**3)/3 + if self.ARD: + self.variances.gradient[:] = np.einsum('nq,n->q',tmp,dL_dKdiag) + else: + self.variances.gradient[:] = np.einsum('nq,n->',tmp,dL_dKdiag) +
      +
      [docs] def gradients_X(self, dL_dK, X, X2=None): + XX = self._product(X, X2) + if X2 is None: + Xp = (self.variances*(X-self.delta))*(XX>0) + else: + Xp = (self.variances*(X2-self.delta))*(XX>0) + if X2 is None: + return np.einsum('nmq,nm->nq',Xp,dL_dK)+np.einsum('mnq,nm->mq',Xp,dL_dK) + else: + return np.einsum('nmq,nm->nq',Xp,dL_dK) +
      +
      [docs] def gradients_X_diag(self, dL_dKdiag, X): + return 2.*self.variances*dL_dKdiag[:,None]*(X-self.delta) +
      +
      [docs] def input_sensitivity(self): + return np.ones(self.input_dim) * self.variances +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/bernoulli.html b/doc/_build/html/_modules/GPy/likelihoods/bernoulli.html new file mode 100644 index 00000000..c3d7cbfd --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/bernoulli.html @@ -0,0 +1,318 @@ + + + + + + + + GPy.likelihoods.bernoulli — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.bernoulli

      +# Copyright (c) 2012-2014 The GPy authors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..util.univariate_Gaussian import std_norm_pdf, std_norm_cdf
      +import link_functions
      +from likelihood import Likelihood
      +from scipy import stats
      +
      +
      [docs]class Bernoulli(Likelihood): + """ + Bernoulli likelihood + + .. math:: + p(y_{i}|\\lambda(f_{i})) = \\lambda(f_{i})^{y_{i}}(1-f_{i})^{1-y_{i}} + + .. Note:: + Y takes values in either {-1, 1} or {0, 1}. + link function should have the domain [0, 1], e.g. probit (default) or Heaviside + + .. See also:: + likelihood.py, for the parent class + """ + def __init__(self, gp_link=None): + if gp_link is None: + gp_link = link_functions.Probit() + + super(Bernoulli, self).__init__(gp_link, 'Bernoulli') + + if isinstance(gp_link , (link_functions.Heaviside, link_functions.Probit)): + self.log_concave = True + + def _preprocess_values(self, Y): + """ + Check if the values of the observations correspond to the values + assumed by the likelihood function. + + ..Note:: Binary classification algorithm works better with classes {-1, 1} + """ + Y_prep = Y.copy() + Y1 = Y[Y.flatten()==1].size + Y2 = Y[Y.flatten()==0].size + assert Y1 + Y2 == Y.size, 'Bernoulli likelihood is meant to be used only with outputs in {0, 1}.' + Y_prep[Y.flatten() == 0] = -1 + return Y_prep + +
      [docs] def moments_match_ep(self, Y_i, tau_i, v_i): + """ + Moments match of the marginal approximation in EP algorithm + + :param i: number of observation (int) + :param tau_i: precision of the cavity distribution (float) + :param v_i: mean/variance of the cavity distribution (float) + """ + if Y_i == 1: + sign = 1. + elif Y_i == 0 or Y_i == -1: + sign = -1 + else: + raise ValueError("bad value for Bernoulli observation (0, 1)") + if isinstance(self.gp_link, link_functions.Probit): + z = sign*v_i/np.sqrt(tau_i**2 + tau_i) + Z_hat = std_norm_cdf(z) + phi = std_norm_pdf(z) + mu_hat = v_i/tau_i + sign*phi/(Z_hat*np.sqrt(tau_i**2 + tau_i)) + sigma2_hat = 1./tau_i - (phi/((tau_i**2+tau_i)*Z_hat))*(z+phi/Z_hat) + + elif isinstance(self.gp_link, link_functions.Heaviside): + a = sign*v_i/np.sqrt(tau_i) + Z_hat = std_norm_cdf(a) + N = std_norm_pdf(a) + mu_hat = v_i/tau_i + sign*N/Z_hat/np.sqrt(tau_i) + sigma2_hat = (1. - a*N/Z_hat - np.square(N/Z_hat))/tau_i + else: + #TODO: do we want to revert to numerical quadrature here? + raise ValueError("Exact moment matching not available for link {}".format(self.gp_link.__name__)) + + return Z_hat, mu_hat, sigma2_hat +
      +
      [docs] def predictive_mean(self, mu, variance, Y_metadata=None): + + if isinstance(self.gp_link, link_functions.Probit): + return stats.norm.cdf(mu/np.sqrt(1+variance)) + + elif isinstance(self.gp_link, link_functions.Heaviside): + return stats.norm.cdf(mu/np.sqrt(variance)) + + else: + raise NotImplementedError +
      +
      [docs] def predictive_variance(self, mu, variance, pred_mean, Y_metadata=None): + + if isinstance(self.gp_link, link_functions.Heaviside): + return 0. + else: + return np.nan +
      + + + +
      [docs] def d2logpdf_dlink2(self, inv_link_f, y, Y_metadata=None): + """ + Hessian at y, given inv_link_f, w.r.t inv_link_f the hessian will be 0 unless i == j + i.e. second derivative logpdf at y given inverse link of f_i and inverse link of f_j w.r.t inverse link of f_i and inverse link of f_j. + + + .. math:: + \\frac{d^{2}\\ln p(y_{i}|\\lambda(f_{i}))}{d\\lambda(f)^{2}} = \\frac{-y_{i}}{\\lambda(f)^{2}} - \\frac{(1-y_{i})}{(1-\\lambda(f))^{2}} + + :param inv_link_f: latent variables inverse link of f. + :type inv_link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata not used in bernoulli + :returns: Diagonal of log hessian matrix (second derivative of log likelihood evaluated at points inverse link of f. + :rtype: Nx1 array + + .. Note:: + Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases + (the distribution for y_i depends only on inverse link of f_i not on inverse link of f_(j!=i) + """ + #d2logpdf_dlink2 = -y/(inv_link_f**2) - (1-y)/((1-inv_link_f)**2) + #d2logpdf_dlink2 = np.where(y, -1./np.square(inv_link_f), -1./np.square(1.-inv_link_f)) + arg = np.where(y, inv_link_f, 1.-inv_link_f) + ret = -1./np.square(np.clip(arg, 1e-3, np.inf)) + if np.any(np.isinf(ret)): + stop + return ret +
      +
      [docs] def d3logpdf_dlink3(self, inv_link_f, y, Y_metadata=None): + """ + Third order derivative log-likelihood function at y given inverse link of f w.r.t inverse link of f + + .. math:: + \\frac{d^{3} \\ln p(y_{i}|\\lambda(f_{i}))}{d^{3}\\lambda(f)} = \\frac{2y_{i}}{\\lambda(f)^{3}} - \\frac{2(1-y_{i}}{(1-\\lambda(f))^{3}} + + :param inv_link_f: latent variables passed through inverse link of f. + :type inv_link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata not used in bernoulli + :returns: third derivative of log likelihood evaluated at points inverse_link(f) + :rtype: Nx1 array + """ + assert np.atleast_1d(inv_link_f).shape == np.atleast_1d(y).shape + #d3logpdf_dlink3 = 2*(y/(inv_link_f**3) - (1-y)/((1-inv_link_f)**3)) + state = np.seterr(divide='ignore') + # TODO check y \in {0, 1} or {-1, 1} + d3logpdf_dlink3 = np.where(y, 2./(inv_link_f**3), -2./((1.-inv_link_f)**3)) + np.seterr(**state) + return d3logpdf_dlink3 +
      +
      [docs] def samples(self, gp, Y_metadata=None): + """ + Returns a set of samples of observations based on a given value of the latent variable. + + :param gp: latent variable + """ + orig_shape = gp.shape + gp = gp.flatten() + ns = np.ones_like(gp, dtype=int) + Ysim = np.random.binomial(ns, self.gp_link.transf(gp)) + return Ysim.reshape(orig_shape) +
      +
      [docs] def exact_inference_gradients(self, dL_dKdiag,Y_metadata=None): + pass
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/exponential.html b/doc/_build/html/_modules/GPy/likelihoods/exponential.html new file mode 100644 index 00000000..d4cc87b2 --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/exponential.html @@ -0,0 +1,234 @@ + + + + + + + + GPy.likelihoods.exponential — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.exponential

      +# Copyright (c) 2012-2014 GPy Authors
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from scipy import stats,special
      +import scipy as sp
      +import link_functions
      +from likelihood import Likelihood
      +
      +
      [docs]class Exponential(Likelihood): + """ + Expoential likelihood + Y is expected to take values in {0,1,2,...} + ----- + $$ + L(x) = \exp(\lambda) * \lambda**Y_i / Y_i! + $$ + """ + def __init__(self,gp_link=None): + if gp_link is None: + gp_link = link_functions.Log() + super(Exponential, self).__init__(gp_link, 'ExpLikelihood') + + + + +
      [docs] def d2logpdf_dlink2(self, link_f, y, Y_metadata=None): + """ + Hessian at y, given link(f), w.r.t link(f) + i.e. second derivative logpdf at y given link(f_i) and link(f_j) w.r.t link(f_i) and link(f_j) + The hessian will be 0 unless i == j + + .. math:: + \\frac{d^{2} \\ln p(y_{i}|\lambda(f_{i}))}{d^{2}\\lambda(f)} = -\\frac{1}{\\lambda(f_{i})^{2}} + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in exponential distribution + :returns: Diagonal of hessian matrix (second derivative of likelihood evaluated at points f) + :rtype: Nx1 array + + .. Note:: + Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases + (the distribution for y_i depends only on link(f_i) not on link(f_(j!=i)) + """ + assert np.atleast_1d(link_f).shape == np.atleast_1d(y).shape + hess = -1./(link_f**2) + #hess = -2*y/(link_f**3) + 1/(link_f**2) + return hess +
      +
      [docs] def d3logpdf_dlink3(self, link_f, y, Y_metadata=None): + """ + Third order derivative log-likelihood function at y given link(f) w.r.t link(f) + + .. math:: + \\frac{d^{3} \\ln p(y_{i}|\lambda(f_{i}))}{d^{3}\\lambda(f)} = \\frac{2}{\\lambda(f_{i})^{3}} + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in exponential distribution + :returns: third derivative of likelihood evaluated at points f + :rtype: Nx1 array + """ + assert np.atleast_1d(link_f).shape == np.atleast_1d(y).shape + d3lik_dlink3 = 2./(link_f**3) + #d3lik_dlink3 = 6*y/(link_f**4) - 2./(link_f**3) + return d3lik_dlink3 +
      +
      [docs] def samples(self, gp): + """ + Returns a set of samples of observations based on a given value of the latent variable. + + :param gp: latent variable + """ + orig_shape = gp.shape + gp = gp.flatten() + Ysim = np.random.exponential(1.0/self.gp_link.transf(gp)) + return Ysim.reshape(orig_shape)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/gamma.html b/doc/_build/html/_modules/GPy/likelihoods/gamma.html new file mode 100644 index 00000000..92d98b88 --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/gamma.html @@ -0,0 +1,239 @@ + + + + + + + + GPy.likelihoods.gamma — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.gamma

      +# Copyright (c) 2012 - 2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from scipy import stats,special
      +import scipy as sp
      +from ..core.parameterization import Param
      +import link_functions
      +from likelihood import Likelihood
      +
      +
      [docs]class Gamma(Likelihood): + """ + Gamma likelihood + + .. math:: + p(y_{i}|\\lambda(f_{i})) = \\frac{\\beta^{\\alpha_{i}}}{\\Gamma(\\alpha_{i})}y_{i}^{\\alpha_{i}-1}e^{-\\beta y_{i}}\\\\ + \\alpha_{i} = \\beta y_{i} + + """ + def __init__(self,gp_link=None,beta=1.): + if gp_link is None: + gp_link = link_functions.Log() + super(Gamma, self).__init__(gp_link, 'Gamma') + + self.beta = Param('beta', beta) + self.link_parameter(self.beta) + self.beta.fix()#TODO: gradients! + + + + +
      [docs] def d2logpdf_dlink2(self, link_f, y, Y_metadata=None): + """ + Hessian at y, given link(f), w.r.t link(f) + i.e. second derivative logpdf at y given link(f_i) and link(f_j) w.r.t link(f_i) and link(f_j) + The hessian will be 0 unless i == j + + .. math:: + \\frac{d^{2} \\ln p(y_{i}|\lambda(f_{i}))}{d^{2}\\lambda(f)} = -\\beta^{2}\\frac{d\\Psi(\\alpha_{i})}{d\\alpha_{i}}\\\\ + \\alpha_{i} = \\beta y_{i} + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in gamma distribution + :returns: Diagonal of hessian matrix (second derivative of likelihood evaluated at points f) + :rtype: Nx1 array + + .. Note:: + Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases + (the distribution for y_i depends only on link(f_i) not on link(f_(j!=i)) + """ + assert np.atleast_1d(link_f).shape == np.atleast_1d(y).shape + hess = -special.polygamma(1, self.beta*link_f)*(self.beta**2) + #old + #return -self.gp_link.d2transf_df2(gp)*self.beta*np.log(obs) + special.polygamma(1,self.gp_link.transf(gp)*self.beta)*(self.gp_link.dtransf_df(gp)*self.beta)**2 + special.psi(self.gp_link.transf(gp)*self.beta)*self.gp_link.d2transf_df2(gp)*self.beta + return hess +
      +
      [docs] def d3logpdf_dlink3(self, link_f, y, Y_metadata=None): + """ + Third order derivative log-likelihood function at y given link(f) w.r.t link(f) + + .. math:: + \\frac{d^{3} \\ln p(y_{i}|\lambda(f_{i}))}{d^{3}\\lambda(f)} = -\\beta^{3}\\frac{d^{2}\\Psi(\\alpha_{i})}{d\\alpha_{i}}\\\\ + \\alpha_{i} = \\beta y_{i} + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in gamma distribution + :returns: third derivative of likelihood evaluated at points f + :rtype: Nx1 array + """ + assert np.atleast_1d(link_f).shape == np.atleast_1d(y).shape + d3lik_dlink3 = -special.polygamma(2, self.beta*link_f)*(self.beta**3) + return d3lik_dlink3
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/gaussian.html b/doc/_build/html/_modules/GPy/likelihoods/gaussian.html new file mode 100644 index 00000000..88ba9f6e --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/gaussian.html @@ -0,0 +1,411 @@ + + + + + + + + GPy.likelihoods.gaussian — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.gaussian

      +# Copyright (c) 2012-2014 The GPy authors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +#TODO
      +"""
      +A lot of this code assumes that the link function is the identity.
      +
      +I think laplace code is okay, but I'm quite sure that the EP moments will only work if the link is identity.
      +
      +Furthermore, exact Guassian inference can only be done for the identity link, so we should be asserting so for all calls which relate to that.
      +
      +James 11/12/13
      +"""
      +
      +import numpy as np
      +from scipy import stats, special
      +import link_functions
      +from likelihood import Likelihood
      +from ..core.parameterization import Param
      +from ..core.parameterization.transformations import Logexp
      +from scipy import stats
      +
      +
      [docs]class Gaussian(Likelihood): + """ + Gaussian likelihood + + .. math:: + \\ln p(y_{i}|\\lambda(f_{i})) = -\\frac{N \\ln 2\\pi}{2} - \\frac{\\ln |K|}{2} - \\frac{(y_{i} - \\lambda(f_{i}))^{T}\\sigma^{-2}(y_{i} - \\lambda(f_{i}))}{2} + + :param variance: variance value of the Gaussian distribution + :param N: Number of data points + :type N: int + """ + def __init__(self, gp_link=None, variance=1., name='Gaussian_noise'): + if gp_link is None: + gp_link = link_functions.Identity() + + assert isinstance(gp_link, link_functions.Identity), "the likelihood only implemented for the identity link" + + super(Gaussian, self).__init__(gp_link, name=name) + + self.variance = Param('variance', variance, Logexp()) + self.link_parameter(self.variance) + + if isinstance(gp_link, link_functions.Identity): + self.log_concave = True + +
      [docs] def betaY(self,Y,Y_metadata=None): + #TODO: ~Ricardo this does not live here + return Y/self.gaussian_variance(Y_metadata) +
      +
      [docs] def gaussian_variance(self, Y_metadata=None): + return self.variance +
      +
      [docs] def update_gradients(self, grad): + self.variance.gradient = grad +
      +
      [docs] def exact_inference_gradients(self, dL_dKdiag,Y_metadata=None): + return dL_dKdiag.sum() +
      + def _preprocess_values(self, Y): + """ + Check if the values of the observations correspond to the values + assumed by the likelihood function. + """ + return Y + + def _moments_match_ep(self, data_i, tau_i, v_i): + """ + Moments match of the marginal approximation in EP algorithm + + :param i: number of observation (int) + :param tau_i: precision of the cavity distribution (float) + :param v_i: mean/variance of the cavity distribution (float) + """ + sigma2_hat = 1./(1./self.variance + tau_i) + mu_hat = sigma2_hat*(data_i/self.variance + v_i) + sum_var = self.variance + 1./tau_i + Z_hat = 1./np.sqrt(2.*np.pi*sum_var)*np.exp(-.5*(data_i - v_i/tau_i)**2./sum_var) + return Z_hat, mu_hat, sigma2_hat + +
      [docs] def predictive_values(self, mu, var, full_cov=False, Y_metadata=None): + if full_cov: + if var.ndim == 2: + var += np.eye(var.shape[0])*self.variance + if var.ndim == 3: + var += np.atleast_3d(np.eye(var.shape[0])*self.variance) + else: + var += self.variance + return mu, var +
      +
      [docs] def predictive_mean(self, mu, sigma): + return mu +
      +
      [docs] def predictive_variance(self, mu, sigma, predictive_mean=None): + return self.variance + sigma**2 +
      +
      [docs] def predictive_quantiles(self, mu, var, quantiles, Y_metadata=None): + return [stats.norm.ppf(q/100.)*np.sqrt(var + self.variance) + mu for q in quantiles] +
      + + + +
      [docs] def d2logpdf_dlink2(self, link_f, y, Y_metadata=None): + """ + Hessian at y, given link_f, w.r.t link_f. + i.e. second derivative logpdf at y given link(f_i) link(f_j) w.r.t link(f_i) and link(f_j) + + The hessian will be 0 unless i == j + + .. math:: + \\frac{d^{2} \\ln p(y_{i}|\\lambda(f_{i}))}{d^{2}f} = -\\frac{1}{\\sigma^{2}} + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata not used in gaussian + :returns: Diagonal of log hessian matrix (second derivative of log likelihood evaluated at points link(f)) + :rtype: Nx1 array + + .. Note:: + Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases + (the distribution for y_i depends only on link(f_i) not on link(f_(j!=i)) + """ + assert np.asarray(link_f).shape == np.asarray(y).shape + N = y.shape[0] + hess = -(1.0/self.variance)*np.ones((N, 1)) + return hess +
      +
      [docs] def d3logpdf_dlink3(self, link_f, y, Y_metadata=None): + """ + Third order derivative log-likelihood function at y given link(f) w.r.t link(f) + + .. math:: + \\frac{d^{3} \\ln p(y_{i}|\\lambda(f_{i}))}{d^{3}\\lambda(f)} = 0 + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata not used in gaussian + :returns: third derivative of log likelihood evaluated at points link(f) + :rtype: Nx1 array + """ + assert np.asarray(link_f).shape == np.asarray(y).shape + N = y.shape[0] + d3logpdf_dlink3 = np.zeros((N,1)) + return d3logpdf_dlink3 +
      + + +
      [docs] def d2logpdf_dlink2_dvar(self, link_f, y, Y_metadata=None): + """ + Gradient of the hessian (d2logpdf_dlink2) w.r.t variance parameter (noise_variance) + + .. math:: + \\frac{d}{d\\sigma^{2}}(\\frac{d^{2} \\ln p(y_{i}|\\lambda(f_{i}))}{d^{2}\\lambda(f)}) = \\frac{1}{\\sigma^{4}} + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata not used in gaussian + :returns: derivative of log hessian evaluated at points link(f_i) and link(f_j) w.r.t variance parameter + :rtype: Nx1 array + """ + assert np.asarray(link_f).shape == np.asarray(y).shape + s_4 = 1.0/(self.variance**2) + N = y.shape[0] + d2logpdf_dlink2_dvar = np.ones((N,1))*s_4 + return d2logpdf_dlink2_dvar +
      + + +
      [docs] def d2logpdf_dlink2_dtheta(self, f, y, Y_metadata=None): + d2logpdf_dlink2_dvar = self.d2logpdf_dlink2_dvar(f, y, Y_metadata=Y_metadata) + return d2logpdf_dlink2_dvar +
      + def _mean(self, gp): + """ + Expected value of y under the Mass (or density) function p(y|f) + + .. math:: + E_{p(y|f)}[y] + """ + return self.gp_link.transf(gp) + + def _variance(self, gp): + """ + Variance of y under the Mass (or density) function p(y|f) + + .. math:: + Var_{p(y|f)}[y] + """ + return self.variance + +
      [docs] def samples(self, gp, Y_metadata=None): + """ + Returns a set of samples of observations based on a given value of the latent variable. + + :param gp: latent variable + """ + orig_shape = gp.shape + gp = gp.flatten() + #orig_shape = gp.shape + gp = gp.flatten() + Ysim = np.array([np.random.normal(self.gp_link.transf(gpj), scale=np.sqrt(self.variance), size=1) for gpj in gp]) + return Ysim.reshape(orig_shape) +
      +
      [docs] def log_predictive_density(self, y_test, mu_star, var_star): + """ + assumes independence + """ + v = var_star + self.variance + return -0.5*np.log(2*np.pi) -0.5*np.log(v) - 0.5*np.square(y_test - mu_star)/v +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/likelihood.html b/doc/_build/html/_modules/GPy/likelihoods/likelihood.html new file mode 100644 index 00000000..78df0385 --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/likelihood.html @@ -0,0 +1,567 @@ + + + + + + + + GPy.likelihoods.likelihood — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.likelihood

      +# Copyright (c) 2012-2014 The GPy authors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from scipy import stats,special
      +import scipy as sp
      +import link_functions
      +from ..util.misc import chain_1, chain_2, chain_3
      +from scipy.integrate import quad
      +import warnings
      +from ..core.parameterization import Parameterized
      +
      +
      [docs]class Likelihood(Parameterized): + """ + Likelihood base class, used to defing p(y|f). + + All instances use _inverse_ link functions, which can be swapped out. It is + expected that inheriting classes define a default inverse link function + + To use this class, inherit and define missing functionality. + + Inheriting classes *must* implement: + pdf_link : a bound method which turns the output of the link function into the pdf + logpdf_link : the logarithm of the above + + To enable use with EP, inheriting classes *must* define: + TODO: a suitable derivative function for any parameters of the class + It is also desirable to define: + moments_match_ep : a function to compute the EP moments If this isn't defined, the moments will be computed using 1D quadrature. + + To enable use with Laplace approximation, inheriting classes *must* define: + Some derivative functions *AS TODO* + + For exact Gaussian inference, define *JH TODO* + + """ + def __init__(self, gp_link, name): + super(Likelihood, self).__init__(name) + assert isinstance(gp_link,link_functions.GPTransformation), "gp_link is not a valid GPTransformation." + self.gp_link = gp_link + self.log_concave = False + + def _gradients(self,partial): + return np.zeros(0) + +
      [docs] def update_gradients(self, partial): + if self.size > 0: + raise NotImplementedError('Must be implemented for likelihoods with parameters to be optimized') +
      + def _preprocess_values(self,Y): + """ + In case it is needed, this function assess the output values or makes any pertinent transformation on them. + + :param Y: observed output + :type Y: Nx1 numpy.darray + + """ + return Y + +
      [docs] def conditional_mean(self, gp): + """ + The mean of the random variable conditioned on one value of the GP + """ + raise NotImplementedError +
      +
      [docs] def conditional_variance(self, gp): + """ + The variance of the random variable conditioned on one value of the GP + """ + raise NotImplementedError +
      +
      [docs] def log_predictive_density(self, y_test, mu_star, var_star): + """ + Calculation of the log predictive density + + .. math: + p(y_{*}|D) = p(y_{*}|f_{*})p(f_{*}|\mu_{*}\\sigma^{2}_{*}) + + :param y_test: test observations (y_{*}) + :type y_test: (Nx1) array + :param mu_star: predictive mean of gaussian p(f_{*}|mu_{*}, var_{*}) + :type mu_star: (Nx1) array + :param var_star: predictive variance of gaussian p(f_{*}|mu_{*}, var_{*}) + :type var_star: (Nx1) array + """ + assert y_test.shape==mu_star.shape + assert y_test.shape==var_star.shape + assert y_test.shape[1] == 1 + def integral_generator(y, m, v): + """Generate a function which can be integrated to give p(Y*|Y) = int p(Y*|f*)p(f*|Y) df*""" + def f(f_star): + return self.pdf(f_star, y)*np.exp(-(1./(2*v))*np.square(m-f_star)) + return f + + scaled_p_ystar, accuracy = zip(*[quad(integral_generator(y, m, v), -np.inf, np.inf) for y, m, v in zip(y_test.flatten(), mu_star.flatten(), var_star.flatten())]) + scaled_p_ystar = np.array(scaled_p_ystar).reshape(-1,1) + p_ystar = scaled_p_ystar/np.sqrt(2*np.pi*var_star) + return np.log(p_ystar) +
      + def _moments_match_ep(self,obs,tau,v): + """ + Calculation of moments using quadrature + + :param obs: observed output + :param tau: cavity distribution 1st natural parameter (precision) + :param v: cavity distribution 2nd natural paramenter (mu*precision) + """ + #Compute first integral for zeroth moment. + #NOTE constant np.sqrt(2*pi/tau) added at the end of the function + mu = v/tau + def int_1(f): + return self.pdf(f, obs)*np.exp(-0.5*tau*np.square(mu-f)) + z_scaled, accuracy = quad(int_1, -np.inf, np.inf) + + #Compute second integral for first moment + def int_2(f): + return f*self.pdf(f, obs)*np.exp(-0.5*tau*np.square(mu-f)) + mean, accuracy = quad(int_2, -np.inf, np.inf) + mean /= z_scaled + + #Compute integral for variance + def int_3(f): + return (f**2)*self.pdf(f, obs)*np.exp(-0.5*tau*np.square(mu-f)) + Ef2, accuracy = quad(int_3, -np.inf, np.inf) + Ef2 /= z_scaled + variance = Ef2 - mean**2 + + #Add constant to the zeroth moment + #NOTE: this constant is not needed in the other moments because it cancells out. + z = z_scaled/np.sqrt(2*np.pi/tau) + + return z, mean, variance + +
      [docs] def variational_expectations(self, Y, m, v, gh_points=None): + """ + Use Gauss-Hermite Quadrature to compute + + E_p(f) [ log p(y|f) ] + d/dm E_p(f) [ log p(y|f) ] + d/dv E_p(f) [ log p(y|f) ] + + where p(f) is a Gaussian with mean m and variance v. The shapes of Y, m and v should match. + + if no gh_points are passed, we construct them using defualt options + """ + + if gh_points is None: + gh_x, gh_w = np.polynomial.hermite.hermgauss(12) + else: + gh_x, gh_w = gh_points + + shape = m.shape + m,v,Y = m.flatten(), v.flatten(), Y.flatten() + + #make a grid of points + X = gh_x[None,:]*np.sqrt(2.*v[:,None]) + m[:,None] + + #evaluate the likelhood for the grid. First ax indexes the data (and mu, var) and the second indexes the grid. + # broadcast needs to be handled carefully. + logp = self.logpdf(X,Y[:,None]) + dlogp_dx = self.dlogpdf_df(X, Y[:,None]) + d2logp_dx2 = self.d2logpdf_df2(X, Y[:,None]) + + #clipping for numerical stability + logp = np.clip(logp,-1e6,1e6) + dlogp_dx = np.clip(dlogp_dx,-1e6,1e6) + d2logp_dx2 = np.clip(d2logp_dx2,-1e6,1e6) + + #average over the gird to get derivatives of the Gaussian's parameters + F = np.dot(logp, gh_w) + dF_dm = np.dot(dlogp_dx, gh_w) + dF_dv = np.dot(d2logp_dx2, gh_w)/2. + + if np.any(np.isnan(dF_dv)) or np.any(np.isinf(dF_dv)): + stop + if np.any(np.isnan(dF_dm)) or np.any(np.isinf(dF_dm)): + stop + + return F.reshape(*shape), dF_dm.reshape(*shape), dF_dv.reshape(*shape) + + + +
      +
      [docs] def predictive_mean(self, mu, variance, Y_metadata=None): + """ + Quadrature calculation of the predictive mean: E(Y_star|Y) = E( E(Y_star|f_star, Y) ) + + :param mu: mean of posterior + :param sigma: standard deviation of posterior + + """ + #conditional_mean: the edpected value of y given some f, under this likelihood + def int_mean(f,m,v): + p = np.exp(-(0.5/v)*np.square(f - m)) + #If p is zero then conditional_mean will overflow + if p < 1e-10: + return 0. + else: + return self.conditional_mean(f)*p + scaled_mean = [quad(int_mean, -np.inf, np.inf,args=(mj,s2j))[0] for mj,s2j in zip(mu,variance)] + mean = np.array(scaled_mean)[:,None] / np.sqrt(2*np.pi*(variance)) + + return mean +
      + def _conditional_mean(self, f): + """Quadrature calculation of the conditional mean: E(Y_star|f)""" + raise NotImplementedError, "implement this function to make predictions" + +
      [docs] def predictive_variance(self, mu,variance, predictive_mean=None, Y_metadata=None): + """ + Approximation to the predictive variance: V(Y_star) + + The following variance decomposition is used: + V(Y_star) = E( V(Y_star|f_star) ) + V( E(Y_star|f_star) ) + + :param mu: mean of posterior + :param sigma: standard deviation of posterior + :predictive_mean: output's predictive mean, if None _predictive_mean function will be called. + + """ + #sigma2 = sigma**2 + normalizer = np.sqrt(2*np.pi*variance) + + # E( V(Y_star|f_star) ) + def int_var(f,m,v): + p = np.exp(-(0.5/v)*np.square(f - m)) + #If p is zero then conditional_variance will overflow + if p < 1e-10: + return 0. + else: + return self.conditional_variance(f)*p + scaled_exp_variance = [quad(int_var, -np.inf, np.inf,args=(mj,s2j))[0] for mj,s2j in zip(mu,variance)] + exp_var = np.array(scaled_exp_variance)[:,None] / normalizer + + #V( E(Y_star|f_star) ) = E( E(Y_star|f_star)**2 ) - E( E(Y_star|f_star) )**2 + + #E( E(Y_star|f_star) )**2 + if predictive_mean is None: + predictive_mean = self.predictive_mean(mu,variance) + predictive_mean_sq = predictive_mean**2 + + #E( E(Y_star|f_star)**2 ) + def int_pred_mean_sq(f,m,v,predictive_mean_sq): + p = np.exp(-(0.5/v)*np.square(f - m)) + #If p is zero then conditional_mean**2 will overflow + if p < 1e-10: + return 0. + else: + return self.conditional_mean(f)**2*p + + scaled_exp_exp2 = [quad(int_pred_mean_sq, -np.inf, np.inf,args=(mj,s2j,pm2j))[0] for mj,s2j,pm2j in zip(mu,variance,predictive_mean_sq)] + exp_exp2 = np.array(scaled_exp_exp2)[:,None] / normalizer + + var_exp = exp_exp2 - predictive_mean_sq + + # V(Y_star) = E[ V(Y_star|f_star) ] + V[ E(Y_star|f_star) ] + # V(Y_star) = E[ V(Y_star|f_star) ] + E(Y_star**2|f_star) - E[Y_star|f_star]**2 + return exp_var + var_exp +
      + + + +
      [docs] def d2logpdf_dlink2(self, inv_link_f, y, Y_metadata=None): + raise NotImplementedError +
      +
      [docs] def d3logpdf_dlink3(self, inv_link_f, y, Y_metadata=None): + raise NotImplementedError +
      + + +
      [docs] def d2logpdf_dlink2_dtheta(self, inv_link_f, y, Y_metadata=None): + raise NotImplementedError +
      +
      [docs] def pdf(self, f, y, Y_metadata=None): + """ + Evaluates the link function link(f) then computes the likelihood (pdf) using it + + .. math: + p(y|\\lambda(f)) + + :param f: latent variables f + :type f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in student t distribution - not used + :returns: likelihood evaluated for this point + :rtype: float + """ + inv_link_f = self.gp_link.transf(f) + return self.pdf_link(inv_link_f, y, Y_metadata=Y_metadata) +
      +
      [docs] def logpdf(self, f, y, Y_metadata=None): + """ + Evaluates the link function link(f) then computes the log likelihood (log pdf) using it + + .. math: + \\log p(y|\\lambda(f)) + + :param f: latent variables f + :type f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in student t distribution - not used + :returns: log likelihood evaluated for this point + :rtype: float + """ + inv_link_f = self.gp_link.transf(f) + return self.logpdf_link(inv_link_f, y, Y_metadata=Y_metadata) +
      +
      [docs] def dlogpdf_df(self, f, y, Y_metadata=None): + """ + Evaluates the link function link(f) then computes the derivative of log likelihood using it + Uses the Faa di Bruno's formula for the chain rule + + .. math:: + \\frac{d\\log p(y|\\lambda(f))}{df} = \\frac{d\\log p(y|\\lambda(f))}{d\\lambda(f)}\\frac{d\\lambda(f)}{df} + + :param f: latent variables f + :type f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in student t distribution - not used + :returns: derivative of log likelihood evaluated for this point + :rtype: 1xN array + """ + inv_link_f = self.gp_link.transf(f) + dlogpdf_dlink = self.dlogpdf_dlink(inv_link_f, y, Y_metadata=Y_metadata) + dlink_df = self.gp_link.dtransf_df(f) + return chain_1(dlogpdf_dlink, dlink_df) +
      +
      [docs] def d2logpdf_df2(self, f, y, Y_metadata=None): + """ + Evaluates the link function link(f) then computes the second derivative of log likelihood using it + Uses the Faa di Bruno's formula for the chain rule + + .. math:: + \\frac{d^{2}\\log p(y|\\lambda(f))}{df^{2}} = \\frac{d^{2}\\log p(y|\\lambda(f))}{d^{2}\\lambda(f)}\\left(\\frac{d\\lambda(f)}{df}\\right)^{2} + \\frac{d\\log p(y|\\lambda(f))}{d\\lambda(f)}\\frac{d^{2}\\lambda(f)}{df^{2}} + + :param f: latent variables f + :type f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in student t distribution - not used + :returns: second derivative of log likelihood evaluated for this point (diagonal only) + :rtype: 1xN array + """ + inv_link_f = self.gp_link.transf(f) + d2logpdf_dlink2 = self.d2logpdf_dlink2(inv_link_f, y, Y_metadata=Y_metadata) + dlink_df = self.gp_link.dtransf_df(f) + dlogpdf_dlink = self.dlogpdf_dlink(inv_link_f, y, Y_metadata=Y_metadata) + d2link_df2 = self.gp_link.d2transf_df2(f) + return chain_2(d2logpdf_dlink2, dlink_df, dlogpdf_dlink, d2link_df2) +
      +
      [docs] def d3logpdf_df3(self, f, y, Y_metadata=None): + """ + Evaluates the link function link(f) then computes the third derivative of log likelihood using it + Uses the Faa di Bruno's formula for the chain rule + + .. math:: + \\frac{d^{3}\\log p(y|\\lambda(f))}{df^{3}} = \\frac{d^{3}\\log p(y|\\lambda(f)}{d\\lambda(f)^{3}}\\left(\\frac{d\\lambda(f)}{df}\\right)^{3} + 3\\frac{d^{2}\\log p(y|\\lambda(f)}{d\\lambda(f)^{2}}\\frac{d\\lambda(f)}{df}\\frac{d^{2}\\lambda(f)}{df^{2}} + \\frac{d\\log p(y|\\lambda(f)}{d\\lambda(f)}\\frac{d^{3}\\lambda(f)}{df^{3}} + + :param f: latent variables f + :type f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in student t distribution - not used + :returns: third derivative of log likelihood evaluated for this point + :rtype: float + """ + inv_link_f = self.gp_link.transf(f) + d3logpdf_dlink3 = self.d3logpdf_dlink3(inv_link_f, y, Y_metadata=Y_metadata) + dlink_df = self.gp_link.dtransf_df(f) + d2logpdf_dlink2 = self.d2logpdf_dlink2(inv_link_f, y, Y_metadata=Y_metadata) + d2link_df2 = self.gp_link.d2transf_df2(f) + dlogpdf_dlink = self.dlogpdf_dlink(inv_link_f, y, Y_metadata=Y_metadata) + d3link_df3 = self.gp_link.d3transf_df3(f) + return chain_3(d3logpdf_dlink3, dlink_df, d2logpdf_dlink2, d2link_df2, dlogpdf_dlink, d3link_df3) +
      +
      [docs] def dlogpdf_dtheta(self, f, y, Y_metadata=None): + """ + TODO: Doc strings + """ + if self.size > 0: + inv_link_f = self.gp_link.transf(f) + return self.dlogpdf_link_dtheta(inv_link_f, y, Y_metadata=Y_metadata) + else: + # There are no parameters so return an empty array for derivatives + return np.zeros([1, 0]) +
      +
      [docs] def dlogpdf_df_dtheta(self, f, y, Y_metadata=None): + """ + TODO: Doc strings + """ + if self.size > 0: + inv_link_f = self.gp_link.transf(f) + dlink_df = self.gp_link.dtransf_df(f) + dlogpdf_dlink_dtheta = self.dlogpdf_dlink_dtheta(inv_link_f, y, Y_metadata=Y_metadata) + return chain_1(dlogpdf_dlink_dtheta, dlink_df) + else: + # There are no parameters so return an empty array for derivatives + return np.zeros([f.shape[0], 0]) +
      +
      [docs] def d2logpdf_df2_dtheta(self, f, y, Y_metadata=None): + """ + TODO: Doc strings + """ + if self.size > 0: + inv_link_f = self.gp_link.transf(f) + dlink_df = self.gp_link.dtransf_df(f) + d2link_df2 = self.gp_link.d2transf_df2(f) + d2logpdf_dlink2_dtheta = self.d2logpdf_dlink2_dtheta(inv_link_f, y, Y_metadata=Y_metadata) + dlogpdf_dlink_dtheta = self.dlogpdf_dlink_dtheta(inv_link_f, y, Y_metadata=Y_metadata) + return chain_2(d2logpdf_dlink2_dtheta, dlink_df, dlogpdf_dlink_dtheta, d2link_df2) + else: + # There are no parameters so return an empty array for derivatives + return np.zeros([f.shape[0], 0]) +
      + def _laplace_gradients(self, f, y, Y_metadata=None): + dlogpdf_dtheta = self.dlogpdf_dtheta(f, y, Y_metadata=Y_metadata) + dlogpdf_df_dtheta = self.dlogpdf_df_dtheta(f, y, Y_metadata=Y_metadata) + d2logpdf_df2_dtheta = self.d2logpdf_df2_dtheta(f, y, Y_metadata=Y_metadata) + + #Parameters are stacked vertically. Must be listed in same order as 'get_param_names' + # ensure we have gradients for every parameter we want to optimize + assert len(dlogpdf_dtheta) == self.size #1 x num_param array + assert dlogpdf_df_dtheta.shape[1] == self.size #f x num_param matrix + assert d2logpdf_df2_dtheta.shape[1] == self.size #f x num_param matrix + + return dlogpdf_dtheta, dlogpdf_df_dtheta, d2logpdf_df2_dtheta + +
      [docs] def predictive_values(self, mu, var, full_cov=False, Y_metadata=None): + """ + Compute mean, variance of the predictive distibution. + + :param mu: mean of the latent variable, f, of posterior + :param var: variance of the latent variable, f, of posterior + :param full_cov: whether to use the full covariance or just the diagonal + :type full_cov: Boolean + """ + + pred_mean = self.predictive_mean(mu, var, Y_metadata) + pred_var = self.predictive_variance(mu, var, pred_mean, Y_metadata) + + return pred_mean, pred_var +
      +
      [docs] def predictive_quantiles(self, mu, var, quantiles, Y_metadata=None): + #compute the quantiles by sampling!!! + N_samp = 1000 + s = np.random.randn(mu.shape[0], N_samp)*np.sqrt(var) + mu + #ss_f = s.flatten() + #ss_y = self.samples(ss_f, Y_metadata) + ss_y = self.samples(s, Y_metadata) + #ss_y = ss_y.reshape(mu.shape[0], N_samp) + + return [np.percentile(ss_y ,q, axis=1)[:,None] for q in quantiles] +
      +
      [docs] def samples(self, gp, Y_metadata=None): + """ + Returns a set of samples of observations based on a given value of the latent variable. + + :param gp: latent variable + """ + raise NotImplementedError
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/link_functions.html b/doc/_build/html/_modules/GPy/likelihoods/link_functions.html new file mode 100644 index 00000000..9b2ab4f2 --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/link_functions.html @@ -0,0 +1,282 @@ + + + + + + + + GPy.likelihoods.link_functions — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.link_functions

      +# Copyright (c) 2012-2014 The GPy authors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from scipy import stats
      +import scipy as sp
      +from GPy.util.univariate_Gaussian import std_norm_pdf,std_norm_cdf,inv_std_norm_cdf
      +
      +_exp_lim_val = np.finfo(np.float64).max
      +_lim_val = np.log(_exp_lim_val)
      +
      +
      [docs]class GPTransformation(object): + """ + Link function class for doing non-Gaussian likelihoods approximation + + :param Y: observed output (Nx1 numpy.darray) + + .. note:: Y values allowed depend on the likelihood_function used + + """ + def __init__(self): + pass + +
      [docs] def transf(self,f): + """ + Gaussian process tranformation function, latent space -> output space + """ + raise NotImplementedError +
      +
      [docs] def dtransf_df(self,f): + """ + derivative of transf(f) w.r.t. f + """ + raise NotImplementedError +
      +
      [docs] def d2transf_df2(self,f): + """ + second derivative of transf(f) w.r.t. f + """ + raise NotImplementedError +
      +
      [docs] def d3transf_df3(self,f): + """ + third derivative of transf(f) w.r.t. f + """ + raise NotImplementedError +
      +
      [docs]class Identity(GPTransformation): + """ + .. math:: + + g(f) = f + + """ +
      [docs] def transf(self,f): + return f +
      +
      [docs] def dtransf_df(self,f): + return np.ones_like(f) +
      +
      [docs] def d2transf_df2(self,f): + return np.zeros_like(f) +
      +
      [docs] def d3transf_df3(self,f): + return np.zeros_like(f) + +
      +
      [docs]class Probit(GPTransformation): + """ + .. math:: + + g(f) = \\Phi^{-1} (mu) + + """ +
      [docs] def transf(self,f): + return std_norm_cdf(f) +
      +
      [docs] def dtransf_df(self,f): + return std_norm_pdf(f) +
      +
      [docs] def d2transf_df2(self,f): + #FIXME + return -f * std_norm_pdf(f) +
      +
      [docs] def d3transf_df3(self,f): + #FIXME + f2 = f**2 + return -(1/(np.sqrt(2*np.pi)))*np.exp(-0.5*(f2))*(1-f2) + +
      +
      [docs]class Cloglog(GPTransformation): + """ + Complementary log-log link + .. math:: + + p(f) = 1 - e^{-e^f} + + or + + f = \log (-\log(1-p)) + + """ +
      [docs] def transf(self,f): + return 1-np.exp(-np.exp(f)) +
      +
      [docs] def dtransf_df(self,f): + return np.exp(f-np.exp(f)) +
      +
      [docs] def d2transf_df2(self,f): + ef = np.exp(f) + return -np.exp(f-ef)*(ef-1.) +
      +
      [docs] def d3transf_df3(self,f): + ef = np.exp(f) + return np.exp(f-ef)*(1.-3*ef + ef**2) + +
      +
      [docs]class Log(GPTransformation): + """ + .. math:: + + g(f) = \\log(\\mu) + + """ +
      [docs] def transf(self,f): + return np.exp(np.clip(f, -_lim_val, _lim_val)) +
      +
      [docs] def dtransf_df(self,f): + return np.exp(np.clip(f, -_lim_val, _lim_val)) +
      +
      [docs] def d2transf_df2(self,f): + return np.exp(np.clip(f, -_lim_val, _lim_val)) +
      +
      [docs] def d3transf_df3(self,f): + return np.exp(np.clip(f, -_lim_val, _lim_val)) +
      +
      [docs]class Log_ex_1(GPTransformation): + """ + .. math:: + + g(f) = \\log(\\exp(\\mu) - 1) + + """ +
      [docs] def transf(self,f): + return np.log(1.+np.exp(f)) +
      +
      [docs] def dtransf_df(self,f): + return np.exp(f)/(1.+np.exp(f)) +
      +
      [docs] def d2transf_df2(self,f): + aux = np.exp(f)/(1.+np.exp(f)) + return aux*(1.-aux) +
      +
      [docs] def d3transf_df3(self,f): + aux = np.exp(f)/(1.+np.exp(f)) + daux_df = aux*(1.-aux) + return daux_df - (2.*aux*daux_df) +
      +
      [docs]class Reciprocal(GPTransformation): +
      [docs] def transf(self,f): + return 1./f +
      +
      [docs] def dtransf_df(self,f): + return -1./(f**2) +
      +
      [docs] def d2transf_df2(self,f): + return 2./(f**3) +
      +
      [docs] def d3transf_df3(self,f): + return -6./(f**4) +
      +
      [docs]class Heaviside(GPTransformation): + """ + + .. math:: + + g(f) = I_{x \\in A} + + """ +
      [docs] def transf(self,f): + #transformation goes here + return np.where(f>0, 1, 0) +
      +
      [docs] def dtransf_df(self,f): + raise NotImplementedError, "This function is not differentiable!" +
      +
      [docs] def d2transf_df2(self,f): + raise NotImplementedError, "This function is not differentiable!"
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/mixed_noise.html b/doc/_build/html/_modules/GPy/likelihoods/mixed_noise.html new file mode 100644 index 00000000..808080a7 --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/mixed_noise.html @@ -0,0 +1,176 @@ + + + + + + + + GPy.likelihoods.mixed_noise — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.mixed_noise

      +# Copyright (c) 2012-2014 The GPy authors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from scipy import stats, special
      +import link_functions
      +from likelihood import Likelihood
      +from gaussian import Gaussian
      +from ..core.parameterization import Param
      +from ..core.parameterization.transformations import Logexp
      +from ..core.parameterization import Parameterized
      +import itertools
      +
      +
      [docs]class MixedNoise(Likelihood): + def __init__(self, likelihoods_list, name='mixed_noise'): + #NOTE at the moment this likelihood only works for using a list of gaussians + super(Likelihood, self).__init__(name=name) + + self.link_parameters(*likelihoods_list) + self.likelihoods_list = likelihoods_list + self.log_concave = False + +
      [docs] def gaussian_variance(self, Y_metadata): + assert all([isinstance(l, Gaussian) for l in self.likelihoods_list]) + ind = Y_metadata['output_index'].flatten() + variance = np.zeros(ind.size) + for lik, j in zip(self.likelihoods_list, range(len(self.likelihoods_list))): + variance[ind==j] = lik.variance + return variance +
      +
      [docs] def betaY(self,Y,Y_metadata): + #TODO not here. + return Y/self.gaussian_variance(Y_metadata=Y_metadata)[:,None] +
      +
      [docs] def update_gradients(self, gradients): + self.gradient = gradients +
      +
      [docs] def exact_inference_gradients(self, dL_dKdiag, Y_metadata): + assert all([isinstance(l, Gaussian) for l in self.likelihoods_list]) + ind = Y_metadata['output_index'].flatten() + return np.array([dL_dKdiag[ind==i].sum() for i in range(len(self.likelihoods_list))]) +
      +
      [docs] def predictive_values(self, mu, var, full_cov=False, Y_metadata=None): + ind = Y_metadata['output_index'].flatten() + _variance = np.array([self.likelihoods_list[j].variance for j in ind ]) + if full_cov: + var += np.eye(var.shape[0])*_variance + else: + var += _variance + return mu, var +
      +
      [docs] def predictive_variance(self, mu, sigma, Y_metadata): + _variance = self.gaussian_variance(Y_metadata) + return _variance + sigma**2 +
      +
      [docs] def predictive_quantiles(self, mu, var, quantiles, Y_metadata): + ind = Y_metadata['output_index'].flatten() + outputs = np.unique(ind) + Q = np.zeros( (mu.size,len(quantiles)) ) + for j in outputs: + q = self.likelihoods_list[j].predictive_quantiles(mu[ind==j,:], + var[ind==j,:],quantiles,Y_metadata=None) + Q[ind==j,:] = np.hstack(q) + return [q[:,None] for q in Q.T] +
      +
      [docs] def samples(self, gp, Y_metadata): + """ + Returns a set of samples of observations based on a given value of the latent variable. + + :param gp: latent variable + """ + N1, N2 = gp.shape + Ysim = np.zeros((N1,N2)) + ind = Y_metadata['output_index'].flatten() + for j in np.unique(ind): + flt = ind==j + gp_filtered = gp[flt,:] + n1 = gp_filtered.shape[0] + lik = self.likelihoods_list[j] + _ysim = np.array([np.random.normal(lik.gp_link.transf(gpj), scale=np.sqrt(lik.variance), size=1) for gpj in gp_filtered.flatten()]) + Ysim[flt,:] = _ysim.reshape(n1,N2) + return Ysim
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/poisson.html b/doc/_build/html/_modules/GPy/likelihoods/poisson.html new file mode 100644 index 00000000..66907840 --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/poisson.html @@ -0,0 +1,251 @@ + + + + + + + + GPy.likelihoods.poisson — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.poisson

      +from __future__ import division
      +# Copyright (c) 2012-2014 Ricardo Andrade, Alan Saul
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from scipy import stats,special
      +import scipy as sp
      +import link_functions
      +from likelihood import Likelihood
      +
      +
      [docs]class Poisson(Likelihood): + """ + Poisson likelihood + + .. math:: + p(y_{i}|\\lambda(f_{i})) = \\frac{\\lambda(f_{i})^{y_{i}}}{y_{i}!}e^{-\\lambda(f_{i})} + + .. Note:: + Y is expected to take values in {0,1,2,...} + """ + def __init__(self, gp_link=None): + if gp_link is None: + gp_link = link_functions.Log() + + super(Poisson, self).__init__(gp_link, name='Poisson') + + def _conditional_mean(self, f): + """ + the expected value of y given a value of f + """ + return self.gp_link.transf(gp) + + + + +
      [docs] def d2logpdf_dlink2(self, link_f, y, Y_metadata=None): + """ + Hessian at y, given link(f), w.r.t link(f) + i.e. second derivative logpdf at y given link(f_i) and link(f_j) w.r.t link(f_i) and link(f_j) + The hessian will be 0 unless i == j + + .. math:: + \\frac{d^{2} \\ln p(y_{i}|\lambda(f_{i}))}{d^{2}\\lambda(f)} = \\frac{-y_{i}}{\\lambda(f_{i})^{2}} + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in poisson distribution + :returns: Diagonal of hessian matrix (second derivative of likelihood evaluated at points f) + :rtype: Nx1 array + + .. Note:: + Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases + (the distribution for y_i depends only on link(f_i) not on link(f_(j!=i)) + """ + assert np.atleast_1d(link_f).shape == np.atleast_1d(y).shape + hess = -y/(link_f**2) + return hess + #d2_df = self.gp_link.d2transf_df2(gp) + #transf = self.gp_link.transf(gp) + #return obs * ((self.gp_link.dtransf_df(gp)/transf)**2 - d2_df/transf) + d2_df +
      +
      [docs] def d3logpdf_dlink3(self, link_f, y, Y_metadata=None): + """ + Third order derivative log-likelihood function at y given link(f) w.r.t link(f) + + .. math:: + \\frac{d^{3} \\ln p(y_{i}|\lambda(f_{i}))}{d^{3}\\lambda(f)} = \\frac{2y_{i}}{\\lambda(f_{i})^{3}} + + :param link_f: latent variables link(f) + :type link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in poisson distribution + :returns: third derivative of likelihood evaluated at points f + :rtype: Nx1 array + """ + assert np.atleast_1d(link_f).shape == np.atleast_1d(y).shape + d3lik_dlink3 = 2*y/(link_f)**3 + return d3lik_dlink3 +
      +
      [docs] def conditional_mean(self,gp): + """ + The mean of the random variable conditioned on one value of the GP + """ + return self.gp_link.transf(gp) +
      +
      [docs] def conditional_variance(self,gp): + """ + The variance of the random variable conditioned on one value of the GP + """ + return self.gp_link.transf(gp) +
      +
      [docs] def samples(self, gp, Y_metadata=None): + """ + Returns a set of samples of observations based on a given value of the latent variable. + + :param gp: latent variable + """ + orig_shape = gp.shape + gp = gp.flatten() + Ysim = np.random.poisson(self.gp_link.transf(gp)) + return Ysim.reshape(orig_shape)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/likelihoods/student_t.html b/doc/_build/html/_modules/GPy/likelihoods/student_t.html new file mode 100644 index 00000000..d93e3fa8 --- /dev/null +++ b/doc/_build/html/_modules/GPy/likelihoods/student_t.html @@ -0,0 +1,373 @@ + + + + + + + + GPy.likelihoods.student_t — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.likelihoods.student_t

      +# Copyright (c) 2012-2014 Ricardo Andrade, Alan Saul
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from scipy import stats, special
      +import scipy as sp
      +import link_functions
      +from scipy import stats, integrate
      +from scipy.special import gammaln, gamma
      +from likelihood import Likelihood
      +from ..core.parameterization import Param
      +from ..core.parameterization.transformations import Logexp
      +
      +
      [docs]class StudentT(Likelihood): + """ + Student T likelihood + + For nomanclature see Bayesian Data Analysis 2003 p576 + + .. math:: + p(y_{i}|\\lambda(f_{i})) = \\frac{\\Gamma\\left(\\frac{v+1}{2}\\right)}{\\Gamma\\left(\\frac{v}{2}\\right)\\sqrt{v\\pi\\sigma^{2}}}\\left(1 + \\frac{1}{v}\\left(\\frac{(y_{i} - f_{i})^{2}}{\\sigma^{2}}\\right)\\right)^{\\frac{-v+1}{2}} + + """ + def __init__(self,gp_link=None, deg_free=5, sigma2=2): + if gp_link is None: + gp_link = link_functions.Identity() + + super(StudentT, self).__init__(gp_link, name='Student_T') + # sigma2 is not a noise parameter, it is a squared scale. + self.sigma2 = Param('t_scale2', float(sigma2), Logexp()) + self.v = Param('deg_free', float(deg_free)) + self.link_parameter(self.sigma2) + self.link_parameter(self.v) + self.v.constrain_fixed() + + self.log_concave = False + +
      [docs] def parameters_changed(self): + self.variance = (self.v / float(self.v - 2)) * self.sigma2 +
      +
      [docs] def update_gradients(self, grads): + """ + Pull out the gradients, be careful as the order must match the order + in which the parameters are added + """ + self.sigma2.gradient = grads[0] + self.v.gradient = grads[1] +
      + + + +
      [docs] def d2logpdf_dlink2(self, inv_link_f, y, Y_metadata=None): + """ + Hessian at y, given link(f), w.r.t link(f) + i.e. second derivative logpdf at y given link(f_i) and link(f_j) w.r.t link(f_i) and link(f_j) + The hessian will be 0 unless i == j + + .. math:: + \\frac{d^{2} \\ln p(y_{i}|\lambda(f_{i}))}{d^{2}\\lambda(f)} = \\frac{(v+1)((y_{i}-\lambda(f_{i}))^{2} - \\sigma^{2}v)}{((y_{i}-\lambda(f_{i}))^{2} + \\sigma^{2}v)^{2}} + + :param inv_link_f: latent variables inv_link(f) + :type inv_link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in student t distribution + :returns: Diagonal of hessian matrix (second derivative of likelihood evaluated at points f) + :rtype: Nx1 array + + .. Note:: + Will return diagonal of hessian, since every where else it is 0, as the likelihood factorizes over cases + (the distribution for y_i depends only on link(f_i) not on link(f_(j!=i)) + """ + assert np.atleast_1d(inv_link_f).shape == np.atleast_1d(y).shape + e = y - inv_link_f + hess = ((self.v + 1)*(e**2 - self.v*self.sigma2)) / ((self.sigma2*self.v + e**2)**2) + return hess +
      +
      [docs] def d3logpdf_dlink3(self, inv_link_f, y, Y_metadata=None): + """ + Third order derivative log-likelihood function at y given link(f) w.r.t link(f) + + .. math:: + \\frac{d^{3} \\ln p(y_{i}|\lambda(f_{i}))}{d^{3}\\lambda(f)} = \\frac{-2(v+1)((y_{i} - \lambda(f_{i}))^3 - 3(y_{i} - \lambda(f_{i})) \\sigma^{2} v))}{((y_{i} - \lambda(f_{i})) + \\sigma^{2} v)^3} + + :param inv_link_f: latent variables link(f) + :type inv_link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in student t distribution + :returns: third derivative of likelihood evaluated at points f + :rtype: Nx1 array + """ + assert np.atleast_1d(inv_link_f).shape == np.atleast_1d(y).shape + e = y - inv_link_f + d3lik_dlink3 = ( -(2*(self.v + 1)*(-e)*(e**2 - 3*self.v*self.sigma2)) / + ((e**2 + self.sigma2*self.v)**3) + ) + return d3lik_dlink3 +
      + + +
      [docs] def d2logpdf_dlink2_dvar(self, inv_link_f, y, Y_metadata=None): + """ + Gradient of the hessian (d2logpdf_dlink2) w.r.t variance parameter (t_noise) + + .. math:: + \\frac{d}{d\\sigma^{2}}(\\frac{d^{2} \\ln p(y_{i}|\lambda(f_{i}))}{d^{2}f}) = \\frac{v(v+1)(\\sigma^{2}v - 3(y_{i} - \lambda(f_{i}))^{2})}{(\\sigma^{2}v + (y_{i} - \lambda(f_{i}))^{2})^{3}} + + :param inv_link_f: latent variables link(f) + :type inv_link_f: Nx1 array + :param y: data + :type y: Nx1 array + :param Y_metadata: Y_metadata which is not used in student t distribution + :returns: derivative of hessian evaluated at points f and f_j w.r.t variance parameter + :rtype: Nx1 array + """ + assert np.atleast_1d(inv_link_f).shape == np.atleast_1d(y).shape + e = y - inv_link_f + d2logpdf_dlink2_dvar = ( (self.v*(self.v+1)*(self.sigma2*self.v - 3*(e**2))) + / ((self.sigma2*self.v + (e**2))**3) + ) + return d2logpdf_dlink2_dvar +
      + + +
      [docs] def d2logpdf_dlink2_dtheta(self, f, y, Y_metadata=None): + d2logpdf_dlink2_dvar = self.d2logpdf_dlink2_dvar(f, y, Y_metadata=Y_metadata) + d2logpdf_dlink2_dv = np.zeros_like(d2logpdf_dlink2_dvar) #FIXME: Not done yet + return np.hstack((d2logpdf_dlink2_dvar, d2logpdf_dlink2_dv)) +
      +
      [docs] def predictive_mean(self, mu, sigma, Y_metadata=None): + # The comment here confuses mean and median. + return self.gp_link.transf(mu) # only true if link is monotonic, which it is. +
      +
      [docs] def predictive_variance(self, mu,variance, predictive_mean=None, Y_metadata=None): + if self.deg_free<=2.: + return np.empty(mu.shape)*np.nan # does not exist for degrees of freedom <= 2. + else: + return super(StudentT, self).predictive_variance(mu, variance, predictive_mean, Y_metadata) +
      +
      [docs] def conditional_mean(self, gp): + return self.gp_link.transf(gp) +
      +
      [docs] def conditional_variance(self, gp): + return self.deg_free/(self.deg_free - 2.) +
      +
      [docs] def samples(self, gp, Y_metadata=None): + """ + Returns a set of samples of observations based on a given value of the latent variable. + + :param gp: latent variable + """ + orig_shape = gp.shape + gp = gp.flatten() + #FIXME: Very slow as we are computing a new random variable per input! + #Can't get it to sample all at the same time + #student_t_samples = np.array([stats.t.rvs(self.v, self.gp_link.transf(gpj),scale=np.sqrt(self.sigma2), size=1) for gpj in gp]) + dfs = np.ones_like(gp)*self.v + scales = np.ones_like(gp)*np.sqrt(self.sigma2) + student_t_samples = stats.t.rvs(dfs, loc=self.gp_link.transf(gp), + scale=scales) + return student_t_samples.reshape(orig_shape)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/mappings/additive.html b/doc/_build/html/_modules/GPy/mappings/additive.html new file mode 100644 index 00000000..f0f2455e --- /dev/null +++ b/doc/_build/html/_modules/GPy/mappings/additive.html @@ -0,0 +1,155 @@ + + + + + + + + GPy.mappings.additive — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.mappings.additive

      +# Copyright (c) 2013, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core.mapping import Mapping
      +import GPy
      +
      +
      [docs]class Additive(Mapping): + """ + Mapping based on adding two existing mappings together. + + .. math:: + + f(\mathbf{x}*) = f_1(\mathbf{x}*) + f_2(\mathbf(x)*) + + :param mapping1: first mapping to add together. + :type mapping1: GPy.mappings.Mapping + :param mapping2: second mapping to add together. + :type mapping2: GPy.mappings.Mapping + :param tensor: whether or not to use the tensor product of input spaces + :type tensor: bool + + """ + + def __init__(self, mapping1, mapping2, tensor=False): + if tensor: + input_dim = mapping1.input_dim + mapping2.input_dim + else: + input_dim = mapping1.input_dim + assert(mapping1.input_dim==mapping2.input_dim) + assert(mapping1.output_dim==mapping2.output_dim) + output_dim = mapping1.output_dim + Mapping.__init__(self, input_dim=input_dim, output_dim=output_dim) + self.mapping1 = mapping1 + self.mapping2 = mapping2 + self.num_params = self.mapping1.num_params + self.mapping2.num_params + self.name = self.mapping1.name + '+' + self.mapping2.name + def _get_param_names(self): + return self.mapping1._get_param_names + self.mapping2._get_param_names + + def _get_params(self): + return np.hstack((self.mapping1._get_params(), self.mapping2._get_params())) + + def _set_params(self, x): + self.mapping1._set_params(x[:self.mapping1.num_params]) + self.mapping2._set_params(x[self.mapping1.num_params:]) + +
      [docs] def randomize(self): + self.mapping1._randomize() + self.mapping2._randomize() +
      +
      [docs] def f(self, X): + return self.mapping1.f(X) + self.mapping2.f(X) +
      +
      [docs] def df_dtheta(self, dL_df, X): + self._df_dA = (dL_df[:, :, None]*self.kern.K(X, self.X)[:, None, :]).sum(0).T + self._df_dbias = (dL_df.sum(0)) + return np.hstack((self._df_dA.flatten(), self._df_dbias)) +
      +
      [docs] def df_dX(self, dL_df, X): + return self.kern.dK_dX((dL_df[:, None, :]*self.A[None, :, :]).sum(2), X, self.X)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/mappings/kernel.html b/doc/_build/html/_modules/GPy/mappings/kernel.html new file mode 100644 index 00000000..b15962f6 --- /dev/null +++ b/doc/_build/html/_modules/GPy/mappings/kernel.html @@ -0,0 +1,154 @@ + + + + + + + + GPy.mappings.kernel — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.mappings.kernel

      +# Copyright (c) 2013, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core.mapping import Mapping
      +import GPy
      +
      +
      [docs]class Kernel(Mapping): + """ + Mapping based on a kernel/covariance function. + + .. math:: + + f(\mathbf{x}*) = \mathbf{A}\mathbf{k}(\mathbf{X}, \mathbf{x}^*) + \mathbf{b} + + :param X: input observations containing :math:`\mathbf{X}` + :type X: ndarray + :param output_dim: dimension of output. + :type output_dim: int + :param kernel: a GPy kernel, defaults to GPy.kern.RBF + :type kernel: GPy.kern.kern + + """ + + def __init__(self, X, output_dim=1, kernel=None): + Mapping.__init__(self, input_dim=X.shape[1], output_dim=output_dim) + if kernel is None: + kernel = GPy.kern.RBF(self.input_dim) + self.kern = kernel + self.X = X + self.num_data = X.shape[0] + self.num_params = self.output_dim*(self.num_data + 1) + self.A = np.array((self.num_data, self.output_dim)) + self.bias = np.array(self.output_dim) + self.randomize() + self.name = 'kernel' + def _get_param_names(self): + return sum([['A_%i_%i' % (n, d) for d in range(self.output_dim)] for n in range(self.num_data)], []) + ['bias_%i' % d for d in range(self.output_dim)] + + def _get_params(self): + return np.hstack((self.A.flatten(), self.bias)) + + def _set_params(self, x): + self.A = x[:self.num_data * self.output_dim].reshape(self.num_data, self.output_dim).copy() + self.bias = x[self.num_data*self.output_dim:].copy() + +
      [docs] def randomize(self): + self.A = np.random.randn(self.num_data, self.output_dim)/np.sqrt(self.num_data+1) + self.bias = np.random.randn(self.output_dim)/np.sqrt(self.num_data+1) +
      +
      [docs] def f(self, X): + return np.dot(self.kern.K(X, self.X),self.A) + self.bias +
      +
      [docs] def df_dtheta(self, dL_df, X): + self._df_dA = (dL_df[:, :, None]*self.kern.K(X, self.X)[:, None, :]).sum(0).T + self._df_dbias = (dL_df.sum(0)) + return np.hstack((self._df_dA.flatten(), self._df_dbias)) +
      +
      [docs] def df_dX(self, dL_df, X): + return self.kern.gradients_X((dL_df[:, None, :]*self.A[None, :, :]).sum(2), X, self.X)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/mappings/linear.html b/doc/_build/html/_modules/GPy/mappings/linear.html new file mode 100644 index 00000000..e2af2bde --- /dev/null +++ b/doc/_build/html/_modules/GPy/mappings/linear.html @@ -0,0 +1,137 @@ + + + + + + + + GPy.mappings.linear — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.mappings.linear

      +# Copyright (c) 2013, 2014 GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core.mapping import Bijective_mapping
      +from ..core.parameterization import Param
      +
      +
      [docs]class Linear(Bijective_mapping): + """ + Mapping based on a linear model. + + .. math:: + + f(\mathbf{x}*) = \mathbf{W}\mathbf{x}^* + \mathbf{b} + + :param X: input observations + :type X: ndarray + :param output_dim: dimension of output. + :type output_dim: int + + """ + + def __init__(self, input_dim=1, output_dim=1, name='linear'): + Bijective_mapping.__init__(self, input_dim=input_dim, output_dim=output_dim, name=name) + self.W = Param('W',np.array((self.input_dim, self.output_dim))) + self.bias = Param('bias',np.array(self.output_dim)) + self.link_parameters(self.W, self.bias) + +
      [docs] def f(self, X): + return np.dot(X,self.W) + self.bias +
      +
      [docs] def g(self, f): + V = np.linalg.solve(np.dot(self.W.T, self.W), W.T) + return np.dot(f-self.bias, V) +
      +
      [docs] def df_dtheta(self, dL_df, X): + df_dW = (dL_df[:, :, None]*X[:, None, :]).sum(0).T + df_dbias = (dL_df.sum(0)) + return np.hstack((df_dW.flatten(), df_dbias)) +
      +
      [docs] def dL_dX(self, partial, X): + """The gradient of L with respect to the inputs to the mapping, where L is a function that is dependent on the output of the mapping, f.""" + return (partial[:, None, :]*self.W[None, :, :]).sum(2)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/mappings/mlp.html b/doc/_build/html/_modules/GPy/mappings/mlp.html new file mode 100644 index 00000000..6bd51a3f --- /dev/null +++ b/doc/_build/html/_modules/GPy/mappings/mlp.html @@ -0,0 +1,224 @@ + + + + + + + + GPy.mappings.mlp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.mappings.mlp

      +# Copyright (c) 2013, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core.mapping import Mapping
      +
      +
      [docs]class MLP(Mapping): + """ + Mapping based on a multi-layer perceptron neural network model. + + .. math:: + + f(\\mathbf{x}*) = \\mathbf{W}^0\\boldsymbol{\\phi}(\\mathbf{W}^1\\mathbf{x}+\\mathbf{b}^1)^* + \\mathbf{b}^0 + + where + + .. math:: + + \\phi(\\cdot) = \\text{tanh}(\\cdot) + + :param X: input observations + :type X: ndarray + :param output_dim: dimension of output. + :type output_dim: int + :param hidden_dim: dimension of hidden layer. If it is an int, there is one hidden layer of the given dimension. If it is a list of ints there are as manny hidden layers as the length of the list, each with the given number of hidden nodes in it. + :type hidden_dim: int or list of ints. + + """ + + def __init__(self, input_dim=1, output_dim=1, hidden_dim=3): + Mapping.__init__(self, input_dim=input_dim, output_dim=output_dim) + self.name = 'mlp' + if isinstance(hidden_dim, int): + hidden_dim = [hidden_dim] + self.hidden_dim = hidden_dim + self.activation = [None]*len(self.hidden_dim) + self.W = [] + self._dL_dW = [] + self.bias = [] + self._dL_dbias = [] + self.W.append(np.zeros((self.input_dim, self.hidden_dim[0]))) + self._dL_dW.append(np.zeros((self.input_dim, self.hidden_dim[0]))) + self.bias.append(np.zeros(self.hidden_dim[0])) + self._dL_dbias.append(np.zeros(self.hidden_dim[0])) + self.num_params = self.hidden_dim[0]*(self.input_dim+1) + for h1, h0 in zip(hidden_dim[1:], hidden_dim[0:-1]): + self.W.append(np.zeros((h0, h1))) + self._dL_dW.append(np.zeros((h0, h1))) + self.bias.append(np.zeros(h1)) + self._dL_dbias.append(np.zeros(h1)) + self.num_params += h1*(h0+1) + self.W.append(np.zeros((self.hidden_dim[-1], self.output_dim))) + self._dL_dW.append(np.zeros((self.hidden_dim[-1], self.output_dim))) + self.bias.append(np.zeros(self.output_dim)) + self._dL_dbias.append(np.zeros(self.output_dim)) + self.num_params += self.output_dim*(self.hidden_dim[-1]+1) + self.randomize() + + def _get_param_names(self): + return sum([['W%i_%i_%i' % (i, n, d) for n in range(self.W[i].shape[0]) for d in range(self.W[i].shape[1])] + ['bias%i_%i' % (i, d) for d in range(self.W[i].shape[1])] for i in range(len(self.W))], []) + + def _get_params(self): + param = np.array([]) + for W, bias in zip(self.W, self.bias): + param = np.hstack((param, W.flatten(), bias)) + return param + + def _set_params(self, x): + start = 0 + for W, bias in zip(self.W, self.bias): + end = W.shape[0]*W.shape[1]+start + W[:] = x[start:end].reshape(W.shape[0], W.shape[1]).copy() + start = end + end = W.shape[1]+end + bias[:] = x[start:end].copy() + start = end + +
      [docs] def randomize(self): + for W, bias in zip(self.W, self.bias): + W[:] = np.random.randn(W.shape[0], W.shape[1])/np.sqrt(W.shape[0]+1) + bias[:] = np.random.randn(W.shape[1])/np.sqrt(W.shape[0]+1) +
      +
      [docs] def f(self, X): + self._f_computations(X) + return np.dot(np.tanh(self.activation[-1]), self.W[-1]) + self.bias[-1] +
      + def _f_computations(self, X): + W = self.W[0] + bias = self.bias[0] + self.activation[0] = np.dot(X,W) + bias + for W, bias, index in zip(self.W[1:-1], self.bias[1:-1], range(1, len(self.activation))): + self.activation[index] = np.dot(np.tanh(self.activation[index-1]), W)+bias + +
      [docs] def df_dtheta(self, dL_df, X): + self._df_computations(dL_df, X) + g = np.array([]) + for gW, gbias in zip(self._dL_dW, self._dL_dbias): + g = np.hstack((g, gW.flatten(), gbias)) + return g +
      + def _df_computations(self, dL_df, X): + self._f_computations(X) + a0 = self.activation[-1] + W = self.W[-1] + self._dL_dW[-1] = (dL_df[:, :, None]*np.tanh(a0[:, None, :])).sum(0).T + dL_dta=(dL_df[:, None, :]*W[None, :, :]).sum(2) + self._dL_dbias[-1] = (dL_df.sum(0)) + for dL_dW, dL_dbias, W, bias, a0, a1 in zip(self._dL_dW[-2:0:-1], + self._dL_dbias[-2:0:-1], + self.W[-2:0:-1], + self.bias[-2:0:-1], + self.activation[-2::-1], + self.activation[-1:0:-1]): + ta = np.tanh(a1) + dL_da = dL_dta*(1-ta*ta) + dL_dW[:] = (dL_da[:, :, None]*np.tanh(a0[:, None, :])).sum(0).T + dL_dbias[:] = (dL_da.sum(0)) + dL_dta = (dL_da[:, None, :]*W[None, :, :]).sum(2) + ta = np.tanh(self.activation[0]) + dL_da = dL_dta*(1-ta*ta) + W = self.W[0] + self._dL_dW[0] = (dL_da[:, :, None]*X[:, None, :]).sum(0).T + self._dL_dbias[0] = (dL_da.sum(0)) + self._dL_dX = (dL_da[:, None, :]*W[None, :, :]).sum(2) + + +
      [docs] def df_dX(self, dL_df, X): + self._df_computations(dL_df, X) + return self._dL_dX +
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/bayesian_gplvm.html b/doc/_build/html/_modules/GPy/models/bayesian_gplvm.html new file mode 100644 index 00000000..5d67129c --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/bayesian_gplvm.html @@ -0,0 +1,328 @@ + + + + + + + + GPy.models.bayesian_gplvm — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.bayesian_gplvm

      +# Copyright (c) 2012 - 2014 the GPy Austhors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from .. import kern
      +from ..core.sparse_gp_mpi import SparseGP_MPI
      +from ..likelihoods import Gaussian
      +from ..core.parameterization.variational import NormalPosterior, NormalPrior
      +from ..inference.latent_function_inference.var_dtc_parallel import VarDTC_minibatch
      +import logging
      +
      +
      [docs]class BayesianGPLVM(SparseGP_MPI): + """ + Bayesian Gaussian Process Latent Variable Model + + :param Y: observed data (np.ndarray) or GPy.likelihood + :type Y: np.ndarray| GPy.likelihood instance + :param input_dim: latent dimensionality + :type input_dim: int + :param init: initialisation method for the latent space + :type init: 'PCA'|'random' + + """ + def __init__(self, Y, input_dim, X=None, X_variance=None, init='PCA', num_inducing=10, + Z=None, kernel=None, inference_method=None, likelihood=None, + name='bayesian gplvm', mpi_comm=None, normalizer=None, + missing_data=False, stochastic=False, batchsize=1): + + self.logger = logging.getLogger(self.__class__.__name__) + if X is None: + from ..util.initialization import initialize_latent + self.logger.info("initializing latent space X with method {}".format(init)) + X, fracs = initialize_latent(init, input_dim, Y) + else: + fracs = np.ones(input_dim) + + self.init = init + + if X_variance is None: + self.logger.info("initializing latent space variance ~ uniform(0,.1)") + X_variance = np.random.uniform(0,.1,X.shape) + + if Z is None: + self.logger.info("initializing inducing inputs") + Z = np.random.permutation(X.copy())[:num_inducing] + assert Z.shape[1] == X.shape[1] + + if kernel is None: + self.logger.info("initializing kernel RBF") + kernel = kern.RBF(input_dim, lengthscale=1./fracs, ARD=True) #+ kern.Bias(input_dim) + kern.White(input_dim) + + if likelihood is None: + likelihood = Gaussian() + + self.variational_prior = NormalPrior() + X = NormalPosterior(X, X_variance) + + if inference_method is None: + if mpi_comm is not None: + inference_method = VarDTC_minibatch(mpi_comm=mpi_comm) + else: + from ..inference.latent_function_inference.var_dtc import VarDTC + self.logger.debug("creating inference_method var_dtc") + inference_method = VarDTC(limit=1 if not missing_data else Y.shape[1]) + if isinstance(inference_method,VarDTC_minibatch): + inference_method.mpi_comm = mpi_comm + + super(BayesianGPLVM,self).__init__(X, Y, Z, kernel, likelihood=likelihood, + name=name, inference_method=inference_method, + normalizer=normalizer, mpi_comm=mpi_comm, + variational_prior=self.variational_prior, + ) + self.link_parameter(self.X, index=0) + +
      [docs] def set_X_gradients(self, X, X_grad): + """Set the gradients of the posterior distribution of X in its specific form.""" + X.mean.gradient, X.variance.gradient = X_grad +
      +
      [docs] def get_X_gradients(self, X): + """Get the gradients of the posterior distribution of X in its specific form.""" + return X.mean.gradient, X.variance.gradient +
      +
      [docs] def parameters_changed(self): + super(BayesianGPLVM,self).parameters_changed() + if isinstance(self.inference_method, VarDTC_minibatch): + return + + kl_fctr = 1. + self._log_marginal_likelihood -= kl_fctr*self.variational_prior.KL_divergence(self.X) + + self.X.mean.gradient, self.X.variance.gradient = self.kern.gradients_qX_expectations( + variational_posterior=self.X, + Z=self.Z, + dL_dpsi0=self.grad_dict['dL_dpsi0'], + dL_dpsi1=self.grad_dict['dL_dpsi1'], + dL_dpsi2=self.grad_dict['dL_dpsi2']) + + self.variational_prior.update_gradients_KL(self.X) + + + #super(BayesianGPLVM, self).parameters_changed() + #self._log_marginal_likelihood -= self.variational_prior.KL_divergence(self.X) + + #self.X.mean.gradient, self.X.variance.gradient = self.kern.gradients_qX_expectations(variational_posterior=self.X, Z=self.Z, dL_dpsi0=self.grad_dict['dL_dpsi0'], dL_dpsi1=self.grad_dict['dL_dpsi1'], dL_dpsi2=self.grad_dict['dL_dpsi2']) + + # This is testing code ------------------------- +# i = np.random.randint(self.X.shape[0]) +# X_ = self.X.mean +# which = np.sqrt(((X_ - X_[i:i+1])**2).sum(1)).argsort()>(max(0, self.X.shape[0]-51)) +# _, _, grad_dict = self.inference_method.inference(self.kern, self.X[which], self.Z, self.likelihood, self.Y[which], self.Y_metadata) +# grad = self.kern.gradients_qX_expectations(variational_posterior=self.X[which], Z=self.Z, dL_dpsi0=grad_dict['dL_dpsi0'], dL_dpsi1=grad_dict['dL_dpsi1'], dL_dpsi2=grad_dict['dL_dpsi2']) +# +# self.X.mean.gradient[:] = 0 +# self.X.variance.gradient[:] = 0 +# self.X.mean.gradient[which] = grad[0] +# self.X.variance.gradient[which] = grad[1] + + # update for the KL divergence +# self.variational_prior.update_gradients_KL(self.X, which) + # ----------------------------------------------- + + # update for the KL divergence + #self.variational_prior.update_gradients_KL(self.X) +
      +
      [docs] def plot_latent(self, labels=None, which_indices=None, + resolution=50, ax=None, marker='o', s=40, + fignum=None, plot_inducing=True, legend=True, + plot_limits=None, + aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={}): + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import dim_reduction_plots + + return dim_reduction_plots.plot_latent(self, labels, which_indices, + resolution, ax, marker, s, + fignum, plot_inducing, legend, + plot_limits, aspect, updates, predict_kwargs, imshow_kwargs) +
      +
      [docs] def do_test_latents(self, Y): + """ + Compute the latent representation for a set of new points Y + + Notes: + This will only work with a univariate Gaussian likelihood (for now) + """ + N_test = Y.shape[0] + input_dim = self.Z.shape[1] + + means = np.zeros((N_test, input_dim)) + covars = np.zeros((N_test, input_dim)) + + dpsi0 = -0.5 * self.input_dim / self.likelihood.variance + dpsi2 = self.grad_dict['dL_dpsi2'][0][None, :, :] # TODO: this may change if we ignore het. likelihoods + V = Y/self.likelihood.variance + + #compute CPsi1V + #if self.Cpsi1V is None: + # psi1V = np.dot(self.psi1.T, self.likelihood.V) + # tmp, _ = linalg.dtrtrs(self._Lm, np.asfortranarray(psi1V), lower=1, trans=0) + # tmp, _ = linalg.dpotrs(self.LB, tmp, lower=1) + # self.Cpsi1V, _ = linalg.dtrtrs(self._Lm, tmp, lower=1, trans=1) + + dpsi1 = np.dot(self.posterior.woodbury_vector, V.T) + + #start = np.zeros(self.input_dim * 2) + + + from scipy.optimize import minimize + + for n, dpsi1_n in enumerate(dpsi1.T[:, :, None]): + args = (input_dim, self.kern.copy(), self.Z, dpsi0, dpsi1_n.T, dpsi2) + res = minimize(latent_cost_and_grad, jac=True, x0=np.hstack((means[n], covars[n])), args=args, method='BFGS') + xopt = res.x + mu, log_S = xopt.reshape(2, 1, -1) + means[n] = mu[0].copy() + covars[n] = np.exp(log_S[0]).copy() + + X = NormalPosterior(means, covars) + + return X +
      +
      [docs] def dmu_dX(self, Xnew): + """ + Calculate the gradient of the prediction at Xnew w.r.t Xnew. + """ + dmu_dX = np.zeros_like(Xnew) + for i in range(self.Z.shape[0]): + dmu_dX += self.kern.gradients_X(self.grad_dict['dL_dpsi1'][i:i + 1, :], Xnew, self.Z[i:i + 1, :]) + return dmu_dX +
      +
      [docs] def dmu_dXnew(self, Xnew): + """ + Individual gradient of prediction at Xnew w.r.t. each sample in Xnew + """ + gradients_X = np.zeros((Xnew.shape[0], self.num_inducing)) + ones = np.ones((1, 1)) + for i in range(self.Z.shape[0]): + gradients_X[:, i] = self.kern.gradients_X(ones, Xnew, self.Z[i:i + 1, :]).sum(-1) + return np.dot(gradients_X, self.grad_dict['dL_dpsi1']) +
      +
      [docs] def plot_steepest_gradient_map(self, *args, ** kwargs): + """ + See GPy.plotting.matplot_dep.dim_reduction_plots.plot_steepest_gradient_map + """ + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import dim_reduction_plots + + return dim_reduction_plots.plot_steepest_gradient_map(self,*args,**kwargs) + +
      +
      [docs]def latent_cost_and_grad(mu_S, input_dim, kern, Z, dL_dpsi0, dL_dpsi1, dL_dpsi2): + """ + objective function for fitting the latent variables for test points + (negative log-likelihood: should be minimised!) + """ + mu = mu_S[:input_dim][None] + log_S = mu_S[input_dim:][None] + S = np.exp(log_S) + + X = NormalPosterior(mu, S) + + psi0 = kern.psi0(Z, X) + psi1 = kern.psi1(Z, X) + psi2 = kern.psi2(Z, X) + + lik = dL_dpsi0 * psi0.sum() + np.einsum('ij,kj->...', dL_dpsi1, psi1) + np.einsum('ijk,lkj->...', dL_dpsi2, psi2) - 0.5 * np.sum(np.square(mu) + S) + 0.5 * np.sum(log_S) + + dLdmu, dLdS = kern.gradients_qX_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, X) + dmu = dLdmu - mu + # dS = S0 + S1 + S2 -0.5 + .5/S + dlnS = S * (dLdS - 0.5) + .5 + + return -lik, -np.hstack((dmu.flatten(), dlnS.flatten()))
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/bayesian_gplvm_minibatch.html b/doc/_build/html/_modules/GPy/models/bayesian_gplvm_minibatch.html new file mode 100644 index 00000000..2a681622 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/bayesian_gplvm_minibatch.html @@ -0,0 +1,363 @@ + + + + + + + + GPy.models.bayesian_gplvm_minibatch — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.bayesian_gplvm_minibatch

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from .. import kern
      +from ..likelihoods import Gaussian
      +from ..core.parameterization.variational import NormalPosterior, NormalPrior
      +from ..inference.latent_function_inference.var_dtc_parallel import VarDTC_minibatch
      +import logging
      +from GPy.models.sparse_gp_minibatch import SparseGPMiniBatch
      +
      +
      [docs]class BayesianGPLVMMiniBatch(SparseGPMiniBatch): + """ + Bayesian Gaussian Process Latent Variable Model + + :param Y: observed data (np.ndarray) or GPy.likelihood + :type Y: np.ndarray| GPy.likelihood instance + :param input_dim: latent dimensionality + :type input_dim: int + :param init: initialisation method for the latent space + :type init: 'PCA'|'random' + + """ + def __init__(self, Y, input_dim, X=None, X_variance=None, init='PCA', num_inducing=10, + Z=None, kernel=None, inference_method=None, likelihood=None, + name='bayesian gplvm', normalizer=None, + missing_data=False, stochastic=False, batchsize=1): + self.logger = logging.getLogger(self.__class__.__name__) + if X is None: + from ..util.initialization import initialize_latent + self.logger.info("initializing latent space X with method {}".format(init)) + X, fracs = initialize_latent(init, input_dim, Y) + else: + fracs = np.ones(input_dim) + + self.init = init + + if X_variance is None: + self.logger.info("initializing latent space variance ~ uniform(0,.1)") + X_variance = np.random.uniform(0,.1,X.shape) + + if Z is None: + self.logger.info("initializing inducing inputs") + Z = np.random.permutation(X.copy())[:num_inducing] + assert Z.shape[1] == X.shape[1] + + if kernel is None: + self.logger.info("initializing kernel RBF") + kernel = kern.RBF(input_dim, lengthscale=1./fracs, ARD=True) #+ kern.Bias(input_dim) + kern.White(input_dim) + + if likelihood is None: + likelihood = Gaussian() + + self.variational_prior = NormalPrior() + X = NormalPosterior(X, X_variance) + + self.kl_factr = 1. + + if inference_method is None: + from ..inference.latent_function_inference.var_dtc import VarDTC + self.logger.debug("creating inference_method var_dtc") + inference_method = VarDTC(limit=1 if not missing_data else Y.shape[1]) + + if kernel.useGPU and isinstance(inference_method, VarDTC_GPU): + kernel.psicomp.GPU_direct = True + + super(BayesianGPLVMMiniBatch,self).__init__(X, Y, Z, kernel, likelihood=likelihood, + name=name, inference_method=inference_method, + normalizer=normalizer, + missing_data=missing_data, stochastic=stochastic, + batchsize=batchsize) + self.X = X + self.link_parameter(self.X, 0) + +
      [docs] def set_X_gradients(self, X, X_grad): + """Set the gradients of the posterior distribution of X in its specific form.""" + X.mean.gradient, X.variance.gradient = X_grad +
      +
      [docs] def get_X_gradients(self, X): + """Get the gradients of the posterior distribution of X in its specific form.""" + return X.mean.gradient, X.variance.gradient +
      + def _inner_parameters_changed(self, kern, X, Z, likelihood, Y, Y_metadata, Lm=None, dL_dKmm=None, subset_indices=None): + posterior, log_marginal_likelihood, grad_dict, current_values, value_indices = super(BayesianGPLVMMiniBatch, self)._inner_parameters_changed(kern, X, Z, likelihood, Y, Y_metadata, Lm=Lm, dL_dKmm=dL_dKmm, subset_indices=subset_indices) + + current_values['meangrad'], current_values['vargrad'] = self.kern.gradients_qX_expectations( + variational_posterior=X, + Z=Z, dL_dpsi0=grad_dict['dL_dpsi0'], + dL_dpsi1=grad_dict['dL_dpsi1'], + dL_dpsi2=grad_dict['dL_dpsi2']) + + kl_fctr = self.kl_factr + if self.missing_data: + d = self.output_dim + log_marginal_likelihood -= kl_fctr*self.variational_prior.KL_divergence(X)/d + else: + log_marginal_likelihood -= kl_fctr*self.variational_prior.KL_divergence(X) + + + # Subsetting Variational Posterior objects, makes the gradients + # empty. We need them to be 0 though: + X.mean.gradient[:] = 0 + X.variance.gradient[:] = 0 + + self.variational_prior.update_gradients_KL(X) + if self.missing_data: + current_values['meangrad'] += kl_fctr*X.mean.gradient/d + current_values['vargrad'] += kl_fctr*X.variance.gradient/d + else: + current_values['meangrad'] += kl_fctr*X.mean.gradient + current_values['vargrad'] += kl_fctr*X.variance.gradient + + if subset_indices is not None: + value_indices['meangrad'] = subset_indices['samples'] + value_indices['vargrad'] = subset_indices['samples'] + return posterior, log_marginal_likelihood, grad_dict, current_values, value_indices + + def _outer_values_update(self, full_values): + """ + Here you put the values, which were collected before in the right places. + E.g. set the gradients of parameters, etc. + """ + super(BayesianGPLVMMiniBatch, self)._outer_values_update(full_values) + self.X.mean.gradient = full_values['meangrad'] + self.X.variance.gradient = full_values['vargrad'] + + def _outer_init_full_values(self): + return dict(meangrad=np.zeros(self.X.mean.shape), + vargrad=np.zeros(self.X.variance.shape)) + +
      [docs] def parameters_changed(self): + super(BayesianGPLVMMiniBatch,self).parameters_changed() + if isinstance(self.inference_method, VarDTC_minibatch): + return + + #super(BayesianGPLVM, self).parameters_changed() + #self._log_marginal_likelihood -= self.variational_prior.KL_divergence(self.X) + + #self.X.mean.gradient, self.X.variance.gradient = self.kern.gradients_qX_expectations(variational_posterior=self.X, Z=self.Z, dL_dpsi0=self.grad_dict['dL_dpsi0'], dL_dpsi1=self.grad_dict['dL_dpsi1'], dL_dpsi2=self.grad_dict['dL_dpsi2']) + + # This is testing code ------------------------- +# i = np.random.randint(self.X.shape[0]) +# X_ = self.X.mean +# which = np.sqrt(((X_ - X_[i:i+1])**2).sum(1)).argsort()>(max(0, self.X.shape[0]-51)) +# _, _, grad_dict = self.inference_method.inference(self.kern, self.X[which], self.Z, self.likelihood, self.Y[which], self.Y_metadata) +# grad = self.kern.gradients_qX_expectations(variational_posterior=self.X[which], Z=self.Z, dL_dpsi0=grad_dict['dL_dpsi0'], dL_dpsi1=grad_dict['dL_dpsi1'], dL_dpsi2=grad_dict['dL_dpsi2']) +# +# self.X.mean.gradient[:] = 0 +# self.X.variance.gradient[:] = 0 +# self.X.mean.gradient[which] = grad[0] +# self.X.variance.gradient[which] = grad[1] + + # update for the KL divergence +# self.variational_prior.update_gradients_KL(self.X, which) + # ----------------------------------------------- + + # update for the KL divergence + #self.variational_prior.update_gradients_KL(self.X) +
      +
      [docs] def plot_latent(self, labels=None, which_indices=None, + resolution=50, ax=None, marker='o', s=40, + fignum=None, plot_inducing=True, legend=True, + plot_limits=None, + aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={}): + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import dim_reduction_plots + + return dim_reduction_plots.plot_latent(self, labels, which_indices, + resolution, ax, marker, s, + fignum, plot_inducing, legend, + plot_limits, aspect, updates, predict_kwargs, imshow_kwargs) +
      +
      [docs] def do_test_latents(self, Y): + """ + Compute the latent representation for a set of new points Y + + Notes: + This will only work with a univariate Gaussian likelihood (for now) + """ + N_test = Y.shape[0] + input_dim = self.Z.shape[1] + + means = np.zeros((N_test, input_dim)) + covars = np.zeros((N_test, input_dim)) + + dpsi0 = -0.5 * self.input_dim / self.likelihood.variance + dpsi2 = self.grad_dict['dL_dpsi2'][0][None, :, :] # TODO: this may change if we ignore het. likelihoods + V = Y/self.likelihood.variance + + #compute CPsi1V + #if self.Cpsi1V is None: + # psi1V = np.dot(self.psi1.T, self.likelihood.V) + # tmp, _ = linalg.dtrtrs(self._Lm, np.asfortranarray(psi1V), lower=1, trans=0) + # tmp, _ = linalg.dpotrs(self.LB, tmp, lower=1) + # self.Cpsi1V, _ = linalg.dtrtrs(self._Lm, tmp, lower=1, trans=1) + + dpsi1 = np.dot(self.posterior.woodbury_vector, V.T) + + #start = np.zeros(self.input_dim * 2) + + + from scipy.optimize import minimize + + for n, dpsi1_n in enumerate(dpsi1.T[:, :, None]): + args = (input_dim, self.kern.copy(), self.Z, dpsi0, dpsi1_n.T, dpsi2) + res = minimize(latent_cost_and_grad, jac=True, x0=np.hstack((means[n], covars[n])), args=args, method='BFGS') + xopt = res.x + mu, log_S = xopt.reshape(2, 1, -1) + means[n] = mu[0].copy() + covars[n] = np.exp(log_S[0]).copy() + + X = NormalPosterior(means, covars) + + return X +
      +
      [docs] def dmu_dX(self, Xnew): + """ + Calculate the gradient of the prediction at Xnew w.r.t Xnew. + """ + dmu_dX = np.zeros_like(Xnew) + for i in range(self.Z.shape[0]): + dmu_dX += self.kern.gradients_X(self.grad_dict['dL_dpsi1'][i:i + 1, :], Xnew, self.Z[i:i + 1, :]) + return dmu_dX +
      +
      [docs] def dmu_dXnew(self, Xnew): + """ + Individual gradient of prediction at Xnew w.r.t. each sample in Xnew + """ + gradients_X = np.zeros((Xnew.shape[0], self.num_inducing)) + ones = np.ones((1, 1)) + for i in range(self.Z.shape[0]): + gradients_X[:, i] = self.kern.gradients_X(ones, Xnew, self.Z[i:i + 1, :]).sum(-1) + return np.dot(gradients_X, self.grad_dict['dL_dpsi1']) +
      +
      [docs] def plot_steepest_gradient_map(self, *args, ** kwargs): + """ + See GPy.plotting.matplot_dep.dim_reduction_plots.plot_steepest_gradient_map + """ + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import dim_reduction_plots + + return dim_reduction_plots.plot_steepest_gradient_map(self,*args,**kwargs) + +
      +
      [docs]def latent_cost_and_grad(mu_S, input_dim, kern, Z, dL_dpsi0, dL_dpsi1, dL_dpsi2): + """ + objective function for fitting the latent variables for test points + (negative log-likelihood: should be minimised!) + """ + mu = mu_S[:input_dim][None] + log_S = mu_S[input_dim:][None] + S = np.exp(log_S) + + X = NormalPosterior(mu, S) + + psi0 = kern.psi0(Z, X) + psi1 = kern.psi1(Z, X) + psi2 = kern.psi2(Z, X) + + lik = dL_dpsi0 * psi0.sum() + np.einsum('ij,kj->...', dL_dpsi1, psi1) + np.einsum('ijk,lkj->...', dL_dpsi2, psi2) - 0.5 * np.sum(np.square(mu) + S) + 0.5 * np.sum(log_S) + + dLdmu, dLdS = kern.gradients_qX_expectations(dL_dpsi0, dL_dpsi1, dL_dpsi2, Z, X) + dmu = dLdmu - mu + # dS = S0 + S1 + S2 -0.5 + .5/S + dlnS = S * (dLdS - 0.5) + .5 + + return -lik, -np.hstack((dmu.flatten(), dlnS.flatten()))
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/bcgplvm.html b/doc/_build/html/_modules/GPy/models/bcgplvm.html new file mode 100644 index 00000000..ebd48c80 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/bcgplvm.html @@ -0,0 +1,141 @@ + + + + + + + + GPy.models.bcgplvm — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.bcgplvm

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from ..core import GP
      +from ..models import GPLVM
      +from ..mappings import *
      +
      +
      +
      [docs]class BCGPLVM(GPLVM): + """ + Back constrained Gaussian Process Latent Variable Model + + :param Y: observed data + :type Y: np.ndarray + :param input_dim: latent dimensionality + :type input_dim: int + :param init: initialisation method for the latent space + :type init: 'PCA'|'random' + :param mapping: mapping for back constraint + :type mapping: GPy.core.Mapping object + + """ + def __init__(self, Y, input_dim, init='PCA', X=None, kernel=None, normalize_Y=False, mapping=None): + + if mapping is None: + mapping = Kernel(X=Y, output_dim=input_dim) + self.mapping = mapping + GPLVM.__init__(self, Y, input_dim, init, X, kernel, normalize_Y) + self.X = self.mapping.f(self.likelihood.Y) + + def _get_param_names(self): + return self.mapping._get_param_names() + GP._get_param_names(self) + + def _get_params(self): + return np.hstack((self.mapping._get_params(), GP._get_params(self))) + + def _set_params(self, x): + self.mapping._set_params(x[:self.mapping.num_params]) + self.X = self.mapping.f(self.likelihood.Y) + GP._set_params(self, x[self.mapping.num_params:]) + + def _log_likelihood_gradients(self): + dL_df = self.kern.gradients_X(self.dL_dK, self.X) + dL_dtheta = self.mapping.df_dtheta(dL_df, self.likelihood.Y) + return np.hstack((dL_dtheta.flatten(), GP._log_likelihood_gradients(self))) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/gp_classification.html b/doc/_build/html/_modules/GPy/models/gp_classification.html new file mode 100644 index 00000000..54e6c5b3 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/gp_classification.html @@ -0,0 +1,123 @@ + + + + + + + + GPy.models.gp_classification — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.gp_classification

      +# Copyright (c) 2013, the GPy Authors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from ..core import GP
      +from .. import likelihoods
      +from .. import kern
      +from ..inference.latent_function_inference.expectation_propagation import EP
      +
      +
      [docs]class GPClassification(GP): + """ + Gaussian Process classification + + This is a thin wrapper around the models.GP class, with a set of sensible defaults + + :param X: input observations + :param Y: observed values, can be None if likelihood is not None + :param kernel: a GPy kernel, defaults to rbf + + .. Note:: Multiple independent outputs are allowed using columns of Y + + """ + + def __init__(self, X, Y, kernel=None,Y_metadata=None): + if kernel is None: + kernel = kern.RBF(X.shape[1]) + + likelihood = likelihoods.Bernoulli() + + GP.__init__(self, X=X, Y=Y, kernel=kernel, likelihood=likelihood, inference_method=EP(), name='gp_classification')
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/gp_coregionalized_regression.html b/doc/_build/html/_modules/GPy/models/gp_coregionalized_regression.html new file mode 100644 index 00000000..0762b10b --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/gp_coregionalized_regression.html @@ -0,0 +1,138 @@ + + + + + + + + GPy.models.gp_coregionalized_regression — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.gp_coregionalized_regression

      +# Copyright (c) 2012 - 2014 the GPy Austhors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core import GP
      +from .. import likelihoods
      +from .. import kern
      +from .. import util
      +
      +
      [docs]class GPCoregionalizedRegression(GP): + """ + Gaussian Process model for heteroscedastic multioutput regression + + This is a thin wrapper around the models.GP class, with a set of sensible defaults + + :param X_list: list of input observations corresponding to each output + :type X_list: list of numpy arrays + :param Y_list: list of observed values related to the different noise models + :type Y_list: list of numpy arrays + :param kernel: a GPy kernel, defaults to RBF ** Coregionalized + :type kernel: None | GPy.kernel defaults + :likelihoods_list: a list of likelihoods, defaults to list of Gaussian likelihoods + :type likelihoods_list: None | a list GPy.likelihoods + :param name: model name + :type name: string + :param W_rank: number tuples of the corregionalization parameters 'W' (see coregionalize kernel documentation) + :type W_rank: integer + :param kernel_name: name of the kernel + :type kernel_name: string + """ + def __init__(self, X_list, Y_list, kernel=None, likelihoods_list=None, name='GPCR',W_rank=1,kernel_name='coreg'): + + #Input and Output + X,Y,self.output_index = util.multioutput.build_XY(X_list,Y_list) + Ny = len(Y_list) + + #Kernel + if kernel is None: + kernel = util.multioutput.ICM(input_dim=X.shape[1]-1, num_outputs=Ny, kernel=kern.RBF(X.shape[1]-1), W_rank=1,name=kernel_name) + + #Likelihood + likelihood = util.multioutput.build_likelihood(Y_list,self.output_index,likelihoods_list) + + super(GPCoregionalizedRegression, self).__init__(X,Y,kernel,likelihood, Y_metadata={'output_index':self.output_index})
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/gp_heteroscedastic_regression.html b/doc/_build/html/_modules/GPy/models/gp_heteroscedastic_regression.html new file mode 100644 index 00000000..8f305101 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/gp_heteroscedastic_regression.html @@ -0,0 +1,135 @@ + + + + + + + + GPy.models.gp_heteroscedastic_regression — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.gp_heteroscedastic_regression

      +# Copyright (c) 2012 - 2014 the GPy Austhors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core import GP
      +from .. import likelihoods
      +from .. import kern
      +from .. import util
      +
      +
      [docs]class GPHeteroscedasticRegression(GP): + """ + Gaussian Process model for heteroscedastic regression + + This is a thin wrapper around the models.GP class, with a set of sensible defaults + + :param X: input observations + :param Y: observed values + :param kernel: a GPy kernel, defaults to rbf + """ + def __init__(self, X, Y, kernel=None, Y_metadata=None): + + Ny = Y.shape[0] + + if Y_metadata is None: + Y_metadata = {'output_index':np.arange(Ny)[:,None]} + else: + assert Y_metadata['output_index'].shape[0] == Ny + + if kernel is None: + kernel = kern.RBF(X.shape[1]) + + #Likelihood + #likelihoods_list = [likelihoods.Gaussian(name="Gaussian_noise_%s" %j) for j in range(Ny)] + noise_terms = np.unique(Y_metadata['output_index'].flatten()) + likelihoods_list = [likelihoods.Gaussian(name="Gaussian_noise_%s" %j) for j in noise_terms] + likelihood = likelihoods.MixedNoise(likelihoods_list=likelihoods_list) + + super(GPHeteroscedasticRegression, self).__init__(X,Y,kernel,likelihood, Y_metadata=Y_metadata) + +
      [docs] def plot(self,*args): + return NotImplementedError
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/gp_kronecker_gaussian_regression.html b/doc/_build/html/_modules/GPy/models/gp_kronecker_gaussian_regression.html new file mode 100644 index 00000000..be4a2691 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/gp_kronecker_gaussian_regression.html @@ -0,0 +1,213 @@ + + + + + + + + GPy.models.gp_kronecker_gaussian_regression — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.gp_kronecker_gaussian_regression

      +# Copyright (c) 2014, James Hensman, Alan Saul
      +# Distributed under the terms of the GNU General public License, see LICENSE.txt
      +
      +import numpy as np
      +from ..core.model import Model
      +from ..core.parameterization import ObsAr
      +from .. import likelihoods
      +
      +
      [docs]class GPKroneckerGaussianRegression(Model): + """ + Kronecker GP regression + + Take two kernels computed on separate spaces K1(X1), K2(X2), and a data + matrix Y which is f size (N1, N2). + + The effective covaraince is np.kron(K2, K1) + The effective data is vec(Y) = Y.flatten(order='F') + + The noise must be iid Gaussian. + + See Stegle et al. + @inproceedings{stegle2011efficient, + title={Efficient inference in matrix-variate gaussian models with $\\backslash$ iid observation noise}, + author={Stegle, Oliver and Lippert, Christoph and Mooij, Joris M and Lawrence, Neil D and Borgwardt, Karsten M}, + booktitle={Advances in Neural Information Processing Systems}, + pages={630--638}, + year={2011} + } + + """ + def __init__(self, X1, X2, Y, kern1, kern2, noise_var=1., name='KGPR'): + Model.__init__(self, name=name) + # accept the construction arguments + self.X1 = ObsAr(X1) + self.X2 = ObsAr(X2) + self.Y = Y + self.kern1, self.kern2 = kern1, kern2 + self.link_parameter(self.kern1) + self.link_parameter(self.kern2) + + self.likelihood = likelihoods.Gaussian() + self.likelihood.variance = noise_var + self.link_parameter(self.likelihood) + + self.num_data1, self.input_dim1 = self.X1.shape + self.num_data2, self.input_dim2 = self.X2.shape + + assert kern1.input_dim == self.input_dim1 + assert kern2.input_dim == self.input_dim2 + assert Y.shape == (self.num_data1, self.num_data2) + +
      [docs] def log_likelihood(self): + return self._log_marginal_likelihood +
      +
      [docs] def parameters_changed(self): + (N1, D1), (N2, D2) = self.X1.shape, self.X2.shape + K1, K2 = self.kern1.K(self.X1), self.kern2.K(self.X2) + + # eigendecompositon + S1, U1 = np.linalg.eigh(K1) + S2, U2 = np.linalg.eigh(K2) + W = np.kron(S2, S1) + self.likelihood.variance + + Y_ = U1.T.dot(self.Y).dot(U2) + + # store these quantities: needed for prediction + Wi = 1./W + Ytilde = Y_.flatten(order='F')*Wi + + self._log_marginal_likelihood = -0.5*self.num_data1*self.num_data2*np.log(2*np.pi)\ + -0.5*np.sum(np.log(W))\ + -0.5*np.dot(Y_.flatten(order='F'), Ytilde) + + # gradients for data fit part + Yt_reshaped = Ytilde.reshape(N1, N2, order='F') + tmp = U1.dot(Yt_reshaped) + dL_dK1 = .5*(tmp*S2).dot(tmp.T) + tmp = U2.dot(Yt_reshaped.T) + dL_dK2 = .5*(tmp*S1).dot(tmp.T) + + # gradients for logdet + Wi_reshaped = Wi.reshape(N1, N2, order='F') + tmp = np.dot(Wi_reshaped, S2) + dL_dK1 += -0.5*(U1*tmp).dot(U1.T) + tmp = np.dot(Wi_reshaped.T, S1) + dL_dK2 += -0.5*(U2*tmp).dot(U2.T) + + self.kern1.update_gradients_full(dL_dK1, self.X1) + self.kern2.update_gradients_full(dL_dK2, self.X2) + + # gradients for noise variance + dL_dsigma2 = -0.5*Wi.sum() + 0.5*np.sum(np.square(Ytilde)) + self.likelihood.variance.gradient = dL_dsigma2 + + # store these quantities for prediction: + self.Wi, self.Ytilde, self.U1, self.U2 = Wi, Ytilde, U1, U2 +
      +
      [docs] def predict(self, X1new, X2new): + """ + Return the predictive mean and variance at a series of new points X1new, X2new + Only returns the diagonal of the predictive variance, for now. + + :param X1new: The points at which to make a prediction + :type X1new: np.ndarray, Nnew x self.input_dim1 + :param X2new: The points at which to make a prediction + :type X2new: np.ndarray, Nnew x self.input_dim2 + + """ + k1xf = self.kern1.K(X1new, self.X1) + k2xf = self.kern2.K(X2new, self.X2) + A = k1xf.dot(self.U1) + B = k2xf.dot(self.U2) + mu = A.dot(self.Ytilde.reshape(self.num_data1, self.num_data2, order='F')).dot(B.T).flatten(order='F') + k1xx = self.kern1.Kdiag(X1new) + k2xx = self.kern2.Kdiag(X2new) + BA = np.kron(B, A) + var = np.kron(k2xx, k1xx) - np.sum(BA**2*self.Wi, 1) + self.likelihood.variance + + return mu[:, None], var[:, None]
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/gp_regression.html b/doc/_build/html/_modules/GPy/models/gp_regression.html new file mode 100644 index 00000000..29cb9e83 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/gp_regression.html @@ -0,0 +1,129 @@ + + + + + + + + GPy.models.gp_regression — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.gp_regression

      +# Copyright (c) 2012 - 2014 the GPy Austhors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core import GP
      +from .. import likelihoods
      +from .. import kern
      +
      +
      [docs]class GPRegression(GP): + """ + Gaussian Process model for regression + + This is a thin wrapper around the models.GP class, with a set of sensible defaults + + :param X: input observations + :param Y: observed values + :param kernel: a GPy kernel, defaults to rbf + :param Norm normalizer: [False] + + Normalize Y with the norm given. + If normalizer is False, no normalization will be done + If it is None, we use GaussianNorm(alization) + + .. Note:: Multiple independent outputs are allowed using columns of Y + + """ + + def __init__(self, X, Y, kernel=None, Y_metadata=None, normalizer=None): + + if kernel is None: + kernel = kern.RBF(X.shape[1]) + + likelihood = likelihoods.Gaussian() + + super(GPRegression, self).__init__(X, Y, kernel, likelihood, name='GP regression', Y_metadata=Y_metadata, normalizer=normalizer) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/gp_var_gauss.html b/doc/_build/html/_modules/GPy/models/gp_var_gauss.html new file mode 100644 index 00000000..ab9df5d7 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/gp_var_gauss.html @@ -0,0 +1,202 @@ + + + + + + + + GPy.models.gp_var_gauss — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.gp_var_gauss

      +# Copyright (c) 2014, James Hensman, Alan Saul
      +# Distributed under the terms of the GNU General public License, see LICENSE.txt
      +
      +import numpy as np
      +from scipy import stats
      +from scipy.special import erf
      +from ..core.model import Model
      +from ..core.parameterization import ObsAr
      +from .. import kern
      +from ..core.parameterization.param import Param
      +from ..util.linalg import pdinv
      +
      +log_2_pi = np.log(2*np.pi)
      +
      +
      +
      [docs]class GPVariationalGaussianApproximation(Model): + """ + The Variational Gaussian Approximation revisited implementation for regression + + @article{Opper:2009, + title = {The Variational Gaussian Approximation Revisited}, + author = {Opper, Manfred and Archambeau, C{\'e}dric}, + journal = {Neural Comput.}, + year = {2009}, + pages = {786--792}, + } + """ + def __init__(self, X, Y, kernel=None): + Model.__init__(self,'Variational GP classification') + # accept the construction arguments + self.X = ObsAr(X) + if kernel is None: + kernel = kern.RBF(X.shape[1]) + kern.White(X.shape[1], 0.01) + self.kern = kernel + self.link_parameter(self.kern) + self.num_data, self.input_dim = self.X.shape + + self.alpha = Param('alpha', np.zeros(self.num_data)) + self.beta = Param('beta', np.ones(self.num_data)) + self.link_parameter(self.alpha) + self.link_parameter(self.beta) + + self.gh_x, self.gh_w = np.polynomial.hermite.hermgauss(20) + self.Ysign = np.where(Y==1, 1, -1).flatten() + +
      [docs] def log_likelihood(self): + """ + Marginal log likelihood evaluation + """ + return self._log_lik +
      +
      [docs] def likelihood_quadrature(self, m, v): + """ + Perform Gauss-Hermite quadrature over the log of the likelihood, with a fixed weight + """ + # assume probit for now. + X = self.gh_x[None, :]*np.sqrt(2.*v[:, None]) + (m*self.Ysign)[:, None] + p = stats.norm.cdf(X) + N = stats.norm.pdf(X) + F = np.log(p).dot(self.gh_w) + NoverP = N/p + dF_dm = (NoverP*self.Ysign[:,None]).dot(self.gh_w) + dF_dv = -0.5*(NoverP**2 + NoverP*X).dot(self.gh_w) + return F, dF_dm, dF_dv +
      +
      [docs] def parameters_changed(self): + K = self.kern.K(self.X) + m = K.dot(self.alpha) + KB = K*self.beta[:, None] + BKB = KB*self.beta[None, :] + A = np.eye(self.num_data) + BKB + Ai, LA, _, Alogdet = pdinv(A) + Sigma = np.diag(self.beta**-2) - Ai/self.beta[:, None]/self.beta[None, :] # posterior coavairance: need full matrix for gradients + var = np.diag(Sigma) + + F, dF_dm, dF_dv = self.likelihood_quadrature(m, var) + dF_da = np.dot(K, dF_dm) + SigmaB = Sigma*self.beta + dF_db = -np.diag(Sigma.dot(np.diag(dF_dv)).dot(SigmaB))*2 + KL = 0.5*(Alogdet + np.trace(Ai) - self.num_data + m.dot(self.alpha)) + dKL_da = m + A_A2 = Ai - Ai.dot(Ai) + dKL_db = np.diag(np.dot(KB.T, A_A2)) + self._log_lik = F.sum() - KL + self.alpha.gradient = dF_da - dKL_da + self.beta.gradient = dF_db - dKL_db + + # K-gradients + dKL_dK = 0.5*(self.alpha[None, :]*self.alpha[:, None] + self.beta[:, None]*self.beta[None, :]*A_A2) + tmp = Ai*self.beta[:, None]/self.beta[None, :] + dF_dK = self.alpha[:, None]*dF_dm[None, :] + np.dot(tmp*dF_dv, tmp.T) + self.kern.update_gradients_full(dF_dK - dKL_dK, self.X) +
      +
      [docs] def predict(self, Xnew): + """ + Predict the function(s) at the new point(s) Xnew. + + :param Xnew: The points at which to make a prediction + :type Xnew: np.ndarray, Nnew x self.input_dim + """ + Wi, _, _, _ = pdinv(self.kern.K(self.X) + np.diag(self.beta**-2)) + Kux = self.kern.K(self.X, Xnew) + mu = np.dot(Kux.T, self.alpha) + WiKux = np.dot(Wi, Kux) + Kxx = self.kern.Kdiag(Xnew) + var = Kxx - np.sum(WiKux*Kux, 0) + + return 0.5*(1+erf(mu/np.sqrt(2.*(var+1))))
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/gplvm.html b/doc/_build/html/_modules/GPy/models/gplvm.html new file mode 100644 index 00000000..1b75c64f --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/gplvm.html @@ -0,0 +1,177 @@ + + + + + + + + GPy.models.gplvm — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.gplvm

      +# Copyright (c) 2012-2014, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from .. import kern
      +from ..core import GP, Param
      +from ..likelihoods import Gaussian
      +from .. import util
      +
      +
      +
      [docs]class GPLVM(GP): + """ + Gaussian Process Latent Variable Model + + + """ + def __init__(self, Y, input_dim, init='PCA', X=None, kernel=None, name="gplvm"): + + """ + :param Y: observed data + :type Y: np.ndarray + :param input_dim: latent dimensionality + :type input_dim: int + :param init: initialisation method for the latent space + :type init: 'PCA'|'random' + """ + if X is None: + from ..util.initialization import initialize_latent + X, fracs = initialize_latent(init, input_dim, Y) + else: + fracs = np.ones(input_dim) + if kernel is None: + kernel = kern.RBF(input_dim, lengthscale=fracs, ARD=input_dim > 1) + kern.Bias(input_dim, np.exp(-2)) + + likelihood = Gaussian() + + super(GPLVM, self).__init__(X, Y, kernel, likelihood, name='GPLVM') + self.X = Param('latent_mean', X) + self.link_parameter(self.X, index=0) + +
      [docs] def parameters_changed(self): + super(GPLVM, self).parameters_changed() + self.X.gradient = self.kern.gradients_X(self.grad_dict['dL_dK'], self.X, None) +
      +
      [docs] def jacobian(self,X): + J = np.zeros((X.shape[0],X.shape[1],self.output_dim)) + for i in range(self.output_dim): + J[:,:,i] = self.kern.gradients_X(self.posterior.woodbury_vector[:,i:i+1], X, self.X) + return J +
      +
      [docs] def magnification(self,X): + target=np.zeros(X.shape[0]) + #J = np.zeros((X.shape[0],X.shape[1],self.output_dim)) + J = self.jacobian(X) + for i in range(X.shape[0]): + target[i]=np.sqrt(np.linalg.det(np.dot(J[i,:,:],np.transpose(J[i,:,:])))) + return target +
      +
      [docs] def plot(self): + assert self.likelihood.Y.shape[1] == 2 + pb.scatter(self.likelihood.Y[:, 0], self.likelihood.Y[:, 1], 40, self.X[:, 0].copy(), linewidth=0, cmap=pb.cm.jet) # @UndefinedVariable + Xnew = np.linspace(self.X.min(), self.X.max(), 200)[:, None] + mu, _ = self.predict(Xnew) + import pylab as pb + pb.plot(mu[:, 0], mu[:, 1], 'k', linewidth=1.5) +
      +
      [docs] def plot_latent(self, labels=None, which_indices=None, + resolution=50, ax=None, marker='o', s=40, + fignum=None, legend=True, + plot_limits=None, + aspect='auto', updates=False, **kwargs): + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import dim_reduction_plots + + return dim_reduction_plots.plot_latent(self, labels, which_indices, + resolution, ax, marker, s, + fignum, False, legend, + plot_limits, aspect, updates, **kwargs) +
      +
      [docs] def plot_magnification(self, *args, **kwargs): + return util.plot_latent.plot_magnification(self, *args, **kwargs)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/gradient_checker.html b/doc/_build/html/_modules/GPy/models/gradient_checker.html new file mode 100644 index 00000000..e9c85ce9 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/gradient_checker.html @@ -0,0 +1,207 @@ + + + + + + + + GPy.models.gradient_checker — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.gradient_checker

      +# ## Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +from ..core.model import Model
      +import itertools
      +import numpy
      +from ..core.parameterization import Param
      +
      +
      [docs]def get_shape(x): + if isinstance(x, numpy.ndarray): + return x.shape + return () +
      +
      [docs]def at_least_one_element(x): + if isinstance(x, (list, tuple)): + return x + return [x] +
      +
      [docs]def flatten_if_needed(x): + return numpy.atleast_1d(x).flatten() +
      +
      [docs]class GradientChecker(Model): + + def __init__(self, f, df, x0, names=None, *args, **kwargs): + """ + :param f: Function to check gradient for + :param df: Gradient of function to check + :param x0: + Initial guess for inputs x (if it has a shape (a,b) this will be reflected in the parameter names). + Can be a list of arrays, if takes a list of arrays. This list will be passed + to f and df in the same order as given here. + If only one argument, make sure not to pass a list!!! + + :type x0: [array-like] | array-like | float | int + :param names: + Names to print, when performing gradcheck. If a list was passed to x0 + a list of names with the same length is expected. + :param args: Arguments passed as f(x, *args, **kwargs) and df(x, *args, **kwargs) + + Examples: + --------- + from GPy.models import GradientChecker + N, M, Q = 10, 5, 3 + + Sinusoid: + + X = numpy.random.rand(N, Q) + grad = GradientChecker(numpy.sin,numpy.cos,X,'x') + grad.checkgrad(verbose=1) + + Using GPy: + + X, Z = numpy.random.randn(N,Q), numpy.random.randn(M,Q) + kern = GPy.kern.linear(Q, ARD=True) + GPy.kern.rbf(Q, ARD=True) + grad = GradientChecker(kern.K, + lambda x: 2*kern.dK_dX(numpy.ones((1,1)), x), + x0 = X.copy(), + names='X') + grad.checkgrad(verbose=1) + grad.randomize() + grad.checkgrad(verbose=1) + """ + Model.__init__(self, 'GradientChecker') + if isinstance(x0, (list, tuple)) and names is None: + self.shapes = [get_shape(xi) for xi in x0] + self.names = ['X{i}'.format(i=i) for i in range(len(x0))] + elif isinstance(x0, (list, tuple)) and names is not None: + self.shapes = [get_shape(xi) for xi in x0] + self.names = names + elif names is None: + self.names = ['X'] + self.shapes = [get_shape(x0)] + else: + self.names = names + self.shapes = [get_shape(x0)] + + for name, xi in zip(self.names, at_least_one_element(x0)): + self.__setattr__(name, Param(name, xi)) + self.link_parameter(self.__getattribute__(name)) +# self._param_names = [] +# for name, shape in zip(self.names, self.shapes): +# self._param_names.extend(map(lambda nameshape: ('_'.join(nameshape)).strip('_'), itertools.izip(itertools.repeat(name), itertools.imap(lambda t: '_'.join(map(str, t)), itertools.product(*map(lambda xi: range(xi), shape)))))) + self.args = args + self.kwargs = kwargs + self.f = f + self.df = df + + def _get_x(self): + if len(self.names) > 1: + return [self.__getattribute__(name) for name in self.names] + list(self.args) + return [self.__getattribute__(self.names[0])] + list(self.args) + +
      [docs] def log_likelihood(self): + return float(numpy.sum(self.f(*self._get_x(), **self.kwargs))) +
      + def _log_likelihood_gradients(self): + return numpy.atleast_1d(self.df(*self._get_x(), **self.kwargs)).flatten() + + #def _get_params(self): + #return numpy.atleast_1d(numpy.hstack(map(lambda name: flatten_if_needed(self.__getattribute__(name)), self.names))) + + #def _set_params(self, x): + #current_index = 0 + #for name, shape in zip(self.names, self.shapes): + #current_size = numpy.prod(shape) + #self.__setattr__(name, x[current_index:current_index + current_size].reshape(shape)) + #current_index += current_size + + #def _get_param_names(self): + #_param_names = [] + #for name, shape in zip(self.names, self.shapes): + #_param_names.extend(map(lambda nameshape: ('_'.join(nameshape)).strip('_'), itertools.izip(itertools.repeat(name), itertools.imap(lambda t: '_'.join(map(str, t)), itertools.product(*map(lambda xi: range(xi), shape)))))) + #return _param_names
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/mrd.html b/doc/_build/html/_modules/GPy/models/mrd.html new file mode 100644 index 00000000..85b4ff73 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/mrd.html @@ -0,0 +1,435 @@ + + + + + + + + GPy.models.mrd — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.mrd

      +# ## Copyright (c) 2013, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +import itertools, logging
      +
      +from ..kern import Kern
      +from ..core.parameterization.variational import NormalPosterior, NormalPrior
      +from ..core.parameterization import Param, Parameterized
      +from ..core.parameterization.observable_array import ObsAr
      +from ..inference.latent_function_inference.var_dtc import VarDTC
      +from ..inference.latent_function_inference import InferenceMethodList
      +from ..likelihoods import Gaussian
      +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.sparse_gp_minibatch import SparseGPMiniBatch
      +
      +
      [docs]class MRD(BayesianGPLVMMiniBatch): + """ + !WARNING: This is bleeding edge code and still in development. + Functionality may change fundamentally during development! + + Apply MRD to all given datasets Y in Ylist. + + Y_i in [n x p_i] + + If Ylist is a dictionary, the keys of the dictionary are the names, and the + values are the different datasets to compare. + + The samples n in the datasets need + to match up, whereas the dimensionality p_d can differ. + + :param [array-like] Ylist: List of datasets to apply MRD on + :param input_dim: latent dimensionality + :type input_dim: int + :param array-like X: mean of starting latent space q in [n x q] + :param array-like X_variance: variance of starting latent space q in [n x q] + :param initx: initialisation method for the latent space : + + * 'concat' - PCA on concatenation of all datasets + * 'single' - Concatenation of PCA on datasets, respectively + * 'random' - Random draw from a Normal(0,1) + + :type initx: ['concat'|'single'|'random'] + :param initz: initialisation method for inducing inputs + :type initz: 'permute'|'random' + :param num_inducing: number of inducing inputs to use + :param Z: initial inducing inputs + :param kernel: list of kernels or kernel to copy for each output + :type kernel: [GPy.kernels.kernels] | GPy.kernels.kernels | None (default) + :param :class:`~GPy.inference.latent_function_inference inference_method: + InferenceMethodList of inferences, or one inference method for all + :param :class:`~GPy.likelihoodss.likelihoods.likelihoods` likelihoods: the likelihoods to use + :param str name: the name of this model + :param [str] Ynames: the names for the datasets given, must be of equal length as Ylist or None + :param bool|Norm normalizer: How to normalize the data? + :param bool stochastic: Should this model be using stochastic gradient descent over the dimensions? + :param bool|[bool] batchsize: either one batchsize for all, or one batchsize per dataset. + """ + def __init__(self, Ylist, input_dim, X=None, X_variance=None, + initx = 'PCA', initz = 'permute', + num_inducing=10, Z=None, kernel=None, + inference_method=None, likelihoods=None, name='mrd', + Ynames=None, normalizer=False, stochastic=False, batchsize=10): + + self.logger = logging.getLogger(self.__class__.__name__) + self.input_dim = input_dim + self.num_inducing = num_inducing + + if isinstance(Ylist, dict): + Ynames, Ylist = zip(*Ylist.items()) + + self.logger.debug("creating observable arrays") + self.Ylist = [ObsAr(Y) for Y in Ylist] + + if Ynames is None: + self.logger.debug("creating Ynames") + Ynames = ['Y{}'.format(i) for i in range(len(Ylist))] + self.names = Ynames + assert len(self.names) == len(self.Ylist), "one name per dataset, or None if Ylist is a dict" + + if inference_method is None: + self.inference_method = InferenceMethodList([VarDTC() for _ in xrange(len(self.Ylist))]) + else: + assert isinstance(inference_method, InferenceMethodList), "please provide one inference method per Y in the list and provide it as InferenceMethodList, inference_method given: {}".format(inference_method) + self.inference_method = inference_method + + if X is None: + X, fracs = self._init_X(initx, Ylist) + else: + fracs = [X.var(0)]*len(Ylist) + + Z = self._init_Z(initz, X) + self.Z = Param('inducing inputs', Z) + self.num_inducing = self.Z.shape[0] # ensure M==N if M>N + + # sort out the kernels + self.logger.info("building kernels") + if kernel is None: + from ..kern import RBF + kernels = [RBF(input_dim, ARD=1, lengthscale=1./fracs[i]) for i in range(len(Ylist))] + elif isinstance(kernel, Kern): + kernels = [] + for i in range(len(Ylist)): + k = kernel.copy() + kernels.append(k) + else: + assert len(kernel) == len(Ylist), "need one kernel per output" + assert all([isinstance(k, Kern) for k in kernel]), "invalid kernel object detected!" + kernels = kernel + + if X_variance is None: + X_variance = np.random.uniform(0.1, 0.2, X.shape) + + self.variational_prior = NormalPrior() + #self.X = NormalPosterior(X, X_variance) + + if likelihoods is None: + likelihoods = [Gaussian(name='Gaussian_noise'.format(i)) for i in range(len(Ylist))] + else: likelihoods = likelihoods + + self.logger.info("adding X and Z") + super(MRD, self).__init__(Y, input_dim, X=X, X_variance=X_variance, num_inducing=num_inducing, + Z=self.Z, kernel=None, inference_method=self.inference_method, likelihood=Gaussian(), + name='manifold relevance determination', normalizer=None, + missing_data=False, stochastic=False, batchsize=1) + + self._log_marginal_likelihood = 0 + + self.unlink_parameter(self.likelihood) + self.unlink_parameter(self.kern) + del self.kern + del self.likelihood + + self.num_data = Ylist[0].shape[0] + if isinstance(batchsize, int): + batchsize = itertools.repeat(batchsize) + + self.bgplvms = [] + + for i, n, k, l, Y, im, bs in itertools.izip(itertools.count(), Ynames, kernels, likelihoods, Ylist, self.inference_method, batchsize): + assert Y.shape[0] == self.num_data, "All datasets need to share the number of datapoints, and those have to correspond to one another" + md = np.isnan(Y).any() + spgp = BayesianGPLVMMiniBatch(Y, input_dim, X, X_variance, + Z=Z, kernel=k, likelihood=l, + inference_method=im, name=n, + normalizer=normalizer, + missing_data=md, + stochastic=stochastic, + batchsize=bs) + spgp.kl_factr = 1./len(Ynames) + spgp.unlink_parameter(spgp.Z) + spgp.unlink_parameter(spgp.X) + del spgp.Z + del spgp.X + spgp.Z = self.Z + spgp.X = self.X + self.link_parameter(spgp, i+2) + self.bgplvms.append(spgp) + + self.posterior = None + self.logger.info("init done") + +
      [docs] def parameters_changed(self): + self._log_marginal_likelihood = 0 + self.Z.gradient[:] = 0. + self.X.gradient[:] = 0. + for b, i in itertools.izip(self.bgplvms, self.inference_method): + self._log_marginal_likelihood += b._log_marginal_likelihood + + self.logger.info('working on im <{}>'.format(hex(id(i)))) + self.Z.gradient[:] += b.full_values['Zgrad'] + grad_dict = b.full_values + + self.X.mean.gradient += grad_dict['meangrad'] + self.X.variance.gradient += grad_dict['vargrad'] + + if isinstance(self.X, VariationalPosterior): + # update for the KL divergence + self.variational_prior.update_gradients_KL(self.X) + self._log_marginal_likelihood -= self.variational_prior.KL_divergence(self.X) + pass +
      +
      [docs] def log_likelihood(self): + return self._log_marginal_likelihood +
      + def _init_X(self, init='PCA', Ylist=None): + if Ylist is None: + Ylist = self.Ylist + if init in "PCA_concat": + X, fracs = initialize_latent('PCA', self.input_dim, np.hstack(Ylist)) + fracs = [fracs]*len(Ylist) + elif init in "PCA_single": + X = np.zeros((Ylist[0].shape[0], self.input_dim)) + fracs = [] + for qs, Y in itertools.izip(np.array_split(np.arange(self.input_dim), len(Ylist)), Ylist): + x,frcs = initialize_latent('PCA', len(qs), Y) + X[:, qs] = x + fracs.append(frcs) + else: # init == 'random': + X = np.random.randn(Ylist[0].shape[0], self.input_dim) + fracs = X.var(0) + fracs = [fracs]*len(Ylist) + X -= X.mean() + X /= X.std() + return X, fracs + + def _init_Z(self, init="permute", X=None): + if X is None: + X = self.X + if init in "permute": + Z = np.random.permutation(X.copy())[:self.num_inducing] + elif init in "random": + Z = np.random.randn(self.num_inducing, self.input_dim) * X.var() + return Z + + def _handle_plotting(self, fignum, axes, plotf, sharex=False, sharey=False): + import matplotlib.pyplot as plt + if axes is None: + fig = plt.figure(num=fignum) + sharex_ax = None + sharey_ax = None + plots = [] + for i, g in enumerate(self.bgplvms): + try: + if sharex: + sharex_ax = ax # @UndefinedVariable + sharex = False # dont set twice + if sharey: + sharey_ax = ax # @UndefinedVariable + sharey = False # dont set twice + except: + pass + if axes is None: + ax = fig.add_subplot(1, len(self.bgplvms), i + 1, sharex=sharex_ax, sharey=sharey_ax) + elif isinstance(axes, (tuple, list, np.ndarray)): + ax = axes[i] + else: + raise ValueError("Need one axes per latent dimension input_dim") + plots.append(plotf(i, g, ax)) + if sharey_ax is not None: + plt.setp(ax.get_yticklabels(), visible=False) + plt.draw() + if axes is None: + try: + fig.tight_layout() + except: + pass + return plots + +
      [docs] def predict(self, Xnew, full_cov=False, Y_metadata=None, kern=None, Yindex=0): + """ + Prediction for data set Yindex[default=0]. + This predicts the output mean and variance for the dataset given in Ylist[Yindex] + """ + b = self.bgplvms[Yindex] + self.posterior = b.posterior + self.kern = b.kern + self.likelihood = b.likelihood + return super(MRD, self).predict(Xnew, full_cov, Y_metadata, kern) + + #=============================================================================== + # TODO: Predict! Maybe even change to several bgplvms, which share an X? + #=============================================================================== + # def plot_predict(self, fignum=None, ax=None, sharex=False, sharey=False, **kwargs): + # fig = self._handle_plotting(fignum, + # ax, + # lambda i, g, ax: ax.imshow(g.predict(g.X)[0], **kwargs), + # sharex=sharex, sharey=sharey) + # return fig +
      +
      [docs] def plot_scales(self, fignum=None, ax=None, titles=None, sharex=False, sharey=True, *args, **kwargs): + """ + + TODO: Explain other parameters + + :param titles: titles for axes of datasets + + """ + if titles is None: + titles = [r'${}$'.format(name) for name in self.names] + ymax = reduce(max, [np.ceil(max(g.kern.input_sensitivity())) for g in self.bgplvms]) + def plotf(i, g, ax): + #ax.set_ylim([0,ymax]) + return g.kern.plot_ARD(ax=ax, title=titles[i], *args, **kwargs) + fig = self._handle_plotting(fignum, ax, plotf, sharex=sharex, sharey=sharey) + return fig +
      +
      [docs] def plot_latent(self, labels=None, which_indices=None, + resolution=50, ax=None, marker='o', s=40, + fignum=None, plot_inducing=True, legend=True, + plot_limits=None, + aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={}): + """ + see plotting.matplot_dep.dim_reduction_plots.plot_latent + if predict_kwargs is None, will plot latent spaces for 0th dataset (and kernel), otherwise give + predict_kwargs=dict(Yindex='index') for plotting only the latent space of dataset with 'index'. + """ + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from matplotlib import pyplot as plt + from ..plotting.matplot_dep import dim_reduction_plots + if "Yindex" not in predict_kwargs: + predict_kwargs['Yindex'] = 0 + + Yindex = predict_kwargs['Yindex'] + if ax is None: + fig = plt.figure(num=fignum) + ax = fig.add_subplot(111) + else: + fig = ax.figure + self.kern = self.bgplvms[Yindex].kern + self.likelihood = self.bgplvms[Yindex].likelihood + plot = dim_reduction_plots.plot_latent(self, labels, which_indices, + resolution, ax, marker, s, + fignum, plot_inducing, legend, + plot_limits, aspect, updates, predict_kwargs, imshow_kwargs) + ax.set_title(self.bgplvms[Yindex].name) + try: + fig.tight_layout() + except: + pass + + return plot +
      + def __getstate__(self): + state = super(MRD, self).__getstate__() + if state.has_key('kern'): + del state['kern'] + if state.has_key('likelihood'): + del state['likelihood'] + return state + + def __setstate__(self, state): + # TODO: + super(MRD, self).__setstate__(state) + self.kern = self.bgplvms[0].kern + self.likelihood = self.bgplvms[0].likelihood + self.parameters_changed()
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/sparse_gp_classification.html b/doc/_build/html/_modules/GPy/models/sparse_gp_classification.html new file mode 100644 index 00000000..37262ad5 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/sparse_gp_classification.html @@ -0,0 +1,140 @@ + + + + + + + + GPy.models.sparse_gp_classification — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.sparse_gp_classification

      +# Copyright (c) 2013, Ricardo Andrade
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from ..core import SparseGP
      +from .. import likelihoods
      +from .. import kern
      +from ..likelihoods import likelihood
      +from ..inference.latent_function_inference import expectation_propagation_dtc
      +
      +
      [docs]class SparseGPClassification(SparseGP): + """ + sparse Gaussian Process model for classification + + This is a thin wrapper around the sparse_GP class, with a set of sensible defaults + + :param X: input observations + :param Y: observed values + :param likelihood: a GPy likelihood, defaults to Binomial with probit link_function + :param kernel: a GPy kernel, defaults to rbf+white + :param normalize_X: whether to normalize the input data before computing (predictions will be in original scales) + :type normalize_X: False|True + :param normalize_Y: whether to normalize the input data before computing (predictions will be in original scales) + :type normalize_Y: False|True + :rtype: model object + + """ + + #def __init__(self, X, Y=None, likelihood=None, kernel=None, normalize_X=False, normalize_Y=False, Z=None, num_inducing=10): + def __init__(self, X, Y=None, likelihood=None, kernel=None, Z=None, num_inducing=10, Y_metadata=None): + + + if kernel is None: + kernel = kern.RBF(X.shape[1]) + + likelihood = likelihoods.Bernoulli() + + if Z is None: + i = np.random.permutation(X.shape[0])[:num_inducing] + Z = X[i].copy() + else: + assert Z.shape[1] == X.shape[1] + + SparseGP.__init__(self, X, Y, Z, kernel, likelihood, inference_method=expectation_propagation_dtc.EPDTC(), name='SparseGPClassification',Y_metadata=Y_metadata) + #def __init__(self, X, Y, Z, kernel, likelihood, inference_method=None, name='sparse gp', Y_metadata=None):
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/sparse_gp_coregionalized_regression.html b/doc/_build/html/_modules/GPy/models/sparse_gp_coregionalized_regression.html new file mode 100644 index 00000000..c7579d41 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/sparse_gp_coregionalized_regression.html @@ -0,0 +1,160 @@ + + + + + + + + GPy.models.sparse_gp_coregionalized_regression — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.sparse_gp_coregionalized_regression

      +# Copyright (c) 2012 - 2014 the GPy Austhors (see AUTHORS.txt)
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core import SparseGP
      +from ..inference.latent_function_inference import VarDTC
      +from .. import likelihoods
      +from .. import kern
      +from .. import util
      +
      +
      [docs]class SparseGPCoregionalizedRegression(SparseGP): + """ + Sparse Gaussian Process model for heteroscedastic multioutput regression + + This is a thin wrapper around the SparseGP class, with a set of sensible defaults + + :param X_list: list of input observations corresponding to each output + :type X_list: list of numpy arrays + :param Y_list: list of observed values related to the different noise models + :type Y_list: list of numpy arrays + :param Z_list: list of inducing inputs (optional) + :type Z_list: empty list | list of numpy arrays + :param kernel: a GPy kernel, defaults to RBF ** Coregionalized + :type kernel: None | GPy.kernel defaults + :likelihoods_list: a list of likelihoods, defaults to list of Gaussian likelihoods + :type likelihoods_list: None | a list GPy.likelihoods + :param num_inducing: number of inducing inputs, defaults to 10 per output (ignored if Z_list is not empty) + :type num_inducing: integer | list of integers + + :param name: model name + :type name: string + :param W_rank: number tuples of the corregionalization parameters 'W' (see coregionalize kernel documentation) + :type W_rank: integer + :param kernel_name: name of the kernel + :type kernel_name: string + """ + + def __init__(self, X_list, Y_list, Z_list=[], kernel=None, likelihoods_list=None, num_inducing=10, X_variance=None, name='SGPCR',W_rank=1,kernel_name='coreg'): + + #Input and Output + X,Y,self.output_index = util.multioutput.build_XY(X_list,Y_list) + Ny = len(Y_list) + + #Kernel + if kernel is None: + kernel = util.multioutput.ICM(input_dim=X.shape[1]-1, num_outputs=Ny, kernel=kern.RBF(X.shape[1]-1), W_rank=1,name=kernel_name) + + #Likelihood + likelihood = util.multioutput.build_likelihood(Y_list,self.output_index,likelihoods_list) + + #Inducing inputs list + if len(Z_list): + assert len(Z_list) == Ny, 'Number of outputs do not match length of inducing inputs list.' + else: + if isinstance(num_inducing,np.int): + num_inducing = [num_inducing] * Ny + num_inducing = np.asarray(num_inducing) + assert num_inducing.size == Ny, 'Number of outputs do not match length of inducing inputs list.' + for ni,Xi in zip(num_inducing,X_list): + i = np.random.permutation(Xi.shape[0])[:ni] + Z_list.append(Xi[i].copy()) + + Z, _, Iz = util.multioutput.build_XY(Z_list) + + super(SparseGPCoregionalizedRegression, self).__init__(X, Y, Z, kernel, likelihood, inference_method=VarDTC(), Y_metadata={'output_index':self.output_index}) + self['.*inducing'][:,-1].fix()
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/sparse_gp_minibatch.html b/doc/_build/html/_modules/GPy/models/sparse_gp_minibatch.html new file mode 100644 index 00000000..46cf520b --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/sparse_gp_minibatch.html @@ -0,0 +1,442 @@ + + + + + + + + GPy.models.sparse_gp_minibatch — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.sparse_gp_minibatch

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from ..core.parameterization.param import Param
      +from ..core.gp import GP
      +from ..inference.latent_function_inference import var_dtc
      +from .. import likelihoods
      +from ..core.parameterization.variational import VariationalPosterior
      +
      +import logging
      +from GPy.inference.latent_function_inference.posterior import Posterior
      +from GPy.inference.optimization.stochastics import SparseGPStochastics,\
      +    SparseGPMissing
      +#no stochastics.py file added! from GPy.inference.optimization.stochastics import SparseGPStochastics,\
      +    #SparseGPMissing
      +logger = logging.getLogger("sparse gp")
      +
      +
      [docs]class SparseGPMiniBatch(GP): + """ + A general purpose Sparse GP model +''' +Created on 3 Nov 2014 + +@author: maxz +''' + + This model allows (approximate) inference using variational DTC or FITC + (Gaussian likelihoods) as well as non-conjugate sparse methods based on + these. + + :param X: inputs + :type X: np.ndarray (num_data x input_dim) + :param likelihood: a likelihood instance, containing the observed data + :type likelihood: GPy.likelihood.(Gaussian | EP | Laplace) + :param kernel: the kernel (covariance function). See link kernels + :type kernel: a GPy.kern.kern instance + :param X_variance: The uncertainty in the measurements of X (Gaussian variance) + :type X_variance: np.ndarray (num_data x input_dim) | None + :param Z: inducing inputs + :type Z: np.ndarray (num_inducing x input_dim) + :param num_inducing: Number of inducing points (optional, default 10. Ignored if Z is not None) + :type num_inducing: int + + """ + + def __init__(self, X, Y, Z, kernel, likelihood, inference_method=None, + name='sparse gp', Y_metadata=None, normalizer=False, + missing_data=False, stochastic=False, batchsize=1): + #pick a sensible inference method + if inference_method is None: + if isinstance(likelihood, likelihoods.Gaussian): + inference_method = var_dtc.VarDTC(limit=1 if not self.missing_data else Y.shape[1]) + else: + #inference_method = ?? + raise NotImplementedError, "what to do what to do?" + print "defaulting to ", inference_method, "for latent function inference" + + self.kl_factr = 1. + self.Z = Param('inducing inputs', Z) + self.num_inducing = Z.shape[0] + + GP.__init__(self, X, Y, kernel, likelihood, inference_method=inference_method, name=name, Y_metadata=Y_metadata, normalizer=normalizer) + self.missing_data = missing_data + + if stochastic and missing_data: + self.missing_data = True + self.ninan = ~np.isnan(Y) + self.stochastics = SparseGPStochastics(self, batchsize) + elif stochastic and not missing_data: + self.missing_data = False + self.stochastics = SparseGPStochastics(self, batchsize) + elif missing_data: + self.missing_data = True + self.ninan = ~np.isnan(Y) + self.stochastics = SparseGPMissing(self) + else: + self.stochastics = False + + logger.info("Adding Z as parameter") + self.link_parameter(self.Z, index=0) + if self.missing_data: + self.Ylist = [] + overall = self.Y_normalized.shape[1] + m_f = lambda i: "Precomputing Y for missing data: {: >7.2%}".format(float(i+1)/overall) + message = m_f(-1) + print message, + for d in xrange(overall): + self.Ylist.append(self.Y_normalized[self.ninan[:, d], d][:, None]) + print ' '*(len(message)+1) + '\r', + message = m_f(d) + print message, + print '' + + self.posterior = None + +
      [docs] def has_uncertain_inputs(self): + return isinstance(self.X, VariationalPosterior) +
      + def _inner_parameters_changed(self, kern, X, Z, likelihood, Y, Y_metadata, Lm=None, dL_dKmm=None, subset_indices=None): + """ + This is the standard part, which usually belongs in parameters_changed. + + For automatic handling of subsampling (such as missing_data, stochastics etc.), we need to put this into an inner + loop, in order to ensure a different handling of gradients etc of different + subsets of data. + + The dict in current_values will be passed aroung as current_values for + the rest of the algorithm, so this is the place to store current values, + such as subsets etc, if necessary. + + If Lm and dL_dKmm can be precomputed (or only need to be computed once) + pass them in here, so they will be passed to the inference_method. + + subset_indices is a dictionary of indices. you can put the indices however you + like them into this dictionary for inner use of the indices inside the + algorithm. + """ + try: + posterior, log_marginal_likelihood, grad_dict = self.inference_method.inference(kern, X, Z, likelihood, Y, Y_metadata, Lm=Lm, dL_dKmm=None) + except: + posterior, log_marginal_likelihood, grad_dict = self.inference_method.inference(kern, X, Z, likelihood, Y, Y_metadata) + current_values = {} + likelihood.update_gradients(grad_dict['dL_dthetaL']) + current_values['likgrad'] = likelihood.gradient.copy() + if subset_indices is None: + subset_indices = {} + if isinstance(X, VariationalPosterior): + #gradients wrt kernel + dL_dKmm = grad_dict['dL_dKmm'] + kern.update_gradients_full(dL_dKmm, Z, None) + current_values['kerngrad'] = kern.gradient.copy() + kern.update_gradients_expectations(variational_posterior=X, + Z=Z, + dL_dpsi0=grad_dict['dL_dpsi0'], + dL_dpsi1=grad_dict['dL_dpsi1'], + dL_dpsi2=grad_dict['dL_dpsi2']) + current_values['kerngrad'] += kern.gradient + + #gradients wrt Z + current_values['Zgrad'] = kern.gradients_X(dL_dKmm, Z) + current_values['Zgrad'] += kern.gradients_Z_expectations( + grad_dict['dL_dpsi0'], + grad_dict['dL_dpsi1'], + grad_dict['dL_dpsi2'], + Z=Z, + variational_posterior=X) + else: + #gradients wrt kernel + kern.update_gradients_diag(grad_dict['dL_dKdiag'], X) + current_values['kerngrad'] = kern.gradient.copy() + kern.update_gradients_full(grad_dict['dL_dKnm'], X, Z) + current_values['kerngrad'] += kern.gradient + kern.update_gradients_full(grad_dict['dL_dKmm'], Z, None) + current_values['kerngrad'] += kern.gradient + #gradients wrt Z + current_values['Zgrad'] = kern.gradients_X(grad_dict['dL_dKmm'], Z) + current_values['Zgrad'] += kern.gradients_X(grad_dict['dL_dKnm'].T, Z, X) + return posterior, log_marginal_likelihood, grad_dict, current_values, subset_indices + + def _inner_take_over_or_update(self, full_values=None, current_values=None, value_indices=None): + """ + This is for automatic updates of values in the inner loop of missing + data handling. Both arguments are dictionaries and the values in + full_values will be updated by the current_gradients. + + If a key from current_values does not exist in full_values, it will be + initialized to the value in current_values. + + If there is indices needed for the update, value_indices can be used for + that. If value_indices has the same key, as current_values, the update + in full_values will be indexed by the indices in value_indices. + + grads: + dictionary of standing gradients (you will have to carefully make sure, that + the ordering is right!). The values in here will be updated such that + full_values[key] += current_values[key] forall key in full_gradients.keys() + + gradients: + dictionary of gradients in the current set of parameters. + + value_indices: + dictionary holding indices for the update in full_values. + if the key exists the update rule is:def df(x): + full_values[key][value_indices[key]] += current_values[key] + """ + for key in current_values.keys(): + if value_indices is not None and value_indices.has_key(key): + index = value_indices[key] + else: + index = slice(None) + if full_values.has_key(key): + full_values[key][index] += current_values[key] + else: + full_values[key] = current_values[key] + + def _inner_values_update(self, current_values): + """ + This exists if there is more to do with the current values. + It will be called allways in the inner loop, so that + you can do additional inner updates for the inside of the missing data + loop etc. This can also be used for stochastic updates, when only working on + one dimension of the output. + """ + pass + + def _outer_values_update(self, full_values): + """ + Here you put the values, which were collected before in the right places. + E.g. set the gradients of parameters, etc. + """ + self.likelihood.gradient = full_values['likgrad'] + self.kern.gradient = full_values['kerngrad'] + self.Z.gradient = full_values['Zgrad'] + + def _outer_init_full_values(self): + """ + If full_values has indices in values_indices, we might want to initialize + the full_values differently, so that subsetting is possible. + + Here you can initialize the full_values for the values needed. + + Keep in mind, that if a key does not exist in full_values when updating + values, it will be set (so e.g. for Z there is no need to initialize Zgrad, + as there is no subsetting needed. For X in BGPLVM on the other hand we probably need + to initialize the gradients for the mean and the variance in order to + have the full gradient for indexing) + """ + return {} + + def _outer_loop_for_missing_data(self): + Lm = None + dL_dKmm = None + + self._log_marginal_likelihood = 0 + self.full_values = self._outer_init_full_values() + + if self.posterior is None: + woodbury_inv = np.zeros((self.num_inducing, self.num_inducing, self.output_dim)) + woodbury_vector = np.zeros((self.num_inducing, self.output_dim)) + else: + woodbury_inv = self.posterior._woodbury_inv + woodbury_vector = self.posterior._woodbury_vector + + if not self.stochastics: + m_f = lambda i: "Inference with missing_data: {: >7.2%}".format(float(i+1)/self.output_dim) + message = m_f(-1) + print message, + + for d in self.stochastics.d: + ninan = self.ninan[:, d] + + if not self.stochastics: + print ' '*(len(message)) + '\r', + message = m_f(d) + print message, + + posterior, log_marginal_likelihood, \ + grad_dict, current_values, value_indices = self._inner_parameters_changed( + self.kern, self.X[ninan], + self.Z, self.likelihood, + self.Ylist[d], self.Y_metadata, + Lm, dL_dKmm, + subset_indices=dict(outputs=d, samples=ninan)) + + self._inner_take_over_or_update(self.full_values, current_values, value_indices) + self._inner_values_update(current_values) + + Lm = posterior.K_chol + dL_dKmm = grad_dict['dL_dKmm'] + woodbury_inv[:, :, d] = posterior.woodbury_inv + woodbury_vector[:, d:d+1] = posterior.woodbury_vector + self._log_marginal_likelihood += log_marginal_likelihood + if not self.stochastics: + print '' + + if self.posterior is None: + self.posterior = Posterior(woodbury_inv=woodbury_inv, woodbury_vector=woodbury_vector, + K=posterior._K, mean=None, cov=None, K_chol=posterior.K_chol) + self._outer_values_update(self.full_values) + + def _outer_loop_without_missing_data(self): + self._log_marginal_likelihood = 0 + + if self.posterior is None: + woodbury_inv = np.zeros((self.num_inducing, self.num_inducing, self.output_dim)) + woodbury_vector = np.zeros((self.num_inducing, self.output_dim)) + else: + woodbury_inv = self.posterior._woodbury_inv + woodbury_vector = self.posterior._woodbury_vector + + d = self.stochastics.d + posterior, log_marginal_likelihood, \ + grad_dict, self.full_values, _ = self._inner_parameters_changed( + self.kern, self.X, + self.Z, self.likelihood, + self.Y_normalized[:, d], self.Y_metadata) + self.grad_dict = grad_dict + + self._log_marginal_likelihood += log_marginal_likelihood + + self._outer_values_update(self.full_values) + + woodbury_inv[:, :, d] = posterior.woodbury_inv[:, :, None] + woodbury_vector[:, d] = posterior.woodbury_vector + if self.posterior is None: + self.posterior = Posterior(woodbury_inv=woodbury_inv, woodbury_vector=woodbury_vector, + K=posterior._K, mean=None, cov=None, K_chol=posterior.K_chol) + +
      [docs] def parameters_changed(self): + if self.missing_data: + self._outer_loop_for_missing_data() + elif self.stochastics: + self._outer_loop_without_missing_data() + else: + self.posterior, self._log_marginal_likelihood, self.grad_dict, self.full_values, _ = self._inner_parameters_changed(self.kern, self.X, self.Z, self.likelihood, self.Y_normalized, self.Y_metadata) + self._outer_values_update(self.full_values) +
      + def _raw_predict(self, Xnew, full_cov=False, kern=None): + """ + Make a prediction for the latent function values + """ + + if kern is None: kern = self.kern + + if not isinstance(Xnew, VariationalPosterior): + Kx = kern.K(self.Z, Xnew) + mu = np.dot(Kx.T, self.posterior.woodbury_vector) + if full_cov: + Kxx = kern.K(Xnew) + if self.posterior.woodbury_inv.ndim == 2: + var = Kxx - np.dot(Kx.T, np.dot(self.posterior.woodbury_inv, Kx)) + elif self.posterior.woodbury_inv.ndim == 3: + var = Kxx[:,:,None] - np.tensordot(np.dot(np.atleast_3d(self.posterior.woodbury_inv).T, Kx).T, Kx, [1,0]).swapaxes(1,2) + var = var + else: + Kxx = kern.Kdiag(Xnew) + var = (Kxx - np.sum(np.dot(np.atleast_3d(self.posterior.woodbury_inv).T, Kx) * Kx[None,:,:], 1)).T + else: + Kx = kern.psi1(self.Z, Xnew) + mu = np.dot(Kx, self.posterior.woodbury_vector) + if full_cov: + raise NotImplementedError, "TODO" + else: + Kxx = kern.psi0(self.Z, Xnew) + psi2 = kern.psi2(self.Z, Xnew) + var = Kxx - np.sum(np.sum(psi2 * Kmmi_LmiBLmi[None, :, :], 1), 1) + return mu, var
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/sparse_gp_regression.html b/doc/_build/html/_modules/GPy/models/sparse_gp_regression.html new file mode 100644 index 00000000..7d0ad0b1 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/sparse_gp_regression.html @@ -0,0 +1,203 @@ + + + + + + + + GPy.models.sparse_gp_regression — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.sparse_gp_regression

      +# Copyright (c) 2012, James Hensman
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from ..core import SparseGP
      +from ..core.sparse_gp_mpi import SparseGP_MPI
      +from .. import likelihoods
      +from .. import kern
      +from ..inference.latent_function_inference import VarDTC
      +from ..core.parameterization.variational import NormalPosterior
      +from GPy.inference.latent_function_inference.var_dtc_parallel import VarDTC_minibatch
      +
      +
      [docs]class SparseGPRegression(SparseGP_MPI): + """ + Gaussian Process model for regression + + This is a thin wrapper around the SparseGP class, with a set of sensible defalts + + :param X: input observations + :param Y: observed values + :param kernel: a GPy kernel, defaults to rbf+white + :param Z: inducing inputs (optional, see note) + :type Z: np.ndarray (num_inducing x input_dim) | None + :param num_inducing: number of inducing points (ignored if Z is passed, see note) + :type num_inducing: int + :rtype: model object + + .. Note:: If no Z array is passed, num_inducing (default 10) points are selected from the data. Other wise num_inducing is ignored + .. Note:: Multiple independent outputs are allowed using columns of Y + + """ + + def __init__(self, X, Y, kernel=None, Z=None, num_inducing=10, X_variance=None, normalizer=None, mpi_comm=None): + num_data, input_dim = X.shape + + # kern defaults to rbf (plus white for stability) + if kernel is None: + kernel = kern.RBF(input_dim)# + kern.white(input_dim, variance=1e-3) + + # Z defaults to a subset of the data + if Z is None: + i = np.random.permutation(num_data)[:min(num_inducing, num_data)] + Z = X.view(np.ndarray)[i].copy() + else: + assert Z.shape[1] == input_dim + + likelihood = likelihoods.Gaussian() + + if not (X_variance is None): + X = NormalPosterior(X,X_variance) + + if mpi_comm is not None: + from ..inference.latent_function_inference.var_dtc_parallel import VarDTC_minibatch + infr = VarDTC_minibatch(mpi_comm=mpi_comm) + else: + infr = VarDTC() + + SparseGP_MPI.__init__(self, X, Y, Z, kernel, likelihood, inference_method=infr, normalizer=normalizer, mpi_comm=mpi_comm) + +
      [docs] def parameters_changed(self): + from ..inference.latent_function_inference.var_dtc_parallel import update_gradients_sparsegp,VarDTC_minibatch + if isinstance(self.inference_method,VarDTC_minibatch): + update_gradients_sparsegp(self, mpi_comm=self.mpi_comm) + else: + super(SparseGPRegression, self).parameters_changed() +
      +
      [docs]class SparseGPRegressionUncertainInput(SparseGP): + """ + Gaussian Process model for regression with Gaussian variance on the inputs (X_variance) + + This is a thin wrapper around the SparseGP class, with a set of sensible defalts + + """ + + def __init__(self, X, X_variance, Y, kernel=None, Z=None, num_inducing=10, normalizer=None): + """ + :param X: input observations + :type X: np.ndarray (num_data x input_dim) + :param X_variance: The uncertainty in the measurements of X (Gaussian variance, optional) + :type X_variance: np.ndarray (num_data x input_dim) + :param Y: observed values + :param kernel: a GPy kernel, defaults to rbf+white + :param Z: inducing inputs (optional, see note) + :type Z: np.ndarray (num_inducing x input_dim) | None + :param num_inducing: number of inducing points (ignored if Z is passed, see note) + :type num_inducing: int + :rtype: model object + + .. Note:: If no Z array is passed, num_inducing (default 10) points are selected from the data. Other wise num_inducing is ignored + .. Note:: Multiple independent outputs are allowed using columns of Y + """ + num_data, input_dim = X.shape + + # kern defaults to rbf (plus white for stability) + if kernel is None: + kernel = kern.RBF(input_dim) + kern.White(input_dim, variance=1e-3) + + # Z defaults to a subset of the data + if Z is None: + i = np.random.permutation(num_data)[:min(num_inducing, num_data)] + Z = X[i].copy() + else: + assert Z.shape[1] == input_dim + + likelihood = likelihoods.Gaussian() + + SparseGP.__init__(self, X, Y, Z, kernel, likelihood, X_variance=X_variance, inference_method=VarDTC(), normalizer=normalizer) + self.ensure_default_constraints()
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/sparse_gplvm.html b/doc/_build/html/_modules/GPy/models/sparse_gplvm.html new file mode 100644 index 00000000..9ff3ab1e --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/sparse_gplvm.html @@ -0,0 +1,137 @@ + + + + + + + + GPy.models.sparse_gplvm — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.sparse_gplvm

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +import sys
      +from GPy.models.sparse_gp_regression import SparseGPRegression
      +
      +
      [docs]class SparseGPLVM(SparseGPRegression): + """ + Sparse Gaussian Process Latent Variable Model + + :param Y: observed data + :type Y: np.ndarray + :param input_dim: latent dimensionality + :type input_dim: int + :param init: initialisation method for the latent space + :type init: 'PCA'|'random' + + """ + def __init__(self, Y, input_dim, X=None, kernel=None, init='PCA', num_inducing=10): + if X is None: + from ..util.initialization import initialize_latent + X, fracs = initialize_latent(init, input_dim, Y) + SparseGPRegression.__init__(self, X, Y, kernel=kernel, num_inducing=num_inducing) + +
      [docs] def parameters_changed(self): + super(SparseGPLVM, self).parameters_changed() + self.X.gradient = self.kern.gradients_X_diag(self.grad_dict['dL_dKdiag'], self.X) + self.X.gradient += self.kern.gradients_X(self.grad_dict['dL_dKnm'], self.X, self.Z) +
      +
      [docs] def plot_latent(self, labels=None, which_indices=None, + resolution=50, ax=None, marker='o', s=40, + fignum=None, plot_inducing=True, legend=True, + plot_limits=None, + aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={}): + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import dim_reduction_plots + + return dim_reduction_plots.plot_latent(self, labels, which_indices, + resolution, ax, marker, s, + fignum, plot_inducing, legend, + plot_limits, aspect, updates, predict_kwargs, imshow_kwargs)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/ss_gplvm.html b/doc/_build/html/_modules/GPy/models/ss_gplvm.html new file mode 100644 index 00000000..2786cc30 --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/ss_gplvm.html @@ -0,0 +1,201 @@ + + + + + + + + GPy.models.ss_gplvm — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.ss_gplvm

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +
      +from ..core.sparse_gp_mpi import SparseGP_MPI
      +from .. import kern
      +from ..likelihoods import Gaussian
      +from ..core.parameterization.variational import SpikeAndSlabPrior, SpikeAndSlabPosterior
      +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
      +
      +
      [docs]class SSGPLVM(SparseGP_MPI): + """ + Spike-and-Slab Gaussian Process Latent Variable Model + + :param Y: observed data (np.ndarray) or GPy.likelihood + :type Y: np.ndarray| GPy.likelihood instance + :param input_dim: latent dimensionality + :type input_dim: int + :param init: initialisation method for the latent space + :type init: 'PCA'|'random' + + """ + def __init__(self, Y, input_dim, X=None, X_variance=None, Gamma=None, init='PCA', num_inducing=10, + Z=None, kernel=None, inference_method=None, likelihood=None, name='Spike_and_Slab GPLVM', group_spike=False, mpi_comm=None, pi=None, learnPi=True,normalizer=False, **kwargs): + + self.group_spike = group_spike + + if X == None: + from ..util.initialization import initialize_latent + X, fracs = initialize_latent(init, input_dim, Y) + else: + fracs = np.ones(input_dim) + + self.init = init + + if X_variance is None: # The variance of the variational approximation (S) + X_variance = np.random.uniform(0,.1,X.shape) + + if Gamma is None: + gamma = np.random.randn(X.shape[0], input_dim) + else: + gamma = Gamma.copy() + + if Z is None: + Z = np.random.permutation(X.copy())[:num_inducing] + assert Z.shape[1] == X.shape[1] + + if likelihood is None: + likelihood = Gaussian() + + if kernel is None: + kernel = kern.RBF(input_dim, lengthscale=fracs, ARD=True) # + kern.white(input_dim) + if kernel.useGPU: + kernel.psicomp = PSICOMP_SSRBF_GPU() + + if inference_method is None: + inference_method = VarDTC_minibatch(mpi_comm=mpi_comm) + + if pi is None: + pi = np.empty((input_dim)) + pi[:] = 0.5 + self.variational_prior = SpikeAndSlabPrior(pi=pi,learnPi=learnPi) # the prior probability of the latent binary variable b + + X = SpikeAndSlabPosterior(X, X_variance, gamma) + + super(SSGPLVM,self).__init__(X, Y, Z, kernel, likelihood, variational_prior=self.variational_prior, inference_method=inference_method, name=name, mpi_comm=mpi_comm, normalizer=normalizer, **kwargs) +# self.X.unfix() +# self.X.variance.constrain_positive() + self.link_parameter(self.X, index=0) + + if self.group_spike: + [self.X.gamma[:,i].tie('tieGamma'+str(i)) for i in xrange(self.X.gamma.shape[1])] # Tie columns together + +
      [docs] def set_X_gradients(self, X, X_grad): + """Set the gradients of the posterior distribution of X in its specific form.""" + X.mean.gradient, X.variance.gradient, X.binary_prob.gradient = X_grad +
      +
      [docs] def get_X_gradients(self, X): + """Get the gradients of the posterior distribution of X in its specific form.""" + return X.mean.gradient, X.variance.gradient, X.binary_prob.gradient +
      +
      [docs] def parameters_changed(self): + super(SSGPLVM,self).parameters_changed() + if isinstance(self.inference_method, VarDTC_minibatch): + return + + self._log_marginal_likelihood -= self.variational_prior.KL_divergence(self.X) + + self.X.mean.gradient, self.X.variance.gradient, self.X.binary_prob.gradient = self.kern.gradients_qX_expectations(variational_posterior=self.X, Z=self.Z, dL_dpsi0=self.grad_dict['dL_dpsi0'], dL_dpsi1=self.grad_dict['dL_dpsi1'], dL_dpsi2=self.grad_dict['dL_dpsi2']) + + # update for the KL divergence + self.variational_prior.update_gradients_KL(self.X) +
      +
      [docs] def input_sensitivity(self): + if self.kern.ARD: + return self.kern.input_sensitivity() + else: + return self.variational_prior.pi +
      +
      [docs] def plot_latent(self, plot_inducing=True, *args, **kwargs): + import sys + assert "matplotlib" in sys.modules, "matplotlib package has not been imported." + from ..plotting.matplot_dep import dim_reduction_plots + + return dim_reduction_plots.plot_latent(self, plot_inducing=plot_inducing, *args, **kwargs) +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/ss_mrd.html b/doc/_build/html/_modules/GPy/models/ss_mrd.html new file mode 100644 index 00000000..ba2ea53c --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/ss_mrd.html @@ -0,0 +1,128 @@ + + + + + + + + GPy.models.ss_mrd — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.ss_mrd

      +"""
      +The Maniforld Relevance Determination model with the spike-and-slab prior
      +"""
      +
      +from ..core import Model
      +from .ss_gplvm import SSGPLVM
      +
      +
      [docs]class SSMRD(Model): + + def __init__(self, Ylist, input_dim, X=None, X_variance=None, + initx = 'PCA', initz = 'permute', + num_inducing=10, Z=None, kernel=None, + inference_method=None, likelihoods=None, name='ss_mrd', Ynames=None): + super(SSMRD, self).__init__(name) + + self.updates = False + self.models = [SSGPLVM(y, input_dim, X=X, X_variance=X_variance, num_inducing=num_inducing,Z=Z,init=initx, + kernel=kernel.copy() if kernel else None,inference_method=inference_method,likelihood=likelihoods, + name='model_'+str(i)) for i,y in enumerate(Ylist)] + self.add_parameters(*(self.models)) + + [[[self.models[m].X.mean[i,j:j+1].tie('mean_'+str(i)+'_'+str(j)) for m in xrange(len(self.models))] for j in xrange(self.models[0].X.mean.shape[1])] + for i in xrange(self.models[0].X.mean.shape[0])] + [[[self.models[m].X.variance[i,j:j+1].tie('var_'+str(i)+'_'+str(j)) for m in xrange(len(self.models))] for j in xrange(self.models[0].X.variance.shape[1])] + for i in xrange(self.models[0].X.variance.shape[0])] + + self.updates = True + +
      [docs] def parameters_changed(self): + super(SSMRD, self).parameters_changed() + self._log_marginal_likelihood = sum([m._log_marginal_likelihood for m in self.models]) +
      +
      [docs] def log_likelihood(self): + return self._log_marginal_likelihood
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/models/warped_gp.html b/doc/_build/html/_modules/GPy/models/warped_gp.html new file mode 100644 index 00000000..9bc2d93b --- /dev/null +++ b/doc/_build/html/_modules/GPy/models/warped_gp.html @@ -0,0 +1,193 @@ + + + + + + + + GPy.models.warped_gp — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.models.warped_gp

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +from ..util.warping_functions import *
      +from ..core import GP
      +from .. import likelihoods
      +from GPy.util.warping_functions import TanhWarpingFunction_d
      +from GPy import kern
      +
      +
      [docs]class WarpedGP(GP): + def __init__(self, X, Y, kernel=None, warping_function=None, warping_terms=3, normalize_X=False, normalize_Y=False): + + if kernel is None: + kernel = kern.rbf(X.shape[1]) + + if warping_function == None: + self.warping_function = TanhWarpingFunction_d(warping_terms) + self.warping_params = (np.random.randn(self.warping_function.n_terms * 3 + 1,) * 1) + + self.scale_data = False + if self.scale_data: + Y = self._scale_data(Y) + self.has_uncertain_inputs = False + self.Y_untransformed = Y.copy() + self.predict_in_warped_space = False + likelihood = likelihoods.Gaussian(self.transform_data(), normalize=normalize_Y) + + GP.__init__(self, X, likelihood, kernel, normalize_X=normalize_X) + self._set_params(self._get_params()) + + def _scale_data(self, Y): + self._Ymax = Y.max() + self._Ymin = Y.min() + return (Y - self._Ymin) / (self._Ymax - self._Ymin) - 0.5 + + def _unscale_data(self, Y): + return (Y + 0.5) * (self._Ymax - self._Ymin) + self._Ymin + + def _set_params(self, x): + self.warping_params = x[:self.warping_function.num_parameters] + Y = self.transform_data() + self.likelihood.set_data(Y) + GP._set_params(self, x[self.warping_function.num_parameters:].copy()) + + def _get_params(self): + return np.hstack((self.warping_params.flatten().copy(), GP._get_params(self).copy())) + + def _get_param_names(self): + warping_names = self.warping_function._get_param_names() + param_names = GP._get_param_names(self) + return warping_names + param_names + +
      [docs] def transform_data(self): + Y = self.warping_function.f(self.Y_untransformed.copy(), self.warping_params).copy() + return Y +
      +
      [docs] def log_likelihood(self): + ll = GP.log_likelihood(self) + jacobian = self.warping_function.fgrad_y(self.Y_untransformed, self.warping_params) + return ll + np.log(jacobian).sum() +
      + def _log_likelihood_gradients(self): + ll_grads = GP._log_likelihood_gradients(self) + alpha = np.dot(self.Ki, self.likelihood.Y.flatten()) + warping_grads = self.warping_function_gradients(alpha) + + warping_grads = np.append(warping_grads[:, :-1].flatten(), warping_grads[0, -1]) + return np.hstack((warping_grads.flatten(), ll_grads.flatten())) + +
      [docs] def warping_function_gradients(self, Kiy): + grad_y = self.warping_function.fgrad_y(self.Y_untransformed, self.warping_params) + grad_y_psi, grad_psi = self.warping_function.fgrad_y_psi(self.Y_untransformed, self.warping_params, + return_covar_chain=True) + djac_dpsi = ((1.0 / grad_y[:, :, None, None]) * grad_y_psi).sum(axis=0).sum(axis=0) + dquad_dpsi = (Kiy[:, None, None, None] * grad_psi).sum(axis=0).sum(axis=0) + + return -dquad_dpsi + djac_dpsi +
      +
      [docs] def plot_warping(self): + self.warping_function.plot(self.warping_params, self.Y_untransformed.min(), self.Y_untransformed.max()) +
      +
      [docs] def predict(self, Xnew, which_parts='all', full_cov=False, pred_init=None): + # normalize X values + Xnew = (Xnew.copy() - self._Xoffset) / self._Xscale + mu, var = GP._raw_predict(self, Xnew, full_cov=full_cov, which_parts=which_parts) + + # now push through likelihood + mean, var, _025pm, _975pm = self.likelihood.predictive_values(mu, var, full_cov) + + if self.predict_in_warped_space: + mean = self.warping_function.f_inv(mean, self.warping_params, y=pred_init) + var = self.warping_function.f_inv(var, self.warping_params) + + if self.scale_data: + mean = self._unscale_data(mean) + + return mean, var, _025pm, _975pm
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/Tango.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/Tango.html new file mode 100644 index 00000000..af3463d5 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/Tango.html @@ -0,0 +1,260 @@ + + + + + + + + GPy.plotting.matplot_dep.Tango — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.Tango

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import matplotlib as mpl
      +import pylab as pb
      +import sys
      +#sys.path.append('/home/james/mlprojects/sitran_cluster/')
      +#from switch_pylab_backend import *
      +
      +
      +#this stuff isn;t really Tango related: maybe it could be moved out? TODO
      +
      [docs]def removeRightTicks(ax=None): + ax = ax or pb.gca() + for i, line in enumerate(ax.get_yticklines()): + if i%2 == 1: # odd indices + line.set_visible(False)
      +
      [docs]def removeUpperTicks(ax=None): + ax = ax or pb.gca() + for i, line in enumerate(ax.get_xticklines()): + if i%2 == 1: # odd indices + line.set_visible(False)
      +
      [docs]def fewerXticks(ax=None,divideby=2): + ax = ax or pb.gca() + ax.set_xticks(ax.get_xticks()[::divideby]) + +
      +colorsHex = {\ +"Aluminium6":"#2e3436",\ +"Aluminium5":"#555753",\ +"Aluminium4":"#888a85",\ +"Aluminium3":"#babdb6",\ +"Aluminium2":"#d3d7cf",\ +"Aluminium1":"#eeeeec",\ +"lightPurple":"#ad7fa8",\ +"mediumPurple":"#75507b",\ +"darkPurple":"#5c3566",\ +"lightBlue":"#729fcf",\ +"mediumBlue":"#3465a4",\ +"darkBlue": "#204a87",\ +"lightGreen":"#8ae234",\ +"mediumGreen":"#73d216",\ +"darkGreen":"#4e9a06",\ +"lightChocolate":"#e9b96e",\ +"mediumChocolate":"#c17d11",\ +"darkChocolate":"#8f5902",\ +"lightRed":"#ef2929",\ +"mediumRed":"#cc0000",\ +"darkRed":"#a40000",\ +"lightOrange":"#fcaf3e",\ +"mediumOrange":"#f57900",\ +"darkOrange":"#ce5c00",\ +"lightButter":"#fce94f",\ +"mediumButter":"#edd400",\ +"darkButter":"#c4a000"} + +darkList = [colorsHex['darkBlue'],colorsHex['darkRed'],colorsHex['darkGreen'], colorsHex['darkOrange'], colorsHex['darkButter'], colorsHex['darkPurple'], colorsHex['darkChocolate'], colorsHex['Aluminium6']] +mediumList = [colorsHex['mediumBlue'], colorsHex['mediumRed'],colorsHex['mediumGreen'], colorsHex['mediumOrange'], colorsHex['mediumButter'], colorsHex['mediumPurple'], colorsHex['mediumChocolate'], colorsHex['Aluminium5']] +lightList = [colorsHex['lightBlue'], colorsHex['lightRed'],colorsHex['lightGreen'], colorsHex['lightOrange'], colorsHex['lightButter'], colorsHex['lightPurple'], colorsHex['lightChocolate'], colorsHex['Aluminium4']] + +
      [docs]def currentDark(): + return darkList[-1]
      +
      [docs]def currentMedium(): + return mediumList[-1]
      +
      [docs]def currentLight(): + return lightList[-1] +
      +
      [docs]def nextDark(): + darkList.append(darkList.pop(0)) + return darkList[-1]
      +
      [docs]def nextMedium(): + mediumList.append(mediumList.pop(0)) + return mediumList[-1]
      +
      [docs]def nextLight(): + lightList.append(lightList.pop(0)) + return lightList[-1] +
      +
      [docs]def reset(): + while not darkList[0]==colorsHex['darkBlue']: + darkList.append(darkList.pop(0)) + while not mediumList[0]==colorsHex['mediumBlue']: + mediumList.append(mediumList.pop(0)) + while not lightList[0]==colorsHex['lightBlue']: + lightList.append(lightList.pop(0)) +
      +
      [docs]def setLightFigures(): + mpl.rcParams['axes.edgecolor']=colorsHex['Aluminium6'] + mpl.rcParams['axes.facecolor']=colorsHex['Aluminium2'] + mpl.rcParams['axes.labelcolor']=colorsHex['Aluminium6'] + mpl.rcParams['figure.edgecolor']=colorsHex['Aluminium6'] + mpl.rcParams['figure.facecolor']=colorsHex['Aluminium2'] + mpl.rcParams['grid.color']=colorsHex['Aluminium6'] + mpl.rcParams['savefig.edgecolor']=colorsHex['Aluminium2'] + mpl.rcParams['savefig.facecolor']=colorsHex['Aluminium2'] + mpl.rcParams['text.color']=colorsHex['Aluminium6'] + mpl.rcParams['xtick.color']=colorsHex['Aluminium6'] + mpl.rcParams['ytick.color']=colorsHex['Aluminium6'] +
      +
      [docs]def setDarkFigures(): + mpl.rcParams['axes.edgecolor']=colorsHex['Aluminium2'] + mpl.rcParams['axes.facecolor']=colorsHex['Aluminium6'] + mpl.rcParams['axes.labelcolor']=colorsHex['Aluminium2'] + mpl.rcParams['figure.edgecolor']=colorsHex['Aluminium2'] + mpl.rcParams['figure.facecolor']=colorsHex['Aluminium6'] + mpl.rcParams['grid.color']=colorsHex['Aluminium2'] + mpl.rcParams['savefig.edgecolor']=colorsHex['Aluminium6'] + mpl.rcParams['savefig.facecolor']=colorsHex['Aluminium6'] + mpl.rcParams['text.color']=colorsHex['Aluminium2'] + mpl.rcParams['xtick.color']=colorsHex['Aluminium2'] + mpl.rcParams['ytick.color']=colorsHex['Aluminium2'] +
      +
      [docs]def hex2rgb(hexcolor): + hexcolor = [hexcolor[1+2*i:1+2*(i+1)] for i in range(3)] + r,g,b = [int(n,16) for n in hexcolor] + return (r,g,b) +
      +colorsRGB = dict([(k,hex2rgb(i)) for k,i in colorsHex.items()]) + +cdict_RB = {'red' :((0.,colorsRGB['mediumRed'][0]/256.,colorsRGB['mediumRed'][0]/256.), + (.5,colorsRGB['mediumPurple'][0]/256.,colorsRGB['mediumPurple'][0]/256.), + (1.,colorsRGB['mediumBlue'][0]/256.,colorsRGB['mediumBlue'][0]/256.)), + 'green':((0.,colorsRGB['mediumRed'][1]/256.,colorsRGB['mediumRed'][1]/256.), + (.5,colorsRGB['mediumPurple'][1]/256.,colorsRGB['mediumPurple'][1]/256.), + (1.,colorsRGB['mediumBlue'][1]/256.,colorsRGB['mediumBlue'][1]/256.)), + 'blue':((0.,colorsRGB['mediumRed'][2]/256.,colorsRGB['mediumRed'][2]/256.), + (.5,colorsRGB['mediumPurple'][2]/256.,colorsRGB['mediumPurple'][2]/256.), + (1.,colorsRGB['mediumBlue'][2]/256.,colorsRGB['mediumBlue'][2]/256.))} + +cdict_BGR = {'red' :((0.,colorsRGB['mediumBlue'][0]/256.,colorsRGB['mediumBlue'][0]/256.), + (.5,colorsRGB['mediumGreen'][0]/256.,colorsRGB['mediumGreen'][0]/256.), + (1.,colorsRGB['mediumRed'][0]/256.,colorsRGB['mediumRed'][0]/256.)), + 'green':((0.,colorsRGB['mediumBlue'][1]/256.,colorsRGB['mediumBlue'][1]/256.), + (.5,colorsRGB['mediumGreen'][1]/256.,colorsRGB['mediumGreen'][1]/256.), + (1.,colorsRGB['mediumRed'][1]/256.,colorsRGB['mediumRed'][1]/256.)), + 'blue':((0.,colorsRGB['mediumBlue'][2]/256.,colorsRGB['mediumBlue'][2]/256.), + (.5,colorsRGB['mediumGreen'][2]/256.,colorsRGB['mediumGreen'][2]/256.), + (1.,colorsRGB['mediumRed'][2]/256.,colorsRGB['mediumRed'][2]/256.))} + + +cdict_Alu = {'red' :((0./5,colorsRGB['Aluminium1'][0]/256.,colorsRGB['Aluminium1'][0]/256.), + (1./5,colorsRGB['Aluminium2'][0]/256.,colorsRGB['Aluminium2'][0]/256.), + (2./5,colorsRGB['Aluminium3'][0]/256.,colorsRGB['Aluminium3'][0]/256.), + (3./5,colorsRGB['Aluminium4'][0]/256.,colorsRGB['Aluminium4'][0]/256.), + (4./5,colorsRGB['Aluminium5'][0]/256.,colorsRGB['Aluminium5'][0]/256.), + (5./5,colorsRGB['Aluminium6'][0]/256.,colorsRGB['Aluminium6'][0]/256.)), + 'green' :((0./5,colorsRGB['Aluminium1'][1]/256.,colorsRGB['Aluminium1'][1]/256.), + (1./5,colorsRGB['Aluminium2'][1]/256.,colorsRGB['Aluminium2'][1]/256.), + (2./5,colorsRGB['Aluminium3'][1]/256.,colorsRGB['Aluminium3'][1]/256.), + (3./5,colorsRGB['Aluminium4'][1]/256.,colorsRGB['Aluminium4'][1]/256.), + (4./5,colorsRGB['Aluminium5'][1]/256.,colorsRGB['Aluminium5'][1]/256.), + (5./5,colorsRGB['Aluminium6'][1]/256.,colorsRGB['Aluminium6'][1]/256.)), + 'blue' :((0./5,colorsRGB['Aluminium1'][2]/256.,colorsRGB['Aluminium1'][2]/256.), + (1./5,colorsRGB['Aluminium2'][2]/256.,colorsRGB['Aluminium2'][2]/256.), + (2./5,colorsRGB['Aluminium3'][2]/256.,colorsRGB['Aluminium3'][2]/256.), + (3./5,colorsRGB['Aluminium4'][2]/256.,colorsRGB['Aluminium4'][2]/256.), + (4./5,colorsRGB['Aluminium5'][2]/256.,colorsRGB['Aluminium5'][2]/256.), + (5./5,colorsRGB['Aluminium6'][2]/256.,colorsRGB['Aluminium6'][2]/256.))} +# cmap_Alu = mpl.colors.LinearSegmentedColormap('TangoAluminium',cdict_Alu,256) +# cmap_BGR = mpl.colors.LinearSegmentedColormap('TangoRedBlue',cdict_BGR,256) +# cmap_RB = mpl.colors.LinearSegmentedColormap('TangoRedBlue',cdict_RB,256) +if __name__=='__main__': + import pylab as pb + pb.figure() + pb.pcolor(pb.rand(10,10),cmap=cmap_RB) + pb.colorbar() + pb.show() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/base_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/base_plots.html new file mode 100644 index 00000000..81853a27 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/base_plots.html @@ -0,0 +1,251 @@ + + + + + + + + GPy.plotting.matplot_dep.base_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.base_plots

      +# #Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +try:
      +    import Tango
      +    import pylab as pb
      +except:
      +    pass
      +import numpy as np
      +
      +
      [docs]def ax_default(fignum, ax): + if ax is None: + fig = pb.figure(fignum) + ax = fig.add_subplot(111) + else: + fig = ax.figure + return fig, ax +
      +
      [docs]def meanplot(x, mu, color=Tango.colorsHex['darkBlue'], ax=None, fignum=None, linewidth=2,**kw): + _, axes = ax_default(fignum, ax) + return axes.plot(x,mu,color=color,linewidth=linewidth,**kw) +
      +
      [docs]def gpplot(x, mu, lower, upper, edgecol=Tango.colorsHex['darkBlue'], fillcol=Tango.colorsHex['lightBlue'], ax=None, fignum=None, **kwargs): + _, axes = ax_default(fignum, ax) + + mu = mu.flatten() + x = x.flatten() + lower = lower.flatten() + upper = upper.flatten() + + plots = [] + + #here's the mean + plots.append(meanplot(x, mu, edgecol, axes)) + + #here's the box + kwargs['linewidth']=0.5 + if not 'alpha' in kwargs.keys(): + kwargs['alpha'] = 0.3 + plots.append(axes.fill(np.hstack((x,x[::-1])),np.hstack((upper,lower[::-1])),color=fillcol,**kwargs)) + + #this is the edge: + plots.append(meanplot(x, upper,color=edgecol,linewidth=0.2,ax=axes)) + plots.append(meanplot(x, lower,color=edgecol,linewidth=0.2,ax=axes)) + + return plots + +
      +
      [docs]def removeRightTicks(ax=None): + ax = ax or pb.gca() + for i, line in enumerate(ax.get_yticklines()): + if i%2 == 1: # odd indices + line.set_visible(False) +
      +
      [docs]def removeUpperTicks(ax=None): + ax = ax or pb.gca() + for i, line in enumerate(ax.get_xticklines()): + if i%2 == 1: # odd indices + line.set_visible(False) +
      +
      [docs]def fewerXticks(ax=None,divideby=2): + ax = ax or pb.gca() + ax.set_xticks(ax.get_xticks()[::divideby]) +
      +
      [docs]def align_subplots(N,M,xlim=None, ylim=None): + """make all of the subplots have the same limits, turn off unnecessary ticks""" + #find sensible xlim,ylim + if xlim is None: + xlim = [np.inf,-np.inf] + for i in range(N*M): + pb.subplot(N,M,i+1) + xlim[0] = min(xlim[0],pb.xlim()[0]) + xlim[1] = max(xlim[1],pb.xlim()[1]) + if ylim is None: + ylim = [np.inf,-np.inf] + for i in range(N*M): + pb.subplot(N,M,i+1) + ylim[0] = min(ylim[0],pb.ylim()[0]) + ylim[1] = max(ylim[1],pb.ylim()[1]) + + for i in range(N*M): + pb.subplot(N,M,i+1) + pb.xlim(xlim) + pb.ylim(ylim) + if (i)%M: + pb.yticks([]) + else: + removeRightTicks() + if i<(M*(N-1)): + pb.xticks([]) + else: + removeUpperTicks() +
      +
      [docs]def align_subplot_array(axes,xlim=None, ylim=None): + """ + Make all of the axes in the array hae the same limits, turn off unnecessary ticks + use pb.subplots() to get an array of axes + """ + #find sensible xlim,ylim + if xlim is None: + xlim = [np.inf,-np.inf] + for ax in axes.flatten(): + xlim[0] = min(xlim[0],ax.get_xlim()[0]) + xlim[1] = max(xlim[1],ax.get_xlim()[1]) + if ylim is None: + ylim = [np.inf,-np.inf] + for ax in axes.flatten(): + ylim[0] = min(ylim[0],ax.get_ylim()[0]) + ylim[1] = max(ylim[1],ax.get_ylim()[1]) + + N,M = axes.shape + for i,ax in enumerate(axes.flatten()): + ax.set_xlim(xlim) + ax.set_ylim(ylim) + if (i)%M: + ax.set_yticks([]) + else: + removeRightTicks(ax) + if i<(M*(N-1)): + ax.set_xticks([]) + else: + removeUpperTicks(ax) +
      +
      [docs]def x_frame1D(X,plot_limits=None,resolution=None): + """ + Internal helper function for making plots, returns a set of input values to plot as well as lower and upper limits + """ + assert X.shape[1] ==1, "x_frame1D is defined for one-dimensional inputs" + if plot_limits is None: + xmin,xmax = X.min(0),X.max(0) + xmin, xmax = xmin-0.2*(xmax-xmin), xmax+0.2*(xmax-xmin) + elif len(plot_limits)==2: + xmin, xmax = plot_limits + else: + raise ValueError, "Bad limits for plotting" + + Xnew = np.linspace(xmin,xmax,resolution or 200)[:,None] + return Xnew, xmin, xmax +
      +
      [docs]def x_frame2D(X,plot_limits=None,resolution=None): + """ + Internal helper function for making plots, returns a set of input values to plot as well as lower and upper limits + """ + assert X.shape[1] ==2, "x_frame2D is defined for two-dimensional inputs" + if plot_limits is None: + xmin,xmax = X.min(0),X.max(0) + xmin, xmax = xmin-0.2*(xmax-xmin), xmax+0.2*(xmax-xmin) + elif len(plot_limits)==2: + xmin, xmax = plot_limits + else: + raise ValueError, "Bad limits for plotting" + + resolution = resolution or 50 + xx,yy = np.mgrid[xmin[0]:xmax[0]:1j*resolution,xmin[1]:xmax[1]:1j*resolution] + Xnew = np.vstack((xx.flatten(),yy.flatten())).T + return Xnew, xx, yy, xmin, xmax
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/dim_reduction_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/dim_reduction_plots.html new file mode 100644 index 00000000..58934bb1 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/dim_reduction_plots.html @@ -0,0 +1,432 @@ + + + + + + + + GPy.plotting.matplot_dep.dim_reduction_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.dim_reduction_plots

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from latent_space_visualizations.controllers.imshow_controller import ImshowController,ImAnnotateController
      +from ...core.parameterization.variational import VariationalPosterior
      +from .base_plots import x_frame2D
      +import itertools
      +try:
      +    import Tango
      +    from matplotlib.cm import get_cmap
      +    import pylab as pb
      +except:
      +    pass
      +
      +
      [docs]def most_significant_input_dimensions(model, which_indices): + """ + Determine which dimensions should be plotted + """ + if which_indices is None: + if model.input_dim == 1: + input_1 = 0 + input_2 = None + if model.input_dim == 2: + input_1, input_2 = 0, 1 + else: + try: + input_1, input_2 = np.argsort(model.input_sensitivity())[::-1][:2] + except: + raise ValueError, "cannot automatically determine which dimensions to plot, please pass 'which_indices'" + else: + input_1, input_2 = which_indices + return input_1, input_2 +
      +
      [docs]def plot_latent(model, labels=None, which_indices=None, + resolution=50, ax=None, marker='o', s=40, + fignum=None, plot_inducing=False, legend=True, + plot_limits=None, + aspect='auto', updates=False, predict_kwargs={}, imshow_kwargs={}): + """ + :param labels: a np.array of size model.num_data containing labels for the points (can be number, strings, etc) + :param resolution: the resolution of the grid on which to evaluate the predictive variance + """ + if ax is None: + fig = pb.figure(num=fignum) + ax = fig.add_subplot(111) + else: + fig = ax.figure + Tango.reset() + + if labels is None: + labels = np.ones(model.num_data) + + input_1, input_2 = most_significant_input_dimensions(model, which_indices) + + #fethch the data points X that we'd like to plot + X = model.X + if isinstance(X, VariationalPosterior): + X = X.mean + else: + X = X + + + if X.shape[0] > 1000: + print "Warning: subsampling X, as it has more samples then 1000. X.shape={!s}".format(X.shape) + subsample = np.random.choice(X.shape[0], size=1000, replace=False) + X = X[subsample] + labels = labels[subsample] + #======================================================================= + # <<<WORK IN PROGRESS>>> + # <<<DO NOT DELETE>>> + # plt.close('all') + # fig, ax = plt.subplots(1,1) + # from GPy.plotting.matplot_dep.dim_reduction_plots import most_significant_input_dimensions + # import matplotlib.patches as mpatches + # i1, i2 = most_significant_input_dimensions(m, None) + # xmin, xmax = 100, -100 + # ymin, ymax = 100, -100 + # legend_handles = [] + # + # X = m.X.mean[:, [i1, i2]] + # X = m.X.variance[:, [i1, i2]] + # + # xmin = X[:,0].min(); xmax = X[:,0].max() + # ymin = X[:,1].min(); ymax = X[:,1].max() + # range_ = [[xmin, xmax], [ymin, ymax]] + # ul = np.unique(labels) + # + # for i, l in enumerate(ul): + # #cdict = dict(red =[(0., colors[i][0], colors[i][0]), (1., colors[i][0], colors[i][0])], + # # green=[(0., colors[i][0], colors[i][1]), (1., colors[i][1], colors[i][1])], + # # blue =[(0., colors[i][0], colors[i][2]), (1., colors[i][2], colors[i][2])], + # # alpha=[(0., 0., .0), (.5, .5, .5), (1., .5, .5)]) + # #cmap = LinearSegmentedColormap('{}'.format(l), cdict) + # cmap = LinearSegmentedColormap.from_list('cmap_{}'.format(str(l)), [colors[i], colors[i]], 255) + # cmap._init() + # #alphas = .5*(1+scipy.special.erf(np.linspace(-2,2, cmap.N+3)))#np.log(np.linspace(np.exp(0), np.exp(1.), cmap.N+3)) + # alphas = (scipy.special.erf(np.linspace(0,2.4, cmap.N+3)))#np.log(np.linspace(np.exp(0), np.exp(1.), cmap.N+3)) + # cmap._lut[:, -1] = alphas + # print l + # x, y = X[labels==l].T + # + # heatmap, xedges, yedges = np.histogram2d(x, y, bins=300, range=range_) + # #heatmap, xedges, yedges = np.histogram2d(x, y, bins=100) + # + # im = ax.imshow(heatmap, extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]], cmap=cmap, aspect='auto', interpolation='nearest', label=str(l)) + # legend_handles.append(mpatches.Patch(color=colors[i], label=l)) + # ax.set_xlim(xmin, xmax) + # ax.set_ylim(ymin, ymax) + # plt.legend(legend_handles, [l.get_label() for l in legend_handles]) + # plt.draw() + # plt.show() + #======================================================================= + + # create a function which computes the shading of latent space according to the output variance + def plot_function(x): + Xtest_full = np.zeros((x.shape[0], model.X.shape[1])) + Xtest_full[:, [input_1, input_2]] = x + _, var = model.predict(Xtest_full, **predict_kwargs) + var = var[:, :1] + return np.log(var) + + #Create an IMshow controller that can re-plot the latent space shading at a good resolution + if plot_limits is None: + xmin, ymin = X[:, [input_1, input_2]].min(0) + xmax, ymax = X[:, [input_1, input_2]].max(0) + x_r, y_r = xmax-xmin, ymax-ymin + xmin -= .1*x_r + xmax += .1*x_r + ymin -= .1*y_r + ymax += .1*y_r + else: + try: + xmin, xmax, ymin, ymax = plot_limits + except (TypeError, ValueError) as e: + raise e.__class__, "Wrong plot limits: {} given -> need (xmin, xmax, ymin, ymax)".format(plot_limits) + view = ImshowController(ax, plot_function, + (xmin, ymin, xmax, ymax), + resolution, aspect=aspect, interpolation='bilinear', + cmap=pb.cm.binary, **imshow_kwargs) + + # make sure labels are in order of input: + labels = np.asarray(labels) + ulabels = [] + for lab in labels: + if not lab in ulabels: + ulabels.append(lab) + + marker = itertools.cycle(list(marker)) + + for i, ul in enumerate(ulabels): + if type(ul) is np.string_: + this_label = ul + elif type(ul) is np.int64: + this_label = 'class %i' % ul + else: + this_label = unicode(ul) + m = marker.next() + + index = np.nonzero(labels == ul)[0] + if model.input_dim == 1: + x = X[index, input_1] + y = np.zeros(index.size) + else: + x = X[index, input_1] + y = X[index, input_2] + ax.scatter(x, y, marker=m, s=s, c=Tango.nextMedium(), label=this_label, linewidth=.2, edgecolor='k', alpha=.9) + + ax.set_xlabel('latent dimension %i' % input_1) + ax.set_ylabel('latent dimension %i' % input_2) + + if not np.all(labels == 1.) and legend: + ax.legend(loc=0, numpoints=1) + + ax.grid(b=False) # remove the grid if present, it doesn't look good + ax.set_aspect('auto') # set a nice aspect ratio + + if plot_inducing: + Z = model.Z + ax.scatter(Z[:, input_1], Z[:, input_2], c='w', s=14, marker="^", edgecolor='k', linewidth=.3, alpha=.6) + + ax.set_xlim((xmin, xmax)) + ax.set_ylim((ymin, ymax)) + + try: + fig.canvas.draw() + fig.tight_layout() + fig.canvas.draw() + except Exception as e: + print "Could not invoke tight layout: {}".format(e) + pass + + if updates: + try: + ax.figure.canvas.show() + except Exception as e: + print "Could not invoke show: {}".format(e) + raw_input('Enter to continue') + view.deactivate() + return ax +
      +
      [docs]def plot_magnification(model, labels=None, which_indices=None, + resolution=60, ax=None, marker='o', s=40, + fignum=None, plot_inducing=False, legend=True, + aspect='auto', updates=False): + """ + :param labels: a np.array of size model.num_data containing labels for the points (can be number, strings, etc) + :param resolution: the resolution of the grid on which to evaluate the predictive variance + """ + if ax is None: + fig = pb.figure(num=fignum) + ax = fig.add_subplot(111) + Tango.reset() + + if labels is None: + labels = np.ones(model.num_data) + + input_1, input_2 = most_significant_input_dimensions(model, which_indices) + + # first, plot the output variance as a function of the latent space + Xtest, xx, yy, xmin, xmax = x_frame2D(model.X[:, [input_1, input_2]], resolution=resolution) + Xtest_full = np.zeros((Xtest.shape[0], model.X.shape[1])) + + def plot_function(x): + Xtest_full[:, [input_1, input_2]] = x + mf=model.magnification(Xtest_full) + return mf + + view = ImshowController(ax, plot_function, + tuple(model.X.min(0)[:, [input_1, input_2]]) + tuple(model.X.max(0)[:, [input_1, input_2]]), + resolution, aspect=aspect, interpolation='bilinear', + cmap=pb.cm.gray) + + # make sure labels are in order of input: + ulabels = [] + for lab in labels: + if not lab in ulabels: + ulabels.append(lab) + + marker = itertools.cycle(list(marker)) + + for i, ul in enumerate(ulabels): + if type(ul) is np.string_: + this_label = ul + elif type(ul) is np.int64: + this_label = 'class %i' % ul + else: + this_label = 'class %i' % i + m = marker.next() + + index = np.nonzero(labels == ul)[0] + if model.input_dim == 1: + x = model.X[index, input_1] + y = np.zeros(index.size) + else: + x = model.X[index, input_1] + y = model.X[index, input_2] + ax.scatter(x, y, marker=m, s=s, color=Tango.nextMedium(), label=this_label) + + ax.set_xlabel('latent dimension %i' % input_1) + ax.set_ylabel('latent dimension %i' % input_2) + + if not np.all(labels == 1.) and legend: + ax.legend(loc=0, numpoints=1) + + ax.set_xlim(xmin[0], xmax[0]) + ax.set_ylim(xmin[1], xmax[1]) + ax.grid(b=False) # remove the grid if present, it doesn't look good + ax.set_aspect('auto') # set a nice aspect ratio + + if plot_inducing: + ax.plot(model.Z[:, input_1], model.Z[:, input_2], '^w') + + if updates: + fig.canvas.show() + raw_input('Enter to continue') + + pb.title('Magnification Factor') + return ax + +
      +
      [docs]def plot_steepest_gradient_map(model, fignum=None, ax=None, which_indices=None, labels=None, data_labels=None, data_marker='o', data_s=40, resolution=20, aspect='auto', updates=False, ** kwargs): + + input_1, input_2 = significant_dims = most_significant_input_dimensions(model, which_indices) + + X = np.zeros((resolution ** 2, model.input_dim)) + indices = np.r_[:X.shape[0]] + if labels is None: + labels = range(model.output_dim) + + def plot_function(x): + X[:, significant_dims] = x + dmu_dX = model.dmu_dXnew(X) + argmax = np.argmax(dmu_dX, 1) + return dmu_dX[indices, argmax], np.array(labels)[argmax] + + if ax is None: + fig = pb.figure(num=fignum) + ax = fig.add_subplot(111) + + if data_labels is None: + data_labels = np.ones(model.num_data) + ulabels = [] + for lab in data_labels: + if not lab in ulabels: + ulabels.append(lab) + marker = itertools.cycle(list(data_marker)) + for i, ul in enumerate(ulabels): + if type(ul) is np.string_: + this_label = ul + elif type(ul) is np.int64: + this_label = 'class %i' % ul + else: + this_label = 'class %i' % i + m = marker.next() + index = np.nonzero(data_labels == ul)[0] + x = model.X[index, input_1] + y = model.X[index, input_2] + ax.scatter(x, y, marker=m, s=data_s, color=Tango.nextMedium(), label=this_label) + + ax.set_xlabel('latent dimension %i' % input_1) + ax.set_ylabel('latent dimension %i' % input_2) + + controller = ImAnnotateController(ax, + plot_function, + tuple(model.X.min(0)[:, significant_dims]) + tuple(model.X.max(0)[:, significant_dims]), + resolution=resolution, + aspect=aspect, + cmap=get_cmap('jet'), + **kwargs) + ax.legend() + ax.figure.tight_layout() + if updates: + pb.show() + clear = raw_input('Enter to continue') + if clear.lower() in 'yes' or clear == '': + controller.deactivate() + return controller.view
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/img_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/img_plots.html new file mode 100644 index 00000000..b4eabe2f --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/img_plots.html @@ -0,0 +1,152 @@ + + + + + + + + GPy.plotting.matplot_dep.img_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.img_plots

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +"""
      +The module contains the tools for ploting 2D image visualizations
      +"""
      +
      +import numpy as np
      +from matplotlib.cm import jet
      +
      +width_max = 15
      +height_max = 12
      +
      +def _calculateFigureSize(x_size, y_size, fig_ncols, fig_nrows, pad):
      +    width = (x_size*fig_ncols+pad*(fig_ncols-1))
      +    height = (y_size*fig_nrows+pad*(fig_nrows-1))
      +    if width > float(height)/height_max*width_max:
      +        return (width_max, float(width_max)/width*height)
      +    else:
      +        return (float(height_max)/height*width, height_max)
      +
      +
      [docs]def plot_2D_images(figure, arr, symmetric=False, pad=None, zoom=None, mode=None, interpolation='nearest'): + ax = figure.add_subplot(111) + if len(arr.shape)==2: + arr = arr.reshape(*((1,)+arr.shape)) + fig_num = arr.shape[0] + y_size = arr.shape[1] + x_size = arr.shape[2] + fig_ncols = int(np.ceil(np.sqrt(fig_num))) + fig_nrows = int(np.ceil((float)(fig_num)/fig_ncols)) + if pad==None: + pad = max(int(min(y_size,x_size)/10),1) + + figsize = _calculateFigureSize(x_size, y_size, fig_ncols, fig_nrows, pad) + #figure.set_size_inches(figsize,forward=True) + #figure.subplots_adjust(left=0.05, bottom=0.05, right=0.95, top=0.95) + + if symmetric: + # symmetric around zero: fix zero as the middle color + mval = max(abs(arr.max()),abs(arr.min())) + arr = arr/(2.*mval)+0.5 + else: + minval,maxval = arr.min(),arr.max() + arr = (arr-minval)/(maxval-minval) + + if mode=='L': + arr_color = np.empty(arr.shape+(3,)) + arr_color[:] = arr.reshape(*(arr.shape+(1,))) + elif mode==None or mode=='jet': + arr_color = jet(arr) + + buf = np.ones((y_size*fig_nrows+pad*(fig_nrows-1), x_size*fig_ncols+pad*(fig_ncols-1), 3),dtype=arr.dtype) + + for y in xrange(fig_nrows): + for x in xrange(fig_ncols): + if y*fig_ncols+x<fig_num: + buf[y*y_size+y*pad:(y+1)*y_size+y*pad, x*x_size+x*pad:(x+1)*x_size+x*pad] = arr_color[y*fig_ncols+x,:,:,:3] + img_plot = ax.imshow(buf, interpolation=interpolation) + ax.axis('off')
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/inference_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/inference_plots.html new file mode 100644 index 00000000..2cd9c339 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/inference_plots.html @@ -0,0 +1,125 @@ + + + + + + + + GPy.plotting.matplot_dep.inference_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.inference_plots

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +try:
      +    import pylab as pb
      +except:
      +    pass
      +#import numpy as np
      +#import Tango
      +#from base_plots import gpplot, x_frame1D, x_frame2D
      +
      +
      +
      [docs]def plot_optimizer(optimizer): + if optimizer.trace == None: + print "No trace present so I can't plot it. Please check that the optimizer actually supplies a trace." + else: + pb.figure() + pb.plot(optimizer.trace) + pb.xlabel('Iteration') + pb.ylabel('f(x)') +
      +
      [docs]def plot_sgd_traces(optimizer): + pb.figure() + pb.subplot(211) + pb.title('Parameters') + for k in optimizer.param_traces.keys(): + pb.plot(optimizer.param_traces[k], label=k) + pb.legend(loc=0) + pb.subplot(212) + pb.title('Objective function') + pb.plot(optimizer.fopt_trace)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/kernel_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/kernel_plots.html new file mode 100644 index 00000000..60a342fa --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/kernel_plots.html @@ -0,0 +1,265 @@ + + + + + + + + GPy.plotting.matplot_dep.kernel_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.kernel_plots

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +import pylab as pb
      +import Tango
      +from matplotlib.textpath import TextPath
      +from matplotlib.transforms import offset_copy
      +from .base_plots import ax_default
      +
      +
      +
      +
      [docs]def add_bar_labels(fig, ax, bars, bottom=0): + transOffset = offset_copy(ax.transData, fig=fig, + x=0., y= -2., units='points') + transOffsetUp = offset_copy(ax.transData, fig=fig, + x=0., y=1., units='points') + for bar in bars: + for i, [patch, num] in enumerate(zip(bar.patches, np.arange(len(bar.patches)))): + if len(bottom) == len(bar): b = bottom[i] + else: b = bottom + height = patch.get_height() + b + xi = patch.get_x() + patch.get_width() / 2. + va = 'top' + c = 'w' + t = TextPath((0, 0), "${xi}$".format(xi=xi), rotation=0, ha='center') + transform = transOffset + if patch.get_extents().height <= t.get_extents().height + 5: + va = 'bottom' + c = 'k' + transform = transOffsetUp + ax.text(xi, height, "${xi}$".format(xi=int(num)), color=c, rotation=0, ha='center', va=va, transform=transform) + + ax.set_xticks([]) + +
      +
      [docs]def plot_bars(fig, ax, x, ard_params, color, name, bottom=0): + return ax.bar(left=x, height=ard_params.view(np.ndarray), width=.8, + bottom=bottom, align='center', + color=color, edgecolor='k', linewidth=1.2, + label=name.replace("_"," ")) +
      +
      [docs]def plot_ARD(kernel, fignum=None, ax=None, title='', legend=False, filtering=None): + """ + If an ARD kernel is present, plot a bar representation using matplotlib + + :param fignum: figure number of the plot + :param ax: matplotlib axis to plot on + :param title: + title of the plot, + pass '' to not print a title + pass None for a generic title + :param filtering: list of names, which to use for plotting ARD parameters. + Only kernels which match names in the list of names in filtering + will be used for plotting. + :type filtering: list of names to use for ARD plot + """ + fig, ax = ax_default(fignum,ax) + + if title is None: + ax.set_title('ARD parameters, %s kernel' % kernel.name) + else: + ax.set_title(title) + + Tango.reset() + bars = [] + + ard_params = np.atleast_2d(kernel.input_sensitivity(summarize=False)) + bottom = 0 + last_bottom = bottom + + x = np.arange(kernel.input_dim) + + if filtering is None: + filtering = kernel.parameter_names(recursive=False) + + for i in range(ard_params.shape[0]): + if kernel.parameters[i].name in filtering: + c = Tango.nextMedium() + bars.append(plot_bars(fig, ax, x, ard_params[i,:], c, kernel.parameters[i].name, bottom=bottom)) + last_bottom = ard_params[i,:] + bottom += last_bottom + else: + print "filtering out {}".format(kernel.parameters[i].name) + + ax.set_xlim(-.5, kernel.input_dim - .5) + add_bar_labels(fig, ax, [bars[-1]], bottom=bottom-last_bottom) + + if legend: + if title is '': + mode = 'expand' + if len(bars) > 1: + mode = 'expand' + ax.legend(bbox_to_anchor=(0., 1.02, 1., 1.02), loc=3, + ncol=len(bars), mode=mode, borderaxespad=0.) + fig.tight_layout(rect=(0, 0, 1, .9)) + else: + ax.legend() + return ax + + +
      +
      [docs]def plot(kernel,x=None, fignum=None, ax=None, title=None, plot_limits=None, resolution=None, **mpl_kwargs): + """ + plot a kernel. + :param x: the value to use for the other kernel argument (kernels are a function of two variables!) + :param fignum: figure number of the plot + :param ax: matplotlib axis to plot on + :param title: the matplotlib title + :param plot_limits: the range over which to plot the kernel + :resolution: the resolution of the lines used in plotting + :mpl_kwargs avalid keyword arguments to pass through to matplotlib (e.g. lw=7) + """ + fig, ax = ax_default(fignum,ax) + + if title is None: + ax.set_title('%s kernel' % kernel.name) + else: + ax.set_title(title) + + + if kernel.input_dim == 1: + if x is None: + x = np.zeros((1, 1)) + else: + x = np.asarray(x) + assert x.size == 1, "The size of the fixed variable x is not 1" + x = x.reshape((1, 1)) + + if plot_limits == None: + xmin, xmax = (x - 5).flatten(), (x + 5).flatten() + elif len(plot_limits) == 2: + xmin, xmax = plot_limits + else: + raise ValueError, "Bad limits for plotting" + + Xnew = np.linspace(xmin, xmax, resolution or 201)[:, None] + Kx = kernel.K(Xnew, x) + ax.plot(Xnew, Kx, **mpl_kwargs) + ax.set_xlim(xmin, xmax) + ax.set_xlabel("x") + ax.set_ylabel("k(x,%0.1f)" % x) + + elif kernel.input_dim == 2: + if x is None: + x = np.zeros((1, 2)) + else: + x = np.asarray(x) + assert x.size == 2, "The size of the fixed variable x is not 2" + x = x.reshape((1, 2)) + + if plot_limits is None: + xmin, xmax = (x - 5).flatten(), (x + 5).flatten() + elif len(plot_limits) == 2: + xmin, xmax = plot_limits + else: + raise ValueError, "Bad limits for plotting" + + resolution = resolution or 51 + xx, yy = np.mgrid[xmin[0]:xmax[0]:1j * resolution, xmin[1]:xmax[1]:1j * resolution] + Xnew = np.vstack((xx.flatten(), yy.flatten())).T + Kx = kernel.K(Xnew, x) + Kx = Kx.reshape(resolution, resolution).T + ax.contour(xx, yy, Kx, vmin=Kx.min(), vmax=Kx.max(), cmap=pb.cm.jet, **mpl_kwargs) # @UndefinedVariable + ax.set_xlim(xmin[0], xmax[0]) + ax.set_ylim(xmin[1], xmax[1]) + ax.set_xlabel("x1") + ax.set_ylabel("x2") + ax.set_title("k(x1,x2 ; %0.1f,%0.1f)" % (x[0, 0], x[0, 1])) + else: + raise NotImplementedError, "Cannot plot a kernel with more than two input dimensions"
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/latent_space_visualizations/controllers/axis_event_controller.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/latent_space_visualizations/controllers/axis_event_controller.html new file mode 100644 index 00000000..e1dfe6b2 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/latent_space_visualizations/controllers/axis_event_controller.html @@ -0,0 +1,241 @@ + + + + + + + + GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller

      +'''
      +Created on 24 Jul 2013
      +
      +@author: maxz
      +'''
      +import numpy
      +
      +
      [docs]class AxisEventController(object): + def __init__(self, ax): + self.ax = ax + self.activate() +
      [docs] def deactivate(self): + for cb_class in self.ax.callbacks.callbacks.values(): + for cb_num in cb_class.keys(): + self.ax.callbacks.disconnect(cb_num)
      +
      [docs] def activate(self): + self.ax.callbacks.connect('xlim_changed', self.xlim_changed) + self.ax.callbacks.connect('ylim_changed', self.ylim_changed)
      +
      [docs] def xlim_changed(self, ax): + pass
      +
      [docs] def ylim_changed(self, ax): + pass + +
      +
      [docs]class AxisChangedController(AxisEventController): + ''' + Buffered control of axis limit changes + ''' + _changing = False + + def __init__(self, ax, update_lim=None): + ''' + Constructor + ''' + super(AxisChangedController, self).__init__(ax) + self._lim_ratio_threshold = update_lim or .95 + self._x_lim = self.ax.get_xlim() + self._y_lim = self.ax.get_ylim() + +
      [docs] def update(self, ax): + pass +
      +
      [docs] def xlim_changed(self, ax): + super(AxisChangedController, self).xlim_changed(ax) + if not self._changing and self.lim_changed(ax.get_xlim(), self._x_lim): + self._changing = True + self._x_lim = ax.get_xlim() + self.update(ax) + self._changing = False +
      +
      [docs] def ylim_changed(self, ax): + super(AxisChangedController, self).ylim_changed(ax) + if not self._changing and self.lim_changed(ax.get_ylim(), self._y_lim): + self._changing = True + self._y_lim = ax.get_ylim() + self.update(ax) + self._changing = False +
      +
      [docs] def extent(self, lim): + return numpy.subtract(*lim) +
      +
      [docs] def lim_changed(self, axlim, savedlim): + axextent = self.extent(axlim) + extent = self.extent(savedlim) + lim_changed = ((axextent / extent) < self._lim_ratio_threshold ** 2 + or (extent / axextent) < self._lim_ratio_threshold ** 2 + or ((1 - (self.extent((axlim[0], savedlim[0])) / self.extent((savedlim[0], axlim[1])))) + < self._lim_ratio_threshold) + or ((1 - (self.extent((savedlim[0], axlim[0])) / self.extent((axlim[0], savedlim[1])))) + < self._lim_ratio_threshold) + ) + return lim_changed +
      + def _buffer_lim(self, lim): + # buffer_size = 1 - self._lim_ratio_threshold + # extent = self.extent(lim) + return lim + +
      +
      [docs]class BufferedAxisChangedController(AxisChangedController): + def __init__(self, ax, plot_function, plot_limits, resolution=50, update_lim=None, **kwargs): + """ + Buffered axis changed controller. Controls the buffer and handles update events for when the axes changed. + + Updated plotting will be after first reload (first time will be within plot limits, after that the limits will be buffered) + + :param plot_function: + function to use for creating image for plotting (return ndarray-like) + plot_function gets called with (2D!) Xtest grid if replotting required + :type plot_function: function + :param plot_limits: + beginning plot limits [xmin, ymin, xmax, ymax] + + :param kwargs: additional kwargs are for pyplot.imshow(**kwargs) + """ + super(BufferedAxisChangedController, self).__init__(ax, update_lim=update_lim) + self.plot_function = plot_function + xmin, ymin, xmax, ymax = plot_limits#self._x_lim # self._compute_buffered(*self._x_lim) + # imshow acts on the limits of the plot, this is why we need to override the limits here, to make sure the right plot limits are used: + self._x_lim = xmin, xmax + self._y_lim = ymin, ymax + self.resolution = resolution + self._not_init = False + self.view = self._init_view(self.ax, self.recompute_X(buffered=False), xmin, xmax, ymin, ymax, **kwargs) + self._not_init = True + +
      [docs] def update(self, ax): + super(BufferedAxisChangedController, self).update(ax) + if self._not_init: + xmin, xmax = self._compute_buffered(*self._x_lim) + ymin, ymax = self._compute_buffered(*self._y_lim) + self.update_view(self.view, self.recompute_X(), xmin, xmax, ymin, ymax) +
      + def _init_view(self, ax, X, xmin, xmax, ymin, ymax): + raise NotImplementedError('return view for this controller') + +
      [docs] def update_view(self, view, X, xmin, xmax, ymin, ymax): + raise NotImplementedError('update view given in here') +
      +
      [docs] def get_grid(self, buffered=True): + if buffered: comp = self._compute_buffered + else: comp = lambda a,b: (a,b) + xmin, xmax = comp(*self._x_lim) + ymin, ymax = comp(*self._y_lim) + x, y = numpy.mgrid[xmin:xmax:1j * self.resolution, ymin:ymax:1j * self.resolution] + return numpy.hstack((x.flatten()[:, None], y.flatten()[:, None])) +
      +
      [docs] def recompute_X(self, buffered=True): + X = self.plot_function(self.get_grid(buffered)) + if isinstance(X, (tuple, list)): + for x in X: + x.shape = [self.resolution, self.resolution] + x[:, :] = x.T[::-1, :] + return X + return X.reshape(self.resolution, self.resolution).T[::-1, :] +
      + def _compute_buffered(self, mi, ma): + buffersize = self._buffersize() + size = ma - mi + return mi - (buffersize * size), ma + (buffersize * size) + + def _buffersize(self): + try: + buffersize = 1. - self._lim_ratio_threshold + except: + buffersize = .4 + return buffersize
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/latent_space_visualizations/controllers/imshow_controller.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/latent_space_visualizations/controllers/imshow_controller.html new file mode 100644 index 00000000..cddaa948 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/latent_space_visualizations/controllers/imshow_controller.html @@ -0,0 +1,165 @@ + + + + + + + + GPy.plotting.matplot_dep.latent_space_visualizations.controllers.imshow_controller — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.latent_space_visualizations.controllers.imshow_controller

      +'''
      +Created on 24 Jul 2013
      +
      +@author: maxz
      +'''
      +from axis_event_controller import BufferedAxisChangedController
      +import itertools
      +import numpy
      +
      +
      +
      [docs]class ImshowController(BufferedAxisChangedController): + def __init__(self, ax, plot_function, plot_limits, resolution=50, update_lim=.8, **kwargs): + """ + :param plot_function: + function to use for creating image for plotting (return ndarray-like) + plot_function gets called with (2D!) Xtest grid if replotting required + :type plot_function: function + :param plot_limits: + beginning plot limits [xmin, ymin, xmax, ymax] + + :param kwargs: additional kwargs are for pyplot.imshow(**kwargs) + """ + super(ImshowController, self).__init__(ax, plot_function, plot_limits, resolution, update_lim, **kwargs) + + def _init_view(self, ax, X, xmin, xmax, ymin, ymax, **kwargs): + return ax.imshow(X, extent=(xmin, xmax, + ymin, ymax), + vmin=X.min(), + vmax=X.max(), + **kwargs) + +
      [docs] def update_view(self, view, X, xmin, xmax, ymin, ymax): + view.set_data(X) + view.set_extent((xmin, xmax, ymin, ymax)) +
      +
      [docs]class ImAnnotateController(ImshowController): + def __init__(self, ax, plot_function, plot_limits, resolution=20, update_lim=.99, **kwargs): + """ + :param plot_function: + function to use for creating image for plotting (return ndarray-like) + plot_function gets called with (2D!) Xtest grid if replotting required + :type plot_function: function + :param plot_limits: + beginning plot limits [xmin, ymin, xmax, ymax] + :param text_props: kwargs for pyplot.text(**text_props) + :param kwargs: additional kwargs are for pyplot.imshow(**kwargs) + """ + super(ImAnnotateController, self).__init__(ax, plot_function, plot_limits, resolution, update_lim, **kwargs) + + def _init_view(self, ax, X, xmin, xmax, ymin, ymax, text_props={}, **kwargs): + view = [super(ImAnnotateController, self)._init_view(ax, X[0], xmin, xmax, ymin, ymax, **kwargs)] + xoffset, yoffset = self._offsets(xmin, xmax, ymin, ymax) + xlin = numpy.linspace(xmin, xmax, self.resolution, endpoint=False) + ylin = numpy.linspace(ymin, ymax, self.resolution, endpoint=False) + for [i, x], [j, y] in itertools.product(enumerate(xlin), enumerate(ylin[::-1])): + view.append(ax.text(x + xoffset, y + yoffset, "{}".format(X[1][j, i]), ha='center', va='center', **text_props)) + return view + +
      [docs] def update_view(self, view, X, xmin, xmax, ymin, ymax): + super(ImAnnotateController, self).update_view(view[0], X[0], xmin, xmax, ymin, ymax) + xoffset, yoffset = self._offsets(xmin, xmax, ymin, ymax) + xlin = numpy.linspace(xmin, xmax, self.resolution, endpoint=False) + ylin = numpy.linspace(ymin, ymax, self.resolution, endpoint=False) + for [[i, x], [j, y]], text in itertools.izip(itertools.product(enumerate(xlin), enumerate(ylin[::-1])), view[1:]): + text.set_x(x + xoffset) + text.set_y(y + yoffset) + text.set_text("{}".format(X[1][j, i])) + return view +
      + def _offsets(self, xmin, xmax, ymin, ymax): + return (xmax - xmin) / (2 * self.resolution), (ymax - ymin) / (2 * self.resolution)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/mapping_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/mapping_plots.html new file mode 100644 index 00000000..f5bcc03f --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/mapping_plots.html @@ -0,0 +1,178 @@ + + + + + + + + GPy.plotting.matplot_dep.mapping_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.mapping_plots

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +try:
      +    import Tango
      +    import pylab as pb
      +except:
      +    pass
      +from base_plots import x_frame1D, x_frame2D
      +
      +
      +
      [docs]def plot_mapping(self, plot_limits=None, which_data='all', which_parts='all', resolution=None, levels=20, samples=0, fignum=None, ax=None, fixed_inputs=[], linecol=Tango.colorsHex['darkBlue']): + """ + Plots the mapping associated with the model. + - In one dimension, the function is plotted. + - In two dimsensions, a contour-plot shows the function + - In higher dimensions, we've not implemented this yet !TODO! + + Can plot only part of the data and part of the posterior functions + using which_data and which_functions + + :param plot_limits: The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits + :type plot_limits: np.array + :param which_data: which if the training data to plot (default all) + :type which_data: 'all' or a slice object to slice self.X, self.Y + :param which_parts: which of the kernel functions to plot (additively) + :type which_parts: 'all', or list of bools + :param resolution: the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D + :type resolution: int + :param levels: number of levels to plot in a contour plot. + :type levels: int + :param samples: the number of a posteriori samples to plot + :type samples: int + :param fignum: figure to plot on. + :type fignum: figure number + :param ax: axes to plot on. + :type ax: axes handle + :param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v. + :type fixed_inputs: a list of tuples + :param linecol: color of line to plot. + :type linecol: + :param levels: for 2D plotting, the number of contour levels to use is ax is None, create a new figure + + """ + # TODO include samples + if which_data == 'all': + which_data = slice(None) + + if ax is None: + fig = pb.figure(num=fignum) + ax = fig.add_subplot(111) + + plotdims = self.input_dim - len(fixed_inputs) + + if plotdims == 1: + + Xu = self.X * self._Xscale + self._Xoffset # NOTE self.X are the normalized values now + + fixed_dims = np.array([i for i,v in fixed_inputs]) + freedim = np.setdiff1d(np.arange(self.input_dim),fixed_dims) + + Xnew, xmin, xmax = x_frame1D(Xu[:,freedim], plot_limits=plot_limits) + Xgrid = np.empty((Xnew.shape[0],self.input_dim)) + Xgrid[:,freedim] = Xnew + for i,v in fixed_inputs: + Xgrid[:,i] = v + + f = self.predict(Xgrid, which_parts=which_parts) + for d in range(y.shape[1]): + ax.plot(Xnew, f[:, d], edgecol=linecol) + + elif self.X.shape[1] == 2: + resolution = resolution or 50 + Xnew, _, _, xmin, xmax = x_frame2D(self.X, plot_limits, resolution) + x, y = np.linspace(xmin[0], xmax[0], resolution), np.linspace(xmin[1], xmax[1], resolution) + f = self.predict(Xnew, which_parts=which_parts) + m = m.reshape(resolution, resolution).T + ax.contour(x, y, f, levels, vmin=m.min(), vmax=m.max(), cmap=pb.cm.jet) # @UndefinedVariable + ax.set_xlim(xmin[0], xmax[0]) + ax.set_ylim(xmin[1], xmax[1]) + + else: + raise NotImplementedError, "Cannot define a frame with more than two input dimensions"
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/maps.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/maps.html new file mode 100644 index 00000000..3410923a --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/maps.html @@ -0,0 +1,269 @@ + + + + + + + + GPy.plotting.matplot_dep.maps — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.maps

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import numpy as np
      +try:
      +    import pylab as pb
      +    from matplotlib.patches import Polygon
      +    from matplotlib.collections import PatchCollection
      +    #from matplotlib import cm
      +    pb.ion()
      +except:
      +    pass
      +import re
      +
      +
      [docs]def plot(shape_records,facecolor='w',edgecolor='k',linewidths=.5, ax=None,xlims=None,ylims=None): + """ + Plot the geometry of a shapefile + + :param shape_records: geometry and attributes list + :type shape_records: ShapeRecord object (output of a shapeRecords() method) + :param facecolor: color to be used to fill in polygons + :param edgecolor: color to be used for lines + :param ax: axes to plot on. + :type ax: axes handle + """ + #Axes handle + if ax is None: + fig = pb.figure() + ax = fig.add_subplot(111) + + #Iterate over shape_records + for srec in shape_records: + points = np.vstack(srec.shape.points) + sparts = srec.shape.parts + par = list(sparts) + [points.shape[0]] + + polygs = [] + for pj in xrange(len(sparts)): + polygs.append(Polygon(points[par[pj]:par[pj+1]])) + ax.add_collection(PatchCollection(polygs,facecolor=facecolor,edgecolor=edgecolor, linewidths=linewidths)) + + #Plot limits + _box = np.vstack([srec.shape.bbox for srec in shape_records]) + minx,miny = np.min(_box[:,:2],0) + maxx,maxy = np.max(_box[:,2:],0) + + if xlims is not None: + minx,maxx = xlims + if ylims is not None: + miny,maxy = ylims + ax.set_xlim(minx,maxx) + ax.set_ylim(miny,maxy) + +
      +
      [docs]def string_match(sf,regex,field=2): + """ + Return the geometry and attributes of a shapefile whose fields match a regular expression given + + :param sf: shapefile + :type sf: shapefile object + :regex: regular expression to match + :type regex: string + :field: field number to be matched with the regex + :type field: integer + """ + index = [] + shape_records = [] + for rec in enumerate(sf.shapeRecords()): + m = re.search(regex,rec[1].record[field]) + if m is not None: + index.append(rec[0]) + shape_records.append(rec[1]) + return index,shape_records +
      +
      [docs]def bbox_match(sf,bbox,inside_only=True): + """ + Return the geometry and attributes of a shapefile that lie within (or intersect) a bounding box + + :param sf: shapefile + :type sf: shapefile object + :param bbox: bounding box + :type bbox: list of floats [x_min,y_min,x_max,y_max] + :inside_only: True if the objects returned are those that lie within the bbox and False if the objects returned are any that intersect the bbox + :type inside_only: Boolean + """ + A,B,C,D = bbox + index = [] + shape_records = [] + for rec in enumerate(sf.shapeRecords()): + a,b,c,d = rec[1].shape.bbox + if inside_only: + if A <= a and B <= b and C >= c and D >= d: + index.append(rec[0]) + shape_records.append(rec[1]) + else: + cond1 = A <= a and B <= b and C >= a and D >= b + cond2 = A <= c and B <= d and C >= c and D >= d + cond3 = A <= a and D >= d and C >= a and B <= d + cond4 = A <= c and D >= b and C >= c and B <= b + cond5 = a <= C and b <= B and d >= D + cond6 = c <= A and b <= B and d >= D + cond7 = d <= B and a <= A and c >= C + cond8 = b <= D and a <= A and c >= C + if cond1 or cond2 or cond3 or cond4 or cond5 or cond6 or cond7 or cond8: + index.append(rec[0]) + shape_records.append(rec[1]) + return index,shape_records + +
      +
      [docs]def plot_bbox(sf,bbox,inside_only=True): + """ + Plot the geometry of a shapefile within a bbox + + :param sf: shapefile + :type sf: shapefile object + :param bbox: bounding box + :type bbox: list of floats [x_min,y_min,x_max,y_max] + :inside_only: True if the objects returned are those that lie within the bbox and False if the objects returned are any that intersect the bbox + :type inside_only: Boolean + """ + index,shape_records = bbox_match(sf,bbox,inside_only) + A,B,C,D = bbox + plot(shape_records,xlims=[bbox[0],bbox[2]],ylims=[bbox[1],bbox[3]]) +
      +
      [docs]def plot_string_match(sf,regex,field,**kwargs): + """ + Plot the geometry of a shapefile whose fields match a regular expression given + + :param sf: shapefile + :type sf: shapefile object + :regex: regular expression to match + :type regex: string + :field: field number to be matched with the regex + :type field: integer + """ + index,shape_records = string_match(sf,regex,field) + plot(shape_records,**kwargs) + +
      +
      [docs]def new_shape_string(sf,name,regex,field=2,type=None): + import shapefile + if type is None: + type = shapefile.POINT + newshp = shapefile.Writer(shapeType = sf.shapeType) + newshp.autoBalance = 1 + + index,shape_records = string_match(sf,regex,field) + + _fi = [sf.fields[j] for j in index] + for f in _fi: + newshp.field(name=f[0],fieldType=f[1],size=f[2],decimal=f[3]) + + _shre = shape_records + for sr in _shre: + _points = [] + _parts = [] + for point in sr.shape.points: + _points.append(point) + _parts.append(_points) + + newshp.line(parts=_parts) + newshp.records.append(sr.record) + print len(sr.record) + + newshp.save(name) + print index +
      +
      [docs]def apply_bbox(sf,ax): + """ + Use bbox as xlim and ylim in ax + """ + limits = sf.bbox + xlim = limits[0],limits[2] + ylim = limits[1],limits[3] + ax.set_xlim(xlim) + ax.set_ylim(ylim)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/models_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/models_plots.html new file mode 100644 index 00000000..899d7f1c --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/models_plots.html @@ -0,0 +1,282 @@ + + + + + + + + GPy.plotting.matplot_dep.models_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.models_plots

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +try:
      +    import Tango
      +    import pylab as pb
      +except:
      +    pass
      +import numpy as np
      +from base_plots import gpplot, x_frame1D, x_frame2D
      +from ...models.gp_coregionalized_regression import GPCoregionalizedRegression
      +from ...models.sparse_gp_coregionalized_regression import SparseGPCoregionalizedRegression
      +from scipy import sparse
      +
      +
      [docs]def plot_fit(model, plot_limits=None, which_data_rows='all', + which_data_ycols='all', fixed_inputs=[], + levels=20, samples=0, fignum=None, ax=None, resolution=None, + plot_raw=False, + linecol=Tango.colorsHex['darkBlue'],fillcol=Tango.colorsHex['lightBlue'], Y_metadata=None, data_symbol='kx'): + """ + Plot the posterior of the GP. + - In one dimension, the function is plotted with a shaded region identifying two standard deviations. + - In two dimsensions, a contour-plot shows the mean predicted function + - In higher dimensions, use fixed_inputs to plot the GP with some of the inputs fixed. + + Can plot only part of the data and part of the posterior functions + using which_data_rowsm which_data_ycols. + + :param plot_limits: The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits + :type plot_limits: np.array + :param which_data_rows: which of the training data to plot (default all) + :type which_data_rows: 'all' or a slice object to slice model.X, model.Y + :param which_data_ycols: when the data has several columns (independant outputs), only plot these + :type which_data_rows: 'all' or a list of integers + :param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v. + :type fixed_inputs: a list of tuples + :param resolution: the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D + :type resolution: int + :param levels: number of levels to plot in a contour plot. + :type levels: int + :param samples: the number of a posteriori samples to plot + :type samples: int + :param fignum: figure to plot on. + :type fignum: figure number + :param ax: axes to plot on. + :type ax: axes handle + :type output: integer (first output is 0) + :param linecol: color of line to plot. + :type linecol: + :param fillcol: color of fill + :param levels: for 2D plotting, the number of contour levels to use is ax is None, create a new figure + """ + #deal with optional arguments + if which_data_rows == 'all': + which_data_rows = slice(None) + if which_data_ycols == 'all': + which_data_ycols = np.arange(model.output_dim) + #if len(which_data_ycols)==0: + #raise ValueError('No data selected for plotting') + if ax is None: + fig = pb.figure(num=fignum) + ax = fig.add_subplot(111) + + if hasattr(model, 'has_uncertain_inputs') and model.has_uncertain_inputs(): + X = model.X.mean + X_variance = model.X.variance + else: + X = model.X + Y = model.Y + if sparse.issparse(Y): Y = Y.todense().view(np.ndarray) + + if hasattr(model, 'Z'): Z = model.Z + + #work out what the inputs are for plotting (1D or 2D) + fixed_dims = np.array([i for i,v in fixed_inputs]) + free_dims = np.setdiff1d(np.arange(model.input_dim),fixed_dims) + plots = {} + #one dimensional plotting + if len(free_dims) == 1: + + #define the frame on which to plot + Xnew, xmin, xmax = x_frame1D(X[:,free_dims], plot_limits=plot_limits, resolution=resolution or 200) + Xgrid = np.empty((Xnew.shape[0],model.input_dim)) + Xgrid[:,free_dims] = Xnew + for i,v in fixed_inputs: + Xgrid[:,i] = v + + #make a prediction on the frame and plot it + if plot_raw: + m, v = model._raw_predict(Xgrid) + lower = m - 2*np.sqrt(v) + upper = m + 2*np.sqrt(v) + else: + if isinstance(model,GPCoregionalizedRegression) or isinstance(model,SparseGPCoregionalizedRegression): + meta = {'output_index': Xgrid[:,-1:].astype(np.int)} + else: + meta = None + m, v = model.predict(Xgrid, full_cov=False, Y_metadata=meta) + lower, upper = model.predict_quantiles(Xgrid, Y_metadata=meta) + + + for d in which_data_ycols: + plots['gpplot'] = gpplot(Xnew, m[:, d], lower[:, d], upper[:, d], ax=ax, edgecol=linecol, fillcol=fillcol) + if not plot_raw: plots['dataplot'] = ax.plot(X[which_data_rows,free_dims], Y[which_data_rows, d], data_symbol, mew=1.5) + + #optionally plot some samples + if samples: #NOTE not tested with fixed_inputs + Ysim = model.posterior_samples(Xgrid, samples) + for yi in Ysim.T: + plots['posterior_samples'] = ax.plot(Xnew, yi[:,None], Tango.colorsHex['darkBlue'], linewidth=0.25) + #ax.plot(Xnew, yi[:,None], marker='x', linestyle='--',color=Tango.colorsHex['darkBlue']) #TODO apply this line for discrete outputs. + + + #add error bars for uncertain (if input uncertainty is being modelled) + if hasattr(model,"has_uncertain_inputs") and model.has_uncertain_inputs(): + plots['xerrorbar'] = ax.errorbar(X[which_data_rows, free_dims].flatten(), Y[which_data_rows, which_data_ycols].flatten(), + xerr=2 * np.sqrt(X_variance[which_data_rows, free_dims].flatten()), + ecolor='k', fmt=None, elinewidth=.5, alpha=.5) + + + #set the limits of the plot to some sensible values + ymin, ymax = min(np.append(Y[which_data_rows, which_data_ycols].flatten(), lower)), max(np.append(Y[which_data_rows, which_data_ycols].flatten(), upper)) + ymin, ymax = ymin - 0.1 * (ymax - ymin), ymax + 0.1 * (ymax - ymin) + ax.set_xlim(xmin, xmax) + ax.set_ylim(ymin, ymax) + + #add inducing inputs (if a sparse model is used) + if hasattr(model,"Z"): + #Zu = model.Z[:,free_dims] * model._Xscale[:,free_dims] + model._Xoffset[:,free_dims] + if isinstance(model,SparseGPCoregionalizedRegression): + Z = Z[Z[:,-1] == Y_metadata['output_index'],:] + Zu = Z[:,free_dims] + z_height = ax.get_ylim()[0] + plots['inducing_inputs'] = ax.plot(Zu, np.zeros_like(Zu) + z_height, 'r|', mew=1.5, markersize=12) + + + + #2D plotting + elif len(free_dims) == 2: + + #define the frame for plotting on + resolution = resolution or 50 + Xnew, _, _, xmin, xmax = x_frame2D(X[:,free_dims], plot_limits, resolution) + Xgrid = np.empty((Xnew.shape[0],model.input_dim)) + Xgrid[:,free_dims] = Xnew + for i,v in fixed_inputs: + Xgrid[:,i] = v + x, y = np.linspace(xmin[0], xmax[0], resolution), np.linspace(xmin[1], xmax[1], resolution) + + #predict on the frame and plot + if plot_raw: + m, _ = model._raw_predict(Xgrid) + else: + if isinstance(model,GPCoregionalizedRegression) or isinstance(model,SparseGPCoregionalizedRegression): + meta = {'output_index': Xgrid[:,-1:].astype(np.int)} + else: + meta = None + m, v = model.predict(Xgrid, full_cov=False, Y_metadata=meta) + for d in which_data_ycols: + m_d = m[:,d].reshape(resolution, resolution).T + plots['contour'] = ax.contour(x, y, m_d, levels, vmin=m.min(), vmax=m.max(), cmap=pb.cm.jet) + if not plot_raw: plots['dataplot'] = ax.scatter(X[which_data_rows, free_dims[0]], X[which_data_rows, free_dims[1]], 40, Y[which_data_rows, d], cmap=pb.cm.jet, vmin=m.min(), vmax=m.max(), linewidth=0.) + + #set the limits of the plot to some sensible values + ax.set_xlim(xmin[0], xmax[0]) + ax.set_ylim(xmin[1], xmax[1]) + + if samples: + warnings.warn("Samples are rather difficult to plot for 2D inputs...") + + #add inducing inputs (if a sparse model is used) + if hasattr(model,"Z"): + #Zu = model.Z[:,free_dims] * model._Xscale[:,free_dims] + model._Xoffset[:,free_dims] + Zu = Z[:,free_dims] + plots['inducing_inputs'] = ax.plot(Zu[:,free_dims[0]], Zu[:,free_dims[1]], 'wo') + + else: + raise NotImplementedError, "Cannot define a frame with more than two input dimensions" + return plots +
      +
      [docs]def plot_fit_f(model, *args, **kwargs): + """ + Plot the GP's view of the world, where the data is normalized and before applying a likelihood. + + All args and kwargs are passed on to models_plots.plot. + """ + kwargs['plot_raw'] = True + plot_fit(model,*args, **kwargs)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/netpbmfile.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/netpbmfile.html new file mode 100644 index 00000000..ef26c42c --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/netpbmfile.html @@ -0,0 +1,425 @@ + + + + + + + + GPy.plotting.matplot_dep.netpbmfile — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.netpbmfile

      +#!/usr/bin/env python
      +# -*- coding: utf-8 -*-
      +# netpbmfile.py
      +
      +# Copyright (c) 2011-2013, Christoph Gohlke
      +# Copyright (c) 2011-2013, The Regents of the University of California
      +# Produced at the Laboratory for Fluorescence Dynamics.
      +# All rights reserved.
      +#
      +# Redistribution and use in source and binary forms, with or without
      +# modification, are permitted provided that the following conditions are met:
      +#
      +# * Redistributions of source code must retain the above copyright
      +#   notice, this list of conditions and the following disclaimer.
      +# * Redistributions in binary form must reproduce the above copyright
      +#   notice, this list of conditions and the following disclaimer in the
      +#   documentation and/or other materials provided with the distribution.
      +# * Neither the name of the copyright holders nor the names of any
      +#   contributors may be used to endorse or promote products derived
      +#   from this software without specific prior written permission.
      +#
      +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      +# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      +# POSSIBILITY OF SUCH DAMAGE.
      +
      +"""Read and write image data from respectively to Netpbm files.
      +
      +This implementation follows the Netpbm format specifications at
      +http://netpbm.sourceforge.net/doc/. No gamma correction is performed.
      +
      +The following image formats are supported: PBM (bi-level), PGM (grayscale),
      +PPM (color), PAM (arbitrary), XV thumbnail (RGB332, read-only).
      +
      +:Author:
      +  `Christoph Gohlke <http://www.lfd.uci.edu/~gohlke/>`_
      +
      +:Organization:
      +  Laboratory for Fluorescence Dynamics, University of California, Irvine
      +
      +:Version: 2013.01.18
      +
      +Requirements
      +------------
      +* `CPython 2.7, 3.2 or 3.3 <http://www.python.org>`_
      +* `Numpy 1.7 <http://www.numpy.org>`_
      +* `Matplotlib 1.2 <http://www.matplotlib.org>`_  (optional for plotting)
      +
      +Examples
      +--------
      +>>> im1 = numpy.array([[0, 1],[65534, 65535]], dtype=numpy.uint16)
      +>>> imsave('_tmp.pgm', im1)
      +>>> im2 = imread('_tmp.pgm')
      +>>> assert numpy.all(im1 == im2)
      +
      +"""
      +
      +from __future__ import division, print_function
      +
      +import sys
      +import re
      +import math
      +from copy import deepcopy
      +
      +import numpy
      +
      +__version__ = '2013.01.18'
      +__docformat__ = 'restructuredtext en'
      +__all__ = ['imread', 'imsave', 'NetpbmFile']
      +
      +
      +
      [docs]def imread(filename, *args, **kwargs): + """Return image data from Netpbm file as numpy array. + + `args` and `kwargs` are arguments to NetpbmFile.asarray(). + + Examples + -------- + >>> image = imread('_tmp.pgm') + + """ + try: + netpbm = NetpbmFile(filename) + image = netpbm.asarray() + finally: + netpbm.close() + return image + +
      +
      [docs]def imsave(filename, data, maxval=None, pam=False): + """Write image data to Netpbm file. + + Examples + -------- + >>> image = numpy.array([[0, 1],[65534, 65535]], dtype=numpy.uint16) + >>> imsave('_tmp.pgm', image) + + """ + try: + netpbm = NetpbmFile(data, maxval=maxval) + netpbm.write(filename, pam=pam) + finally: + netpbm.close() + +
      +
      [docs]class NetpbmFile(object): + """Read and write Netpbm PAM, PBM, PGM, PPM, files.""" + + _types = {b'P1': b'BLACKANDWHITE', b'P2': b'GRAYSCALE', b'P3': b'RGB', + b'P4': b'BLACKANDWHITE', b'P5': b'GRAYSCALE', b'P6': b'RGB', + b'P7 332': b'RGB', b'P7': b'RGB_ALPHA'} + + def __init__(self, arg=None, **kwargs): + """Initialize instance from filename, open file, or numpy array.""" + for attr in ('header', 'magicnum', 'width', 'height', 'maxval', + 'depth', 'tupltypes', '_filename', '_fh', '_data'): + setattr(self, attr, None) + if arg is None: + self._fromdata([], **kwargs) + elif isinstance(arg, basestring): + self._fh = open(arg, 'rb') + self._filename = arg + self._fromfile(self._fh, **kwargs) + elif hasattr(arg, 'seek'): + self._fromfile(arg, **kwargs) + self._fh = arg + else: + self._fromdata(arg, **kwargs) + +
      [docs] def asarray(self, copy=True, cache=False, **kwargs): + """Return image data from file as numpy array.""" + data = self._data + if data is None: + data = self._read_data(self._fh, **kwargs) + if cache: + self._data = data + else: + return data + return deepcopy(data) if copy else data +
      +
      [docs] def write(self, arg, **kwargs): + """Write instance to file.""" + if hasattr(arg, 'seek'): + self._tofile(arg, **kwargs) + else: + with open(arg, 'wb') as fid: + self._tofile(fid, **kwargs) +
      +
      [docs] def close(self): + """Close open file. Future asarray calls might fail.""" + if self._filename and self._fh: + self._fh.close() + self._fh = None +
      + def __del__(self): + self.close() + + def _fromfile(self, fh): + """Initialize instance from open file.""" + fh.seek(0) + data = fh.read(4096) + if (len(data) < 7) or not (b'0' < data[1:2] < b'8'): + raise ValueError("Not a Netpbm file:\n%s" % data[:32]) + try: + self._read_pam_header(data) + except Exception: + try: + self._read_pnm_header(data) + except Exception: + raise ValueError("Not a Netpbm file:\n%s" % data[:32]) + + def _read_pam_header(self, data): + """Read PAM header and initialize instance.""" + regroups = re.search( + b"(^P7[\n\r]+(?:(?:[\n\r]+)|(?:#.*)|" + b"(HEIGHT\s+\d+)|(WIDTH\s+\d+)|(DEPTH\s+\d+)|(MAXVAL\s+\d+)|" + b"(?:TUPLTYPE\s+\w+))*ENDHDR\n)", data).groups() + self.header = regroups[0] + self.magicnum = b'P7' + for group in regroups[1:]: + key, value = group.split() + setattr(self, unicode(key).lower(), int(value)) + matches = re.findall(b"(TUPLTYPE\s+\w+)", self.header) + self.tupltypes = [s.split(None, 1)[1] for s in matches] + + def _read_pnm_header(self, data): + """Read PNM header and initialize instance.""" + bpm = data[1:2] in b"14" + regroups = re.search(b"".join(( + b"(^(P[123456]|P7 332)\s+(?:#.*[\r\n])*", + b"\s*(\d+)\s+(?:#.*[\r\n])*", + b"\s*(\d+)\s+(?:#.*[\r\n])*" * (not bpm), + b"\s*(\d+)\s(?:\s*#.*[\r\n]\s)*)")), data).groups() + (1, ) * bpm + self.header = regroups[0] + self.magicnum = regroups[1] + self.width = int(regroups[2]) + self.height = int(regroups[3]) + self.maxval = int(regroups[4]) + self.depth = 3 if self.magicnum in b"P3P6P7 332" else 1 + self.tupltypes = [self._types[self.magicnum]] + + def _read_data(self, fh, byteorder='>'): + """Return image data from open file as numpy array.""" + fh.seek(len(self.header)) + data = fh.read() + dtype = 'u1' if self.maxval < 256 else byteorder + 'u2' + depth = 1 if self.magicnum == b"P7 332" else self.depth + shape = [-1, self.height, self.width, depth] + size = numpy.prod(shape[1:]) + if self.magicnum in b"P1P2P3": + data = numpy.array(data.split(None, size)[:size], dtype) + data = data.reshape(shape) + elif self.maxval == 1: + shape[2] = int(math.ceil(self.width / 8)) + data = numpy.frombuffer(data, dtype).reshape(shape) + data = numpy.unpackbits(data, axis=-2)[:, :, :self.width, :] + else: + data = numpy.frombuffer(data, dtype) + data = data[:size * (data.size // size)].reshape(shape) + if data.shape[0] < 2: + data = data.reshape(data.shape[1:]) + if data.shape[-1] < 2: + data = data.reshape(data.shape[:-1]) + if self.magicnum == b"P7 332": + rgb332 = numpy.array(list(numpy.ndindex(8, 8, 4)), numpy.uint8) + rgb332 *= [36, 36, 85] + data = numpy.take(rgb332, data, axis=0) + return data + + def _fromdata(self, data, maxval=None): + """Initialize instance from numpy array.""" + data = numpy.array(data, ndmin=2, copy=True) + if data.dtype.kind not in "uib": + raise ValueError("not an integer type: %s" % data.dtype) + if data.dtype.kind == 'i' and numpy.min(data) < 0: + raise ValueError("data out of range: %i" % numpy.min(data)) + if maxval is None: + maxval = numpy.max(data) + maxval = 255 if maxval < 256 else 65535 + if maxval < 0 or maxval > 65535: + raise ValueError("data out of range: %i" % maxval) + data = data.astype('u1' if maxval < 256 else '>u2') + self._data = data + if data.ndim > 2 and data.shape[-1] in (3, 4): + self.depth = data.shape[-1] + self.width = data.shape[-2] + self.height = data.shape[-3] + self.magicnum = b'P7' if self.depth == 4 else b'P6' + else: + self.depth = 1 + self.width = data.shape[-1] + self.height = data.shape[-2] + self.magicnum = b'P5' if maxval > 1 else b'P4' + self.maxval = maxval + self.tupltypes = [self._types[self.magicnum]] + self.header = self._header() + + def _tofile(self, fh, pam=False): + """Write Netbm file.""" + fh.seek(0) + fh.write(self._header(pam)) + data = self.asarray(copy=False) + if self.maxval == 1: + data = numpy.packbits(data, axis=-1) + data.tofile(fh) + + def _header(self, pam=False): + """Return file header as byte string.""" + if pam or self.magicnum == b'P7': + header = "\n".join(( + "P7", + "HEIGHT %i" % self.height, + "WIDTH %i" % self.width, + "DEPTH %i" % self.depth, + "MAXVAL %i" % self.maxval, + "\n".join("TUPLTYPE %s" % unicode(i) for i in self.tupltypes), + "ENDHDR\n")) + elif self.maxval == 1: + header = "P4 %i %i\n" % (self.width, self.height) + elif self.depth == 1: + header = "P5 %i %i %i\n" % (self.width, self.height, self.maxval) + else: + header = "P6 %i %i %i\n" % (self.width, self.height, self.maxval) + if sys.version_info[0] > 2: + header = bytes(header, 'ascii') + return header + + def __str__(self): + """Return information about instance.""" + return unicode(self.header) + +
      +if sys.version_info[0] > 2: + basestring = str + unicode = lambda x: str(x, 'ascii') + +if __name__ == "__main__": + # Show images specified on command line or all images in current directory + from glob import glob + from matplotlib import pyplot + files = sys.argv[1:] if len(sys.argv) > 1 else glob('*.p*m') + for fname in files: + try: + pam = NetpbmFile(fname) + img = pam.asarray(copy=False) + if False: + pam.write('_tmp.pgm.out', pam=True) + img2 = imread('_tmp.pgm.out') + assert numpy.all(img == img2) + imsave('_tmp.pgm.out', img) + img2 = imread('_tmp.pgm.out') + assert numpy.all(img == img2) + pam.close() + except ValueError as e: + print(fname, e) + continue + _shape = img.shape + if img.ndim > 3 or (img.ndim > 2 and img.shape[-1] not in (3, 4)): + img = img[0] + cmap = 'gray' if pam.maxval > 1 else 'binary' + pyplot.imshow(img, cmap, interpolation='nearest') + pyplot.title("%s %s %s %s" % (fname, unicode(pam.magicnum), + _shape, img.dtype)) + pyplot.show() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/priors_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/priors_plots.html new file mode 100644 index 00000000..c473829d --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/priors_plots.html @@ -0,0 +1,126 @@ + + + + + + + + GPy.plotting.matplot_dep.priors_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.priors_plots

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +try:
      +    import pylab as pb
      +except:
      +    pass
      +
      +
      +
      [docs]def univariate_plot(prior): + rvs = prior.rvs(1000) + pb.hist(rvs, 100, normed=True) + xmin, xmax = pb.xlim() + xx = np.linspace(xmin, xmax, 1000) + pb.plot(xx, prior.pdf(xx), 'r', linewidth=2) +
      +
      [docs]def plot(prior): + + if prior.input_dim == 2: + rvs = prior.rvs(200) + pb.plot(rvs[:, 0], rvs[:, 1], 'kx', mew=1.5) + xmin, xmax = pb.xlim() + ymin, ymax = pb.ylim() + xx, yy = np.mgrid[xmin:xmax:100j, ymin:ymax:100j] + xflat = np.vstack((xx.flatten(), yy.flatten())).T + zz = prior.pdf(xflat).reshape(100, 100) + pb.contour(xx, yy, zz, linewidths=2) + + else: + raise NotImplementedError, "Cannot define a frame with more than two input dimensions"
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/ssgplvm.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/ssgplvm.html new file mode 100644 index 00000000..3f30a9e5 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/ssgplvm.html @@ -0,0 +1,122 @@ + + + + + + + + GPy.plotting.matplot_dep.ssgplvm — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.ssgplvm

      +"""
      +The module plotting results for SSGPLVM
      +"""
      +
      +import pylab
      +
      +from ...models import SSGPLVM
      +from img_plots import plot_2D_images
      +
      +
      [docs]class SSGPLVM_plot(object): + def __init__(self,model, imgsize): + assert isinstance(model,SSGPLVM) + self.model = model + self.imgsize= imgsize + assert model.Y.shape[1] == imgsize[0]*imgsize[1] + +
      [docs] def plot_inducing(self): + fig1 = pylab.figure() + mean = self.model.posterior.mean + arr = mean.reshape(*(mean.shape[0],self.imgsize[1],self.imgsize[0])) + plot_2D_images(fig1, arr) + fig1.gca().set_title('The mean of inducing points') + + fig2 = pylab.figure() + covar = self.model.posterior.covariance + plot_2D_images(fig2, covar) + fig2.gca().set_title('The variance of inducing points') +
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/svig_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/svig_plots.html new file mode 100644 index 00000000..27a58121 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/svig_plots.html @@ -0,0 +1,137 @@ + + + + + + + + GPy.plotting.matplot_dep.svig_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.svig_plots

      +# Copyright (c) 2012, James Hensman and Nicolo' Fusi
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +import pylab as pb
      +
      +
      +
      [docs]def plot(model, ax=None, fignum=None, Z_height=None, **kwargs): + + if ax is None: + fig = pb.figure(num=fignum) + ax = fig.add_subplot(111) + + #horrible hack here: + data = model.likelihood.data.copy() + model.likelihood.data = model.Y + GP.plot(model, ax=ax, **kwargs) + model.likelihood.data = data + + Zu = model.Z * model._Xscale + model._Xoffset + if model.input_dim==1: + ax.plot(model.X_batch, model.likelihood.data, 'gx',mew=2) + if Z_height is None: + Z_height = ax.get_ylim()[0] + ax.plot(Zu, np.zeros_like(Zu) + Z_height, 'r|', mew=1.5, markersize=12) + + if model.input_dim==2: + ax.scatter(model.X[:,0], model.X[:,1], 20., model.Y[:,0], linewidth=0, cmap=pb.cm.jet) # @UndefinedVariable + ax.plot(Zu[:,0], Zu[:,1], 'w^') +
      +
      [docs]def plot_traces(model): + + pb.figure() + t = np.array(model._param_trace) + pb.subplot(2,1,1) + for l,ti in zip(model._get_param_names(),t.T): + if not l[:3]=='iip': + pb.plot(ti,label=l) + pb.legend(loc=0) + + pb.subplot(2,1,2) + pb.plot(np.asarray(model._ll_trace),label='stochastic likelihood') + pb.legend(loc=0)
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/variational_plots.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/variational_plots.html new file mode 100644 index 00000000..91f7b038 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/variational_plots.html @@ -0,0 +1,194 @@ + + + + + + + + GPy.plotting.matplot_dep.variational_plots — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.variational_plots

      +import pylab as pb, numpy as np
      +
      +
      [docs]def plot(parameterized, fignum=None, ax=None, colors=None): + """ + Plot latent space X in 1D: + + - if fig is given, create input_dim subplots in fig and plot in these + - if ax is given plot input_dim 1D latent space plots of X into each `axis` + - if neither fig nor ax is given create a figure with fignum and plot in there + + colors: + colors of different latent space dimensions input_dim + + """ + if ax is None: + fig = pb.figure(num=fignum, figsize=(8, min(12, (2 * parameterized.mean.shape[1])))) + if colors is None: + colors = pb.gca()._get_lines.color_cycle + pb.clf() + else: + colors = iter(colors) + plots = [] + means, variances = parameterized.mean, parameterized.variance + x = np.arange(means.shape[0]) + for i in range(means.shape[1]): + if ax is None: + a = fig.add_subplot(means.shape[1], 1, i + 1) + elif isinstance(ax, (tuple, list)): + a = ax[i] + else: + raise ValueError("Need one ax per latent dimension input_dim") + a.plot(means, c='k', alpha=.3) + plots.extend(a.plot(x, means.T[i], c=colors.next(), label=r"$\mathbf{{X_{{{}}}}}$".format(i))) + a.fill_between(x, + means.T[i] - 2 * np.sqrt(variances.T[i]), + means.T[i] + 2 * np.sqrt(variances.T[i]), + facecolor=plots[-1].get_color(), + alpha=.3) + a.legend(borderaxespad=0.) + a.set_xlim(x.min(), x.max()) + if i < means.shape[1] - 1: + a.set_xticklabels('') + pb.draw() + fig.tight_layout(h_pad=.01) # , rect=(0, 0, 1, .95)) + return fig +
      +
      [docs]def plot_SpikeSlab(parameterized, fignum=None, ax=None, colors=None, side_by_side=True): + """ + Plot latent space X in 1D: + + - if fig is given, create input_dim subplots in fig and plot in these + - if ax is given plot input_dim 1D latent space plots of X into each `axis` + - if neither fig nor ax is given create a figure with fignum and plot in there + + colors: + colors of different latent space dimensions input_dim + + """ + if ax is None: + if side_by_side: + fig = pb.figure(num=fignum, figsize=(16, min(12, (2 * parameterized.mean.shape[1])))) + else: + fig = pb.figure(num=fignum, figsize=(8, min(12, (2 * parameterized.mean.shape[1])))) + if colors is None: + colors = pb.gca()._get_lines.color_cycle + pb.clf() + else: + colors = iter(colors) + plots = [] + means, variances, gamma = parameterized.mean, parameterized.variance, parameterized.binary_prob + x = np.arange(means.shape[0]) + for i in range(means.shape[1]): + if side_by_side: + sub1 = (means.shape[1],2,2*i+1) + sub2 = (means.shape[1],2,2*i+2) + else: + sub1 = (means.shape[1]*2,1,2*i+1) + sub2 = (means.shape[1]*2,1,2*i+2) + + # mean and variance plot + a = fig.add_subplot(*sub1) + a.plot(means, c='k', alpha=.3) + plots.extend(a.plot(x, means.T[i], c=colors.next(), label=r"$\mathbf{{X_{{{}}}}}$".format(i))) + a.fill_between(x, + means.T[i] - 2 * np.sqrt(variances.T[i]), + means.T[i] + 2 * np.sqrt(variances.T[i]), + facecolor=plots[-1].get_color(), + alpha=.3) + a.legend(borderaxespad=0.) + a.set_xlim(x.min(), x.max()) + if i < means.shape[1] - 1: + a.set_xticklabels('') + # binary prob plot + a = fig.add_subplot(*sub2) + a.bar(x,gamma[:,i],bottom=0.,linewidth=0,width=1.0,align='center') + a.set_xlim(x.min(), x.max()) + a.set_ylim([0.,1.]) + pb.draw() + fig.tight_layout(h_pad=.01) # , rect=(0, 0, 1, .95)) + return fig
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/plotting/matplot_dep/visualize.html b/doc/_build/html/_modules/GPy/plotting/matplot_dep/visualize.html new file mode 100644 index 00000000..79e232c1 --- /dev/null +++ b/doc/_build/html/_modules/GPy/plotting/matplot_dep/visualize.html @@ -0,0 +1,656 @@ + + + + + + + + GPy.plotting.matplot_dep.visualize — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.plotting.matplot_dep.visualize

      +import matplotlib.pyplot as plt
      +from mpl_toolkits.mplot3d import Axes3D
      +import GPy
      +import numpy as np
      +import matplotlib as mpl
      +import time
      +from GPy.core.parameterization.variational import VariationalPosterior
      +try:
      +    import visual
      +    visual_available = True
      +
      +except ImportError:
      +    visual_available = False
      +
      +
      +
      [docs]class data_show: + """ + The data_show class is a base class which describes how to visualize a + particular data set. For example, motion capture data can be plotted as a + stick figure, or images are shown using imshow. This class enables latent + to data visualizations for the GP-LVM. + """ + def __init__(self, vals): + self.vals = vals.copy() + # If no axes are defined, create some. + +
      [docs] def modify(self, vals): + raise NotImplementedError, "this needs to be implemented to use the data_show class" +
      +
      [docs] def close(self): + raise NotImplementedError, "this needs to be implemented to use the data_show class" +
      +
      [docs]class vpython_show(data_show): + """ + the vpython_show class is a base class for all visualization methods that use vpython to display. It is initialized with a scene. If the scene is set to None it creates a scene window. + """ + + def __init__(self, vals, scene=None): + data_show.__init__(self, vals) + # If no axes are defined, create some. + + if scene==None: + self.scene = visual.display(title='Data Visualization') + else: + self.scene = scene + +
      [docs] def close(self): + self.scene.exit() + + +
      +
      [docs]class matplotlib_show(data_show): + """ + the matplotlib_show class is a base class for all visualization methods that use matplotlib. It is initialized with an axis. If the axis is set to None it creates a figure window. + """ + def __init__(self, vals, axes=None): + data_show.__init__(self, vals) + # If no axes are defined, create some. + + if axes==None: + fig = plt.figure() + self.axes = fig.add_subplot(111) + else: + self.axes = axes + +
      [docs] def close(self): + plt.close(self.axes.get_figure()) +
      +
      [docs]class vector_show(matplotlib_show): + """ + A base visualization class that just shows a data vector as a plot of + vector elements alongside their indices. + """ + def __init__(self, vals, axes=None): + matplotlib_show.__init__(self, vals, axes) + #assert vals.ndim == 2, "Please give a vector in [n x 1] to plot" + #assert vals.shape[1] == 1, "only showing a vector in one dimension" + self.size = vals.size + self.handle = self.axes.plot(np.arange(0, vals.size)[:, None], vals)[0] + +
      [docs] def modify(self, vals): + self.vals = vals.copy() + xdata, ydata = self.handle.get_data() + assert vals.size == self.size, "values passed into modify changed size! vals.size:{} != in.size:{}".format(vals.size, self.size) + self.handle.set_data(xdata, self.vals) + self.axes.figure.canvas.draw() + +
      +
      [docs]class lvm(matplotlib_show): + def __init__(self, vals, model, data_visualize, latent_axes=None, sense_axes=None, latent_index=[0,1], disable_drag=False): + """Visualize a latent variable model + + :param model: the latent variable model to visualize. + :param data_visualize: the object used to visualize the data which has been modelled. + :type data_visualize: visualize.data_show type. + :param latent_axes: the axes where the latent visualization should be plotted. + """ + if vals is None: + if isinstance(model.X, VariationalPosterior): + vals = model.X.mean.values + else: + vals = model.X.values + if len(vals.shape)==1: + vals = vals[None,:] + matplotlib_show.__init__(self, vals, axes=latent_axes) + + if isinstance(latent_axes,mpl.axes.Axes): + self.cid = latent_axes.figure.canvas.mpl_connect('button_press_event', self.on_click) + if not disable_drag: + self.cid = latent_axes.figure.canvas.mpl_connect('motion_notify_event', self.on_move) + self.cid = latent_axes.figure.canvas.mpl_connect('axes_leave_event', self.on_leave) + self.cid = latent_axes.figure.canvas.mpl_connect('axes_enter_event', self.on_enter) + else: + self.cid = latent_axes[0].figure.canvas.mpl_connect('button_press_event', self.on_click) + if not disable_drag: + self.cid = latent_axes[0].figure.canvas.mpl_connect('motion_notify_event', self.on_move) + self.cid = latent_axes[0].figure.canvas.mpl_connect('axes_leave_event', self.on_leave) + self.cid = latent_axes[0].figure.canvas.mpl_connect('axes_enter_event', self.on_enter) + + self.data_visualize = data_visualize + self.model = model + self.latent_axes = latent_axes + self.sense_axes = sense_axes + self.called = False + self.move_on = False + self.latent_index = latent_index + self.latent_dim = model.input_dim + self.disable_drag = disable_drag + + # The red cross which shows current latent point. + self.latent_values = vals + self.latent_handle = self.latent_axes.plot([0],[0],'rx',mew=2)[0] + self.modify(vals) + self.show_sensitivities() + +
      [docs] def modify(self, vals): + """When latent values are modified update the latent representation and ulso update the output visualization.""" + self.vals = vals.view(np.ndarray).copy() + y = self.model.predict(self.vals)[0] + self.data_visualize.modify(y) + self.latent_handle.set_data(self.vals[0,self.latent_index[0]], self.vals[0,self.latent_index[1]]) + self.axes.figure.canvas.draw() + +
      +
      [docs] def on_enter(self,event): + pass
      +
      [docs] def on_leave(self,event): + pass +
      +
      [docs] def on_click(self, event): + if event.inaxes!=self.latent_axes: return + if self.disable_drag: + self.move_on = True + self.called = True + self.on_move(event) + else: + self.move_on = not self.move_on + self.called = True +
      +
      [docs] def on_move(self, event): + if event.inaxes!=self.latent_axes: return + if self.called and self.move_on: + # Call modify code on move + self.latent_values[:, self.latent_index[0]]=event.xdata + self.latent_values[:, self.latent_index[1]]=event.ydata + self.modify(self.latent_values) +
      +
      [docs] def show_sensitivities(self): + # A click in the bar chart axis for selection a dimension. + if self.sense_axes != None: + self.sense_axes.cla() + self.sense_axes.bar(np.arange(self.model.input_dim), self.model.input_sensitivity(), color='b') + + if self.latent_index[1] == self.latent_index[0]: + self.sense_axes.bar(np.array(self.latent_index[0]), self.model.input_sensitivity()[self.latent_index[0]], color='y') + self.sense_axes.bar(np.array(self.latent_index[1]), self.model.input_sensitivity()[self.latent_index[1]], color='y') + + else: + self.sense_axes.bar(np.array(self.latent_index[0]), self.model.input_sensitivity()[self.latent_index[0]], color='g') + self.sense_axes.bar(np.array(self.latent_index[1]), self.model.input_sensitivity()[self.latent_index[1]], color='r') + + self.sense_axes.figure.canvas.draw() + +
      +
      [docs]class lvm_subplots(lvm): + """ + latent_axes is a np array of dimension np.ceil(input_dim/2), + one for each pair of the latent dimensions. + """ + def __init__(self, vals, Model, data_visualize, latent_axes=None, sense_axes=None): + self.nplots = int(np.ceil(Model.input_dim/2.))+1 + assert len(latent_axes)==self.nplots + if vals==None: + vals = Model.X[0, :] + self.latent_values = vals + + for i, axis in enumerate(latent_axes): + if i == self.nplots-1: + if self.nplots*2!=Model.input_dim: + latent_index = [i*2, i*2] + lvm.__init__(self, self.latent_vals, Model, data_visualize, axis, sense_axes, latent_index=latent_index) + else: + latent_index = [i*2, i*2+1] + lvm.__init__(self, self.latent_vals, Model, data_visualize, axis, latent_index=latent_index) + + +
      +
      [docs]class lvm_dimselect(lvm): + """ + A visualizer for latent variable models which allows selection of the latent dimensions to use by clicking on a bar chart of their length scales. + + For an example of the visualizer's use try: + + GPy.examples.dimensionality_reduction.BGPVLM_oil() + + """ + def __init__(self, vals, model, data_visualize, latent_axes=None, sense_axes=None, latent_index=[0, 1], labels=None): + if latent_axes==None and sense_axes==None: + self.fig,(latent_axes,self.sense_axes) = plt.subplots(1,2) + elif sense_axes==None: + fig=plt.figure() + self.sense_axes = fig.add_subplot(111) + else: + self.sense_axes = sense_axes + self.labels = labels + lvm.__init__(self,vals,model,data_visualize,latent_axes,sense_axes,latent_index) + self.show_sensitivities() + print self.latent_values + print "use left and right mouse buttons to select dimensions" + + +
      [docs] def on_click(self, event): + if event.inaxes==self.sense_axes: + new_index = max(0,min(int(np.round(event.xdata-0.5)),self.model.input_dim-1)) + if event.button == 1: + # Make it red if and y-axis (red=port=left) if it is a left button click + self.latent_index[1] = new_index + else: + # Make it green and x-axis (green=starboard=right) if it is a right button click + self.latent_index[0] = new_index + + self.show_sensitivities() + + self.latent_axes.cla() + self.model.plot_latent(which_indices=self.latent_index, + ax=self.latent_axes, labels=self.labels) + self.latent_handle = self.latent_axes.plot([0],[0],'rx',mew=2)[0] + self.modify(self.latent_values) + + elif event.inaxes==self.latent_axes: + self.move_on = not self.move_on + + self.called = True + + +
      +
      [docs] def on_leave(self,event): + print type(self.latent_values) + latent_values = self.latent_values.copy() + y = self.model.predict(latent_values[None,:])[0] + self.data_visualize.modify(y) + + +
      +
      [docs]class image_show(matplotlib_show): + """Show a data vector as an image. This visualizer rehapes the output vector and displays it as an image. + + :param vals: the values of the output to display. + :type vals: ndarray + :param axes: the axes to show the output on. + :type vals: axes handle + :param dimensions: the dimensions that the image needs to be transposed to for display. + :type dimensions: tuple + :param transpose: whether to transpose the image before display. + :type bool: default is False. + :param order: whether array is in Fortan ordering ('F') or Python ordering ('C'). Default is python ('C'). + :type order: string + :param invert: whether to invert the pixels or not (default False). + :type invert: bool + :param palette: a palette to use for the image. + :param preset_mean: the preset mean of a scaled image. + :type preset_mean: double + :param preset_std: the preset standard deviation of a scaled image. + :type preset_std: double + :param cmap: the colormap for image visualization + :type cmap: matplotlib.cm""" + + def __init__(self, vals, axes=None, dimensions=(16,16), transpose=False, order='C', invert=False, scale=False, palette=[], preset_mean=0., preset_std=1., select_image=0, cmap=None): + matplotlib_show.__init__(self, vals, axes) + self.dimensions = dimensions + self.transpose = transpose + self.order = order + self.invert = invert + self.scale = scale + self.palette = palette + self.preset_mean = preset_mean + self.preset_std = preset_std + self.select_image = select_image # This is used when the y vector contains multiple images concatenated. + + self.set_image(self.vals) + if not self.palette == []: # Can just show the image (self.set_image() took care of setting the palette) + self.handle = self.axes.imshow(self.vals, interpolation='nearest') + elif cmap==None: # Use a jet map. + self.handle = self.axes.imshow(self.vals, cmap=plt.cm.jet, interpolation='nearest') # @UndefinedVariable + else: # Use the selected map. + self.handle = self.axes.imshow(self.vals, cmap=cmap, interpolation='nearest') # @UndefinedVariable + plt.show() + +
      [docs] def modify(self, vals): + self.set_image(vals.copy()) + self.handle.set_array(self.vals) + self.axes.figure.canvas.draw() +
      +
      [docs] def set_image(self, vals): + dim = self.dimensions[0] * self.dimensions[1] + num_images = np.sqrt(vals[0,].size/dim) + if num_images > 1 and num_images.is_integer(): # Show a mosaic of images + num_images = np.int(num_images) + self.vals = np.zeros((self.dimensions[0]*num_images, self.dimensions[1]*num_images)) + for iR in range(num_images): + for iC in range(num_images): + cur_img_id = iR*num_images + iC + cur_img = np.reshape(vals[0,dim*cur_img_id+np.array(range(dim))], self.dimensions, order=self.order) + first_row = iR*self.dimensions[0] + last_row = (iR+1)*self.dimensions[0] + first_col = iC*self.dimensions[1] + last_col = (iC+1)*self.dimensions[1] + self.vals[first_row:last_row, first_col:last_col] = cur_img + + else: + self.vals = np.reshape(vals[0,dim*self.select_image+np.array(range(dim))], self.dimensions, order=self.order) + if self.transpose: + self.vals = self.vals.T + # if not self.scale: + # self.vals = self.vals + if self.invert: + self.vals = -self.vals + + # un-normalizing, for visualisation purposes: + self.vals = self.vals*self.preset_std + self.preset_mean + # Clipping the values: + #self.vals[self.vals < 0] = 0 + #self.vals[self.vals > 255] = 255 + #else: + #self.vals = 255*(self.vals - self.vals.min())/(self.vals.max() - self.vals.min()) + if not self.palette == []: # applying using an image palette (e.g. if the image has been quantized) + from PIL import Image + self.vals = Image.fromarray(self.vals.astype('uint8')) + self.vals.putpalette(self.palette) # palette is a list, must be loaded before calling this function +
      +
      [docs]class mocap_data_show_vpython(vpython_show): + """Base class for visualizing motion capture data using visual module.""" + + def __init__(self, vals, scene=None, connect=None, radius=0.1): + vpython_show.__init__(self, vals, scene) + self.radius = radius + self.connect = connect + self.process_values() + self.draw_edges() + self.draw_vertices() + +
      [docs] def draw_vertices(self): + self.spheres = [] + for i in range(self.vals.shape[0]): + self.spheres.append(visual.sphere(pos=(self.vals[i, 0], self.vals[i, 2], self.vals[i, 1]), radius=self.radius)) + self.scene.visible=True +
      +
      [docs] def draw_edges(self): + self.rods = [] + self.line_handle = [] + if not self.connect==None: + self.I, self.J = np.nonzero(self.connect) + for i, j in zip(self.I, self.J): + pos, axis = self.pos_axis(i, j) + self.rods.append(visual.cylinder(pos=pos, axis=axis, radius=self.radius)) +
      +
      [docs] def modify_vertices(self): + for i in range(self.vals.shape[0]): + self.spheres[i].pos = (self.vals[i, 0], self.vals[i, 2], self.vals[i, 1]) +
      +
      [docs] def modify_edges(self): + self.line_handle = [] + if not self.connect==None: + self.I, self.J = np.nonzero(self.connect) + for rod, i, j in zip(self.rods, self.I, self.J): + rod.pos, rod.axis = self.pos_axis(i, j) +
      +
      [docs] def pos_axis(self, i, j): + pos = [] + axis = [] + pos.append(self.vals[i, 0]) + axis.append(self.vals[j, 0]-self.vals[i,0]) + pos.append(self.vals[i, 2]) + axis.append(self.vals[j, 2]-self.vals[i,2]) + pos.append(self.vals[i, 1]) + axis.append(self.vals[j, 1]-self.vals[i,1]) + return pos, axis +
      +
      [docs] def modify(self, vals): + self.vals = vals.copy() + self.process_values() + self.modify_edges() + self.modify_vertices() +
      +
      [docs] def process_values(self): + raise NotImplementedError, "this needs to be implemented to use the data_show class" +
      +
      [docs]class mocap_data_show(matplotlib_show): + """Base class for visualizing motion capture data.""" + + def __init__(self, vals, axes=None, connect=None): + if axes==None: + fig = plt.figure() + axes = fig.add_subplot(111, projection='3d', aspect='equal') + matplotlib_show.__init__(self, vals, axes) + + self.connect = connect + self.process_values() + self.initialize_axes() + self.draw_vertices() + self.finalize_axes() + self.draw_edges() + self.axes.figure.canvas.draw() + +
      [docs] def draw_vertices(self): + self.points_handle = self.axes.scatter(self.vals[:, 0], self.vals[:, 1], self.vals[:, 2]) +
      +
      [docs] def draw_edges(self): + self.line_handle = [] + if not self.connect==None: + x = [] + y = [] + z = [] + self.I, self.J = np.nonzero(self.connect) + for i, j in zip(self.I, self.J): + x.append(self.vals[i, 0]) + x.append(self.vals[j, 0]) + x.append(np.NaN) + y.append(self.vals[i, 1]) + y.append(self.vals[j, 1]) + y.append(np.NaN) + z.append(self.vals[i, 2]) + z.append(self.vals[j, 2]) + z.append(np.NaN) + self.line_handle = self.axes.plot(np.array(x), np.array(y), np.array(z), 'b-') +
      +
      [docs] def modify(self, vals): + self.vals = vals.copy() + self.process_values() + self.initialize_axes_modify() + self.draw_vertices() + self.initialize_axes() + self.finalize_axes_modify() + self.draw_edges() + self.axes.figure.canvas.draw() +
      +
      [docs] def process_values(self): + raise NotImplementedError, "this needs to be implemented to use the data_show class" +
      +
      [docs] def initialize_axes(self, boundary=0.05): + """Set up the axes with the right limits and scaling.""" + bs = [(self.vals[:, i].max()-self.vals[:, i].min())*boundary for i in xrange(3)] + self.x_lim = np.array([self.vals[:, 0].min()-bs[0], self.vals[:, 0].max()+bs[0]]) + self.y_lim = np.array([self.vals[:, 1].min()-bs[1], self.vals[:, 1].max()+bs[1]]) + self.z_lim = np.array([self.vals[:, 2].min()-bs[2], self.vals[:, 2].max()+bs[2]]) +
      +
      [docs] def initialize_axes_modify(self): + self.points_handle.remove() + self.line_handle[0].remove() +
      +
      [docs] def finalize_axes(self): + self.axes.set_xlim(self.x_lim) + self.axes.set_ylim(self.y_lim) + self.axes.set_zlim(self.z_lim) + self.axes.auto_scale_xyz([-1., 1.], [-1., 1.], [-1., 1.]) + +# self.axes.set_aspect('equal') +# self.axes.autoscale(enable=False) +
      +
      [docs] def finalize_axes_modify(self): + self.axes.set_xlim(self.x_lim) + self.axes.set_ylim(self.y_lim) + self.axes.set_zlim(self.z_lim) +
      +
      [docs]class stick_show(mocap_data_show): + """Show a three dimensional point cloud as a figure. Connect elements of the figure together using the matrix connect.""" + def __init__(self, vals, connect=None, axes=None): + if len(vals.shape)==1: + vals = vals[None,:] + mocap_data_show.__init__(self, vals, axes=axes, connect=connect) + +
      [docs] def process_values(self): + self.vals = self.vals.reshape((3, self.vals.shape[1]/3)).T +
      +
      [docs]class skeleton_show(mocap_data_show): + """data_show class for visualizing motion capture data encoded as a skeleton with angles.""" + def __init__(self, vals, skel, axes=None, padding=0): + """data_show class for visualizing motion capture data encoded as a skeleton with angles. + :param vals: set of modeled angles to use for printing in the axis when it's first created. + :type vals: np.array + :param skel: skeleton object that has the parameters of the motion capture skeleton associated with it. + :type skel: mocap.skeleton object + :param padding: + :type int + """ + self.skel = skel + self.padding = padding + connect = skel.connection_matrix() + mocap_data_show.__init__(self, vals, axes=axes, connect=connect) +
      [docs] def process_values(self): + """Takes a set of angles and converts them to the x,y,z coordinates in the internal prepresentation of the class, ready for plotting. + + :param vals: the values that are being modelled.""" + + if self.padding>0: + channels = np.zeros((self.vals.shape[0], self.vals.shape[1]+self.padding)) + channels[:, 0:self.vals.shape[0]] = self.vals + else: + channels = self.vals + vals_mat = self.skel.to_xyz(channels.flatten()) + self.vals = np.zeros_like(vals_mat) + # Flip the Y and Z axes + self.vals[:, 0] = vals_mat[:, 0].copy() + self.vals[:, 1] = vals_mat[:, 2].copy() + self.vals[:, 2] = vals_mat[:, 1].copy() +
      +
      [docs] def wrap_around(self, lim, connect): + quot = lim[1] - lim[0] + self.vals = rem(self.vals, quot)+lim[0] + nVals = floor(self.vals/quot) + for i in range(connect.shape[0]): + for j in find(connect[i, :]): + if nVals[i] != nVals[j]: + connect[i, j] = False + return connect + +
      +
      [docs]def data_play(Y, visualizer, frame_rate=30): + """Play a data set using the data_show object given. + + :Y: the data set to be visualized. + :param visualizer: the data show objectwhether to display during optimisation + :type visualizer: data_show + + Example usage: + + This example loads in the CMU mocap database (http://mocap.cs.cmu.edu) subject number 35 motion number 01. It then plays it using the mocap_show visualize object. + + .. code-block:: python + + data = GPy.util.datasets.cmu_mocap(subject='35', train_motions=['01']) + Y = data['Y'] + Y[:, 0:3] = 0. # Make figure walk in place + visualize = GPy.util.visualize.skeleton_show(Y[0, :], data['skel']) + GPy.util.visualize.data_play(Y, visualize) + + """ + + + for y in Y: + visualizer.modify(y[None, :]) + time.sleep(1./float(frame_rate))
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing.html b/doc/_build/html/_modules/GPy/testing.html new file mode 100644 index 00000000..2491ec56 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing.html @@ -0,0 +1,108 @@ + + + + + + + + GPy.testing — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing

      +# Copyright (c) 2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +"""
      +
      +MaxZ
      +
      +"""
      +import unittest
      +import sys
      +
      +
      [docs]def deepTest(reason): + if reason: + return lambda x:x + return unittest.skip("Not deep scanning, enable deepscan by adding 'deep' argument")
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/examples_tests.html b/doc/_build/html/_modules/GPy/testing/examples_tests.html new file mode 100644 index 00000000..f25d2c91 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/examples_tests.html @@ -0,0 +1,201 @@ + + + + + + + + GPy.testing.examples_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.examples_tests

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import unittest
      +import numpy as np
      +import GPy
      +import inspect
      +import pkgutil
      +import os
      +import random
      +from nose.tools import nottest
      +import sys
      +import itertools
      +
      +
      [docs]class ExamplesTests(unittest.TestCase): + def _checkgrad(self, Model): + self.assertTrue(Model.checkgrad()) + + def _model_instance(self, Model): + self.assertTrue(isinstance(Model, GPy.models)) +
      +
      [docs]def model_checkgrads(model): + model.randomize() + #NOTE: Step as 1e-4, this should be acceptable for more peaky models + return model.checkgrad(step=1e-4) +
      +
      [docs]def model_instance(model): + return isinstance(model, GPy.core.model.Model) +
      +
      [docs]def flatten_nested(lst): + result = [] + for element in lst: + if hasattr(element, '__iter__'): + result.extend(flatten_nested(element)) + else: + result.append(element) + return result +
      +@nottest +
      [docs]def test_models(): + optimize=False + plot=True + examples_path = os.path.dirname(GPy.examples.__file__) + # Load modules + failing_models = {} + for loader, module_name, is_pkg in pkgutil.iter_modules([examples_path]): + # Load examples + module_examples = loader.find_module(module_name).load_module(module_name) + print "MODULE", module_examples + print "Before" + print inspect.getmembers(module_examples, predicate=inspect.isfunction) + functions = [ func for func in inspect.getmembers(module_examples, predicate=inspect.isfunction) if func[0].startswith('_') is False ][::-1] + print "After" + print functions + for example in functions: + if example[0] in ['epomeo_gpx']: + #These are the edge cases that we might want to handle specially + if example[0] == 'epomeo_gpx' and not GPy.util.datasets.gpxpy_available: + print "Skipping as gpxpy is not available to parse GPS" + continue + + print "Testing example: ", example[0] + # Generate model + + try: + models = [ example[1](optimize=optimize, plot=plot) ] + #If more than one model returned, flatten them + models = flatten_nested(models) + except Exception as e: + failing_models[example[0]] = "Cannot make model: \n{e}".format(e=e) + else: + print models + model_checkgrads.description = 'test_checkgrads_%s' % example[0] + try: + for model in models: + if not model_checkgrads(model): + failing_models[model_checkgrads.description] = False + except Exception as e: + failing_models[model_checkgrads.description] = e + + model_instance.description = 'test_instance_%s' % example[0] + try: + for model in models: + if not model_instance(model): + failing_models[model_instance.description] = False + except Exception as e: + failing_models[model_instance.description] = e + + #yield model_checkgrads, model + #yield model_instance, model + + print "Finished checking module {m}".format(m=module_name) + if len(failing_models.keys()) > 0: + print "Failing models: " + print failing_models + + if len(failing_models.keys()) > 0: + print failing_models + raise Exception(failing_models) + +
      +if __name__ == "__main__": + print "Running unit tests, please be (very) patient..." + # unittest.main() + test_models() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/fitc.html b/doc/_build/html/_modules/GPy/testing/fitc.html new file mode 100644 index 00000000..bc6de069 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/fitc.html @@ -0,0 +1,129 @@ + + + + + + + + GPy.testing.fitc — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.fitc

      +# Copyright (c) 2014, James Hensman
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import unittest
      +import numpy as np
      +import GPy
      +
      +
      [docs]class FITCtest(unittest.TestCase): +
      [docs] def setUp(self): + ###################################### + # # 1 dimensional example + + N = 20 + # sample inputs and outputs + self.X1D = np.random.uniform(-3., 3., (N, 1)) + self.Y1D = np.sin(self.X1D) + np.random.randn(N, 1) * 0.05 + + ###################################### + # # 2 dimensional example + + # sample inputs and outputs + self.X2D = np.random.uniform(-3., 3., (N, 2)) + self.Y2D = np.sin(self.X2D[:, 0:1]) * np.sin(self.X2D[:, 1:2]) + np.random.randn(N, 1) * 0.05 +
      +
      [docs] def test_fitc_1d(self): + m = GPy.models.SparseGPRegression(self.X1D, self.Y1D) + m.inference_method=GPy.inference.latent_function_inference.FITC() + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_fitc_2d(self): + m = GPy.models.SparseGPRegression(self.X2D, self.Y2D) + m.inference_method=GPy.inference.latent_function_inference.FITC() + self.assertTrue(m.checkgrad()) +
      + +
      +
      + + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/index_operations_tests.html b/doc/_build/html/_modules/GPy/testing/index_operations_tests.html new file mode 100644 index 00000000..ffb20ca9 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/index_operations_tests.html @@ -0,0 +1,231 @@ + + + + + + + + GPy.testing.index_operations_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.index_operations_tests

      +# Copyright (c) 2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import unittest
      +import numpy as np
      +from GPy.core.parameterization.index_operations import ParameterIndexOperations,\
      +    ParameterIndexOperationsView
      +
      +one, two, three = 'one', 'two', 'three'
      +
      +
      [docs]class Test(unittest.TestCase): + +
      [docs] def setUp(self): + self.param_index = ParameterIndexOperations() + self.param_index.add(one, [3,9]) + self.param_index.add(two, [0,5]) + self.param_index.add(three, [2,4,7,10]) + self.view = ParameterIndexOperationsView(self.param_index, 2, 6) +
      +
      [docs] def test_clear(self): + self.param_index.clear() + self.assertDictEqual(self.param_index._properties, {}) +
      +
      [docs] def test_remove(self): + removed = self.param_index.remove(three, np.r_[3:13]) + self.assertListEqual(removed.tolist(), [4,7,10]) + self.assertListEqual(self.param_index[three].tolist(), [2]) + removed = self.param_index.remove(one, [1]) + self.assertListEqual(removed.tolist(), []) + self.assertListEqual(self.param_index[one].tolist(), [3,9]) + self.assertListEqual(self.param_index.remove('not in there', []).tolist(), []) + removed = self.param_index.remove(one, [9]) + self.assertListEqual(removed.tolist(), [9]) + self.assertListEqual(self.param_index[one].tolist(), [3]) + self.assertListEqual(self.param_index.remove('not in there', [2,3,4]).tolist(), []) + self.assertListEqual(self.view.remove('not in there', [2,3,4]).tolist(), []) +
      +
      [docs] def test_shift_left(self): + self.view.shift_left(0, 2) + self.assertListEqual(self.param_index[three].tolist(), [2,5,8]) + self.assertListEqual(self.param_index[two].tolist(), [0,3]) + self.assertListEqual(self.param_index[one].tolist(), [7]) + #======================================================================= + # 0 1 2 3 4 5 6 7 8 9 10 + # one + # two two + # three three three + # view: [0 1 2 3 4 5 ] + #======================================================================= + self.assertListEqual(self.view[three].tolist(), [0,3]) + self.assertListEqual(self.view[two].tolist(), [1]) + self.assertListEqual(self.view[one].tolist(), [5]) + self.param_index.shift_left(7, 1) + #======================================================================= + # 0 1 2 3 4 5 6 7 8 9 10 + # + # two two + # three three three + # view: [0 1 2 3 4 5 ] + #======================================================================= + self.assertListEqual(self.param_index[three].tolist(), [2,5,7]) + self.assertListEqual(self.param_index[two].tolist(), [0,3]) + self.assertListEqual(self.param_index[one].tolist(), []) + self.assertListEqual(self.view[three].tolist(), [0,3,5]) + self.assertListEqual(self.view[two].tolist(), [1]) + self.assertListEqual(self.view[one].tolist(), []) +
      +
      [docs] def test_shift_right(self): + self.view.shift_right(3, 2) + self.assertListEqual(self.param_index[three].tolist(), [2,4,9,12]) + self.assertListEqual(self.param_index[two].tolist(), [0,7]) + self.assertListEqual(self.param_index[one].tolist(), [3,11]) +
      +
      [docs] def test_index_view(self): + #======================================================================= + # 0 1 2 3 4 5 6 7 8 9 10 + # one one + # two two + # three three three three + # view: [0 1 2 3 4 5 ] + #======================================================================= + self.view = ParameterIndexOperationsView(self.param_index, 2, 6) + self.assertSetEqual(set(self.view.properties()), set([one, two, three])) + for v,p in zip(self.view.properties_for(np.r_[:6]), self.param_index.properties_for(np.r_[2:2+6])): + self.assertEqual(v, p) + self.assertSetEqual(set(self.view[two]), set([3])) + self.assertSetEqual(set(self.param_index[two]), set([0, 5])) + self.view.add(two, np.array([0])) + self.assertSetEqual(set(self.view[two]), set([0,3])) + self.assertSetEqual(set(self.param_index[two]), set([0, 2, 5])) + self.view.clear() + for v,p in zip(self.view.properties_for(np.r_[:6]), self.param_index.properties_for(np.r_[2:2+6])): + self.assertEqual(v, p) + self.assertEqual(v, []) + param_index = ParameterIndexOperations() + param_index.add(one, [3,9]) + param_index.add(two, [0,5]) + param_index.add(three, [2,4,7,10]) + view2 = ParameterIndexOperationsView(param_index, 2, 8) + self.view.update(view2) + for [i,v],[i2,v2] in zip(sorted(param_index.items()), sorted(self.param_index.items())): + self.assertEqual(i, i2) + np.testing.assert_equal(v, v2) +
      +
      [docs] def test_view_of_view(self): + #======================================================================= + # 0 1 2 3 4 5 6 7 8 9 10 + # one one + # two two + # three three three three + # view: [0 1 2 3 4 5 ] + # view2: [0 1 2 3 4 5 ] + #======================================================================= + view2 = ParameterIndexOperationsView(self.view, 2, 6) + view2.shift_right(0, 2) +
      +
      [docs] def test_indexview_remove(self): + removed = self.view.remove(two, [3]) + self.assertListEqual(removed.tolist(), [3]) + removed = self.view.remove(three, np.r_[:5]) + self.assertListEqual(removed.tolist(), [0, 2]) +
      +
      [docs] def test_misc(self): + for k,v in self.param_index.copy()._properties.iteritems(): + self.assertListEqual(self.param_index[k].tolist(), v.tolist()) + self.assertEqual(self.param_index.size, 8) + self.assertEqual(self.view.size, 5) +
      +
      [docs] def test_print(self): + print self.param_index + print self.view +
      +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.test_index_view'] + unittest.main() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/inference_tests.html b/doc/_build/html/_modules/GPy/testing/inference_tests.html new file mode 100644 index 00000000..200f2790 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/inference_tests.html @@ -0,0 +1,180 @@ + + + + + + + + GPy.testing.inference_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.inference_tests

      +# Copyright (c) 2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +"""
      +The test cases for various inference algorithms
      +"""
      +
      +import unittest, itertools
      +import numpy as np
      +import GPy
      +
      +
      +
      [docs]class InferenceXTestCase(unittest.TestCase): + +
      [docs] def genData(self): + D1,D2,N = 12,12,50 + np.random.seed(1234) + + x = np.linspace(0, 4 * np.pi, N)[:, None] + s1 = np.vectorize(lambda x: np.sin(x)) + s2 = np.vectorize(lambda x: np.cos(x)**2) + s3 = np.vectorize(lambda x:-np.exp(-np.cos(2 * x))) + sS = np.vectorize(lambda x: np.cos(x)) + + s1 = s1(x) + s2 = s2(x) + s3 = s3(x) + sS = sS(x) + + s1 -= s1.mean(); s1 /= s1.std(0) + s2 -= s2.mean(); s2 /= s2.std(0) + s3 -= s3.mean(); s3 /= s3.std(0) + sS -= sS.mean(); sS /= sS.std(0) + + S1 = np.hstack([s1, sS]) + S2 = np.hstack([s3, sS]) + + P1 = np.random.randn(S1.shape[1], D1) + P2 = np.random.randn(S2.shape[1], D2) + + Y1 = S1.dot(P1) + Y2 = S2.dot(P2) + + Y1 += .01 * np.random.randn(*Y1.shape) + Y2 += .01 * np.random.randn(*Y2.shape) + + Y1 -= Y1.mean(0) + Y2 -= Y2.mean(0) + Y1 /= Y1.std(0) + Y2 /= Y2.std(0) + + slist = [s1, s2, s3, sS] + slist_names = ["s1", "s2", "s3", "sS"] + Ylist = [Y1, Y2] + + return Ylist +
      +
      [docs] def test_inferenceX_BGPLVM(self): + Ys = self.genData() + m = GPy.models.BayesianGPLVM(Ys[0],5,kernel=GPy.kern.Linear(5,ARD=True)) + + x,mi = m.infer_newX(m.Y, optimize=False) + self.assertTrue(mi.checkgrad()) + + m.optimize(max_iters=10000) + x,mi = m.infer_newX(m.Y) + + self.assertTrue(np.allclose(m.X.mean, mi.X.mean)) + self.assertTrue(np.allclose(m.X.variance, mi.X.variance)) +
      +
      [docs] def test_inferenceX_GPLVM(self): + Ys = self.genData() + m = GPy.models.GPLVM(Ys[0],3,kernel=GPy.kern.RBF(3,ARD=True)) + + x,mi = m.infer_newX(m.Y, optimize=False) + self.assertTrue(mi.checkgrad()) + +# m.optimize(max_iters=10000) +# x,mi = m.infer_newX(m.Y) +# self.assertTrue(np.allclose(m.X, x)) + +
      +if __name__ == "__main__": + unittest.main() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/kernel_tests.html b/doc/_build/html/_modules/GPy/testing/kernel_tests.html new file mode 100644 index 00000000..3f1d0306 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/kernel_tests.html @@ -0,0 +1,525 @@ + + + + + + + + GPy.testing.kernel_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.kernel_tests

      +# Copyright (c) 2012, 2013 GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import unittest
      +import numpy as np
      +import GPy
      +import sys
      +from GPy.core.parameterization.param import Param
      +
      +verbose = 0
      +
      +
      +
      [docs]class Kern_check_model(GPy.core.Model): + """ + This is a dummy model class used as a base class for checking that the + gradients of a given kernel are implemented correctly. It enables + checkgrad() to be called independently on a kernel. + """ + def __init__(self, kernel=None, dL_dK=None, X=None, X2=None): + GPy.core.Model.__init__(self, 'kernel_test_model') + if kernel==None: + kernel = GPy.kern.RBF(1) + kernel.randomize(loc=1, scale=0.1) + if X is None: + X = np.random.randn(20, kernel.input_dim) + if dL_dK is None: + if X2 is None: + dL_dK = np.ones((X.shape[0], X.shape[0])) + else: + dL_dK = np.ones((X.shape[0], X2.shape[0])) + + self.kernel = kernel + self.X = X + self.X2 = X2 + self.dL_dK = dL_dK + +
      [docs] def is_positive_semi_definite(self): + v = np.linalg.eig(self.kernel.K(self.X))[0] + if any(v.real<=-1e-10): + print v.real.min() + return False + else: + return True +
      +
      [docs] def log_likelihood(self): + return np.sum(self.dL_dK*self.kernel.K(self.X, self.X2)) +
      +
      [docs]class Kern_check_dK_dtheta(Kern_check_model): + """ + This class allows gradient checks for the gradient of a kernel with + respect to parameters. + """ + def __init__(self, kernel=None, dL_dK=None, X=None, X2=None): + Kern_check_model.__init__(self,kernel=kernel,dL_dK=dL_dK, X=X, X2=X2) + self.link_parameter(self.kernel) + +
      [docs] def parameters_changed(self): + return self.kernel.update_gradients_full(self.dL_dK, self.X, self.X2) + +
      +
      [docs]class Kern_check_dKdiag_dtheta(Kern_check_model): + """ + This class allows gradient checks of the gradient of the diagonal of a + kernel with respect to the parameters. + """ + def __init__(self, kernel=None, dL_dK=None, X=None): + Kern_check_model.__init__(self,kernel=kernel,dL_dK=dL_dK, X=X, X2=None) + self.link_parameter(self.kernel) + +
      [docs] def log_likelihood(self): + return (np.diag(self.dL_dK)*self.kernel.Kdiag(self.X)).sum() +
      +
      [docs] def parameters_changed(self): + self.kernel.update_gradients_diag(np.diag(self.dL_dK), self.X) +
      +
      [docs]class Kern_check_dK_dX(Kern_check_model): + """This class allows gradient checks for the gradient of a kernel with respect to X. """ + def __init__(self, kernel=None, dL_dK=None, X=None, X2=None): + Kern_check_model.__init__(self,kernel=kernel,dL_dK=dL_dK, X=X, X2=X2) + self.X = Param('X',X) + self.link_parameter(self.X) + +
      [docs] def parameters_changed(self): + self.X.gradient[:] = self.kernel.gradients_X(self.dL_dK, self.X, self.X2) +
      +
      [docs]class Kern_check_dKdiag_dX(Kern_check_dK_dX): + """This class allows gradient checks for the gradient of a kernel diagonal with respect to X. """ + def __init__(self, kernel=None, dL_dK=None, X=None, X2=None): + Kern_check_dK_dX.__init__(self,kernel=kernel,dL_dK=dL_dK, X=X, X2=None) + +
      [docs] def log_likelihood(self): + return (np.diag(self.dL_dK)*self.kernel.Kdiag(self.X)).sum() +
      +
      [docs] def parameters_changed(self): + self.X.gradient[:] = self.kernel.gradients_X_diag(self.dL_dK.diagonal(), self.X) + + +
      +
      [docs]def check_kernel_gradient_functions(kern, X=None, X2=None, output_ind=None, verbose=False, fixed_X_dims=None): + """ + This function runs on kernels to check the correctness of their + implementation. It checks that the covariance function is positive definite + for a randomly generated data set. + + :param kern: the kernel to be tested. + :type kern: GPy.kern.Kernpart + :param X: X input values to test the covariance function. + :type X: ndarray + :param X2: X2 input values to test the covariance function. + :type X2: ndarray + + """ + pass_checks = True + if X is None: + X = np.random.randn(10, kern.input_dim) + if output_ind is not None: + X[:, output_ind] = np.random.randint(kern.output_dim, X.shape[0]) + if X2 is None: + X2 = np.random.randn(20, kern.input_dim) + if output_ind is not None: + X2[:, output_ind] = np.random.randint(kern.output_dim, X2.shape[0]) + + if verbose: + print("Checking covariance function is positive definite.") + result = Kern_check_model(kern, X=X).is_positive_semi_definite() + if result and verbose: + print("Check passed.") + if not result: + print("Positive definite check failed for " + kern.name + " covariance function.") + pass_checks = False + assert(result) + return False + + if verbose: + print("Checking gradients of K(X, X) wrt theta.") + result = Kern_check_dK_dtheta(kern, X=X, X2=None).checkgrad(verbose=verbose) + if result and verbose: + print("Check passed.") + if not result: + print("Gradient of K(X, X) wrt theta failed for " + kern.name + " covariance function. Gradient values as follows:") + Kern_check_dK_dtheta(kern, X=X, X2=None).checkgrad(verbose=True) + pass_checks = False + assert(result) + return False + + if verbose: + print("Checking gradients of K(X, X2) wrt theta.") + result = Kern_check_dK_dtheta(kern, X=X, X2=X2).checkgrad(verbose=verbose) + if result and verbose: + print("Check passed.") + if not result: + print("Gradient of K(X, X) wrt theta failed for " + kern.name + " covariance function. Gradient values as follows:") + Kern_check_dK_dtheta(kern, X=X, X2=X2).checkgrad(verbose=True) + pass_checks = False + assert(result) + return False + + if verbose: + print("Checking gradients of Kdiag(X) wrt theta.") + try: + result = Kern_check_dKdiag_dtheta(kern, X=X).checkgrad(verbose=verbose) + except NotImplementedError: + result=True + if verbose: + print("update_gradients_diag not implemented for " + kern.name) + if result and verbose: + print("Check passed.") + if not result: + print("Gradient of Kdiag(X) wrt theta failed for " + kern.name + " covariance function. Gradient values as follows:") + Kern_check_dKdiag_dtheta(kern, X=X).checkgrad(verbose=True) + pass_checks = False + assert(result) + return False + + if verbose: + print("Checking gradients of K(X, X) wrt X.") + try: + testmodel = Kern_check_dK_dX(kern, X=X, X2=None) + if fixed_X_dims is not None: + testmodel.X[:,fixed_X_dims].fix() + result = testmodel.checkgrad(verbose=verbose) + except NotImplementedError: + result=True + if verbose: + print("gradients_X not implemented for " + kern.name) + if result and verbose: + print("Check passed.") + if not result: + print("Gradient of K(X, X) wrt X failed for " + kern.name + " covariance function. Gradient values as follows:") + testmodel.checkgrad(verbose=True) + import ipdb;ipdb.set_trace() + assert(result) + pass_checks = False + return False + + if verbose: + print("Checking gradients of K(X, X2) wrt X.") + try: + testmodel = Kern_check_dK_dX(kern, X=X, X2=X2) + if fixed_X_dims is not None: + testmodel.X[:,fixed_X_dims].fix() + result = testmodel.checkgrad(verbose=verbose) + except NotImplementedError: + result=True + if verbose: + print("gradients_X not implemented for " + kern.name) + if result and verbose: + print("Check passed.") + if not result: + print("Gradient of K(X, X2) wrt X failed for " + kern.name + " covariance function. Gradient values as follows:") + testmodel.checkgrad(verbose=True) + assert(result) + pass_checks = False + return False + + if verbose: + print("Checking gradients of Kdiag(X) wrt X.") + try: + testmodel = Kern_check_dKdiag_dX(kern, X=X) + if fixed_X_dims is not None: + testmodel.X[:,fixed_X_dims].fix() + result = testmodel.checkgrad(verbose=verbose) + except NotImplementedError: + result=True + if verbose: + print("gradients_X not implemented for " + kern.name) + if result and verbose: + print("Check passed.") + if not result: + print("Gradient of Kdiag(X) wrt X failed for " + kern.name + " covariance function. Gradient values as follows:") + Kern_check_dKdiag_dX(kern, X=X).checkgrad(verbose=True) + pass_checks = False + assert(result) + return False + + return pass_checks + + +
      +
      [docs]class KernelGradientTestsContinuous(unittest.TestCase): +
      [docs] def setUp(self): + self.N, self.D = 10, 5 + self.X = np.random.randn(self.N,self.D) + self.X2 = np.random.randn(self.N+10,self.D) + + continuous_kerns = ['RBF', 'Linear'] + self.kernclasses = [getattr(GPy.kern, s) for s in continuous_kerns] +
      +
      [docs] def test_Matern32(self): + k = GPy.kern.Matern32(self.D) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs] def test_Prod(self): + k = GPy.kern.Matern32(2, active_dims=[2,3]) * GPy.kern.RBF(2, active_dims=[0,4]) + GPy.kern.Linear(self.D) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs] def test_Prod2(self): + k = (GPy.kern.RBF(2, active_dims=[0,4]) * GPy.kern.Linear(self.D)) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs] def test_Prod3(self): + k = (GPy.kern.RBF(2, active_dims=[0,4]) * GPy.kern.Linear(self.D)) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs] def test_Add(self): + k = GPy.kern.Matern32(2, active_dims=[2,3]) + GPy.kern.RBF(2, active_dims=[0,4]) + GPy.kern.Linear(self.D) + k += GPy.kern.Matern32(2, active_dims=[2,3]) + GPy.kern.RBF(2, active_dims=[0,4]) + GPy.kern.Linear(self.D) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs] def test_Add_dims(self): + k = GPy.kern.Matern32(2, active_dims=[2,self.D]) + GPy.kern.RBF(2, active_dims=[0,4]) + GPy.kern.Linear(self.D) + k.randomize() + self.assertRaises(IndexError, k.K, self.X) + k = GPy.kern.Matern32(2, active_dims=[2,self.D-1]) + GPy.kern.RBF(2, active_dims=[0,4]) + GPy.kern.Linear(self.D) + k.randomize() + # assert it runs: + try: + k.K(self.X) + except AssertionError: + raise AssertionError, "k.K(X) should run on self.D-1 dimension" +
      +
      [docs] def test_Matern52(self): + k = GPy.kern.Matern52(self.D) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs] def test_RBF(self): + k = GPy.kern.RBF(self.D) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs] def test_Linear(self): + k = GPy.kern.Linear(self.D) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs] def test_LinearFull(self): + k = GPy.kern.LinearFull(self.D, self.D-1) + k.randomize() + self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) +
      +
      [docs]class KernelTestsMiscellaneous(unittest.TestCase): +
      [docs] def setUp(self): + N, D = 100, 10 + self.X = np.linspace(-np.pi, +np.pi, N)[:,None] * np.random.uniform(-10,10,D) + self.rbf = GPy.kern.RBF(2, active_dims=np.arange(0,4,2)) + self.linear = GPy.kern.Linear(2, active_dims=(3,9)) + self.matern = GPy.kern.Matern32(3, active_dims=np.array([1,7,9])) + self.sumkern = self.rbf + self.linear + self.sumkern += self.matern + self.sumkern.randomize() +
      +
      [docs] def test_which_parts(self): + self.assertTrue(np.allclose(self.sumkern.K(self.X, which_parts=[self.linear, self.matern]), self.linear.K(self.X)+self.matern.K(self.X))) + self.assertTrue(np.allclose(self.sumkern.K(self.X, which_parts=[self.linear, self.rbf]), self.linear.K(self.X)+self.rbf.K(self.X))) + self.assertTrue(np.allclose(self.sumkern.K(self.X, which_parts=self.sumkern.parts[0]), self.rbf.K(self.X))) +
      +
      [docs]class KernelTestsNonContinuous(unittest.TestCase): +
      [docs] def setUp(self): + N0 = 3 + N1 = 9 + N2 = 4 + N = N0+N1+N2 + self.D = 3 + self.X = np.random.randn(N, self.D+1) + indices = np.random.random_integers(0, 2, size=N) + self.X[indices==0, -1] = 0 + self.X[indices==1, -1] = 1 + self.X[indices==2, -1] = 2 + #self.X = self.X[self.X[:, -1].argsort(), :] + self.X2 = np.random.randn((N0+N1)*2, self.D+1) + self.X2[:(N0*2), -1] = 0 + self.X2[(N0*2):, -1] = 1 +
      +
      [docs] def test_IndependentOutputs(self): + k = GPy.kern.RBF(self.D, active_dims=range(self.D)) + kern = GPy.kern.IndependentOutputs(k, -1, 'ind_single') + self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose, fixed_X_dims=-1)) + k = [GPy.kern.RBF(1, active_dims=[1], name='rbf1'), GPy.kern.RBF(self.D, active_dims=range(self.D), name='rbf012'), GPy.kern.RBF(2, active_dims=[0,2], name='rbf02')] + kern = GPy.kern.IndependentOutputs(k, -1, name='ind_split') + self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose, fixed_X_dims=-1)) +
      +
      [docs] def test_Hierarchical(self): + k = [GPy.kern.RBF(2, active_dims=[0,2], name='rbf1'), GPy.kern.RBF(2, active_dims=[0,2], name='rbf2')] + kern = GPy.kern.IndependentOutputs(k, -1, name='ind_split') + self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose, fixed_X_dims=-1)) + +
      +
      [docs] def test_ODE_UY(self): + kern = GPy.kern.ODE_UY(2, active_dims=[0, self.D]) + X = self.X[self.X[:,-1]!=2] + X2 = self.X2[self.X2[:,-1]!=2] + self.assertTrue(check_kernel_gradient_functions(kern, X=X, X2=X2, verbose=verbose, fixed_X_dims=-1)) +
      +
      [docs]class Coregionalize_weave_test(unittest.TestCase): + """ + Make sure that the coregionalize kernel work with and without weave enabled + """ +
      [docs] def setUp(self): + self.k = GPy.kern.Coregionalize(1, output_dim=12) + self.N1, self.N2 = 100, 200 + self.X = np.random.randint(0,12,(self.N1,1)) + self.X2 = np.random.randint(0,12,(self.N2,1)) +
      +
      [docs] def test_sym(self): + dL_dK = np.random.randn(self.N1, self.N1) + GPy.util.config.config.set('weave', 'working', 'True') + K_weave = self.k.K(self.X) + self.k.update_gradients_full(dL_dK, self.X) + grads_weave = self.k.gradient.copy() + + GPy.util.config.config.set('weave', 'working', 'False') + K_numpy = self.k.K(self.X) + self.k.update_gradients_full(dL_dK, self.X) + grads_numpy = self.k.gradient.copy() + + self.assertTrue(np.allclose(K_numpy, K_weave)) + self.assertTrue(np.allclose(grads_numpy, grads_weave)) +
      +
      [docs] def test_nonsym(self): + dL_dK = np.random.randn(self.N1, self.N2) + GPy.util.config.config.set('weave', 'working', 'True') + K_weave = self.k.K(self.X, self.X2) + self.k.update_gradients_full(dL_dK, self.X, self.X2) + grads_weave = self.k.gradient.copy() + + GPy.util.config.config.set('weave', 'working', 'False') + K_numpy = self.k.K(self.X, self.X2) + self.k.update_gradients_full(dL_dK, self.X, self.X2) + grads_numpy = self.k.gradient.copy() + + self.assertTrue(np.allclose(K_numpy, K_weave)) + self.assertTrue(np.allclose(grads_numpy, grads_weave)) + + #reset the weave state for any other tests
      + GPy.util.config.config.set('weave', 'working', 'False') + + + +
      +if __name__ == "__main__": + print "Running unit tests, please be (very) patient..." + unittest.main() +# np.random.seed(0) +# N0 = 3 +# N1 = 9 +# N2 = 4 +# N = N0+N1+N2 +# D = 3 +# X = np.random.randn(N, D+1) +# indices = np.random.random_integers(0, 2, size=N) +# X[indices==0, -1] = 0 +# X[indices==1, -1] = 1 +# X[indices==2, -1] = 2 +# #X = X[X[:, -1].argsort(), :] +# X2 = np.random.randn((N0+N1)*2, D+1) +# X2[:(N0*2), -1] = 0 +# X2[(N0*2):, -1] = 1 +# k = [GPy.kern.RBF(1, active_dims=[1], name='rbf1'), GPy.kern.RBF(D, name='rbf012'), GPy.kern.RBF(2, active_dims=[0,2], name='rbf02')] +# kern = GPy.kern.IndependentOutputs(k, -1, name='ind_split') +# assert(check_kernel_gradient_functions(kern, X=X, X2=X2, verbose=verbose, fixed_X_dims=-1)) +# k = GPy.kern.RBF(D) +# kern = GPy.kern.IndependentOutputs(k, -1, 'ind_single') +# assert(check_kernel_gradient_functions(kern, X=X, X2=X2, verbose=verbose, fixed_X_dims=-1)) +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/likelihood_tests.html b/doc/_build/html/_modules/GPy/testing/likelihood_tests.html new file mode 100644 index 00000000..9444a50d --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/likelihood_tests.html @@ -0,0 +1,806 @@ + + + + + + + + GPy.testing.likelihood_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.likelihood_tests

      +# Copyright (c) 2014, Alan Saul
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import numpy as np
      +import unittest
      +import GPy
      +from GPy.models import GradientChecker
      +import functools
      +import inspect
      +from GPy.likelihoods import link_functions
      +from GPy.core.parameterization import Param
      +from functools import partial
      +#np.random.seed(300)
      +#np.random.seed(7)
      +
      +#np.seterr(divide='raise')
      +
      [docs]def dparam_partial(inst_func, *args): + """ + If we have a instance method that needs to be called but that doesn't + take the parameter we wish to change to checkgrad, then this function + will change the variable using set params. + + inst_func: should be a instance function of an object that we would like + to change + param: the param that will be given to set_params + args: anything else that needs to be given to the function (for example + the f or Y that are being used in the function whilst we tweak the + param + """ + def param_func(param_val, param_name, inst_func, args): + #inst_func.im_self._set_params(param) + #inst_func.im_self.add_parameter(Param(param_name, param_val)) + inst_func.im_self[param_name] = param_val + return inst_func(*args) + return functools.partial(param_func, inst_func=inst_func, args=args) +
      +
      [docs]def dparam_checkgrad(func, dfunc, params, params_names, args, constraints=None, randomize=False, verbose=False): + """ + checkgrad expects a f: R^N -> R^1 and df: R^N -> R^N + However if we are holding other parameters fixed and moving something else + We need to check the gradient of each of the fixed parameters + (f and y for example) seperately, whilst moving another parameter. + Otherwise f: gives back R^N and + df: gives back R^NxM where M is + The number of parameters and N is the number of data + Need to take a slice out from f and a slice out of df + """ + print "\n{} likelihood: {} vs {}".format(func.im_self.__class__.__name__, + func.__name__, dfunc.__name__) + partial_f = dparam_partial(func, *args) + partial_df = dparam_partial(dfunc, *args) + gradchecking = True + zipped_params = zip(params, params_names) + for param_ind, (param_val, param_name) in enumerate(zipped_params): + #Check one parameter at a time, make sure it is 2d (as some gradients only return arrays) then strip out the parameter + fnum = np.atleast_2d(partial_f(param_val, param_name))[:, param_ind].shape[0] + dfnum = np.atleast_2d(partial_df(param_val, param_name))[:, param_ind].shape[0] + for fixed_val in range(dfnum): + #dlik and dlik_dvar gives back 1 value for each + f_ind = min(fnum, fixed_val+1) - 1 + print "fnum: {} dfnum: {} f_ind: {} fixed_val: {}".format(fnum, dfnum, f_ind, fixed_val) + #Make grad checker with this param moving, note that set_params is NOT being called + #The parameter is being set directly with __setattr__ + #Check only the parameter and function value we wish to check at a time + grad = GradientChecker(lambda p_val: np.atleast_2d(partial_f(p_val, param_name))[f_ind, param_ind], + lambda p_val: np.atleast_2d(partial_df(p_val, param_name))[fixed_val, param_ind], + param_val, [param_name]) + + if constraints is not None: + for constrain_param, constraint in constraints: + if grad.grep_param_names(constrain_param): + constraint(constrain_param, grad) + else: + print "parameter didn't exist" + print constrain_param, " ", constraint + if randomize: + grad.randomize() + if verbose: + print grad + grad.checkgrad(verbose=1) + if not grad.checkgrad(verbose=True): + gradchecking = False + + return gradchecking + +
      +from nose.tools import with_setup +
      [docs]class TestNoiseModels(object): + """ + Generic model checker + """ +
      [docs] def setUp(self): + self.N = 15 + self.D = 3 + self.X = np.random.rand(self.N, self.D)*10 + + self.real_std = 0.1 + noise = np.random.randn(*self.X[:, 0].shape)*self.real_std + self.Y = (np.sin(self.X[:, 0]*2*np.pi) + noise)[:, None] + self.f = np.random.rand(self.N, 1) + self.binary_Y = np.asarray(np.random.rand(self.N) > 0.5, dtype=np.int)[:, None] + self.positive_Y = np.exp(self.Y.copy()) + tmp = np.round(self.X[:, 0]*3-3)[:, None] + np.random.randint(0,3, self.X.shape[0])[:, None] + self.integer_Y = np.where(tmp > 0, tmp, 0) + + self.var = 0.2 + + self.var = np.random.rand(1) + + #Make a bigger step as lower bound can be quite curved + self.step = 1e-4 +
      +
      [docs] def tearDown(self): + self.Y = None + self.f = None + self.X = None +
      +
      [docs] def test_scale2_models(self): + self.setUp() + + #################################################### + # Constraint wrappers so we can just list them off # + #################################################### + def constrain_fixed(regex, model): + model[regex].constrain_fixed() + + def constrain_negative(regex, model): + model[regex].constrain_negative() + + def constrain_positive(regex, model): + model[regex].constrain_positive() + + def constrain_bounded(regex, model, lower, upper): + """ + Used like: partial(constrain_bounded, lower=0, upper=1) + """ + model[regex].constrain_bounded(lower, upper) + + """ + Dictionary where we nest models we would like to check + Name: { + "model": model_instance, + "grad_params": { + "names": [names_of_params_we_want, to_grad_check], + "vals": [values_of_params, to_start_at], + "constrain": [constraint_wrappers, listed_here] + }, + "laplace": boolean_of_whether_model_should_work_for_laplace, + "ep": boolean_of_whether_model_should_work_for_laplace, + "link_f_constraints": [constraint_wrappers, listed_here] + } + """ + noise_models = {"Student_t_default": { + "model": GPy.likelihoods.StudentT(deg_free=5, sigma2=self.var), + "grad_params": { + "names": [".*t_scale2"], + "vals": [self.var], + "constraints": [(".*t_scale2", constrain_positive), (".*deg_free", constrain_fixed)] + #"constraints": [("t_scale2", constrain_positive), ("deg_free", partial(constrain_fixed, value=5))] + }, + "laplace": True + }, + "Student_t_1_var": { + "model": GPy.likelihoods.StudentT(deg_free=5, sigma2=self.var), + "grad_params": { + "names": [".*t_scale2"], + "vals": [1.0], + "constraints": [(".*t_scale2", constrain_positive), (".*deg_free", constrain_fixed)] + }, + "laplace": True + }, + "Student_t_small_deg_free": { + "model": GPy.likelihoods.StudentT(deg_free=1.5, sigma2=self.var), + "grad_params": { + "names": [".*t_scale2"], + "vals": [self.var], + "constraints": [(".*t_scale2", constrain_positive), (".*deg_free", constrain_fixed)] + }, + "laplace": True + }, + "Student_t_small_var": { + "model": GPy.likelihoods.StudentT(deg_free=5, sigma2=self.var), + "grad_params": { + "names": [".*t_scale2"], + "vals": [0.001], + "constraints": [(".*t_scale2", constrain_positive), (".*deg_free", constrain_fixed)] + }, + "laplace": True + }, + "Student_t_large_var": { + "model": GPy.likelihoods.StudentT(deg_free=5, sigma2=self.var), + "grad_params": { + "names": [".*t_scale2"], + "vals": [10.0], + "constraints": [(".*t_scale2", constrain_positive), (".*deg_free", constrain_fixed)] + }, + "laplace": True + }, + "Student_t_approx_gauss": { + "model": GPy.likelihoods.StudentT(deg_free=1000, sigma2=self.var), + "grad_params": { + "names": [".*t_scale2"], + "vals": [self.var], + "constraints": [(".*t_scale2", constrain_positive), (".*deg_free", constrain_fixed)] + }, + "laplace": True + }, + "Student_t_log": { + "model": GPy.likelihoods.StudentT(gp_link=link_functions.Log(), deg_free=5, sigma2=self.var), + "grad_params": { + "names": [".*t_scale2"], + "vals": [self.var], + "constraints": [(".*t_scale2", constrain_positive), (".*deg_free", constrain_fixed)] + }, + "laplace": True + }, + "Gaussian_default": { + "model": GPy.likelihoods.Gaussian(variance=self.var), + "grad_params": { + "names": [".*variance"], + "vals": [self.var], + "constraints": [(".*variance", constrain_positive)] + }, + "laplace": True, + "ep": False # FIXME: Should be True when we have it working again + }, + #"Gaussian_log": { + #"model": GPy.likelihoods.gaussian(gp_link=link_functions.Log(), variance=self.var, D=self.D, N=self.N), + #"grad_params": { + #"names": ["noise_model_variance"], + #"vals": [self.var], + #"constraints": [constrain_positive] + #}, + #"laplace": True + #}, + #"Gaussian_probit": { + #"model": GPy.likelihoods.gaussian(gp_link=link_functions.Probit(), variance=self.var, D=self.D, N=self.N), + #"grad_params": { + #"names": ["noise_model_variance"], + #"vals": [self.var], + #"constraints": [constrain_positive] + #}, + #"laplace": True + #}, + #"Gaussian_log_ex": { + #"model": GPy.likelihoods.gaussian(gp_link=link_functions.Log_ex_1(), variance=self.var, D=self.D, N=self.N), + #"grad_params": { + #"names": ["noise_model_variance"], + #"vals": [self.var], + #"constraints": [constrain_positive] + #}, + #"laplace": True + #}, + "Bernoulli_default": { + "model": GPy.likelihoods.Bernoulli(), + "link_f_constraints": [partial(constrain_bounded, lower=0, upper=1)], + "laplace": True, + "Y": self.binary_Y, + "ep": False # FIXME: Should be True when we have it working again + }, + "Exponential_default": { + "model": GPy.likelihoods.Exponential(), + "link_f_constraints": [constrain_positive], + "Y": self.positive_Y, + "laplace": True, + }, + "Poisson_default": { + "model": GPy.likelihoods.Poisson(), + "link_f_constraints": [constrain_positive], + "Y": self.integer_Y, + "laplace": True, + "ep": False #Should work though... + }#, + #GAMMA needs some work!"Gamma_default": { + #"model": GPy.likelihoods.Gamma(), + #"link_f_constraints": [constrain_positive], + #"Y": self.positive_Y, + #"laplace": True + #} + } + + for name, attributes in noise_models.iteritems(): + model = attributes["model"] + if "grad_params" in attributes: + params = attributes["grad_params"] + param_vals = params["vals"] + param_names= params["names"] + param_constraints = params["constraints"] + else: + params = [] + param_vals = [] + param_names = [] + constrain_positive = [] + param_constraints = [] # ??? TODO: Saul to Fix. + if "link_f_constraints" in attributes: + link_f_constraints = attributes["link_f_constraints"] + else: + link_f_constraints = [] + if "Y" in attributes: + Y = attributes["Y"].copy() + else: + Y = self.Y.copy() + if "f" in attributes: + f = attributes["f"].copy() + else: + f = self.f.copy() + if "laplace" in attributes: + laplace = attributes["laplace"] + else: + laplace = False + if "ep" in attributes: + ep = attributes["ep"] + else: + ep = False + + #if len(param_vals) > 1: + #raise NotImplementedError("Cannot support multiple params in likelihood yet!") + + #Required by all + #Normal derivatives + yield self.t_logpdf, model, Y, f + yield self.t_dlogpdf_df, model, Y, f + yield self.t_d2logpdf_df2, model, Y, f + #Link derivatives + yield self.t_dlogpdf_dlink, model, Y, f, link_f_constraints + yield self.t_d2logpdf_dlink2, model, Y, f, link_f_constraints + if laplace: + #Laplace only derivatives + yield self.t_d3logpdf_df3, model, Y, f + yield self.t_d3logpdf_dlink3, model, Y, f, link_f_constraints + #Params + yield self.t_dlogpdf_dparams, model, Y, f, param_vals, param_names, param_constraints + yield self.t_dlogpdf_df_dparams, model, Y, f, param_vals, param_names, param_constraints + yield self.t_d2logpdf2_df2_dparams, model, Y, f, param_vals, param_names, param_constraints + #Link params + yield self.t_dlogpdf_link_dparams, model, Y, f, param_vals, param_names, param_constraints + yield self.t_dlogpdf_dlink_dparams, model, Y, f, param_vals, param_names, param_constraints + yield self.t_d2logpdf2_dlink2_dparams, model, Y, f, param_vals, param_names, param_constraints + + #laplace likelihood gradcheck + yield self.t_laplace_fit_rbf_white, model, self.X, Y, f, self.step, param_vals, param_names, param_constraints + if ep: + #ep likelihood gradcheck + yield self.t_ep_fit_rbf_white, model, self.X, Y, f, self.step, param_vals, param_names, param_constraints + + + self.tearDown() + + ############# + # dpdf_df's # + #############
      + @with_setup(setUp, tearDown) +
      [docs] def t_logpdf(self, model, Y, f): + print "\n{}".format(inspect.stack()[0][3]) + print model + #print model._get_params() + np.testing.assert_almost_equal( + model.pdf(f.copy(), Y.copy()).prod(), + np.exp(model.logpdf(f.copy(), Y.copy()).sum()) + ) +
      + @with_setup(setUp, tearDown) +
      [docs] def t_dlogpdf_df(self, model, Y, f): + print "\n{}".format(inspect.stack()[0][3]) + self.description = "\n{}".format(inspect.stack()[0][3]) + logpdf = functools.partial(model.logpdf, y=Y) + dlogpdf_df = functools.partial(model.dlogpdf_df, y=Y) + grad = GradientChecker(logpdf, dlogpdf_df, f.copy(), 'g') + grad.randomize() + print model + assert grad.checkgrad(verbose=1) +
      + @with_setup(setUp, tearDown) +
      [docs] def t_d2logpdf_df2(self, model, Y, f): + print "\n{}".format(inspect.stack()[0][3]) + dlogpdf_df = functools.partial(model.dlogpdf_df, y=Y) + d2logpdf_df2 = functools.partial(model.d2logpdf_df2, y=Y) + grad = GradientChecker(dlogpdf_df, d2logpdf_df2, f.copy(), 'g') + grad.randomize() + print model + assert grad.checkgrad(verbose=1) +
      + @with_setup(setUp, tearDown) +
      [docs] def t_d3logpdf_df3(self, model, Y, f): + print "\n{}".format(inspect.stack()[0][3]) + d2logpdf_df2 = functools.partial(model.d2logpdf_df2, y=Y) + d3logpdf_df3 = functools.partial(model.d3logpdf_df3, y=Y) + grad = GradientChecker(d2logpdf_df2, d3logpdf_df3, f.copy(), 'g') + grad.randomize() + print model + assert grad.checkgrad(verbose=1) + + ############## + # df_dparams # + ##############
      + @with_setup(setUp, tearDown) +
      [docs] def t_dlogpdf_dparams(self, model, Y, f, params, params_names, param_constraints): + print "\n{}".format(inspect.stack()[0][3]) + print model + assert ( + dparam_checkgrad(model.logpdf, model.dlogpdf_dtheta, + params, params_names, args=(f, Y), constraints=param_constraints, + randomize=False, verbose=True) + ) +
      + @with_setup(setUp, tearDown) +
      [docs] def t_dlogpdf_df_dparams(self, model, Y, f, params, params_names, param_constraints): + print "\n{}".format(inspect.stack()[0][3]) + print model + assert ( + dparam_checkgrad(model.dlogpdf_df, model.dlogpdf_df_dtheta, + params, params_names, args=(f, Y), constraints=param_constraints, + randomize=False, verbose=True) + ) +
      + @with_setup(setUp, tearDown) +
      [docs] def t_d2logpdf2_df2_dparams(self, model, Y, f, params, params_names, param_constraints): + print "\n{}".format(inspect.stack()[0][3]) + print model + assert ( + dparam_checkgrad(model.d2logpdf_df2, model.d2logpdf_df2_dtheta, + params, params_names, args=(f, Y), constraints=param_constraints, + randomize=False, verbose=True) + ) + + ################ + # dpdf_dlink's # + ################
      + @with_setup(setUp, tearDown) + + @with_setup(setUp, tearDown) +
      [docs] def t_d2logpdf_dlink2(self, model, Y, f, link_f_constraints): + print "\n{}".format(inspect.stack()[0][3]) + dlogpdf_dlink = functools.partial(model.dlogpdf_dlink, y=Y) + d2logpdf_dlink2 = functools.partial(model.d2logpdf_dlink2, y=Y) + grad = GradientChecker(dlogpdf_dlink, d2logpdf_dlink2, f.copy(), 'g') + + #Apply constraints to link_f values + for constraint in link_f_constraints: + constraint('g', grad) + + grad.randomize() + print grad + print model + assert grad.checkgrad(verbose=1) +
      + @with_setup(setUp, tearDown) +
      [docs] def t_d3logpdf_dlink3(self, model, Y, f, link_f_constraints): + print "\n{}".format(inspect.stack()[0][3]) + d2logpdf_dlink2 = functools.partial(model.d2logpdf_dlink2, y=Y) + d3logpdf_dlink3 = functools.partial(model.d3logpdf_dlink3, y=Y) + grad = GradientChecker(d2logpdf_dlink2, d3logpdf_dlink3, f.copy(), 'g') + + #Apply constraints to link_f values + for constraint in link_f_constraints: + constraint('g', grad) + + grad.randomize() + print grad + print model + assert grad.checkgrad(verbose=1) + + ################# + # dlink_dparams # + #################
      + @with_setup(setUp, tearDown) + + @with_setup(setUp, tearDown) + + @with_setup(setUp, tearDown) +
      [docs] def t_d2logpdf2_dlink2_dparams(self, model, Y, f, params, param_names, param_constraints): + print "\n{}".format(inspect.stack()[0][3]) + print model + assert ( + dparam_checkgrad(model.d2logpdf_dlink2, model.d2logpdf_dlink2_dtheta, + params, param_names, args=(f, Y), constraints=param_constraints, + randomize=False, verbose=True) + ) + + ################ + # laplace test # + ################
      + @with_setup(setUp, tearDown) +
      [docs] def t_laplace_fit_rbf_white(self, model, X, Y, f, step, param_vals, param_names, constraints): + print "\n{}".format(inspect.stack()[0][3]) + #Normalize + Y = Y/Y.max() + white_var = 1e-6 + kernel = GPy.kern.RBF(X.shape[1]) + GPy.kern.White(X.shape[1]) + laplace_likelihood = GPy.inference.latent_function_inference.Laplace() + m = GPy.core.GP(X.copy(), Y.copy(), kernel, likelihood=model, inference_method=laplace_likelihood) + m['.*white'].constrain_fixed(white_var) + + #Set constraints + for constrain_param, constraint in constraints: + constraint(constrain_param, m) + + print m + m.randomize() + + #Set params + for param_num in range(len(param_names)): + name = param_names[param_num] + m[name] = param_vals[param_num] + + #m.optimize(max_iters=8) + print m + #if not m.checkgrad(step=step): + #m.checkgrad(verbose=1, step=step) + #NOTE this test appears to be stochastic for some likelihoods (student t?) + # appears to all be working in test mode right now... + #if isinstance(model, GPy.likelihoods.StudentT): + assert m.checkgrad(verbose=1, step=step) + + ########### + # EP test # + ###########
      + @with_setup(setUp, tearDown) +
      [docs] def t_ep_fit_rbf_white(self, model, X, Y, f, step, param_vals, param_names, constraints): + print "\n{}".format(inspect.stack()[0][3]) + #Normalize + Y = Y/Y.max() + white_var = 1e-6 + kernel = GPy.kern.RBF(X.shape[1]) + GPy.kern.White(X.shape[1]) + ep_inf = GPy.inference.latent_function_inference.EP() + m = GPy.core.GP(X.copy(), Y.copy(), kernel=kernel, likelihood=model, inference_method=ep_inf) + m['.*white'].constrain_fixed(white_var) + + for param_num in range(len(param_names)): + name = param_names[param_num] + m[name] = param_vals[param_num] + constraints[param_num](name, m) + + m.randomize() + print m + assert m.checkgrad(verbose=1, step=step) + +
      +
      [docs]class LaplaceTests(unittest.TestCase): + """ + Specific likelihood tests, not general enough for the above tests + """ + +
      [docs] def setUp(self): + self.N = 5 + self.D = 3 + self.X = np.random.rand(self.N, self.D)*10 + + self.real_std = 0.1 + noise = np.random.randn(*self.X[:, 0].shape)*self.real_std + self.Y = (np.sin(self.X[:, 0]*2*np.pi) + noise)[:, None] + self.f = np.random.rand(self.N, 1) + + self.var = 0.2 + + self.var = np.random.rand(1) + self.stu_t = GPy.likelihoods.StudentT(deg_free=5, sigma2=self.var) + #TODO: gaussians with on Identity link. self.gauss = GPy.likelihoods.Gaussian(gp_link=link_functions.Log(), variance=self.var) + self.gauss = GPy.likelihoods.Gaussian(variance=self.var) + + #Make a bigger step as lower bound can be quite curved + self.step = 1e-6 +
      +
      [docs] def tearDown(self): + self.stu_t = None + self.gauss = None + self.Y = None + self.f = None + self.X = None +
      +
      [docs] def test_gaussian_d2logpdf_df2_2(self): + print "\n{}".format(inspect.stack()[0][3]) + self.Y = None + + self.N = 2 + self.D = 1 + self.X = np.linspace(0, self.D, self.N)[:, None] + self.real_std = 0.2 + noise = np.random.randn(*self.X.shape)*self.real_std + self.Y = np.sin(self.X*2*np.pi) + noise + self.f = np.random.rand(self.N, 1) + + dlogpdf_df = functools.partial(self.gauss.dlogpdf_df, y=self.Y) + d2logpdf_df2 = functools.partial(self.gauss.d2logpdf_df2, y=self.Y) + grad = GradientChecker(dlogpdf_df, d2logpdf_df2, self.f.copy(), 'g') + grad.randomize() + + self.assertTrue(grad.checkgrad(verbose=1)) +
      +
      [docs] def test_laplace_log_likelihood(self): + debug = False + real_std = 0.1 + initial_var_guess = 0.5 + + #Start a function, any function + X = np.linspace(0.0, np.pi*2, 100)[:, None] + Y = np.sin(X) + np.random.randn(*X.shape)*real_std + Y = Y/Y.max() + #Yc = Y.copy() + #Yc[75:80] += 1 + kernel1 = GPy.kern.RBF(X.shape[1]) + GPy.kern.White(X.shape[1]) + #FIXME: Make sure you can copy kernels when params is fixed + #kernel2 = kernel1.copy() + kernel2 = GPy.kern.RBF(X.shape[1]) + GPy.kern.White(X.shape[1]) + + gauss_distr1 = GPy.likelihoods.Gaussian(variance=initial_var_guess) + exact_inf = GPy.inference.latent_function_inference.ExactGaussianInference() + m1 = GPy.core.GP(X, Y.copy(), kernel=kernel1, likelihood=gauss_distr1, inference_method=exact_inf) + m1['.*white'].constrain_fixed(1e-6) + m1['.*rbf.variance'] = initial_var_guess + m1['.*rbf.variance'].constrain_bounded(1e-4, 10) + m1.randomize() + + gauss_distr2 = GPy.likelihoods.Gaussian(variance=initial_var_guess) + laplace_inf = GPy.inference.latent_function_inference.Laplace() + m2 = GPy.core.GP(X, Y.copy(), kernel=kernel2, likelihood=gauss_distr2, inference_method=laplace_inf) + m2['.*white'].constrain_fixed(1e-6) + m2['.*rbf.variance'].constrain_bounded(1e-4, 10) + m2.randomize() + + if debug: + print m1 + print m2 + optimizer = 'scg' + print "Gaussian" + m1.optimize(optimizer, messages=debug) + print "Laplace Gaussian" + m2.optimize(optimizer, messages=debug) + if debug: + print m1 + print m2 + + m2[:] = m1[:] + + #Predict for training points to get posterior mean and variance + post_mean, post_var = m1.predict(X) + post_mean_approx, post_var_approx, = m2.predict(X) + + if debug: + import pylab as pb + pb.figure(5) + pb.title('posterior means') + pb.scatter(X, post_mean, c='g') + pb.scatter(X, post_mean_approx, c='r', marker='x') + + pb.figure(6) + pb.title('plot_f') + m1.plot_f(fignum=6) + m2.plot_f(fignum=6) + fig, axes = pb.subplots(2, 1) + fig.suptitle('Covariance matricies') + a1 = pb.subplot(121) + a1.matshow(m1.likelihood.covariance_matrix) + a2 = pb.subplot(122) + a2.matshow(m2.likelihood.covariance_matrix) + + pb.figure(8) + pb.scatter(X, m1.likelihood.Y, c='g') + pb.scatter(X, m2.likelihood.Y, c='r', marker='x') + + + + #Check Y's are the same + np.testing.assert_almost_equal(m1.Y, m2.Y, decimal=5) + #Check marginals are the same + np.testing.assert_almost_equal(m1.log_likelihood(), m2.log_likelihood(), decimal=2) + #Check marginals are the same with random + m1.randomize() + m2[:] = m1[:] + + np.testing.assert_almost_equal(m1.log_likelihood(), m2.log_likelihood(), decimal=2) + + #Check they are checkgradding + #m1.checkgrad(verbose=1) + #m2.checkgrad(verbose=1) + self.assertTrue(m1.checkgrad(verbose=True)) + self.assertTrue(m2.checkgrad(verbose=True)) +
      +if __name__ == "__main__": + print "Running unit tests" + unittest.main() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/model_tests.html b/doc/_build/html/_modules/GPy/testing/model_tests.html new file mode 100644 index 00000000..467fe747 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/model_tests.html @@ -0,0 +1,605 @@ + + + + + + + + GPy.testing.model_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.model_tests

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import unittest
      +import numpy as np
      +import GPy
      +
      +
      [docs]class MiscTests(unittest.TestCase): +
      [docs] def setUp(self): + self.N = 20 + self.N_new = 50 + self.D = 1 + self.X = np.random.uniform(-3., 3., (self.N, 1)) + self.Y = np.sin(self.X) + np.random.randn(self.N, self.D) * 0.05 + self.X_new = np.random.uniform(-3., 3., (self.N_new, 1)) +
      +
      [docs] def test_raw_predict(self): + k = GPy.kern.RBF(1) + m = GPy.models.GPRegression(self.X, self.Y, kernel=k) + m.randomize() + m.likelihood.variance = .5 + Kinv = np.linalg.pinv(k.K(self.X) + np.eye(self.N) * m.likelihood.variance) + K_hat = k.K(self.X_new) - k.K(self.X_new, self.X).dot(Kinv).dot(k.K(self.X, self.X_new)) + mu_hat = k.K(self.X_new, self.X).dot(Kinv).dot(m.Y_normalized) + + mu, covar = m._raw_predict(self.X_new, full_cov=True) + self.assertEquals(mu.shape, (self.N_new, self.D)) + self.assertEquals(covar.shape, (self.N_new, self.N_new)) + np.testing.assert_almost_equal(K_hat, covar) + np.testing.assert_almost_equal(mu_hat, mu) + + mu, var = m._raw_predict(self.X_new) + self.assertEquals(mu.shape, (self.N_new, self.D)) + self.assertEquals(var.shape, (self.N_new, 1)) + np.testing.assert_almost_equal(np.diag(K_hat)[:, None], var) + np.testing.assert_almost_equal(mu_hat, mu) +
      +
      [docs] def test_sparse_raw_predict(self): + k = GPy.kern.RBF(1) + m = GPy.models.SparseGPRegression(self.X, self.Y, kernel=k) + m.randomize() + Z = m.Z[:] + X = self.X[:] + + # Not easy to check if woodbury_inv is correct in itself as it requires a large derivation and expression + Kinv = m.posterior.woodbury_inv + K_hat = k.K(self.X_new) - k.K(self.X_new, Z).dot(Kinv).dot(k.K(Z, self.X_new)) + + mu, covar = m._raw_predict(self.X_new, full_cov=True) + self.assertEquals(mu.shape, (self.N_new, self.D)) + self.assertEquals(covar.shape, (self.N_new, self.N_new)) + np.testing.assert_almost_equal(K_hat, covar) + # np.testing.assert_almost_equal(mu_hat, mu) + + mu, var = m._raw_predict(self.X_new) + self.assertEquals(mu.shape, (self.N_new, self.D)) + self.assertEquals(var.shape, (self.N_new, 1)) + np.testing.assert_almost_equal(np.diag(K_hat)[:, None], var) + # np.testing.assert_almost_equal(mu_hat, mu) +
      +
      [docs] def test_likelihood_replicate(self): + m = GPy.models.GPRegression(self.X, self.Y) + m2 = GPy.models.GPRegression(self.X, self.Y) + np.testing.assert_equal(m.log_likelihood(), m2.log_likelihood()) + m.randomize() + m2[:] = m[''].values() + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + m.randomize() + m2[''] = m[:] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + m.randomize() + m2[:] = m[:] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + m.randomize() + m2[''] = m[''] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + + m.kern.lengthscale.randomize() + m2[:] = m[:] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + + m.Gaussian_noise.randomize() + m2[:] = m[:] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + + m['.*var'] = 2 + m2['.*var'] = m['.*var'] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + +
      +
      [docs] def test_likelihood_set(self): + m = GPy.models.GPRegression(self.X, self.Y) + m2 = GPy.models.GPRegression(self.X, self.Y) + np.testing.assert_equal(m.log_likelihood(), m2.log_likelihood()) + + m.kern.lengthscale.randomize() + m2.kern.lengthscale = m.kern.lengthscale + np.testing.assert_equal(m.log_likelihood(), m2.log_likelihood()) + + m.kern.lengthscale.randomize() + m2['.*lengthscale'] = m.kern.lengthscale + np.testing.assert_equal(m.log_likelihood(), m2.log_likelihood()) + + m.kern.lengthscale.randomize() + m2['.*lengthscale'] = m.kern['.*lengthscale'] + np.testing.assert_equal(m.log_likelihood(), m2.log_likelihood()) + + m.kern.lengthscale.randomize() + m2.kern.lengthscale = m.kern['.*lengthscale'] + np.testing.assert_equal(m.log_likelihood(), m2.log_likelihood()) +
      +
      [docs] def test_missing_data(self): + from GPy import kern + from GPy.models.bayesian_gplvm_minibatch import BayesianGPLVMMiniBatch + from GPy.examples.dimensionality_reduction import _simulate_matern + + D1, D2, D3, N, num_inducing, Q = 13, 5, 8, 400, 3, 4 + _, _, Ylist = _simulate_matern(D1, D2, D3, N, num_inducing, False) + Y = Ylist[0] + + inan = np.random.binomial(1, .9, size=Y.shape).astype(bool) # 80% missing data + Ymissing = Y.copy() + Ymissing[inan] = np.nan + + k = kern.Linear(Q, ARD=True) + kern.White(Q, np.exp(-2)) # + kern.bias(Q) + m = BayesianGPLVMMiniBatch(Ymissing, Q, init="random", num_inducing=num_inducing, + kernel=k, missing_data=True) + assert(m.checkgrad()) + + k = kern.RBF(Q, ARD=True) + kern.White(Q, np.exp(-2)) # + kern.bias(Q) + m = BayesianGPLVMMiniBatch(Ymissing, Q, init="random", num_inducing=num_inducing, + kernel=k, missing_data=True) + assert(m.checkgrad()) +
      +
      [docs] def test_likelihood_replicate_kern(self): + m = GPy.models.GPRegression(self.X, self.Y) + m2 = GPy.models.GPRegression(self.X, self.Y) + np.testing.assert_equal(m.log_likelihood(), m2.log_likelihood()) + m.kern.randomize() + m2.kern[''] = m.kern[:] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + m.kern.randomize() + m2.kern[:] = m.kern[:] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + m.kern.randomize() + m2.kern[''] = m.kern[''] + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) + m.kern.randomize() + m2.kern[:] = m.kern[''].values() + np.testing.assert_almost_equal(m.log_likelihood(), m2.log_likelihood()) +
      +
      [docs] def test_big_model(self): + m = GPy.examples.dimensionality_reduction.mrd_simulation(optimize=0, plot=0, plot_sim=0) + m.X.fix() + print m + m.unfix() + m.checkgrad() + print m + m.fix() + print m + m.inducing_inputs.unfix() + print m + m.checkgrad() + m.unfix() + m.checkgrad() + m.checkgrad() + print m +
      +
      [docs] def test_model_set_params(self): + m = GPy.models.GPRegression(self.X, self.Y) + lengthscale = np.random.uniform() + m.kern.lengthscale = lengthscale + np.testing.assert_equal(m.kern.lengthscale, lengthscale) + m.kern.lengthscale *= 1 + m['.*var'] -= .1 + np.testing.assert_equal(m.kern.lengthscale, lengthscale) + m.optimize() + print m +
      +
      [docs] def test_model_optimize(self): + X = np.random.uniform(-3., 3., (20, 1)) + Y = np.sin(X) + np.random.randn(20, 1) * 0.05 + m = GPy.models.GPRegression(X, Y) + m.optimize() + print m +
      +
      [docs]class GradientTests(np.testing.TestCase): +
      [docs] def setUp(self): + ###################################### + # # 1 dimensional example + + # sample inputs and outputs + self.X1D = np.random.uniform(-3., 3., (20, 1)) + self.Y1D = np.sin(self.X1D) + np.random.randn(20, 1) * 0.05 + + ###################################### + # # 2 dimensional example + + # sample inputs and outputs + self.X2D = np.random.uniform(-3., 3., (40, 2)) + self.Y2D = np.sin(self.X2D[:, 0:1]) * np.sin(self.X2D[:, 1:2]) + np.random.randn(40, 1) * 0.05 +
      +
      [docs] def check_model(self, kern, model_type='GPRegression', dimension=1, uncertain_inputs=False): + # Get the correct gradients + if dimension == 1: + X = self.X1D + Y = self.Y1D + else: + X = self.X2D + Y = self.Y2D + # Get model type (GPRegression, SparseGPRegression, etc) + model_fit = getattr(GPy.models, model_type) + + # noise = GPy.kern.White(dimension) + kern = kern # + noise + if uncertain_inputs: + m = model_fit(X, Y, kernel=kern, X_variance=np.random.rand(X.shape[0], X.shape[1])) + else: + m = model_fit(X, Y, kernel=kern) + m.randomize() + # contrain all parameters to be positive + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_GPRegression_rbf_1d(self): + ''' Testing the GP regression with rbf kernel with white kernel on 1d data ''' + rbf = GPy.kern.RBF(1) + self.check_model(rbf, model_type='GPRegression', dimension=1) +
      +
      [docs] def test_GPRegression_rbf_2D(self): + ''' Testing the GP regression with rbf kernel on 2d data ''' + rbf = GPy.kern.RBF(2) + self.check_model(rbf, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_rbf_ARD_2D(self): + ''' Testing the GP regression with rbf kernel on 2d data ''' + k = GPy.kern.RBF(2, ARD=True) + self.check_model(k, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_mlp_1d(self): + ''' Testing the GP regression with mlp kernel with white kernel on 1d data ''' + mlp = GPy.kern.MLP(1) + self.check_model(mlp, model_type='GPRegression', dimension=1) + + # TODO: + # def test_GPRegression_poly_1d(self): + # ''' Testing the GP regression with polynomial kernel with white kernel on 1d data ''' + # mlp = GPy.kern.Poly(1, degree=5) + # self.check_model(mlp, model_type='GPRegression', dimension=1) +
      +
      [docs] def test_GPRegression_matern52_1D(self): + ''' Testing the GP regression with matern52 kernel on 1d data ''' + matern52 = GPy.kern.Matern52(1) + self.check_model(matern52, model_type='GPRegression', dimension=1) +
      +
      [docs] def test_GPRegression_matern52_2D(self): + ''' Testing the GP regression with matern52 kernel on 2d data ''' + matern52 = GPy.kern.Matern52(2) + self.check_model(matern52, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_matern52_ARD_2D(self): + ''' Testing the GP regression with matern52 kernel on 2d data ''' + matern52 = GPy.kern.Matern52(2, ARD=True) + self.check_model(matern52, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_matern32_1D(self): + ''' Testing the GP regression with matern32 kernel on 1d data ''' + matern32 = GPy.kern.Matern32(1) + self.check_model(matern32, model_type='GPRegression', dimension=1) +
      +
      [docs] def test_GPRegression_matern32_2D(self): + ''' Testing the GP regression with matern32 kernel on 2d data ''' + matern32 = GPy.kern.Matern32(2) + self.check_model(matern32, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_matern32_ARD_2D(self): + ''' Testing the GP regression with matern32 kernel on 2d data ''' + matern32 = GPy.kern.Matern32(2, ARD=True) + self.check_model(matern32, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_exponential_1D(self): + ''' Testing the GP regression with exponential kernel on 1d data ''' + exponential = GPy.kern.Exponential(1) + self.check_model(exponential, model_type='GPRegression', dimension=1) +
      +
      [docs] def test_GPRegression_exponential_2D(self): + ''' Testing the GP regression with exponential kernel on 2d data ''' + exponential = GPy.kern.Exponential(2) + self.check_model(exponential, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_exponential_ARD_2D(self): + ''' Testing the GP regression with exponential kernel on 2d data ''' + exponential = GPy.kern.Exponential(2, ARD=True) + self.check_model(exponential, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_bias_kern_1D(self): + ''' Testing the GP regression with bias kernel on 1d data ''' + bias = GPy.kern.Bias(1) + self.check_model(bias, model_type='GPRegression', dimension=1) +
      +
      [docs] def test_GPRegression_bias_kern_2D(self): + ''' Testing the GP regression with bias kernel on 2d data ''' + bias = GPy.kern.Bias(2) + self.check_model(bias, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_linear_kern_1D_ARD(self): + ''' Testing the GP regression with linear kernel on 1d data ''' + linear = GPy.kern.Linear(1, ARD=True) + self.check_model(linear, model_type='GPRegression', dimension=1) +
      +
      [docs] def test_GPRegression_linear_kern_2D_ARD(self): + ''' Testing the GP regression with linear kernel on 2d data ''' + linear = GPy.kern.Linear(2, ARD=True) + self.check_model(linear, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_GPRegression_linear_kern_1D(self): + ''' Testing the GP regression with linear kernel on 1d data ''' + linear = GPy.kern.Linear(1) + self.check_model(linear, model_type='GPRegression', dimension=1) +
      +
      [docs] def test_GPRegression_linear_kern_2D(self): + ''' Testing the GP regression with linear kernel on 2d data ''' + linear = GPy.kern.Linear(2) + self.check_model(linear, model_type='GPRegression', dimension=2) +
      +
      [docs] def test_SparseGPRegression_rbf_white_kern_1d(self): + ''' Testing the sparse GP regression with rbf kernel with white kernel on 1d data ''' + rbf = GPy.kern.RBF(1) + self.check_model(rbf, model_type='SparseGPRegression', dimension=1) +
      +
      [docs] def test_SparseGPRegression_rbf_white_kern_2D(self): + ''' Testing the sparse GP regression with rbf kernel on 2d data ''' + rbf = GPy.kern.RBF(2) + self.check_model(rbf, model_type='SparseGPRegression', dimension=2) +
      +
      [docs] def test_SparseGPRegression_rbf_linear_white_kern_1D(self): + ''' Testing the sparse GP regression with rbf kernel on 2d data ''' + rbflin = GPy.kern.RBF(1) + GPy.kern.Linear(1) + self.check_model(rbflin, model_type='SparseGPRegression', dimension=1) +
      +
      [docs] def test_SparseGPRegression_rbf_linear_white_kern_2D(self): + ''' Testing the sparse GP regression with rbf kernel on 2d data ''' + rbflin = GPy.kern.RBF(2) + GPy.kern.Linear(2) + self.check_model(rbflin, model_type='SparseGPRegression', dimension=2) + + # @unittest.expectedFailure
      +
      [docs] def test_SparseGPRegression_rbf_linear_white_kern_2D_uncertain_inputs(self): + ''' Testing the sparse GP regression with rbf, linear kernel on 2d data with uncertain inputs''' + rbflin = GPy.kern.RBF(2) + GPy.kern.Linear(2) + raise unittest.SkipTest("This is not implemented yet!") + self.check_model(rbflin, model_type='SparseGPRegression', dimension=2, uncertain_inputs=1) + + # @unittest.expectedFailure
      +
      [docs] def test_SparseGPRegression_rbf_linear_white_kern_1D_uncertain_inputs(self): + ''' Testing the sparse GP regression with rbf, linear kernel on 1d data with uncertain inputs''' + rbflin = GPy.kern.RBF(1) + GPy.kern.Linear(1) + raise unittest.SkipTest("This is not implemented yet!") + self.check_model(rbflin, model_type='SparseGPRegression', dimension=1, uncertain_inputs=1) +
      +
      [docs] def test_GPLVM_rbf_bias_white_kern_2D(self): + """ Testing GPLVM with rbf + bias kernel """ + N, input_dim, D = 50, 1, 2 + X = np.random.rand(N, input_dim) + k = GPy.kern.RBF(input_dim, 0.5, 0.9 * np.ones((1,))) + GPy.kern.Bias(input_dim, 0.1) + GPy.kern.White(input_dim, 0.05) + K = k.K(X) + Y = np.random.multivariate_normal(np.zeros(N), K, input_dim).T + m = GPy.models.GPLVM(Y, input_dim, kernel=k) + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_GPLVM_rbf_linear_white_kern_2D(self): + """ Testing GPLVM with rbf + bias kernel """ + N, input_dim, D = 50, 1, 2 + X = np.random.rand(N, input_dim) + k = GPy.kern.Linear(input_dim) + GPy.kern.Bias(input_dim, 0.1) + GPy.kern.White(input_dim, 0.05) + K = k.K(X) + Y = np.random.multivariate_normal(np.zeros(N), K, input_dim).T + m = GPy.models.GPLVM(Y, input_dim, init='PCA', kernel=k) + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_GP_EP_probit(self): + N = 20 + X = np.hstack([np.random.normal(5, 2, N / 2), np.random.normal(10, 2, N / 2)])[:, None] + Y = np.hstack([np.ones(N / 2), np.zeros(N / 2)])[:, None] + kernel = GPy.kern.RBF(1) + m = GPy.models.GPClassification(X, Y, kernel=kernel) + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_sparse_EP_DTC_probit(self): + N = 20 + X = np.hstack([np.random.normal(5, 2, N / 2), np.random.normal(10, 2, N / 2)])[:, None] + Y = np.hstack([np.ones(N / 2), np.zeros(N / 2)])[:, None] + Z = np.linspace(0, 15, 4)[:, None] + kernel = GPy.kern.RBF(1) + m = GPy.models.SparseGPClassification(X, Y, kernel=kernel, Z=Z) + # distribution = GPy.likelihoods.likelihood_functions.Bernoulli() + # likelihood = GPy.likelihoods.EP(Y, distribution) + # m = GPy.core.SparseGP(X, likelihood, kernel, Z) + # m.ensure_default_constraints() + self.assertTrue(m.checkgrad()) +
      + @unittest.expectedFailure +
      [docs] def test_generalized_FITC(self): + N = 20 + X = np.hstack([np.random.rand(N / 2) + 1, np.random.rand(N / 2) - 1])[:, None] + k = GPy.kern.RBF(1) + GPy.kern.White(1) + Y = np.hstack([np.ones(N / 2), np.zeros(N / 2)])[:, None] + m = GPy.models.FITCClassification(X, Y, kernel=k) + m.update_likelihood_approximation() + self.assertTrue(m.checkgrad()) +
      + @unittest.expectedFailure +
      [docs] def test_multioutput_regression_1D(self): + X1 = np.random.rand(50, 1) * 8 + X2 = np.random.rand(30, 1) * 5 + X = np.vstack((X1, X2)) + Y1 = np.sin(X1) + np.random.randn(*X1.shape) * 0.05 + Y2 = -np.sin(X2) + np.random.randn(*X2.shape) * 0.05 + Y = np.vstack((Y1, Y2)) + + k1 = GPy.kern.RBF(1) + m = GPy.models.GPMultioutputRegression(X_list=[X1, X2], Y_list=[Y1, Y2], kernel_list=[k1]) + import ipdb;ipdb.set_trace() + m.constrain_fixed('.*rbf_var', 1.) + self.assertTrue(m.checkgrad()) +
      + @unittest.expectedFailure +
      [docs] def test_multioutput_sparse_regression_1D(self): + X1 = np.random.rand(500, 1) * 8 + X2 = np.random.rand(300, 1) * 5 + X = np.vstack((X1, X2)) + Y1 = np.sin(X1) + np.random.randn(*X1.shape) * 0.05 + Y2 = -np.sin(X2) + np.random.randn(*X2.shape) * 0.05 + Y = np.vstack((Y1, Y2)) + + k1 = GPy.kern.RBF(1) + m = GPy.models.SparseGPMultioutputRegression(X_list=[X1, X2], Y_list=[Y1, Y2], kernel_list=[k1]) + m.constrain_fixed('.*rbf_var', 1.) + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_gp_heteroscedastic_regression(self): + num_obs = 25 + X = np.random.randint(0, 140, num_obs) + X = X[:, None] + Y = 25. + np.sin(X / 20.) * 2. + np.random.rand(num_obs)[:, None] + kern = GPy.kern.Bias(1) + GPy.kern.RBF(1) + m = GPy.models.GPHeteroscedasticRegression(X, Y, kern) + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_sparse_gp_heteroscedastic_regression(self): + num_obs = 25 + X = np.random.randint(0, 140, num_obs) + X = X[:, None] + Y = 25. + np.sin(X / 20.) * 2. + np.random.rand(num_obs)[:, None] + kern = GPy.kern.Bias(1) + GPy.kern.RBF(1) + Y_metadata = {'output_index':np.arange(num_obs)[:,None]} + noise_terms = np.unique(Y_metadata['output_index'].flatten()) + likelihoods_list = [GPy.likelihoods.Gaussian(name="Gaussian_noise_%s" %j) for j in noise_terms] + likelihood = GPy.likelihoods.MixedNoise(likelihoods_list=likelihoods_list) + m = GPy.core.SparseGP(X, Y, X[np.random.choice(num_obs, 10)], + kern, likelihood, + GPy.inference.latent_function_inference.VarDTC(), + Y_metadata=Y_metadata) + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_gp_kronecker_gaussian(self): + N1, N2 = 30, 20 + X1 = np.random.randn(N1, 1) + X2 = np.random.randn(N2, 1) + X1.sort(0); X2.sort(0) + k1 = GPy.kern.RBF(1) # + GPy.kern.White(1) + k2 = GPy.kern.RBF(1) # + GPy.kern.White(1) + Y = np.random.randn(N1, N2) + Y = Y - Y.mean(0) + Y = Y / Y.std(0) + m = GPy.models.GPKroneckerGaussianRegression(X1, X2, Y, k1, k2) + + # build the model the dumb way + assert (N1 * N2 < 1000), "too much data for standard GPs!" + yy, xx = np.meshgrid(X2, X1) + Xgrid = np.vstack((xx.flatten(order='F'), yy.flatten(order='F'))).T + kg = GPy.kern.RBF(1, active_dims=[0]) * GPy.kern.RBF(1, active_dims=[1]) + mm = GPy.models.GPRegression(Xgrid, Y.reshape(-1, 1, order='F'), kernel=kg) + + m.randomize() + mm[:] = m[:] + assert np.allclose(m.log_likelihood(), mm.log_likelihood()) + assert np.allclose(m.gradient, mm.gradient) + X1test = np.random.randn(100, 1) + X2test = np.random.randn(100, 1) + mean1, var1 = m.predict(X1test, X2test) + yy, xx = np.meshgrid(X2test, X1test) + Xgrid = np.vstack((xx.flatten(order='F'), yy.flatten(order='F'))).T + mean2, var2 = mm.predict(Xgrid) + assert np.allclose(mean1, mean2) + assert np.allclose(var1, var2) +
      +
      [docs] def test_gp_VGPC(self): + num_obs = 25 + X = np.random.randint(0, 140, num_obs) + X = X[:, None] + Y = 25. + np.sin(X / 20.) * 2. + np.random.rand(num_obs)[:, None] + kern = GPy.kern.Bias(1) + GPy.kern.RBF(1) + m = GPy.models.GPVariationalGaussianApproximation(X, Y, kern) + self.assertTrue(m.checkgrad()) + +
      +if __name__ == "__main__": + print "Running unit tests, please be (very) patient..." + unittest.main() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/observable_tests.html b/doc/_build/html/_modules/GPy/testing/observable_tests.html new file mode 100644 index 00000000..a8465f26 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/observable_tests.html @@ -0,0 +1,228 @@ + + + + + + + + GPy.testing.observable_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.observable_tests

      +# Copyright (c) 2014, Max Zwiessele
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import unittest
      +from GPy.core.parameterization.parameterized import Parameterized
      +from GPy.core.parameterization.param import Param
      +import numpy
      +
      +# One trigger in init
      +_trigger_start = -1
      +
      +
      [docs]class ParamTestParent(Parameterized): + parent_changed_count = _trigger_start +
      [docs] def parameters_changed(self): + self.parent_changed_count += 1 +
      +
      [docs]class ParameterizedTest(Parameterized): + # One trigger after initialization + params_changed_count = _trigger_start +
      [docs] def parameters_changed(self): + self.params_changed_count += 1 +
      +
      [docs]class Test(unittest.TestCase): + +
      [docs] def setUp(self): + self.parent = ParamTestParent('test parent') + self.par = ParameterizedTest('test model') + self.par2 = ParameterizedTest('test model 2') + self.p = Param('test parameter', numpy.random.normal(1,2,(10,3))) + + self.par.link_parameter(self.p) + self.par.link_parameter(Param('test1', numpy.random.normal(0,1,(1,)))) + self.par.link_parameter(Param('test2', numpy.random.normal(0,1,(1,)))) + + self.par2.link_parameter(Param('par2 test1', numpy.random.normal(0,1,(1,)))) + self.par2.link_parameter(Param('par2 test2', numpy.random.normal(0,1,(1,)))) + + self.parent.link_parameter(self.par) + self.parent.link_parameter(self.par2) + + self._observer_triggered = None + self._trigger_count = 0 + self._first = None + self._second = None +
      + def _trigger(self, me, which): + self._observer_triggered = which + self._trigger_count += 1 + if self._first is not None: + self._second = self._trigger + else: + self._first = self._trigger + + def _trigger_priority(self, me, which): + if self._first is not None: + self._second = self._trigger_priority + else: + self._first = self._trigger_priority + +
      [docs] def test_observable(self): + self.par.add_observer(self, self._trigger, -1) + self.assertEqual(self.par.params_changed_count, 0, 'no params changed yet') + self.assertEqual(self.par.params_changed_count, self.parent.parent_changed_count, 'parent should be triggered as often as param') + + self.p[0,1] = 3 # trigger observers + self.assertIs(self._observer_triggered, self.p, 'observer should have triggered') + self.assertEqual(self._trigger_count, 1, 'observer should have triggered once') + self.assertEqual(self.par.params_changed_count, 1, 'params changed once') + self.assertEqual(self.par.params_changed_count, self.parent.parent_changed_count, 'parent should be triggered as often as param') + + self.par.remove_observer(self) + self.p[0,1] = 4 + self.assertIs(self._observer_triggered, self.p, 'observer should not have triggered') + self.assertEqual(self._trigger_count, 1, 'observer should have triggered once') + self.assertEqual(self.par.params_changed_count, 2, 'params changed second') + self.assertEqual(self.par.params_changed_count, self.parent.parent_changed_count, 'parent should be triggered as often as param') + + self.par.add_observer(self, self._trigger, -1) + self.p[0,1] = 4 + self.assertIs(self._observer_triggered, self.p, 'observer should have triggered') + self.assertEqual(self._trigger_count, 2, 'observer should have triggered once') + self.assertEqual(self.par.params_changed_count, 3, 'params changed second') + self.assertEqual(self.par.params_changed_count, self.parent.parent_changed_count, 'parent should be triggered as often as param') + + self.par.remove_observer(self, self._trigger) + self.p[0,1] = 3 + self.assertIs(self._observer_triggered, self.p, 'observer should not have triggered') + self.assertEqual(self._trigger_count, 2, 'observer should have triggered once') + self.assertEqual(self.par.params_changed_count, 4, 'params changed second') + self.assertEqual(self.par.params_changed_count, self.parent.parent_changed_count, 'parent should be triggered as often as param') +
      +
      [docs] def test_set_params(self): + self.assertEqual(self.par.params_changed_count, 0, 'no params changed yet') + self.par.param_array[:] = 1 + self.par._trigger_params_changed() + self.assertEqual(self.par.params_changed_count, 1, 'now params changed') + self.assertEqual(self.parent.parent_changed_count, self.par.params_changed_count) + + self.par.param_array[:] = 2 + self.par._trigger_params_changed() + self.assertEqual(self.par.params_changed_count, 2, 'now params changed') + self.assertEqual(self.parent.parent_changed_count, self.par.params_changed_count) + +
      +
      [docs] def test_priority_notify(self): + self.assertEqual(self.par.params_changed_count, 0) + self.par.notify_observers(0, None) + self.assertEqual(self.par.params_changed_count, 1) + self.assertEqual(self.parent.parent_changed_count, self.par.params_changed_count) + + self.par.notify_observers(0, -numpy.inf) + self.assertEqual(self.par.params_changed_count, 2) + self.assertEqual(self.parent.parent_changed_count, 1) +
      +
      [docs] def test_priority(self): + self.par.add_observer(self, self._trigger, -1) + self.par.add_observer(self, self._trigger_priority, 0) + self.par.notify_observers(0) + self.assertEqual(self._first, self._trigger_priority, 'priority should be first') + self.assertEqual(self._second, self._trigger, 'priority should be first') + + self.par.remove_observer(self) + self._first = self._second = None + + self.par.add_observer(self, self._trigger, 1) + self.par.add_observer(self, self._trigger_priority, 0) + self.par.notify_observers(0) + self.assertEqual(self._first, self._trigger, 'priority should be second') + self.assertEqual(self._second, self._trigger_priority, 'priority should be second') +
      +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.testName'] + unittest.main() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/parameterized_tests.html b/doc/_build/html/_modules/GPy/testing/parameterized_tests.html new file mode 100644 index 00000000..734308e5 --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/parameterized_tests.html @@ -0,0 +1,353 @@ + + + + + + + + GPy.testing.parameterized_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.parameterized_tests

      +'''
      +Created on Feb 13, 2014
      +
      +@author: maxzwiessele
      +'''
      +import unittest
      +import GPy
      +import numpy as np
      +from GPy.core.parameterization.parameter_core import HierarchyError
      +from GPy.core.parameterization.observable_array import ObsAr
      +from GPy.core.parameterization.transformations import NegativeLogexp, Logistic
      +from GPy.core.parameterization.parameterized import Parameterized
      +from GPy.core.parameterization.param import Param
      +from GPy.core.parameterization.index_operations import ParameterIndexOperations
      +
      +
      [docs]class ArrayCoreTest(unittest.TestCase): +
      [docs] def setUp(self): + self.X = np.random.normal(1,1, size=(100,10)) + self.obsX = ObsAr(self.X) +
      +
      [docs] def test_init(self): + X = ObsAr(self.X) + X2 = ObsAr(X) + self.assertIs(X, X2, "no new Observable array, when Observable is given") +
      +
      [docs] def test_slice(self): + t1 = self.X[2:78] + t2 = self.obsX[2:78] + self.assertListEqual(t1.tolist(), t2.tolist(), "Slicing should be the exact same, as in ndarray") +
      +
      [docs]class ParameterizedTest(unittest.TestCase): + +
      [docs] def setUp(self): + self.rbf = GPy.kern.RBF(20) + self.white = GPy.kern.White(1) + from GPy.core.parameterization import Param + from GPy.core.parameterization.transformations import Logistic + self.param = Param('param', np.random.uniform(0,1,(10,5)), Logistic(0, 1)) + + self.test1 = GPy.core.Parameterized("test model") + self.test1.param = self.param + self.test1.kern = self.rbf+self.white + self.test1.link_parameter(self.test1.kern) + self.test1.link_parameter(self.param, 0) + + # print self.test1: + #============================================================================= + # test_model. | Value | Constraint | Prior | Tied to + # param | (25L, 2L) | {0.0,1.0} | | + # add.rbf.variance | 1.0 | 0.0,1.0 +ve | | + # add.rbf.lengthscale | 1.0 | 0.0,1.0 +ve | | + # add.white.variance | 1.0 | 0.0,1.0 +ve | | + #============================================================================= + + x = np.linspace(-2,6,4)[:,None] + y = np.sin(x) + self.testmodel = GPy.models.GPRegression(x,y) + # print self.testmodel: + #============================================================================= + # GP_regression. | Value | Constraint | Prior | Tied to + # rbf.variance | 1.0 | +ve | | + # rbf.lengthscale | 1.0 | +ve | | + # Gaussian_noise.variance | 1.0 | +ve | | + #============================================================================= +
      +
      [docs] def test_add_parameter(self): + self.assertEquals(self.rbf._parent_index_, 0) + self.assertEquals(self.white._parent_index_, 1) + self.assertEquals(self.param._parent_index_, 0) + pass +
      +
      [docs] def test_fixes(self): + self.white.fix(warning=False) + self.test1.unlink_parameter(self.param) + self.assertTrue(self.test1._has_fixes()) + from GPy.core.parameterization.transformations import FIXED, UNFIXED + self.assertListEqual(self.test1._fixes_.tolist(),[UNFIXED,UNFIXED,FIXED]) + self.test1.kern.link_parameter(self.white, 0) + self.assertListEqual(self.test1._fixes_.tolist(),[FIXED,UNFIXED,UNFIXED]) + self.test1.kern.rbf.fix() + self.assertListEqual(self.test1._fixes_.tolist(),[FIXED]*3) + self.test1.fix() + self.assertTrue(self.test1.is_fixed) + self.assertListEqual(self.test1._fixes_.tolist(),[FIXED]*self.test1.size) +
      +
      [docs] def test_remove_parameter(self): + from GPy.core.parameterization.transformations import FIXED, UNFIXED, __fixed__, Logexp + self.white.fix() + self.test1.kern.unlink_parameter(self.white) + self.assertIs(self.test1._fixes_,None) + + self.assertIsInstance(self.white.constraints, ParameterIndexOperations) + self.assertListEqual(self.white._fixes_.tolist(), [FIXED]) + self.assertIs(self.test1.constraints, self.rbf.constraints._param_index_ops) + self.assertIs(self.test1.constraints, self.param.constraints._param_index_ops) + + self.test1.link_parameter(self.white, 0) + self.assertIs(self.test1.constraints, self.white.constraints._param_index_ops) + self.assertIs(self.test1.constraints, self.rbf.constraints._param_index_ops) + self.assertIs(self.test1.constraints, self.param.constraints._param_index_ops) + self.assertListEqual(self.test1.constraints[__fixed__].tolist(), [0]) + self.assertIs(self.white._fixes_,None) + self.assertListEqual(self.test1._fixes_.tolist(),[FIXED] + [UNFIXED] * 52) + + self.test1.unlink_parameter(self.white) + self.assertIs(self.test1._fixes_,None) + self.assertListEqual(self.white._fixes_.tolist(), [FIXED]) + self.assertIs(self.test1.constraints, self.rbf.constraints._param_index_ops) + self.assertIs(self.test1.constraints, self.param.constraints._param_index_ops) + self.assertListEqual(self.test1.constraints[Logexp()].tolist(), range(self.param.size, self.param.size+self.rbf.size)) +
      +
      [docs] def test_remove_parameter_param_array_grad_array(self): + val = self.test1.kern.param_array.copy() + self.test1.kern.unlink_parameter(self.white) + self.assertListEqual(self.test1.kern.param_array.tolist(), val[:2].tolist()) +
      +
      [docs] def test_add_parameter_already_in_hirarchy(self): + self.assertRaises(HierarchyError, self.test1.link_parameter, self.white.parameters[0]) +
      +
      [docs] def test_default_constraints(self): + self.assertIs(self.rbf.variance.constraints._param_index_ops, self.rbf.constraints._param_index_ops) + self.assertIs(self.test1.constraints, self.rbf.constraints._param_index_ops) + self.assertListEqual(self.rbf.constraints.indices()[0].tolist(), range(2)) + from GPy.core.parameterization.transformations import Logexp + kern = self.test1.kern + self.test1.unlink_parameter(kern) + self.assertListEqual(kern.constraints[Logexp()].tolist(), range(3)) +
      +
      [docs] def test_constraints(self): + self.rbf.constrain(GPy.transformations.Square(), False) + self.assertListEqual(self.test1.constraints[GPy.transformations.Square()].tolist(), range(self.param.size, self.param.size+self.rbf.size)) + self.assertListEqual(self.test1.constraints[GPy.transformations.Logexp()].tolist(), [self.param.size+self.rbf.size]) + + self.test1.kern.unlink_parameter(self.rbf) + self.assertListEqual(self.test1.constraints[GPy.transformations.Square()].tolist(), []) +
      + +
      [docs] def test_constraints_views(self): + self.assertEqual(self.white.constraints._offset, self.param.size+self.rbf.size) + self.assertEqual(self.rbf.constraints._offset, self.param.size) + self.assertEqual(self.param.constraints._offset, 0) +
      +
      [docs] def test_fixing_randomize(self): + self.white.fix(warning=True) + val = float(self.white.variance) + self.test1.randomize() + self.assertEqual(val, self.white.variance) +
      +
      [docs] def test_randomize(self): + ps = self.test1.param.view(np.ndarray).copy() + self.test1.param[2:5].fix() + self.test1.param.randomize() + self.assertFalse(np.all(ps==self.test1.param),str(ps)+str(self.test1.param)) +
      +
      [docs] def test_fixing_randomize_parameter_handling(self): + self.rbf.fix(warning=True) + val = float(self.rbf.variance) + self.test1.kern.randomize() + self.assertEqual(val, self.rbf.variance) +
      +
      [docs] def test_updates(self): + val = float(self.testmodel.log_likelihood()) + self.testmodel.update_model(False) + self.testmodel.kern.randomize() + self.testmodel.likelihood.randomize() + self.assertEqual(val, self.testmodel.log_likelihood()) + self.testmodel.update_model(True) + self.assertNotEqual(val, self.testmodel.log_likelihood()) +
      +
      [docs] def test_fixing_optimize(self): + self.testmodel.kern.lengthscale.fix() + val = float(self.testmodel.kern.lengthscale) + self.testmodel.randomize() + self.assertEqual(val, self.testmodel.kern.lengthscale) +
      +
      [docs] def test_add_parameter_in_hierarchy(self): + self.test1.kern.rbf.link_parameter(Param("NEW", np.random.rand(2), NegativeLogexp()), 1) + self.assertListEqual(self.test1.constraints[NegativeLogexp()].tolist(), range(self.param.size+1, self.param.size+1 + 2)) + self.assertListEqual(self.test1.constraints[GPy.transformations.Logistic(0,1)].tolist(), range(self.param.size)) + self.assertListEqual(self.test1.constraints[GPy.transformations.Logexp(0,1)].tolist(), np.r_[50, 53:55].tolist()) +
      +
      [docs] def test_regular_expression_misc(self): + self.testmodel.kern.lengthscale.fix() + val = float(self.testmodel.kern.lengthscale) + self.testmodel.randomize() + self.assertEqual(val, self.testmodel.kern.lengthscale) + + variances = self.testmodel['.*var'].values() + self.testmodel['.*var'].fix() + self.testmodel.randomize() + np.testing.assert_equal(variances, self.testmodel['.*var'].values()) +
      +
      [docs] def test_fix_unfix(self): + fixed = self.testmodel.kern.lengthscale.fix() + self.assertListEqual(fixed.tolist(), [0]) + unfixed = self.testmodel.kern.lengthscale.unfix() + self.testmodel.kern.lengthscale.constrain_positive() + self.assertListEqual(unfixed.tolist(), [0]) + + fixed = self.testmodel.kern.fix() + self.assertListEqual(fixed.tolist(), [0,1]) + unfixed = self.testmodel.kern.unfix() + self.assertListEqual(unfixed.tolist(), [0,1]) +
      +
      [docs] def test_constraints_in_init(self): + class Test(Parameterized): + def __init__(self, name=None, parameters=[], *a, **kw): + super(Test, self).__init__(name=name) + self.x = Param('x', np.random.uniform(0,1,(3,4))) + self.x[0].constrain_bounded(0,1) + self.link_parameter(self.x) + self.x[1].fix() + t = Test() + c = {Logistic(0,1): np.array([0, 1, 2, 3]), 'fixed': np.array([4, 5, 6, 7])} + np.testing.assert_equal(t.x.constraints[Logistic(0,1)], c[Logistic(0,1)]) + np.testing.assert_equal(t.x.constraints['fixed'], c['fixed']) +
      +
      [docs] def test_parameter_modify_in_init(self): + class TestLikelihood(Parameterized): + def __init__(self, param1 = 2., param2 = 3.): + super(TestLikelihood, self).__init__("TestLike") + self.p1 = Param('param1', param1) + self.p2 = Param('param2', param2) + + self.link_parameter(self.p1) + self.link_parameter(self.p2) + + self.p1.fix() + self.p1.unfix() + self.p2.constrain_negative() + self.p1.fix() + self.p2.constrain_positive() + self.p2.fix() + self.p2.constrain_positive() + + m = TestLikelihood() + print m + val = m.p1.values.copy() + self.assert_(m.p1.is_fixed) + self.assert_(m.constraints[GPy.constraints.Logexp()].tolist(), [1]) + m.randomize() + self.assertEqual(m.p1, val) +
      +
      [docs] def test_printing(self): + print self.test1 + print self.param + print self.test1[''] +
      +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.test_add_parameter'] + unittest.main() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/pickle_tests.html b/doc/_build/html/_modules/GPy/testing/pickle_tests.html new file mode 100644 index 00000000..7114a4ef --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/pickle_tests.html @@ -0,0 +1,316 @@ + + + + + + + + GPy.testing.pickle_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.pickle_tests

      +'''
      +Created on 13 Mar 2014
      +
      +@author: maxz
      +'''
      +import unittest, itertools
      +#import cPickle as pickle
      +import pickle
      +import numpy as np
      +from GPy.core.parameterization.index_operations import ParameterIndexOperations,\
      +    ParameterIndexOperationsView
      +import tempfile
      +from GPy.core.parameterization.param import Param
      +from GPy.core.parameterization.observable_array import ObsAr
      +from GPy.core.parameterization.priors import Gaussian
      +from GPy.kern._src.rbf import RBF
      +from GPy.kern._src.linear import Linear
      +from GPy.kern._src.static import Bias, White
      +from GPy.examples.dimensionality_reduction import mrd_simulation
      +from GPy.core.parameterization.variational import NormalPosterior
      +from GPy.models.gp_regression import GPRegression
      +
      +
      [docs]def toy_model(): + X = np.linspace(0,1,50)[:, None] + Y = np.sin(X) + m = GPRegression(X=X, Y=Y) + return m +
      +
      [docs]class ListDictTestCase(unittest.TestCase): +
      [docs] def assertListDictEquals(self, d1, d2, msg=None): + for k,v in d1.iteritems(): + self.assertListEqual(list(v), list(d2[k]), msg)
      +
      [docs] def assertArrayListEquals(self, l1, l2): + for a1, a2 in itertools.izip(l1,l2): + np.testing.assert_array_equal(a1, a2) +
      +
      [docs]class Test(ListDictTestCase): +
      [docs] def test_parameter_index_operations(self): + pio = ParameterIndexOperations(dict(test1=np.array([4,3,1,6,4]), test2=np.r_[2:130])) + piov = ParameterIndexOperationsView(pio, 20, 250) + self.assertListDictEquals(dict(piov.items()), dict(piov.copy().iteritems())) + self.assertListDictEquals(dict(pio.iteritems()), dict(pio.copy().items())) + + self.assertArrayListEquals(pio.copy().indices(), pio.indices()) + self.assertArrayListEquals(piov.copy().indices(), piov.indices()) + + with tempfile.TemporaryFile('w+b') as f: + pickle.dump(pio, f) + f.seek(0) + pio2 = pickle.load(f) + self.assertListDictEquals(pio._properties, pio2._properties) + + with tempfile.TemporaryFile('w+b') as f: + pickle.dump(piov, f) + f.seek(0) + pio2 = pickle.load(f) + self.assertListDictEquals(dict(piov.items()), dict(pio2.iteritems())) +
      +
      [docs] def test_param(self): + param = Param('test', np.arange(4*2).reshape(4,2)) + param[0].constrain_positive() + param[1].fix() + param[2].set_prior(Gaussian(0,1)) + pcopy = param.copy() + self.assertListEqual(param.tolist(), pcopy.tolist()) + self.assertListEqual(str(param).split('\n'), str(pcopy).split('\n')) + self.assertIsNot(param, pcopy) + with tempfile.TemporaryFile('w+b') as f: + pickle.dump(param, f) + f.seek(0) + pcopy = pickle.load(f) + self.assertListEqual(param.tolist(), pcopy.tolist()) + self.assertSequenceEqual(str(param), str(pcopy)) +
      +
      [docs] def test_observable_array(self): + obs = ObsAr(np.arange(4*2).reshape(4,2)) + pcopy = obs.copy() + self.assertListEqual(obs.tolist(), pcopy.tolist()) + with tempfile.TemporaryFile('w+b') as f: + pickle.dump(obs, f) + f.seek(0) + pcopy = pickle.load(f) + self.assertListEqual(obs.tolist(), pcopy.tolist()) + self.assertSequenceEqual(str(obs), str(pcopy)) +
      +
      [docs] def test_parameterized(self): + par = RBF(1, active_dims=[1]) + Linear(2, active_dims=[0,2]) + Bias(3) + White(3) + par.gradient = 10 + par.randomize() + pcopy = par.copy() + self.assertIsInstance(pcopy.constraints, ParameterIndexOperations) + self.assertIsInstance(pcopy.rbf.constraints, ParameterIndexOperationsView) + self.assertIs(pcopy.constraints, pcopy.rbf.constraints._param_index_ops) + self.assertIs(pcopy.constraints, pcopy.rbf.lengthscale.constraints._param_index_ops) + self.assertIs(pcopy.constraints, pcopy.linear.constraints._param_index_ops) + self.assertListEqual(par.param_array.tolist(), pcopy.param_array.tolist()) + pcopy.gradient = 10 # gradient does not get copied anymore + self.assertListEqual(par.gradient_full.tolist(), pcopy.gradient_full.tolist()) + self.assertSequenceEqual(str(par), str(pcopy)) + self.assertIsNot(par.param_array, pcopy.param_array) + self.assertIsNot(par.gradient_full, pcopy.gradient_full) + with tempfile.TemporaryFile('w+b') as f: + par.pickle(f) + f.seek(0) + pcopy = pickle.load(f) + self.assertListEqual(par.param_array.tolist(), pcopy.param_array.tolist()) + pcopy.gradient = 10 + np.testing.assert_allclose(par.linear.gradient_full, pcopy.linear.gradient_full) + np.testing.assert_allclose(pcopy.linear.gradient_full, 10) + self.assertSequenceEqual(str(par), str(pcopy)) +
      +
      [docs] def test_model(self): + par = toy_model() + pcopy = par.copy() + self.assertListEqual(par.param_array.tolist(), pcopy.param_array.tolist()) + np.testing.assert_allclose(par.gradient_full, pcopy.gradient_full) + self.assertSequenceEqual(str(par), str(pcopy)) + self.assertIsNot(par.param_array, pcopy.param_array) + self.assertIsNot(par.gradient_full, pcopy.gradient_full) + self.assertTrue(pcopy.checkgrad()) + self.assert_(np.any(pcopy.gradient!=0.0)) + with tempfile.TemporaryFile('w+b') as f: + par.pickle(f) + f.seek(0) + pcopy = pickle.load(f) + self.assertListEqual(par.param_array.tolist(), pcopy.param_array.tolist()) + np.testing.assert_allclose(par.gradient_full, pcopy.gradient_full) + self.assertSequenceEqual(str(par), str(pcopy)) + self.assert_(pcopy.checkgrad()) +
      +
      [docs] def test_modelrecreation(self): + par = toy_model() + pcopy = GPRegression(par.X.copy(), par.Y.copy(), kernel=par.kern.copy()) + np.testing.assert_allclose(par.param_array, pcopy.param_array) + np.testing.assert_allclose(par.gradient_full, pcopy.gradient_full) + self.assertSequenceEqual(str(par), str(pcopy)) + self.assertIsNot(par.param_array, pcopy.param_array) + self.assertIsNot(par.gradient_full, pcopy.gradient_full) + self.assertTrue(pcopy.checkgrad()) + self.assert_(np.any(pcopy.gradient!=0.0)) + pcopy.optimize('bfgs') + par.optimize('bfgs') + np.testing.assert_allclose(pcopy.param_array, par.param_array, atol=1e-6) + par.randomize() + with tempfile.TemporaryFile('w+b') as f: + par.pickle(f) + f.seek(0) + pcopy = pickle.load(f) + np.testing.assert_allclose(par.param_array, pcopy.param_array) + np.testing.assert_allclose(par.gradient_full, pcopy.gradient_full, atol=1e-6) + self.assertSequenceEqual(str(par), str(pcopy)) + self.assert_(pcopy.checkgrad()) +
      +
      [docs] def test_posterior(self): + X = np.random.randn(3,5) + Xv = np.random.rand(*X.shape) + par = NormalPosterior(X,Xv) + par.gradient = 10 + pcopy = par.copy() + pcopy.gradient = 10 + self.assertListEqual(par.param_array.tolist(), pcopy.param_array.tolist()) + self.assertListEqual(par.gradient_full.tolist(), pcopy.gradient_full.tolist()) + self.assertSequenceEqual(str(par), str(pcopy)) + self.assertIsNot(par.param_array, pcopy.param_array) + self.assertIsNot(par.gradient_full, pcopy.gradient_full) + with tempfile.TemporaryFile('w+b') as f: + par.pickle(f) + f.seek(0) + pcopy = pickle.load(f) + self.assertListEqual(par.param_array.tolist(), pcopy.param_array.tolist()) + pcopy.gradient = 10 + np.testing.assert_allclose(par.gradient_full, pcopy.gradient_full) + np.testing.assert_allclose(pcopy.mean.gradient_full, 10) + self.assertSequenceEqual(str(par), str(pcopy)) +
      +
      [docs] def test_model_concat(self): + par = mrd_simulation(optimize=0, plot=0, plot_sim=0) + par.randomize() + pcopy = par.copy() + self.assertListEqual(par.param_array.tolist(), pcopy.param_array.tolist()) + self.assertListEqual(par.gradient_full.tolist(), pcopy.gradient_full.tolist()) + self.assertSequenceEqual(str(par), str(pcopy)) + self.assertIsNot(par.param_array, pcopy.param_array) + self.assertIsNot(par.gradient_full, pcopy.gradient_full) + self.assertTrue(par.checkgrad()) + self.assertTrue(pcopy.checkgrad()) + self.assert_(np.any(pcopy.gradient!=0.0)) + with tempfile.TemporaryFile('w+b') as f: + par.pickle(f) + f.seek(0) + pcopy = pickle.load(f) + self.assertListEqual(par.param_array.tolist(), pcopy.param_array.tolist()) + np.testing.assert_allclose(par.gradient_full, pcopy.gradient_full) + self.assertSequenceEqual(str(par), str(pcopy)) + self.assert_(pcopy.checkgrad()) +
      + def _callback(self, what, which): + what.count += 1 + + @unittest.skip + def test_add_observer(self): + par = toy_model() + par.name = "original" + par.count = 0 + par.add_observer(self, self._callback, 1) + pcopy = GPRegression(par.X.copy(), par.Y.copy(), kernel=par.kern.copy()) + self.assertNotIn(par.observers[0], pcopy.observers) + pcopy = par.copy() + pcopy.name = "copy" + self.assertTrue(par.checkgrad()) + self.assertTrue(pcopy.checkgrad()) + self.assertTrue(pcopy.kern.checkgrad()) + import ipdb;ipdb.set_trace() + self.assertIn(par.observers[0], pcopy.observers) + self.assertEqual(par.count, 3) + self.assertEqual(pcopy.count, 6) # 3 of each call to checkgrad +
      +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.test_parameter_index_operations'] + unittest.main() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/testing/prior_tests.html b/doc/_build/html/_modules/GPy/testing/prior_tests.html new file mode 100644 index 00000000..a93d160f --- /dev/null +++ b/doc/_build/html/_modules/GPy/testing/prior_tests.html @@ -0,0 +1,210 @@ + + + + + + + + GPy.testing.prior_tests — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.testing.prior_tests

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import unittest
      +import numpy as np
      +import GPy
      +
      +
      [docs]class PriorTests(unittest.TestCase): +
      [docs] def test_lognormal(self): + xmin, xmax = 1, 2.5*np.pi + b, C, SNR = 1, 0, 0.1 + X = np.linspace(xmin, xmax, 500) + y = b*X + C + 1*np.sin(X) + y += 0.05*np.random.randn(len(X)) + X, y = X[:, None], y[:, None] + m = GPy.models.GPRegression(X, y) + lognormal = GPy.priors.LogGaussian(1, 2) + m.rbf.set_prior(lognormal) + m.randomize() + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_Gamma(self): + xmin, xmax = 1, 2.5*np.pi + b, C, SNR = 1, 0, 0.1 + X = np.linspace(xmin, xmax, 500) + y = b*X + C + 1*np.sin(X) + y += 0.05*np.random.randn(len(X)) + X, y = X[:, None], y[:, None] + m = GPy.models.GPRegression(X, y) + Gamma = GPy.priors.Gamma(1, 1) + m.rbf.set_prior(Gamma) + m.randomize() + self.assertTrue(m.checkgrad()) +
      +
      [docs] def test_incompatibility(self): + xmin, xmax = 1, 2.5*np.pi + b, C, SNR = 1, 0, 0.1 + X = np.linspace(xmin, xmax, 500) + y = b*X + C + 1*np.sin(X) + y += 0.05*np.random.randn(len(X)) + X, y = X[:, None], y[:, None] + m = GPy.models.GPRegression(X, y) + gaussian = GPy.priors.Gaussian(1, 1) + # setting a Gaussian prior on non-negative parameters + # should raise an assertionerror. + self.assertRaises(AssertionError, m.rbf.set_prior, gaussian) +
      +
      [docs] def test_set_prior(self): + xmin, xmax = 1, 2.5*np.pi + b, C, SNR = 1, 0, 0.1 + X = np.linspace(xmin, xmax, 500) + y = b*X + C + 1*np.sin(X) + y += 0.05*np.random.randn(len(X)) + X, y = X[:, None], y[:, None] + m = GPy.models.GPRegression(X, y) + + gaussian = GPy.priors.Gaussian(1, 1) + #m.rbf.set_prior(gaussian) + # setting a Gaussian prior on non-negative parameters + # should raise an assertionerror. + self.assertRaises(AssertionError, m.rbf.set_prior, gaussian) +
      +
      [docs] def test_set_gaussian_for_reals(self): + xmin, xmax = 1, 2.5*np.pi + b, C, SNR = 1, 0, 0.1 + X = np.linspace(xmin, xmax, 500) + y = b*X + C + 1*np.sin(X) + y += 0.05*np.random.randn(len(X)) + X, y = X[:, None], y[:, None] + m = GPy.models.SparseGPRegression(X, y) + + gaussian = GPy.priors.Gaussian(1, 1) + m.Z.set_prior(gaussian) + # setting a Gaussian prior on non-negative parameters + # should raise an assertionerror. + #self.assertRaises(AssertionError, m.Z.set_prior, gaussian) + + +
      +
      [docs] def test_fixed_domain_check(self): + xmin, xmax = 1, 2.5*np.pi + b, C, SNR = 1, 0, 0.1 + X = np.linspace(xmin, xmax, 500) + y = b*X + C + 1*np.sin(X) + y += 0.05*np.random.randn(len(X)) + X, y = X[:, None], y[:, None] + m = GPy.models.GPRegression(X, y) + + m.rbf.fix() + gaussian = GPy.priors.Gaussian(1, 1) + # setting a Gaussian prior on non-negative parameters + # should raise an assertionerror. + self.assertRaises(AssertionError, m.rbf.set_prior, gaussian) +
      +
      [docs] def test_fixed_domain_check1(self): + xmin, xmax = 1, 2.5*np.pi + b, C, SNR = 1, 0, 0.1 + X = np.linspace(xmin, xmax, 500) + y = b*X + C + 1*np.sin(X) + y += 0.05*np.random.randn(len(X)) + X, y = X[:, None], y[:, None] + m = GPy.models.GPRegression(X, y) + + m.kern.lengthscale.fix() + gaussian = GPy.priors.Gaussian(1, 1) + # setting a Gaussian prior on non-negative parameters + # should raise an assertionerror. + self.assertRaises(AssertionError, m.rbf.set_prior, gaussian) + + +
      +if __name__ == "__main__": + print "Running unit tests, please be (very) patient..." + unittest.main() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/block_matrices.html b/doc/_build/html/_modules/GPy/util/block_matrices.html new file mode 100644 index 00000000..db4d90d5 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/block_matrices.html @@ -0,0 +1,120 @@ + + + + + + + + GPy.util.block_matrices — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.block_matrices

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import numpy as np
      +
      +
      [docs]def get_blocks(A, blocksizes): + assert (A.shape[0]==A.shape[1]) and len(A.shape)==2, "can;t blockify this non-square matrix" + N = np.sum(blocksizes) + assert A.shape[0] == N, "bad blocksizes" + num_blocks = len(blocksizes) + B = np.empty(shape=(num_blocks, num_blocks), dtype=np.object) + count_i = 0 + for Bi, i in enumerate(blocksizes): + count_j = 0 + for Bj, j in enumerate(blocksizes): + B[Bi, Bj] = A[count_i:count_i + i, count_j : count_j + j] + count_j += j + count_i += i + return B + + +
      +if __name__=='__main__': + A = np.zeros((5,5)) + B = get_blocks(A,[2,3]) + B[0,0] += 7 + print B +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/caching.html b/doc/_build/html/_modules/GPy/util/caching.html new file mode 100644 index 00000000..fa213467 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/caching.html @@ -0,0 +1,289 @@ + + + + + + + + GPy.util.caching — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.caching

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +from ..core.parameterization.observable import Observable
      +import collections, weakref
      +
      +
      [docs]class Cacher(object): + def __init__(self, operation, limit=5, ignore_args=(), force_kwargs=()): + """ + Parameters: + *********** + :param callable operation: function to cache + :param int limit: depth of cacher + :param [int] ignore_args: list of indices, pointing at arguments to ignore in *args of operation(*args). This includes self! + :param [str] force_kwargs: list of kwarg names (strings). If a kwarg with that name is given, the cacher will force recompute and wont cache anything. + :param int verbose: verbosity level. 0: no print outs, 1: casual print outs, 2: debug level print outs + """ + self.limit = int(limit) + self.ignore_args = ignore_args + self.force_kwargs = force_kwargs + self.operation = operation + self.order = collections.deque() + self.cached_inputs = {} # point from cache_ids to a list of [ind_ids], which where used in cache cache_id + + #======================================================================= + # point from each ind_id to [ref(obj), cache_ids] + # 0: a weak reference to the object itself + # 1: the cache_ids in which this ind_id is used (len will be how many times we have seen this ind_id) + self.cached_input_ids = {} + #======================================================================= + + self.cached_outputs = {} # point from cache_ids to outputs + self.inputs_changed = {} # point from cache_ids to bools + +
      [docs] def id(self, obj): + """returns the self.id of an object, to be used in caching individual self.ids""" + return hex(id(obj)) +
      +
      [docs] def combine_inputs(self, args, kw, ignore_args): + "Combines the args and kw in a unique way, such that ordering of kwargs does not lead to recompute" + inputs= args + tuple(c[1] for c in sorted(kw.items(), key=lambda x: x[0])) + # REMOVE the ignored arguments from input and PREVENT it from being checked!!! + return [a for i,a in enumerate(inputs) if i not in ignore_args] +
      +
      [docs] def prepare_cache_id(self, combined_args_kw): + "get the cacheid (conc. string of argument self.ids in order)" + cache_id = "".join(self.id(a) for a in combined_args_kw) + return cache_id +
      +
      [docs] def ensure_cache_length(self, cache_id): + "Ensures the cache is within its limits and has one place free" + if len(self.order) == self.limit: + # we have reached the limit, so lets release one element + cache_id = self.order.popleft() + combined_args_kw = self.cached_inputs[cache_id] + for ind in combined_args_kw: + if ind is not None: + ind_id = self.id(ind) + tmp = self.cached_input_ids.get(ind_id, None) + if tmp is not None: + ref, cache_ids = tmp + if len(cache_ids) == 1 and ref() is not None: + ref().remove_observer(self, self.on_cache_changed) + del self.cached_input_ids[ind_id] + else: + cache_ids.remove(cache_id) + self.cached_input_ids[ind_id] = [ref, cache_ids] + del self.cached_outputs[cache_id] + del self.inputs_changed[cache_id] + del self.cached_inputs[cache_id] +
      +
      [docs] def add_to_cache(self, cache_id, inputs, output): + """This adds cache_id to the cache, with inputs and output""" + self.inputs_changed[cache_id] = False + self.cached_outputs[cache_id] = output + self.order.append(cache_id) + self.cached_inputs[cache_id] = inputs + for a in inputs: + if a is not None: + ind_id = self.id(a) + v = self.cached_input_ids.get(ind_id, [weakref.ref(a), []]) + v[1].append(cache_id) + if len(v[1]) == 1: + a.add_observer(self, self.on_cache_changed) + self.cached_input_ids[ind_id] = v +
      + def __call__(self, *args, **kw): + """ + A wrapper function for self.operation, + """ + #======================================================================= + # !WARNING CACHE OFFSWITCH! + # return self.operation(*args, **kw) + #======================================================================= + + # 1: Check whether we have forced recompute arguments: + if len(self.force_kwargs) != 0: + for k in self.force_kwargs: + if k in kw and kw[k] is not None: + return self.operation(*args, **kw) + + # 2: prepare_cache_id and get the unique self.id string for this call + inputs = self.combine_inputs(args, kw, self.ignore_args) + cache_id = self.prepare_cache_id(inputs) + # 2: if anything is not cachable, we will just return the operation, without caching + if reduce(lambda a, b: a or (not (isinstance(b, Observable) or b is None)), inputs, False): + #print 'WARNING: '+self.operation.__name__ + ' not cacheable!' + #print [not (isinstance(b, Observable)) for b in inputs] + return self.operation(*args, **kw) + # 3&4: check whether this cache_id has been cached, then has it changed? + try: + if(self.inputs_changed[cache_id]): + # 4: This happens, when elements have changed for this cache self.id + self.inputs_changed[cache_id] = False + self.cached_outputs[cache_id] = self.operation(*args, **kw) + except KeyError: + # 3: This is when we never saw this chache_id: + self.ensure_cache_length(cache_id) + self.add_to_cache(cache_id, inputs, self.operation(*args, **kw)) + except: + self.reset() + raise + # 5: We have seen this cache_id and it is cached: + return self.cached_outputs[cache_id] + +
      [docs] def on_cache_changed(self, direct, which=None): + """ + A callback funtion, which sets local flags when the elements of some cached inputs change + + this function gets 'hooked up' to the inputs when we cache them, and upon their elements being changed we update here. + """ + for what in [direct, which]: + if what is not None: + ind_id = self.id(what) + _, cache_ids = self.cached_input_ids.get(ind_id, [None, []]) + for cache_id in cache_ids: + self.inputs_changed[cache_id] = True +
      +
      [docs] def reset(self): + """ + Totally reset the cache + """ + [a().remove_observer(self, self.on_cache_changed) if (a() is not None) else None for [a, _] in self.cached_input_ids.values()] + self.cached_input_ids = {} + self.cached_outputs = {} + self.inputs_changed = {} +
      + def __deepcopy__(self, memo=None): + return Cacher(self.operation, self.limit, self.ignore_args, self.force_kwargs) + + def __getstate__(self, memo=None): + raise NotImplementedError, "Trying to pickle Cacher object with function {}, pickling functions not possible.".format(str(self.operation)) + + def __setstate__(self, memo=None): + raise NotImplementedError, "Trying to pickle Cacher object with function {}, pickling functions not possible.".format(str(self.operation)) + + @property + def __name__(self): + return self.operation.__name__ +
      +from functools import partial, update_wrapper + +
      [docs]class Cacher_wrap(object): + def __init__(self, f, limit, ignore_args, force_kwargs): + self.limit = limit + self.ignore_args = ignore_args + self.force_kwargs = force_kwargs + self.f = f + update_wrapper(self, self.f) + def __get__(self, obj, objtype=None): + return partial(self, obj) + def __call__(self, *args, **kwargs): + obj = args[0] + # import ipdb;ipdb.set_trace() + try: + caches = obj.__cachers + except AttributeError: + caches = obj.__cachers = {} + try: + cacher = caches[self.f] + except KeyError: + cacher = caches[self.f] = Cacher(self.f, self.limit, self.ignore_args, self.force_kwargs) + return cacher(*args, **kwargs) +
      +
      [docs]class Cache_this(object): + """ + A decorator which can be applied to bound methods in order to cache them + """ + def __init__(self, limit=5, ignore_args=(), force_kwargs=()): + self.limit = limit + self.ignore_args = ignore_args + self.force_args = force_kwargs + def __call__(self, f): + newf = Cacher_wrap(f, self.limit, self.ignore_args, self.force_args) + update_wrapper(newf, f) + return newf
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/classification.html b/doc/_build/html/_modules/GPy/util/classification.html new file mode 100644 index 00000000..1528ca1d --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/classification.html @@ -0,0 +1,127 @@ + + + + + + + + GPy.util.classification — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.classification

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import numpy as np
      +
      +
      [docs]def conf_matrix(p,labels,names=['1','0'],threshold=.5,show=True): + """ + Returns error rate and true/false positives in a binary classification problem + - Actual classes are displayed by column. + - Predicted classes are displayed by row. + + :param p: array of class '1' probabilities. + :param labels: array of actual classes. + :param names: list of class names, defaults to ['1','0']. + :param threshold: probability value used to decide the class. + :param show: whether the matrix should be shown or not + :type show: False|True + """ + assert p.size == labels.size, "Arrays p and labels have different dimensions." + decision = np.ones((labels.size,1)) + decision[p<threshold] = 0 + diff = decision - labels + false_0 = diff[diff == -1].size + false_1 = diff[diff == 1].size + true_1 = np.sum(decision[diff ==0]) + true_0 = labels.size - true_1 - false_0 - false_1 + error = (false_1 + false_0)/np.float(labels.size) + if show: + print 100. - error * 100,'% instances correctly classified' + print '%-10s| %-10s| %-10s| ' % ('',names[0],names[1]) + print '----------|------------|------------|' + print '%-10s| %-10s| %-10s| ' % (names[0],true_1,false_0) + print '%-10s| %-10s| %-10s| ' % (names[1],false_1,true_0) + return error,true_1, false_1, true_0, false_0
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/datasets.html b/doc/_build/html/_modules/GPy/util/datasets.html new file mode 100644 index 00000000..16c47ae5 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/datasets.html @@ -0,0 +1,1563 @@ + + + + + + + + GPy.util.datasets — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.datasets

      +import csv
      +import os
      +import copy
      +import numpy as np
      +import GPy
      +import scipy.io
      +import cPickle as pickle
      +import zipfile
      +import tarfile
      +import datetime
      +import json
      +import re
      +
      +from config import *
      +
      +ipython_available=True
      +try:
      +    import IPython
      +except ImportError:
      +    ipython_available=False
      +
      +
      +import sys, urllib2
      +
      +
      [docs]def reporthook(a,b,c): + # ',' at the end of the line is important! + #print "% 3.1f%% of %d bytes\r" % (min(100, float(a * b) / c * 100), c), + #you can also use sys.stdout.write + sys.stdout.write("\r% 3.1f%% of %d bytes" % (min(100, float(a * b) / c * 100), c)) + sys.stdout.flush() + +# Global variables
      +data_path = os.path.expandvars(config.get('datasets', 'dir')) +#data_path = os.path.join(os.path.dirname(__file__), 'datasets') +default_seed = 10000 +overide_manual_authorize=False +neil_url = 'http://staffwww.dcs.shef.ac.uk/people/N.Lawrence/dataset_mirror/' + +# Read data resources from json file. +# Don't do this when ReadTheDocs is scanning as it breaks things +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' #Checks if RTD is scanning + +if not (on_rtd): + path = os.path.join(os.path.dirname(__file__), 'data_resources.json') + json_data=open(path).read() + data_resources = json.loads(json_data) + +if not (on_rtd): + path = os.path.join(os.path.dirname(__file__), 'football_teams.json') + json_data=open(path).read() + football_dict = json.loads(json_data) + + + +
      [docs]def prompt_user(prompt): + """Ask user for agreeing to data set licenses.""" + # raw_input returns the empty string for "enter" + yes = set(['yes', 'y']) + no = set(['no','n']) + + try: + print(prompt) + choice = raw_input().lower() + # would like to test for exception here, but not sure if we can do that without importing IPython + except: + print('Stdin is not implemented.') + print('You need to set') + print('overide_manual_authorize=True') + print('to proceed with the download. Please set that variable and continue.') + raise + + + if choice in yes: + return True + elif choice in no: + return False + else: + print("Your response was a " + choice) + print("Please respond with 'yes', 'y' or 'no', 'n'") + #return prompt_user() + +
      +
      [docs]def data_available(dataset_name=None): + """Check if the data set is available on the local machine already.""" + from itertools import izip_longest + dr = data_resources[dataset_name] + zip_urls = (dr['files'], ) + if dr.has_key('save_names'): zip_urls += (dr['save_names'], ) + else: zip_urls += ([],) + + for file_list, save_list in izip_longest(*zip_urls, fillvalue=[]): + for f, s in izip_longest(file_list, save_list, fillvalue=None): + if s is not None: f=s # If there is a save_name given, use that one + if not os.path.exists(os.path.join(data_path, dataset_name, f)): + return False + return True +
      +
      [docs]def download_url(url, store_directory, save_name=None, messages=True, suffix=''): + """Download a file from a url and save it to disk.""" + i = url.rfind('/') + file = url[i+1:] + print file + dir_name = os.path.join(data_path, store_directory) + + if save_name is None: save_name = os.path.join(dir_name, file) + else: save_name = os.path.join(dir_name, save_name) + + if suffix is None: suffix='' + + print "Downloading ", url, "->", save_name + if not os.path.exists(dir_name): + os.makedirs(dir_name) + try: + response = urllib2.urlopen(url+suffix) + except urllib2.URLError, e: + if not hasattr(e, "code"): + raise + response = e + if response.code > 399 and response.code<500: + raise ValueError('Tried url ' + url + suffix + ' and received client error ' + str(response.code)) + elif response.code > 499: + raise ValueError('Tried url ' + url + suffix + ' and received server error ' + str(response.code)) + with open(save_name, 'wb') as f: + meta = response.info() + content_length_str = meta.getheaders("Content-Length") + if content_length_str: + file_size = int(content_length_str[0]) + else: + file_size = None + status = "" + file_size_dl = 0 + block_sz = 8192 + line_length=30 + while True: + buff = response.read(block_sz) + if not buff: + break + file_size_dl += len(buff) + f.write(buff) + sys.stdout.write(" "*(len(status)) + "\r") + if file_size: + status = r"[{perc: <{ll}}] {dl:7.3f}/{full:.3f}MB".format(dl=file_size_dl/(1048576.), + full=file_size/(1048576.), ll=line_length, + perc="="*int(line_length*float(file_size_dl)/file_size)) + else: + status = r"[{perc: <{ll}}] {dl:7.3f}MB".format(dl=file_size_dl/(1048576.), + ll=line_length, + perc="."*int(line_length*float(file_size_dl/(10*1048576.)))) + + sys.stdout.write(status) + sys.stdout.flush() + sys.stdout.write(" "*(len(status)) + "\r") + print status + # if we wanted to get more sophisticated maybe we should check the response code here again even for successes. + #with open(save_name, 'wb') as f: + # f.write(response.read()) + + #urllib.urlretrieve(url+suffix, save_name, reporthook) +
      +
      [docs]def authorize_download(dataset_name=None): + """Check with the user that the are happy with terms and conditions for the data set.""" + print('Acquiring resource: ' + dataset_name) + # TODO, check resource is in dictionary! + print('') + dr = data_resources[dataset_name] + print('Details of data: ') + print(dr['details']) + print('') + if dr['citation']: + print('Please cite:') + print(dr['citation']) + print('') + if dr['size']: + print('After downloading the data will take up ' + str(dr['size']) + ' bytes of space.') + print('') + print('Data will be stored in ' + os.path.join(data_path, dataset_name) + '.') + print('') + if overide_manual_authorize: + if dr['license']: + print('You have agreed to the following license:') + print(dr['license']) + print('') + return True + else: + if dr['license']: + print('You must also agree to the following license:') + print(dr['license']) + print('') + return prompt_user('Do you wish to proceed with the download? [yes/no]') +
      +
      [docs]def download_data(dataset_name=None): + """Check with the user that the are happy with terms and conditions for the data set, then download it.""" + import itertools + + dr = data_resources[dataset_name] + if not authorize_download(dataset_name): + raise Exception("Permission to download data set denied.") + + zip_urls = (dr['urls'], dr['files']) + + if dr.has_key('save_names'): zip_urls += (dr['save_names'], ) + else: zip_urls += ([],) + + if dr.has_key('suffices'): zip_urls += (dr['suffices'], ) + else: zip_urls += ([],) + + for url, files, save_names, suffices in itertools.izip_longest(*zip_urls, fillvalue=[]): + for f, save_name, suffix in itertools.izip_longest(files, save_names, suffices, fillvalue=None): + download_url(os.path.join(url,f), dataset_name, save_name, suffix=suffix) + + return True +
      +
      [docs]def data_details_return(data, data_set): + """Update the data component of the data dictionary with details drawn from the data_resources.""" + data.update(data_resources[data_set]) + return data + +
      +
      [docs]def cmu_urls_files(subj_motions, messages = True): + ''' + Find which resources are missing on the local disk for the requested CMU motion capture motions. + ''' + dr = data_resources['cmu_mocap_full'] + cmu_url = dr['urls'][0] + + subjects_num = subj_motions[0] + motions_num = subj_motions[1] + + resource = {'urls' : [], 'files' : []} + # Convert numbers to strings + subjects = [] + motions = [list() for _ in range(len(subjects_num))] + for i in range(len(subjects_num)): + curSubj = str(int(subjects_num[i])) + if int(subjects_num[i]) < 10: + curSubj = '0' + curSubj + subjects.append(curSubj) + for j in range(len(motions_num[i])): + curMot = str(int(motions_num[i][j])) + if int(motions_num[i][j]) < 10: + curMot = '0' + curMot + motions[i].append(curMot) + + all_skels = [] + + assert len(subjects) == len(motions) + + all_motions = [] + + for i in range(len(subjects)): + skel_dir = os.path.join(data_path, 'cmu_mocap') + cur_skel_file = os.path.join(skel_dir, subjects[i] + '.asf') + + url_required = False + file_download = [] + if not os.path.exists(cur_skel_file): + # Current skel file doesn't exist. + if not os.path.isdir(skel_dir): + os.makedirs(skel_dir) + # Add skel file to list. + url_required = True + file_download.append(subjects[i] + '.asf') + for j in range(len(motions[i])): + file_name = subjects[i] + '_' + motions[i][j] + '.amc' + cur_motion_file = os.path.join(skel_dir, file_name) + if not os.path.exists(cur_motion_file): + url_required = True + file_download.append(subjects[i] + '_' + motions[i][j] + '.amc') + if url_required: + resource['urls'].append(cmu_url + '/' + subjects[i] + '/') + resource['files'].append(file_download) + return resource +
      +try: + import gpxpy + import gpxpy.gpx + gpxpy_available = True + +except ImportError: + gpxpy_available = False + +if gpxpy_available: + def epomeo_gpx(data_set='epomeo_gpx', sample_every=4): + if not data_available(data_set): + download_data(data_set) + files = ['endomondo_1', 'endomondo_2', 'garmin_watch_via_endomondo','viewranger_phone', 'viewranger_tablet'] + + X = [] + for file in files: + gpx_file = open(os.path.join(data_path, 'epomeo_gpx', file + '.gpx'), 'r') + + gpx = gpxpy.parse(gpx_file) + segment = gpx.tracks[0].segments[0] + points = [point for track in gpx.tracks for segment in track.segments for point in segment.points] + data = [[(point.time-datetime.datetime(2013,8,21)).total_seconds(), point.latitude, point.longitude, point.elevation] for point in points] + X.append(np.asarray(data)[::sample_every, :]) + gpx_file.close() + return data_details_return({'X' : X, 'info' : 'Data is an array containing time in seconds, latitude, longitude and elevation in that order.'}, data_set) + +#del gpxpy_available + + + +# Some general utilities. +
      [docs]def sample_class(f): + p = 1. / (1. + np.exp(-f)) + c = np.random.binomial(1, p) + c = np.where(c, 1, -1) + return c +
      +
      [docs]def boston_housing(data_set='boston_housing'): + if not data_available(data_set): + download_data(data_set) + all_data = np.genfromtxt(os.path.join(data_path, data_set, 'housing.data')) + X = all_data[:, 0:13] + Y = all_data[:, 13:14] + return data_details_return({'X' : X, 'Y': Y}, data_set) +
      +
      [docs]def brendan_faces(data_set='brendan_faces'): + if not data_available(data_set): + download_data(data_set) + mat_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'frey_rawface.mat')) + Y = mat_data['ff'].T + return data_details_return({'Y': Y}, data_set) +
      +
      [docs]def della_gatta_TRP63_gene_expression(data_set='della_gatta', gene_number=None): + if not data_available(data_set): + download_data(data_set) + mat_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'DellaGattadata.mat')) + X = np.double(mat_data['timepoints']) + if gene_number == None: + Y = mat_data['exprs_tp53_RMA'] + else: + Y = mat_data['exprs_tp53_RMA'][:, gene_number] + if len(Y.shape) == 1: + Y = Y[:, None] + return data_details_return({'X': X, 'Y': Y, 'gene_number' : gene_number}, data_set) + + +
      +
      [docs]def football_data(season='1314', data_set='football_data'): + """Football data from English games since 1993. This downloads data from football-data.co.uk for the given season. """ + def league2num(string): + league_dict = {'E0':0, 'E1':1, 'E2': 2, 'E3': 3, 'EC':4} + return league_dict[string] + + def football2num(string): + if football_dict.has_key(string): + return football_dict[string] + else: + football_dict[string] = len(football_dict)+1 + return len(football_dict)+1 + + data_set_season = data_set + '_' + season + data_resources[data_set_season] = copy.deepcopy(data_resources[data_set]) + data_resources[data_set_season]['urls'][0]+=season + '/' + start_year = int(season[0:2]) + end_year = int(season[2:4]) + files = ['E0.csv', 'E1.csv', 'E2.csv', 'E3.csv'] + if start_year>4 and start_year < 93: + files += ['EC.csv'] + data_resources[data_set_season]['files'] = [files] + if not data_available(data_set_season): + download_data(data_set_season) + import pylab as pb + for file in reversed(files): + filename = os.path.join(data_path, data_set_season, file) + # rewrite files removing blank rows. + writename = os.path.join(data_path, data_set_season, 'temp.csv') + input = open(filename, 'rb') + output = open(writename, 'wb') + writer = csv.writer(output) + for row in csv.reader(input): + if any(field.strip() for field in row): + writer.writerow(row) + input.close() + output.close() + table = np.loadtxt(writename,skiprows=1, usecols=(0, 1, 2, 3, 4, 5), converters = {0: league2num, 1: pb.datestr2num, 2:football2num, 3:football2num}, delimiter=',') + X = table[:, :4] + Y = table[:, 4:] + return data_details_return({'X': X, 'Y': Y}, data_set) +
      +
      [docs]def sod1_mouse(data_set='sod1_mouse'): + if not data_available(data_set): + download_data(data_set) + from pandas import read_csv + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'sod1_C57_129_exprs.csv') + Y = read_csv(filename, header=0, index_col=0) + num_repeats=4 + num_time=4 + num_cond=4 + X = 1 + return data_details_return({'X': X, 'Y': Y}, data_set) +
      +
      [docs]def spellman_yeast(data_set='spellman_yeast'): + if not data_available(data_set): + download_data(data_set) + from pandas import read_csv + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'combined.txt') + Y = read_csv(filename, header=0, index_col=0, sep='\t') + return data_details_return({'Y': Y}, data_set) +
      +
      [docs]def spellman_yeast_cdc15(data_set='spellman_yeast'): + if not data_available(data_set): + download_data(data_set) + from pandas import read_csv + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'combined.txt') + Y = read_csv(filename, header=0, index_col=0, sep='\t') + t = np.asarray([10, 30, 50, 70, 80, 90, 100, 110, 120, 130, 140, 150, 170, 180, 190, 200, 210, 220, 230, 240, 250, 270, 290]) + times = ['cdc15_'+str(time) for time in t] + Y = Y[times].T + t = t[:, None] + return data_details_return({'Y' : Y, 't': t, 'info': 'Time series of synchronized yeast cells from the CDC-15 experiment of Spellman et al (1998).'}, data_set) +
      +
      [docs]def lee_yeast_ChIP(data_set='lee_yeast_ChIP'): + if not data_available(data_set): + download_data(data_set) + from pandas import read_csv + import zipfile + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'binding_by_gene.tsv') + S = read_csv(filename, header=1, index_col=0, sep='\t') + transcription_factors = [col for col in S.columns if col[:7] != 'Unnamed'] + annotations = S[['Unnamed: 1', 'Unnamed: 2', 'Unnamed: 3']] + S = S[transcription_factors] + return data_details_return({'annotations' : annotations, 'Y' : S, 'transcription_factors': transcription_factors}, data_set) + + +
      +
      [docs]def fruitfly_tomancak(data_set='fruitfly_tomancak', gene_number=None): + if not data_available(data_set): + download_data(data_set) + from pandas import read_csv + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'tomancak_exprs.csv') + Y = read_csv(filename, header=0, index_col=0).T + num_repeats = 3 + num_time = 12 + xt = np.linspace(0, num_time-1, num_time) + xr = np.linspace(0, num_repeats-1, num_repeats) + xtime, xrepeat = np.meshgrid(xt, xr) + X = np.vstack((xtime.flatten(), xrepeat.flatten())).T + return data_details_return({'X': X, 'Y': Y, 'gene_number' : gene_number}, data_set) +
      +
      [docs]def drosophila_protein(data_set='drosophila_protein'): + if not data_available(data_set): + download_data(data_set) + from pandas import read_csv + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'becker_et_al.csv') + Y = read_csv(filename, header=0) + return data_details_return({'Y': Y}, data_set) +
      +
      [docs]def drosophila_knirps(data_set='drosophila_protein'): + if not data_available(data_set): + download_data(data_set) + from pandas import read_csv + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'becker_et_al.csv') + # in the csv file we have facts_kni and ext_kni. We treat facts_kni as protein and ext_kni as mRNA + df = read_csv(filename, header=0) + t = df['t'][:,None] + x = df['x'][:,None] + + g = df['expression1'][:,None] + p = df['expression2'][:,None] + + leng = x.shape[0] + + T = np.vstack([t,t]) + S = np.vstack([x,x]) + inx = np.zeros(leng*2)[:,None] + + inx[leng*2/2:leng*2]=1 + X = np.hstack([T,S,inx]) + Y = np.vstack([g,p]) + return data_details_return({'Y': Y, 'X': X}, data_set) + +# This will be for downloading google trends data.
      + +
      [docs]def oil(data_set='three_phase_oil_flow'): + """The three phase oil data from Bishop and James (1993).""" + if not data_available(data_set): + download_data(data_set) + oil_train_file = os.path.join(data_path, data_set, 'DataTrn.txt') + oil_trainlbls_file = os.path.join(data_path, data_set, 'DataTrnLbls.txt') + oil_test_file = os.path.join(data_path, data_set, 'DataTst.txt') + oil_testlbls_file = os.path.join(data_path, data_set, 'DataTstLbls.txt') + oil_valid_file = os.path.join(data_path, data_set, 'DataVdn.txt') + oil_validlbls_file = os.path.join(data_path, data_set, 'DataVdnLbls.txt') + fid = open(oil_train_file) + X = np.fromfile(fid, sep='\t').reshape((-1, 12)) + fid.close() + fid = open(oil_test_file) + Xtest = np.fromfile(fid, sep='\t').reshape((-1, 12)) + fid.close() + fid = open(oil_valid_file) + Xvalid = np.fromfile(fid, sep='\t').reshape((-1, 12)) + fid.close() + fid = open(oil_trainlbls_file) + Y = np.fromfile(fid, sep='\t').reshape((-1, 3)) * 2. - 1. + fid.close() + fid = open(oil_testlbls_file) + Ytest = np.fromfile(fid, sep='\t').reshape((-1, 3)) * 2. - 1. + fid.close() + fid = open(oil_validlbls_file) + Yvalid = np.fromfile(fid, sep='\t').reshape((-1, 3)) * 2. - 1. + fid.close() + return data_details_return({'X': X, 'Y': Y, 'Xtest': Xtest, 'Ytest': Ytest, 'Xtest' : Xtest, 'Xvalid': Xvalid, 'Yvalid': Yvalid}, data_set) + #else: + # throw an error +
      +
      [docs]def oil_100(seed=default_seed, data_set = 'three_phase_oil_flow'): + np.random.seed(seed=seed) + data = oil() + indices = np.random.permutation(1000) + indices = indices[0:100] + X = data['X'][indices, :] + Y = data['Y'][indices, :] + return data_details_return({'X': X, 'Y': Y, 'info': "Subsample of the full oil data extracting 100 values randomly without replacement, here seed was " + str(seed)}, data_set) +
      +
      [docs]def pumadyn(seed=default_seed, data_set='pumadyn-32nm'): + if not data_available(data_set): + download_data(data_set) + path = os.path.join(data_path, data_set) + tar = tarfile.open(os.path.join(path, 'pumadyn-32nm.tar.gz')) + print('Extracting file.') + tar.extractall(path=path) + tar.close() + # Data is variance 1, no need to normalize. + data = np.loadtxt(os.path.join(data_path, data_set, 'pumadyn-32nm', 'Dataset.data.gz')) + indices = np.random.permutation(data.shape[0]) + indicesTrain = indices[0:7168] + indicesTest = indices[7168:-1] + indicesTrain.sort(axis=0) + indicesTest.sort(axis=0) + X = data[indicesTrain, 0:-2] + Y = data[indicesTrain, -1][:, None] + Xtest = data[indicesTest, 0:-2] + Ytest = data[indicesTest, -1][:, None] + return data_details_return({'X': X, 'Y': Y, 'Xtest': Xtest, 'Ytest': Ytest, 'seed': seed}, data_set) +
      +
      [docs]def robot_wireless(data_set='robot_wireless'): + # WiFi access point strengths on a tour around UW Paul Allen building. + if not data_available(data_set): + download_data(data_set) + file_name = os.path.join(data_path, data_set, 'uw-floor.txt') + all_time = np.genfromtxt(file_name, usecols=(0)) + macaddress = np.genfromtxt(file_name, usecols=(1), dtype='string') + x = np.genfromtxt(file_name, usecols=(2)) + y = np.genfromtxt(file_name, usecols=(3)) + strength = np.genfromtxt(file_name, usecols=(4)) + addresses = np.unique(macaddress) + times = np.unique(all_time) + addresses.sort() + times.sort() + allY = np.zeros((len(times), len(addresses))) + allX = np.zeros((len(times), 2)) + allY[:]=-92. + strengths={} + for address, j in zip(addresses, range(len(addresses))): + ind = np.nonzero(address==macaddress) + temp_strengths=strength[ind] + temp_x=x[ind] + temp_y=y[ind] + temp_times = all_time[ind] + for time in temp_times: + vals = time==temp_times + if any(vals): + ind2 = np.nonzero(vals) + i = np.nonzero(time==times) + allY[i, j] = temp_strengths[ind2] + allX[i, 0] = temp_x[ind2] + allX[i, 1] = temp_y[ind2] + allY = (allY + 85.)/15. + + X = allX[0:215, :] + Y = allY[0:215, :] + + Xtest = allX[215:, :] + Ytest = allY[215:, :] + return data_details_return({'X': X, 'Y': Y, 'Xtest': Xtest, 'Ytest': Ytest, 'addresses' : addresses, 'times' : times}, data_set) +
      +
      [docs]def silhouette(data_set='ankur_pose_data'): + # Ankur Agarwal and Bill Trigg's silhoutte data. + if not data_available(data_set): + download_data(data_set) + mat_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'ankurDataPoseSilhouette.mat')) + inMean = np.mean(mat_data['Y']) + inScales = np.sqrt(np.var(mat_data['Y'])) + X = mat_data['Y'] - inMean + X = X / inScales + Xtest = mat_data['Y_test'] - inMean + Xtest = Xtest / inScales + Y = mat_data['Z'] + Ytest = mat_data['Z_test'] + return data_details_return({'X': X, 'Y': Y, 'Xtest': Xtest, 'Ytest': Ytest}, data_set) +
      +
      [docs]def decampos_digits(data_set='decampos_characters', which_digits=[0,1,2,3,4,5,6,7,8,9]): + if not data_available(data_set): + download_data(data_set) + path = os.path.join(data_path, data_set) + digits = np.load(os.path.join(path, 'digits.npy')) + digits = digits[which_digits,:,:,:] + num_classes, num_samples, height, width = digits.shape + Y = digits.reshape((digits.shape[0]*digits.shape[1],digits.shape[2]*digits.shape[3])) + lbls = np.array([[l]*num_samples for l in which_digits]).reshape(Y.shape[0], 1) + str_lbls = np.array([[str(l)]*num_samples for l in which_digits]) + return data_details_return({'Y': Y, 'lbls': lbls, 'str_lbls' : str_lbls, 'info': 'Digits data set from the de Campos characters data'}, data_set) +
      +
      [docs]def ripley_synth(data_set='ripley_prnn_data'): + if not data_available(data_set): + download_data(data_set) + train = np.genfromtxt(os.path.join(data_path, data_set, 'synth.tr'), skip_header=1) + X = train[:, 0:2] + y = train[:, 2:3] + test = np.genfromtxt(os.path.join(data_path, data_set, 'synth.te'), skip_header=1) + Xtest = test[:, 0:2] + ytest = test[:, 2:3] + return data_details_return({'X': X, 'Y': y, 'Xtest': Xtest, 'Ytest': ytest, 'info': 'Synthetic data generated by Ripley for a two class classification problem.'}, data_set) +
      +
      [docs]def global_average_temperature(data_set='global_temperature', num_train=1000, refresh_data=False): + path = os.path.join(data_path, data_set) + if data_available(data_set) and not refresh_data: + print 'Using cached version of the data set, to use latest version set refresh_data to True' + else: + download_data(data_set) + data = np.loadtxt(os.path.join(data_path, data_set, 'GLBTS.long.data')) + print 'Most recent data observation from month ', data[-1, 1], ' in year ', data[-1, 0] + allX = data[data[:, 3]!=-99.99, 2:3] + allY = data[data[:, 3]!=-99.99, 3:4] + X = allX[:num_train, 0:1] + Xtest = allX[num_train:, 0:1] + Y = allY[:num_train, 0:1] + Ytest = allY[num_train:, 0:1] + return data_details_return({'X': X, 'Y': Y, 'Xtest': Xtest, 'Ytest': Ytest, 'info': "Mauna Loa data with " + str(num_train) + " values used as training points."}, data_set) +
      +
      [docs]def mauna_loa(data_set='mauna_loa', num_train=545, refresh_data=False): + path = os.path.join(data_path, data_set) + if data_available(data_set) and not refresh_data: + print 'Using cached version of the data set, to use latest version set refresh_data to True' + else: + download_data(data_set) + data = np.loadtxt(os.path.join(data_path, data_set, 'co2_mm_mlo.txt')) + print 'Most recent data observation from month ', data[-1, 1], ' in year ', data[-1, 0] + allX = data[data[:, 3]!=-99.99, 2:3] + allY = data[data[:, 3]!=-99.99, 3:4] + X = allX[:num_train, 0:1] + Xtest = allX[num_train:, 0:1] + Y = allY[:num_train, 0:1] + Ytest = allY[num_train:, 0:1] + return data_details_return({'X': X, 'Y': Y, 'Xtest': Xtest, 'Ytest': Ytest, 'info': "Mauna Loa data with " + str(num_train) + " values used as training points."}, data_set) + +
      +
      [docs]def boxjenkins_airline(data_set='boxjenkins_airline', num_train=96): + path = os.path.join(data_path, data_set) + if not data_available(data_set): + download_data(data_set) + data = np.loadtxt(os.path.join(data_path, data_set, 'boxjenkins_airline.csv'), delimiter=',') + Y = data[:num_train, 1:2] + X = data[:num_train, 0:1] + Xtest = data[num_train:, 0:1] + Ytest = data[num_train:, 1:2] + return data_details_return({'X': X, 'Y': Y, 'Xtest': Xtest, 'Ytest': Ytest, 'info': "Montly airline passenger data from Box & Jenkins 1976."}, data_set) + +
      +
      [docs]def osu_run1(data_set='osu_run1', sample_every=4): + path = os.path.join(data_path, data_set) + if not data_available(data_set): + download_data(data_set) + zip = zipfile.ZipFile(os.path.join(data_path, data_set, 'run1TXT.ZIP'), 'r') + for name in zip.namelist(): + zip.extract(name, path) + Y, connect = GPy.util.mocap.load_text_data('Aug210106', path) + Y = Y[0:-1:sample_every, :] + return data_details_return({'Y': Y, 'connect' : connect}, data_set) +
      +
      [docs]def swiss_roll_generated(num_samples=1000, sigma=0.0): + with open(os.path.join(os.path.dirname(__file__), 'datasets', 'swiss_roll.pickle')) as f: + data = pickle.load(f) + Na = data['Y'].shape[0] + perm = np.random.permutation(np.r_[:Na])[:num_samples] + Y = data['Y'][perm, :] + t = data['t'][perm] + c = data['colors'][perm, :] + so = np.argsort(t) + Y = Y[so, :] + t = t[so] + c = c[so, :] + return {'Y':Y, 't':t, 'colors':c} +
      +
      [docs]def hapmap3(data_set='hapmap3'): + """ + The HapMap phase three SNP dataset - 1184 samples out of 11 populations. + + SNP_matrix (A) encoding [see Paschou et all. 2007 (PCA-Correlated SNPs...)]: + Let (B1,B2) be the alphabetically sorted bases, which occur in the j-th SNP, then + + / 1, iff SNPij==(B1,B1) + Aij = | 0, iff SNPij==(B1,B2) + \ -1, iff SNPij==(B2,B2) + + The SNP data and the meta information (such as iid, sex and phenotype) are + stored in the dataframe datadf, index is the Individual ID, + with following columns for metainfo: + + * family_id -> Family ID + * paternal_id -> Paternal ID + * maternal_id -> Maternal ID + * sex -> Sex (1=male; 2=female; other=unknown) + * phenotype -> Phenotype (-9, or 0 for unknown) + * population -> Population string (e.g. 'ASW' - 'YRI') + * rest are SNP rs (ids) + + More information is given in infodf: + + * Chromosome: + - autosomal chromosemes -> 1-22 + - X X chromosome -> 23 + - Y Y chromosome -> 24 + - XY Pseudo-autosomal region of X -> 25 + - MT Mitochondrial -> 26 + * Relative Positon (to Chromosome) [base pairs] + """ + try: + from pandas import read_pickle, DataFrame + from sys import stdout + import bz2 + except ImportError as i: + raise i, "Need pandas for hapmap dataset, make sure to install pandas (http://pandas.pydata.org/) before loading the hapmap dataset" + + dir_path = os.path.join(data_path,'hapmap3') + hapmap_file_name = 'hapmap3_r2_b36_fwd.consensus.qc.poly' + unpacked_files = [os.path.join(dir_path, hapmap_file_name+ending) for ending in ['.ped', '.map']] + unpacked_files_exist = reduce(lambda a, b:a and b, map(os.path.exists, unpacked_files)) + + if not unpacked_files_exist and not data_available(data_set): + download_data(data_set) + + preprocessed_data_paths = [os.path.join(dir_path,hapmap_file_name + file_name) for file_name in \ + ['.snps.pickle', + '.info.pickle', + '.nan.pickle']] + + if not reduce(lambda a,b: a and b, map(os.path.exists, preprocessed_data_paths)): + if not overide_manual_authorize and not prompt_user("Preprocessing requires ~25GB " + "of memory and can take a (very) long time, continue? [Y/n]"): + print "Preprocessing required for further usage." + return + status = "Preprocessing data, please be patient..." + print status + def write_status(message, progress, status): + stdout.write(" "*len(status)); stdout.write("\r"); stdout.flush() + status = r"[{perc: <{ll}}] {message: <13s}".format(message=message, ll=20, + perc="="*int(20.*progress/100.)) + stdout.write(status); stdout.flush() + return status + if not unpacked_files_exist: + status=write_status('unpacking...', 0, '') + curr = 0 + for newfilepath in unpacked_files: + if not os.path.exists(newfilepath): + filepath = newfilepath + '.bz2' + file_size = os.path.getsize(filepath) + with open(newfilepath, 'wb') as new_file, open(filepath, 'rb') as f: + decomp = bz2.BZ2Decompressor() + file_processed = 0 + buffsize = 100 * 1024 + for data in iter(lambda : f.read(buffsize), b''): + new_file.write(decomp.decompress(data)) + file_processed += len(data) + status=write_status('unpacking...', curr+12.*file_processed/(file_size), status) + curr += 12 + status=write_status('unpacking...', curr, status) + os.remove(filepath) + status=write_status('reading .ped...', 25, status) + # Preprocess data: + snpstrnp = np.loadtxt(unpacked_files[0], dtype=str) + status=write_status('reading .map...', 33, status) + mapnp = np.loadtxt(unpacked_files[1], dtype=str) + status=write_status('reading relationships.txt...', 42, status) + # and metainfo: + infodf = DataFrame.from_csv(os.path.join(dir_path,'./relationships_w_pops_121708.txt'), header=0, sep='\t') + infodf.set_index('IID', inplace=1) + status=write_status('filtering nan...', 45, status) + snpstr = snpstrnp[:,6:].astype('S1').reshape(snpstrnp.shape[0], -1, 2) + inan = snpstr[:,:,0] == '0' + status=write_status('filtering reference alleles...', 55, status) + ref = np.array(map(lambda x: np.unique(x)[-2:], snpstr.swapaxes(0,1)[:,:,:])) + status=write_status('encoding snps...', 70, status) + # Encode the information for each gene in {-1,0,1}: + status=write_status('encoding snps...', 73, status) + snps = (snpstr==ref[None,:,:]) + status=write_status('encoding snps...', 76, status) + snps = (snps*np.array([1,-1])[None,None,:]) + status=write_status('encoding snps...', 78, status) + snps = snps.sum(-1) + status=write_status('encoding snps...', 81, status) + snps = snps.astype('i8') + status=write_status('marking nan values...', 88, status) + # put in nan values (masked as -128): + snps[inan] = -128 + status=write_status('setting up meta...', 94, status) + # get meta information: + metaheader = np.r_[['family_id', 'iid', 'paternal_id', 'maternal_id', 'sex', 'phenotype']] + metadf = DataFrame(columns=metaheader, data=snpstrnp[:,:6]) + metadf.set_index('iid', inplace=1) + metadf = metadf.join(infodf.population) + metadf.to_pickle(preprocessed_data_paths[1]) + # put everything together: + status=write_status('setting up snps...', 96, status) + snpsdf = DataFrame(index=metadf.index, data=snps, columns=mapnp[:,1]) + with open(preprocessed_data_paths[0], 'wb') as f: + pickle.dump(f, snpsdf, protocoll=-1) + status=write_status('setting up snps...', 98, status) + inandf = DataFrame(index=metadf.index, data=inan, columns=mapnp[:,1]) + inandf.to_pickle(preprocessed_data_paths[2]) + status=write_status('done :)', 100, status) + print '' + else: + print "loading snps..." + snpsdf = read_pickle(preprocessed_data_paths[0]) + print "loading metainfo..." + metadf = read_pickle(preprocessed_data_paths[1]) + print "loading nan entries..." + inandf = read_pickle(preprocessed_data_paths[2]) + snps = snpsdf.values + populations = metadf.population.values.astype('S3') + hapmap = dict(name=data_set, + description='The HapMap phase three SNP dataset - ' + '1184 samples out of 11 populations. inan is a ' + 'boolean array, containing wheather or not the ' + 'given entry is nan (nans are masked as ' + '-128 in snps).', + snpsdf=snpsdf, + metadf=metadf, + snps=snps, + inan=inandf.values, + inandf=inandf, + populations=populations) + return hapmap +
      +
      [docs]def singlecell(data_set='singlecell'): + if not data_available(data_set): + download_data(data_set) + + from pandas import read_csv + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'singlecell.csv') + Y = read_csv(filename, header=0, index_col=0) + genes = Y.columns + labels = Y.index + # data = np.loadtxt(os.path.join(dir_path, 'singlecell.csv'), delimiter=",", dtype=str) + return data_details_return({'Y': Y, 'info' : "qPCR singlecell experiment in Mouse, measuring 48 gene expressions in 1-64 cell states. The labels have been created as in Guo et al. [2010]", + 'genes': genes, 'labels':labels, + }, data_set) +
      +
      [docs]def singlecell_rna_seq_islam(dataset='singlecell_islam'): + if not data_available(dataset): + download_data(dataset) + + from pandas import read_csv, DataFrame, concat + dir_path = os.path.join(data_path, dataset) + filename = os.path.join(dir_path, 'GSE29087_L139_expression_tab.txt.gz') + data = read_csv(filename, sep='\t', skiprows=6, compression='gzip', header=None) + header1 = read_csv(filename, sep='\t', header=None, skiprows=5, nrows=1, compression='gzip') + header2 = read_csv(filename, sep='\t', header=None, skiprows=3, nrows=1, compression='gzip') + data.columns = np.concatenate((header1.ix[0, :], header2.ix[0, 7:])) + Y = data.set_index("Feature").ix[8:, 6:-4].T.astype(float) + + # read the info .soft + filename = os.path.join(dir_path, 'GSE29087_family.soft.gz') + info = read_csv(filename, sep='\t', skiprows=0, compression='gzip', header=None) + # split at ' = ' + info = DataFrame(info.ix[:,0].str.split(' = ').tolist()) + # only take samples: + info = info[info[0].str.contains("!Sample")] + info[0] = info[0].apply(lambda row: row[len("!Sample_"):]) + + groups = info.groupby(0).groups + # remove 'GGG' from barcodes + barcode = info[1][groups['barcode']].apply(lambda row: row[:-3]) + + title = info[1][groups['title']] + title.index = barcode + title.name = 'title' + geo_accession = info[1][groups['geo_accession']] + geo_accession.index = barcode + geo_accession.name = 'geo_accession' + case_id = info[1][groups['source_name_ch1']] + case_id.index = barcode + case_id.name = 'source_name_ch1' + + info = concat([title, geo_accession, case_id], axis=1) + labels = info.join(Y).source_name_ch1[:-4] + labels[labels=='Embryonic stem cell'] = "ES" + labels[labels=='Embryonic fibroblast'] = "MEF" + + return data_details_return({'Y': Y, + 'info': '92 single cells (48 mouse ES cells, 44 mouse embryonic fibroblasts and 4 negative controls) were analyzed by single-cell tagged reverse transcription (STRT)', + 'genes': Y.columns, + 'labels': labels, + 'datadf': data, + 'infodf': info}, dataset) +
      +
      [docs]def singlecell_rna_seq_deng(dataset='singlecell_deng'): + if not data_available(dataset): + download_data(dataset) + + from pandas import read_csv, isnull + dir_path = os.path.join(data_path, dataset) + + # read the info .soft + filename = os.path.join(dir_path, 'GSE45719_series_matrix.txt.gz') + info = read_csv(filename, sep='\t', skiprows=0, compression='gzip', header=None, nrows=29, index_col=0) + summary = info.loc['!Series_summary'][1] + design = info.loc['!Series_overall_design'] + + # only take samples: + sample_info = read_csv(filename, sep='\t', skiprows=30, compression='gzip', header=0, index_col=0).T + sample_info.columns = sample_info.columns.to_series().apply(lambda row: row[len("!Sample_"):]) + sample_info.columns.name = sample_info.columns.name[len("!Sample_"):] + sample_info = sample_info[['geo_accession', 'characteristics_ch1', 'description']] + sample_info = sample_info.iloc[:, np.r_[0:4, 5:sample_info.shape[1]]] + c = sample_info.columns.to_series() + c[1:4] = ['strain', 'cross', 'developmental_stage'] + sample_info.columns = c + + # get the labels right: + rep = re.compile('\(.*\)') + def filter_dev_stage(row): + if isnull(row): + row = "2-cell stage embryo" + if row.startswith("developmental stage: "): + row = row[len("developmental stage: "):] + if row == 'adult': + row += " liver" + row = row.replace(' stage ', ' ') + row = rep.sub(' ', row) + row = row.strip(' ') + return row + labels = sample_info.developmental_stage.apply(filter_dev_stage) + + # Extract the tar file + filename = os.path.join(dir_path, 'GSE45719_Raw.tar') + with tarfile.open(filename, 'r') as files: + print "Extracting Archive {}...".format(files.name) + data = None + gene_info = None + message = '' + members = files.getmembers() + overall = len(members) + for i, file_info in enumerate(members): + f = files.extractfile(file_info) + inner = read_csv(f, sep='\t', header=0, compression='gzip', index_col=0) + print ' '*(len(message)+1) + '\r', + message = "{: >7.2%}: Extracting: {}".format(float(i+1)/overall, file_info.name[:20]+"...txt.gz") + print message, + if data is None: + data = inner.RPKM.to_frame() + data.columns = [file_info.name[:-18]] + gene_info = inner.Refseq_IDs.to_frame() + gene_info.columns = [file_info.name[:-18]] + else: + data[file_info.name[:-18]] = inner.RPKM + gene_info[file_info.name[:-18]] = inner.Refseq_IDs + + # Strip GSM number off data index + rep = re.compile('GSM\d+_') + data.columns = data.columns.to_series().apply(lambda row: row[rep.match(row).end():]) + data = data.T + + # make sure the same index gets used + sample_info.index = data.index + + # get the labels from the description + #rep = re.compile('fibroblast|\d+-cell|embryo|liver|early blastocyst|mid blastocyst|late blastocyst|blastomere|zygote', re.IGNORECASE) + + sys.stdout.write(' '*len(message) + '\r') + sys.stdout.flush() + print + print "Read Archive {}".format(files.name) + + return data_details_return({'Y': data, + 'series_info': info, + 'sample_info': sample_info, + 'gene_info': gene_info, + 'summary': summary, + 'design': design, + 'genes': data.columns, + 'labels': labels, + }, dataset) + +
      +
      [docs]def swiss_roll_1000(): + return swiss_roll(num_samples=1000) +
      +
      [docs]def swiss_roll(num_samples=3000, data_set='swiss_roll'): + if not data_available(data_set): + download_data(data_set) + mat_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'swiss_roll_data.mat')) + Y = mat_data['X_data'][:, 0:num_samples].transpose() + return data_details_return({'Y': Y, 'X': mat_data['X_data'], 'info': "The first " + str(num_samples) + " points from the swiss roll data of Tennenbaum, de Silva and Langford (2001)."}, data_set) +
      +
      [docs]def isomap_faces(num_samples=698, data_set='isomap_face_data'): + if not data_available(data_set): + download_data(data_set) + mat_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'face_data.mat')) + Y = mat_data['images'][:, 0:num_samples].transpose() + return data_details_return({'Y': Y, 'poses' : mat_data['poses'], 'lights': mat_data['lights'], 'info': "The first " + str(num_samples) + " points from the face data of Tennenbaum, de Silva and Langford (2001)."}, data_set) +
      +
      [docs]def simulation_BGPLVM(): + mat_data = scipy.io.loadmat(os.path.join(data_path, 'BGPLVMSimulation.mat')) + Y = np.array(mat_data['Y'], dtype=float) + S = np.array(mat_data['initS'], dtype=float) + mu = np.array(mat_data['initMu'], dtype=float) + #return data_details_return({'S': S, 'Y': Y, 'mu': mu}, data_set) + return {'Y': Y, 'S': S, + 'mu' : mu, + 'info': "Simulated test dataset generated in MATLAB to compare BGPLVM between python and MATLAB"} +
      +
      [docs]def toy_rbf_1d(seed=default_seed, num_samples=500): + """ + Samples values of a function from an RBF covariance with very small noise for inputs uniformly distributed between -1 and 1. + + :param seed: seed to use for random sampling. + :type seed: int + :param num_samples: number of samples to sample in the function (default 500). + :type num_samples: int + + """ + np.random.seed(seed=seed) + num_in = 1 + X = np.random.uniform(low= -1.0, high=1.0, size=(num_samples, num_in)) + X.sort(axis=0) + rbf = GPy.kern.RBF(num_in, variance=1., lengthscale=np.array((0.25,))) + white = GPy.kern.White(num_in, variance=1e-2) + kernel = rbf + white + K = kernel.K(X) + y = np.reshape(np.random.multivariate_normal(np.zeros(num_samples), K), (num_samples, 1)) + return {'X':X, 'Y':y, 'info': "Sampled " + str(num_samples) + " values of a function from an RBF covariance with very small noise for inputs uniformly distributed between -1 and 1."} +
      +
      [docs]def toy_rbf_1d_50(seed=default_seed): + np.random.seed(seed=seed) + data = toy_rbf_1d() + indices = np.random.permutation(data['X'].shape[0]) + indices = indices[0:50] + indices.sort(axis=0) + X = data['X'][indices, :] + Y = data['Y'][indices, :] + return {'X': X, 'Y': Y, 'info': "Subsamples the toy_rbf_sample with 50 values randomly taken from the original sample.", 'seed' : seed} + +
      +
      [docs]def toy_linear_1d_classification(seed=default_seed): + np.random.seed(seed=seed) + x1 = np.random.normal(-3, 5, 20) + x2 = np.random.normal(3, 5, 20) + X = (np.r_[x1, x2])[:, None] + return {'X': X, 'Y': sample_class(2.*X), 'F': 2.*X, 'seed' : seed} +
      +
      [docs]def olivetti_glasses(data_set='olivetti_glasses', num_training=200, seed=default_seed): + path = os.path.join(data_path, data_set) + if not data_available(data_set): + download_data(data_set) + y = np.load(os.path.join(path, 'has_glasses.np')) + y = np.where(y=='y',1,0).reshape(-1,1) + faces = scipy.io.loadmat(os.path.join(path, 'olivettifaces.mat'))['faces'].T + np.random.seed(seed=seed) + index = np.random.permutation(faces.shape[0]) + X = faces[index[:num_training],:] + Xtest = faces[index[num_training:],:] + Y = y[index[:num_training],:] + Ytest = y[index[num_training:]] + return data_details_return({'X': X, 'Y': Y, 'Xtest': Xtest, 'Ytest': Ytest, 'seed' : seed, 'info': "ORL Faces with labels identifiying who is wearing glasses and who isn't. Data is randomly partitioned according to given seed. Presence or absence of glasses was labelled by James Hensman."}, 'olivetti_faces') +
      +
      [docs]def olivetti_faces(data_set='olivetti_faces'): + path = os.path.join(data_path, data_set) + if not data_available(data_set): + download_data(data_set) + zip = zipfile.ZipFile(os.path.join(path, 'att_faces.zip'), 'r') + for name in zip.namelist(): + zip.extract(name, path) + Y = [] + lbls = [] + for subject in range(40): + for image in range(10): + image_path = os.path.join(path, 'orl_faces', 's'+str(subject+1), str(image+1) + '.pgm') + from GPy.util import netpbmfile + Y.append(netpbmfile.imread(image_path).flatten()) + lbls.append(subject) + Y = np.asarray(Y) + lbls = np.asarray(lbls)[:, None] + return data_details_return({'Y': Y, 'lbls' : lbls, 'info': "ORL Faces processed to 64x64 images."}, data_set) +
      +
      [docs]def xw_pen(data_set='xw_pen'): + if not data_available(data_set): + download_data(data_set) + Y = np.loadtxt(os.path.join(data_path, data_set, 'xw_pen_15.csv'), delimiter=',') + X = np.arange(485)[:, None] + return data_details_return({'Y': Y, 'X': X, 'info': "Tilt data from a personalized digital assistant pen. Plot in original paper showed regression between time steps 175 and 275."}, data_set) + +
      +
      [docs]def download_rogers_girolami_data(data_set='rogers_girolami_data'): + if not data_available('rogers_girolami_data'): + download_data(data_set) + path = os.path.join(data_path, data_set) + tar_file = os.path.join(path, 'firstcoursemldata.tar.gz') + tar = tarfile.open(tar_file) + print('Extracting file.') + tar.extractall(path=path) + tar.close() +
      +
      [docs]def olympic_100m_men(data_set='rogers_girolami_data'): + download_rogers_girolami_data() + olympic_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'data', 'olympics.mat'))['male100'] + + X = olympic_data[:, 0][:, None] + Y = olympic_data[:, 1][:, None] + return data_details_return({'X': X, 'Y': Y, 'info': "Olympic sprint times for 100 m men from 1896 until 2008. Example is from Rogers and Girolami's First Course in Machine Learning."}, data_set) +
      +
      [docs]def olympic_100m_women(data_set='rogers_girolami_data'): + download_rogers_girolami_data() + olympic_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'data', 'olympics.mat'))['female100'] + + X = olympic_data[:, 0][:, None] + Y = olympic_data[:, 1][:, None] + return data_details_return({'X': X, 'Y': Y, 'info': "Olympic sprint times for 100 m women from 1896 until 2008. Example is from Rogers and Girolami's First Course in Machine Learning."}, data_set) +
      +
      [docs]def olympic_200m_women(data_set='rogers_girolami_data'): + download_rogers_girolami_data() + olympic_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'data', 'olympics.mat'))['female200'] + + X = olympic_data[:, 0][:, None] + Y = olympic_data[:, 1][:, None] + return data_details_return({'X': X, 'Y': Y, 'info': "Olympic 200 m winning times for women from 1896 until 2008. Data is from Rogers and Girolami's First Course in Machine Learning."}, data_set) +
      +
      [docs]def olympic_200m_men(data_set='rogers_girolami_data'): + download_rogers_girolami_data() + olympic_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'data', 'olympics.mat'))['male200'] + + X = olympic_data[:, 0][:, None] + Y = olympic_data[:, 1][:, None] + return data_details_return({'X': X, 'Y': Y, 'info': "Male 200 m winning times for women from 1896 until 2008. Data is from Rogers and Girolami's First Course in Machine Learning."}, data_set) +
      +
      [docs]def olympic_400m_women(data_set='rogers_girolami_data'): + download_rogers_girolami_data() + olympic_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'data', 'olympics.mat'))['female400'] + + X = olympic_data[:, 0][:, None] + Y = olympic_data[:, 1][:, None] + return data_details_return({'X': X, 'Y': Y, 'info': "Olympic 400 m winning times for women until 2008. Data is from Rogers and Girolami's First Course in Machine Learning."}, data_set) +
      +
      [docs]def olympic_400m_men(data_set='rogers_girolami_data'): + download_rogers_girolami_data() + olympic_data = scipy.io.loadmat(os.path.join(data_path, data_set, 'data', 'olympics.mat'))['male400'] + + X = olympic_data[:, 0][:, None] + Y = olympic_data[:, 1][:, None] + return data_details_return({'X': X, 'Y': Y, 'info': "Male 400 m winning times for women until 2008. Data is from Rogers and Girolami's First Course in Machine Learning."}, data_set) +
      +
      [docs]def olympic_marathon_men(data_set='olympic_marathon_men'): + if not data_available(data_set): + download_data(data_set) + olympics = np.genfromtxt(os.path.join(data_path, data_set, 'olympicMarathonTimes.csv'), delimiter=',') + X = olympics[:, 0:1] + Y = olympics[:, 1:2] + return data_details_return({'X': X, 'Y': Y}, data_set) +
      +
      [docs]def olympic_sprints(data_set='rogers_girolami_data'): + """All olympics sprint winning times for multiple output prediction.""" + X = np.zeros((0, 2)) + Y = np.zeros((0, 1)) + for i, dataset in enumerate([olympic_100m_men, + olympic_100m_women, + olympic_200m_men, + olympic_200m_women, + olympic_400m_men, + olympic_400m_women]): + data = dataset() + year = data['X'] + time = data['Y'] + X = np.vstack((X, np.hstack((year, np.ones_like(year)*i)))) + Y = np.vstack((Y, time)) + data['X'] = X + data['Y'] = Y + data['info'] = "Olympics sprint event winning for men and women to 2008. Data is from Rogers and Girolami's First Course in Machine Learning." + return data_details_return({ + 'X': X, + 'Y': Y, + 'info': "Olympics sprint event winning for men and women to 2008. Data is from Rogers and Girolami's First Course in Machine Learning.", + 'output_info': { + 0:'100m Men', + 1:'100m Women', + 2:'200m Men', + 3:'200m Women', + 4:'400m Men', + 5:'400m Women'} + }, data_set) + +# def movielens_small(partNo=1,seed=default_seed): +# np.random.seed(seed=seed) + +# fileName = os.path.join(data_path, 'movielens', 'small', 'u' + str(partNo) + '.base') +# fid = open(fileName) +# uTrain = np.fromfile(fid, sep='\t', dtype=np.int16).reshape((-1, 4)) +# fid.close() +# maxVals = np.amax(uTrain, axis=0) +# numUsers = maxVals[0] +# numFilms = maxVals[1] +# numRatings = uTrain.shape[0] + +# Y = scipy.sparse.lil_matrix((numFilms, numUsers), dtype=np.int8) +# for i in range(numUsers): +# ind = pb.mlab.find(uTrain[:, 0]==i+1) +# Y[uTrain[ind, 1]-1, i] = uTrain[ind, 2] + +# fileName = os.path.join(data_path, 'movielens', 'small', 'u' + str(partNo) + '.test') +# fid = open(fileName) +# uTest = np.fromfile(fid, sep='\t', dtype=np.int16).reshape((-1, 4)) +# fid.close() +# numTestRatings = uTest.shape[0] + +# Ytest = scipy.sparse.lil_matrix((numFilms, numUsers), dtype=np.int8) +# for i in range(numUsers): +# ind = pb.mlab.find(uTest[:, 0]==i+1) +# Ytest[uTest[ind, 1]-1, i] = uTest[ind, 2] + +# lbls = np.empty((1,1)) +# lblstest = np.empty((1,1)) +# return {'Y':Y, 'lbls':lbls, 'Ytest':Ytest, 'lblstest':lblstest} + +
      +
      [docs]def crescent_data(num_data=200, seed=default_seed): + """ +Data set formed from a mixture of four Gaussians. In each class two of the Gaussians are elongated at right angles to each other and offset to form an approximation to the crescent data that is popular in semi-supervised learning as a toy problem. + + :param num_data_part: number of data to be sampled (default is 200). + :type num_data: int + :param seed: random seed to be used for data generation. + :type seed: int + + """ + np.random.seed(seed=seed) + sqrt2 = np.sqrt(2) + # Rotation matrix + R = np.array([[sqrt2 / 2, -sqrt2 / 2], [sqrt2 / 2, sqrt2 / 2]]) + # Scaling matrices + scales = [] + scales.append(np.array([[3, 0], [0, 1]])) + scales.append(np.array([[3, 0], [0, 1]])) + scales.append([[1, 0], [0, 3]]) + scales.append([[1, 0], [0, 3]]) + means = [] + means.append(np.array([4, 4])) + means.append(np.array([0, 4])) + means.append(np.array([-4, -4])) + means.append(np.array([0, -4])) + + Xparts = [] + num_data_part = [] + num_data_total = 0 + for i in range(0, 4): + num_data_part.append(round(((i + 1) * num_data) / 4.)) + num_data_part[i] -= num_data_total + part = np.random.normal(size=(num_data_part[i], 2)) + part = np.dot(np.dot(part, scales[i]), R) + means[i] + Xparts.append(part) + num_data_total += num_data_part[i] + X = np.vstack((Xparts[0], Xparts[1], Xparts[2], Xparts[3])) + + Y = np.vstack((np.ones((num_data_part[0] + num_data_part[1], 1)), -np.ones((num_data_part[2] + num_data_part[3], 1)))) + return {'X':X, 'Y':Y, 'info': "Two separate classes of data formed approximately in the shape of two crescents."} +
      +
      [docs]def creep_data(data_set='creep_rupture'): + """Brun and Yoshida's metal creep rupture data.""" + if not data_available(data_set): + download_data(data_set) + path = os.path.join(data_path, data_set) + tar_file = os.path.join(path, 'creeprupt.tar') + tar = tarfile.open(tar_file) + print('Extracting file.') + tar.extractall(path=path) + tar.close() + all_data = np.loadtxt(os.path.join(data_path, data_set, 'taka')) + y = all_data[:, 1:2].copy() + features = [0] + features.extend(range(2, 31)) + X = all_data[:, features].copy() + return data_details_return({'X': X, 'y': y}, data_set) +
      +
      [docs]def cifar10_patches(data_set='cifar-10'): + """The Candian Institute for Advanced Research 10 image data set. Code for loading in this data is taken from this Boris Babenko's blog post, original code available here: http://bbabenko.tumblr.com/post/86756017649/learning-low-level-vision-feautres-in-10-lines-of-code""" + dir_path = os.path.join(data_path, data_set) + filename = os.path.join(dir_path, 'cifar-10-python.tar.gz') + if not data_available(data_set): + download_data(data_set) + import tarfile + # This code is from Boris Babenko's blog post. + # http://bbabenko.tumblr.com/post/86756017649/learning-low-level-vision-feautres-in-10-lines-of-code + tfile = tarfile.open(filename, 'r:gz') + tfile.extractall(dir_path) + + with open(os.path.join(dir_path, 'cifar-10-batches-py','data_batch_1'),'rb') as f: + data = pickle.load(f) + + images = data['data'].reshape((-1,3,32,32)).astype('float32')/255 + images = np.rollaxis(images, 1, 4) + patches = np.zeros((0,5,5,3)) + for x in range(0,32-5,5): + for y in range(0,32-5,5): + patches = np.concatenate((patches, images[:,x:x+5,y:y+5,:]), axis=0) + patches = patches.reshape((patches.shape[0],-1)) + return data_details_return({'Y': patches, "info" : "32x32 pixel patches extracted from the CIFAR-10 data by Boris Babenko to demonstrate k-means features."}, data_set) +
      +
      [docs]def cmu_mocap_49_balance(data_set='cmu_mocap'): + """Load CMU subject 49's one legged balancing motion that was used by Alvarez, Luengo and Lawrence at AISTATS 2009.""" + train_motions = ['18', '19'] + test_motions = ['20'] + data = cmu_mocap('49', train_motions, test_motions, sample_every=4, data_set=data_set) + data['info'] = "One legged balancing motions from CMU data base subject 49. As used in Alvarez, Luengo and Lawrence at AISTATS 2009. It consists of " + data['info'] + return data +
      +
      [docs]def cmu_mocap_35_walk_jog(data_set='cmu_mocap'): + """Load CMU subject 35's walking and jogging motions, the same data that was used by Taylor, Roweis and Hinton at NIPS 2007. but without their preprocessing. Also used by Lawrence at AISTATS 2007.""" + train_motions = ['01', '02', '03', '04', '05', '06', + '07', '08', '09', '10', '11', '12', + '13', '14', '15', '16', '17', '19', + '20', '21', '22', '23', '24', '25', + '26', '28', '30', '31', '32', '33', '34'] + test_motions = ['18', '29'] + data = cmu_mocap('35', train_motions, test_motions, sample_every=4, data_set=data_set) + data['info'] = "Walk and jog data from CMU data base subject 35. As used in Tayor, Roweis and Hinton at NIPS 2007, but without their pre-processing (i.e. as used by Lawrence at AISTATS 2007). It consists of " + data['info'] + return data +
      +
      [docs]def cmu_mocap(subject, train_motions, test_motions=[], sample_every=4, data_set='cmu_mocap'): + """Load a given subject's training and test motions from the CMU motion capture data.""" + # Load in subject skeleton. + subject_dir = os.path.join(data_path, data_set) + + # Make sure the data is downloaded. + all_motions = train_motions + test_motions + resource = cmu_urls_files(([subject], [all_motions])) + data_resources[data_set] = data_resources['cmu_mocap_full'].copy() + data_resources[data_set]['files'] = resource['files'] + data_resources[data_set]['urls'] = resource['urls'] + if resource['urls']: + download_data(data_set) + + skel = GPy.util.mocap.acclaim_skeleton(os.path.join(subject_dir, subject + '.asf')) + + # Set up labels for each sequence + exlbls = np.eye(len(train_motions)) + + # Load sequences + tot_length = 0 + temp_Y = [] + temp_lbls = [] + for i in range(len(train_motions)): + temp_chan = skel.load_channels(os.path.join(subject_dir, subject + '_' + train_motions[i] + '.amc')) + temp_Y.append(temp_chan[::sample_every, :]) + temp_lbls.append(np.tile(exlbls[i, :], (temp_Y[i].shape[0], 1))) + tot_length += temp_Y[i].shape[0] + + Y = np.zeros((tot_length, temp_Y[0].shape[1])) + lbls = np.zeros((tot_length, temp_lbls[0].shape[1])) + + end_ind = 0 + for i in range(len(temp_Y)): + start_ind = end_ind + end_ind += temp_Y[i].shape[0] + Y[start_ind:end_ind, :] = temp_Y[i] + lbls[start_ind:end_ind, :] = temp_lbls[i] + if len(test_motions) > 0: + temp_Ytest = [] + temp_lblstest = [] + + testexlbls = np.eye(len(test_motions)) + tot_test_length = 0 + for i in range(len(test_motions)): + temp_chan = skel.load_channels(os.path.join(subject_dir, subject + '_' + test_motions[i] + '.amc')) + temp_Ytest.append(temp_chan[::sample_every, :]) + temp_lblstest.append(np.tile(testexlbls[i, :], (temp_Ytest[i].shape[0], 1))) + tot_test_length += temp_Ytest[i].shape[0] + + # Load test data + Ytest = np.zeros((tot_test_length, temp_Ytest[0].shape[1])) + lblstest = np.zeros((tot_test_length, temp_lblstest[0].shape[1])) + + end_ind = 0 + for i in range(len(temp_Ytest)): + start_ind = end_ind + end_ind += temp_Ytest[i].shape[0] + Ytest[start_ind:end_ind, :] = temp_Ytest[i] + lblstest[start_ind:end_ind, :] = temp_lblstest[i] + else: + Ytest = None + lblstest = None + + info = 'Subject: ' + subject + '. Training motions: ' + for motion in train_motions: + info += motion + ', ' + info = info[:-2] + if len(test_motions) > 0: + info += '. Test motions: ' + for motion in test_motions: + info += motion + ', ' + info = info[:-2] + '.' + else: + info += '.' + if sample_every != 1: + info += ' Data is sub-sampled to every ' + str(sample_every) + ' frames.' + return data_details_return({'Y': Y, 'lbls' : lbls, 'Ytest': Ytest, 'lblstest' : lblstest, 'info': info, 'skel': skel}, data_set) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/debug.html b/doc/_build/html/_modules/GPy/util/debug.html new file mode 100644 index 00000000..8c5bc593 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/debug.html @@ -0,0 +1,129 @@ + + + + + + + + GPy.util.debug — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.debug

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +"""
      +The module for some general debug tools
      +"""
      +
      +import numpy as np
      +
      +
      [docs]def checkFinite(arr, name=None): + if name is None: + name = 'Array with ID['+str(id(arr))+']' + + if np.any(np.logical_not(np.isfinite(arr))): + idx = np.where(np.logical_not(np.isfinite(arr)))[0] + print name+' at indices '+str(idx)+' have not finite values: '+str(arr[idx])+'!' + return False + return True +
      +
      [docs]def checkFullRank(m, tol=1e-10, name=None, force_check=False): + if name is None: + name = 'Matrix with ID['+str(id(m))+']' + assert len(m.shape)==2 and m.shape[0]==m.shape[1], 'The input of checkFullRank has to be a square matrix!' + + if not force_check and m.shape[0]>=10000: + print 'The size of '+name+'is too big to check (>=10000)!' + return True + + s = np.real(np.linalg.eigvals(m)) + + if s.min()/s.max()<tol: + print name+' is close to singlar!' + print 'The eigen values of '+name+' is '+str(s) + return False + return True
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/decorators.html b/doc/_build/html/_modules/GPy/util/decorators.html new file mode 100644 index 00000000..8dfb80f3 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/decorators.html @@ -0,0 +1,112 @@ + + + + + + + + GPy.util.decorators — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.decorators

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import numpy as np
      +from functools import wraps
      +
      +
      [docs]def silence_errors(f): + """ + This wraps a function and it silences numpy errors that + happen during the execution. After the function has exited, it restores + the previous state of the warnings. + """ + @wraps(f) + def wrapper(*args, **kwds): + status = np.seterr(all='ignore') + result = f(*args, **kwds) + np.seterr(**status) + return result + return wrapper
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/diag.html b/doc/_build/html/_modules/GPy/util/diag.html new file mode 100644 index 00000000..78aa335c --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/diag.html @@ -0,0 +1,209 @@ + + + + + + + + GPy.util.diag — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.diag

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +
      +
      [docs]def view(A, offset=0): + """ + Get a view on the diagonal elements of a 2D array. + + This is actually a view (!) on the diagonal of the array, so you can + in-place adjust the view. + + :param :class:`ndarray` A: 2 dimensional numpy array + :param int offset: view offset to give back (negative entries allowed) + :rtype: :class:`ndarray` view of diag(A) + + >>> import numpy as np + >>> X = np.arange(9).reshape(3,3) + >>> view(X) + array([0, 4, 8]) + >>> d = view(X) + >>> d += 2 + >>> view(X) + array([ 2, 6, 10]) + >>> view(X, offset=-1) + array([3, 7]) + >>> subtract(X, 3, offset=-1) + array([[ 2, 1, 2], + [ 0, 6, 5], + [ 6, 4, 10]]) + """ + from numpy.lib.stride_tricks import as_strided + assert A.ndim == 2, "only implemented for 2 dimensions" + assert A.shape[0] == A.shape[1], "attempting to get the view of non-square matrix?!" + if offset > 0: + return as_strided(A[0, offset:], shape=(A.shape[0] - offset, ), strides=((A.shape[0]+1)*A.itemsize, )) + elif offset < 0: + return as_strided(A[-offset:, 0], shape=(A.shape[0] + offset, ), strides=((A.shape[0]+1)*A.itemsize, )) + else: + return as_strided(A, shape=(A.shape[0], ), strides=((A.shape[0]+1)*A.itemsize, )) +
      +
      [docs]def offdiag_view(A, offset=0): + from numpy.lib.stride_tricks import as_strided + assert A.ndim == 2, "only implemented for 2 dimensions" + Af = as_strided(A, shape=(A.size,), strides=(A.itemsize,)) + return as_strided(Af[(1+offset):], shape=(A.shape[0]-1, A.shape[1]), strides=(A.strides[0] + A.itemsize, A.strides[1])) +
      +def _diag_ufunc(A,b,offset,func): + dA = view(A, offset); func(dA,b,dA) + return A + +
      [docs]def times(A, b, offset=0): + """ + Times the view of A with b in place (!). + Returns modified A + Broadcasting is allowed, thus b can be scalar. + + if offset is not zero, make sure b is of right shape! + + :param ndarray A: 2 dimensional array + :param ndarray-like b: either one dimensional or scalar + :param int offset: same as in view. + :rtype: view of A, which is adjusted inplace + """ + return _diag_ufunc(A, b, offset, np.multiply)
      +multiply = times + +
      [docs]def divide(A, b, offset=0): + """ + Divide the view of A by b in place (!). + Returns modified A + Broadcasting is allowed, thus b can be scalar. + + if offset is not zero, make sure b is of right shape! + + :param ndarray A: 2 dimensional array + :param ndarray-like b: either one dimensional or scalar + :param int offset: same as in view. + :rtype: view of A, which is adjusted inplace + """ + return _diag_ufunc(A, b, offset, np.divide) +
      +
      [docs]def add(A, b, offset=0): + """ + Add b to the view of A in place (!). + Returns modified A. + Broadcasting is allowed, thus b can be scalar. + + if offset is not zero, make sure b is of right shape! + + :param ndarray A: 2 dimensional array + :param ndarray-like b: either one dimensional or scalar + :param int offset: same as in view. + :rtype: view of A, which is adjusted inplace + """ + return _diag_ufunc(A, b, offset, np.add) +
      +
      [docs]def subtract(A, b, offset=0): + """ + Subtract b from the view of A in place (!). + Returns modified A. + Broadcasting is allowed, thus b can be scalar. + + if offset is not zero, make sure b is of right shape! + + :param ndarray A: 2 dimensional array + :param ndarray-like b: either one dimensional or scalar + :param int offset: same as in view. + :rtype: view of A, which is adjusted inplace + """ + return _diag_ufunc(A, b, offset, np.subtract) +
      +if __name__ == '__main__': + import doctest + doctest.testmod() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/erfcx.html b/doc/_build/html/_modules/GPy/util/erfcx.html new file mode 100644 index 00000000..61793218 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/erfcx.html @@ -0,0 +1,156 @@ + + + + + + + + GPy.util.erfcx — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.erfcx

      +## Copyright (C) 2010 Soren Hauberg
      +##
      +## Copyright James Hensman 2011
      +## 
      +## This program is free software; you can redistribute it and/or modify it
      +## under the terms of the GNU General Public License as published by
      +## the Free Software Foundation; either version 3 of the License, or (at
      +## your option) any later version.
      +##
      +## This program is distributed in the hope that it will be useful, but
      +## WITHOUT ANY WARRANTY; without even the implied warranty of
      +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      +## General Public License for more details.
      +##
      +## You should have received a copy of the GNU General Public License
      +## along with this program; see the file COPYING.  If not, see
      +## <http://www.gnu.org/licenses/>.
      +
      +import numpy as np
      +
      +
      [docs]def erfcx (arg): + arg = np.atleast_1d(arg) + assert(np.all(np.isreal(arg)),"erfcx: input must be real") + + ## Get precision dependent thresholds -- or not :p + xneg = -26.628; + xmax = 2.53e+307; + + ## Allocate output + result = np.zeros (arg.shape) + + ## Find values where erfcx can be evaluated + idx_neg = (arg < xneg); + idx_max = (arg > xmax); + idx = ~(idx_neg | idx_max); + + arg = arg [idx]; + + ## Perform the actual computation + t = 3.97886080735226 / (np.abs (arg) + 3.97886080735226); + u = t - 0.5; + y = (((((((((u * 0.00127109764952614092 + 1.19314022838340944e-4) * u \ + - 0.003963850973605135) * u - 8.70779635317295828e-4) * u + \ + 0.00773672528313526668) * u + 0.00383335126264887303) * u - \ + 0.0127223813782122755) * u - 0.0133823644533460069) * u + \ + 0.0161315329733252248) * u + 0.0390976845588484035) * u + \ + 0.00249367200053503304; + y = ((((((((((((y * u - 0.0838864557023001992) * u - \ + 0.119463959964325415) * u + 0.0166207924969367356) * u + \ + 0.357524274449531043) * u + 0.805276408752910567) * u + \ + 1.18902982909273333) * u + 1.37040217682338167) * u + \ + 1.31314653831023098) * u + 1.07925515155856677) * u + \ + 0.774368199119538609) * u + 0.490165080585318424) * u + \ + 0.275374741597376782) * t; + + y [arg < 0] = 2 * np.exp (arg [arg < 0]**2) - y [arg < 0]; + + ## Put the results back into something with the same size is the original input + result [idx] = y; + result [idx_neg] = np.inf; + ## result (idx_max) = 0; # not needed as we initialise with zeros + return(result) +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/functions.html b/doc/_build/html/_modules/GPy/util/functions.html new file mode 100644 index 00000000..d3250c5d --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/functions.html @@ -0,0 +1,121 @@ + + + + + + + + GPy.util.functions — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.functions

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +import numpy as np
      +from scipy.special import erf, erfc, erfcx
      +import sys
      +epsilon = sys.float_info.epsilon
      +lim_val = -np.log(epsilon) 
      +
      +
      [docs]def logisticln(x): + return np.where(x<lim_val, np.where(x>-lim_val, -np.log(1+np.exp(-x)), -x), -np.log(1+epsilon)) +
      +
      [docs]def logistic(x): + return np.where(x<lim_val, np.where(x>-lim_val, 1/(1+np.exp(-x)), epsilon/(epsilon+1)), 1/(1+epsilon)) +
      +
      [docs]def normcdf(x): + g=0.5*erfc(-x/np.sqrt(2)) + return np.where(g==0, epsilon, np.where(g==1, 1-epsilon, g)) +
      +
      [docs]def normcdfln(x): + return np.where(x < 0, -.5*x*x + np.log(.5) + np.log(erfcx(-x/np.sqrt(2))), np.log(normcdf(x))) +
      +
      [docs]def clip_exp(x): + return np.where(x<lim_val, np.where(x>-lim_val, np.exp(x), epsilon), 1/epsilon) +
      +
      [docs]def differfln(x0, x1): + # this is a, hopefully!, a numerically more stable variant of log(erf(x0)-erf(x1)) = log(erfc(x1)-erfc(x0)). + return np.where(x0>x1, -x1*x1 + np.log(erfcx(x1)-np.exp(-x0**2+x1**2)*erfcx(x0)), -x0*x0 + np.log(np.exp(-x1**2+x0**2)*erfcx(x1) - erfcx(x0)))
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/gpu_init.html b/doc/_build/html/_modules/GPy/util/gpu_init.html new file mode 100644 index 00000000..13b7ff9e --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/gpu_init.html @@ -0,0 +1,142 @@ + + + + + + + + GPy.util.gpu_init — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.gpu_init

      +"""
      +The package for scikits.cuda initialization
      +
      +Global variables: initSuccess
      +providing CUBLAS handle: cublas_handle
      +"""
      +
      +gpu_initialized = False
      +gpu_device = None
      +gpu_context = None
      +MPI_enabled = False
      +
      +try:
      +    from mpi4py import MPI
      +    MPI_enabled = True
      +except:
      +    pass
      +
      +try:
      +    if MPI_enabled and MPI.COMM_WORLD.size>1:
      +        from .parallel import get_id_within_node
      +        gpuid = get_id_within_node()
      +        import pycuda.driver
      +        pycuda.driver.init()
      +        if gpuid>=pycuda.driver.Device.count():
      +            print '['+MPI.Get_processor_name()+'] more processes than the GPU numbers!'
      +            #MPI.COMM_WORLD.Abort()
      +            raise
      +        gpu_device = pycuda.driver.Device(gpuid)
      +        gpu_context = gpu_device.make_context()
      +        gpu_initialized = True
      +    else:
      +        import pycuda.autoinit
      +        gpu_initialized = True
      +except:
      +    pass
      +
      +try:
      +    from scikits.cuda import cublas
      +    import scikits.cuda.linalg as culinalg
      +    culinalg.init()
      +    cublas_handle = cublas.cublasCreate()
      +except:
      +    pass
      +
      +
      [docs]def closeGPU(): + if gpu_context is not None: + gpu_context.detach()
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/initialization.html b/doc/_build/html/_modules/GPy/util/initialization.html new file mode 100644 index 00000000..4eda4d50 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/initialization.html @@ -0,0 +1,117 @@ + + + + + + + + GPy.util.initialization — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.initialization

      +'''
      +Created on 24 Feb 2014
      +
      +@author: maxz
      +'''
      +
      +import numpy as np
      +from GPy.util.pca import PCA
      +
      +
      [docs]def initialize_latent(init, input_dim, Y): + Xr = np.asfortranarray(np.random.randn(Y.shape[0], input_dim)) + if init == 'PCA': + p = PCA(Y) + PC = p.project(Y, min(input_dim, Y.shape[1])) + Xr[:PC.shape[0], :PC.shape[1]] = PC + var = .1*p.fracs[:input_dim] + else: + var = Xr.var(0) + + Xr -= Xr.mean(0) + Xr /= Xr.std(0) + + return Xr, var/var.max()
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/linalg.html b/doc/_build/html/_modules/GPy/util/linalg.html new file mode 100644 index 00000000..9f44dfe9 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/linalg.html @@ -0,0 +1,627 @@ + + + + + + + + GPy.util.linalg — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.linalg

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +# tdot function courtesy of Ian Murray:
      +# Iain Murray, April 2013. iain contactable via iainmurray.net
      +# http://homepages.inf.ed.ac.uk/imurray2/code/tdot/tdot.py
      +
      +import numpy as np
      +from scipy import linalg, weave
      +import types
      +import ctypes
      +from ctypes import byref, c_char, c_int, c_double # TODO
      +import scipy
      +import warnings
      +import os
      +from config import config
      +import logging
      +
      +_scipyversion = np.float64((scipy.__version__).split('.')[:2])
      +_fix_dpotri_scipy_bug = True
      +if np.all(_scipyversion >= np.array([0, 14])):
      +    from scipy.linalg import lapack
      +    _fix_dpotri_scipy_bug = False
      +elif np.all(_scipyversion >= np.array([0, 12])):
      +    #import scipy.linalg.lapack.clapack as lapack
      +    from scipy.linalg import lapack
      +else:
      +    from scipy.linalg.lapack import flapack as lapack
      +
      +if config.getboolean('anaconda', 'installed') and config.getboolean('anaconda', 'MKL'):
      +    try:
      +        anaconda_path = str(config.get('anaconda', 'location'))
      +        mkl_rt = ctypes.cdll.LoadLibrary(os.path.join(anaconda_path, 'DLLs', 'mkl_rt.dll'))
      +        dsyrk = mkl_rt.dsyrk
      +        dsyr = mkl_rt.dsyr
      +        _blas_available = True
      +        print 'anaconda installed and mkl is loaded'
      +    except:
      +        _blas_available = False
      +else:
      +    try:
      +        _blaslib = ctypes.cdll.LoadLibrary(np.core._dotblas.__file__) # @UndefinedVariable
      +        dsyrk = _blaslib.dsyrk_
      +        dsyr = _blaslib.dsyr_
      +        _blas_available = True
      +    except AttributeError as e:
      +        _blas_available = False
      +        warnings.warn("warning: caught this exception:" + str(e))
      +
      +
      [docs]def force_F_ordered_symmetric(A): + """ + return a F ordered version of A, assuming A is symmetric + """ + if A.flags['F_CONTIGUOUS']: + return A + if A.flags['C_CONTIGUOUS']: + return A.T + else: + return np.asfortranarray(A) +
      +
      [docs]def force_F_ordered(A): + """ + return a F ordered version of A, assuming A is triangular + """ + if A.flags['F_CONTIGUOUS']: + return A + print "why are your arrays not F order?" + return np.asfortranarray(A) + +# def jitchol(A, maxtries=5): +# A = force_F_ordered_symmetric(A) +# L, info = lapack.dpotrf(A, lower=1) +# if info == 0: +# return L +# else: +# if maxtries==0: +# raise linalg.LinAlgError, "not positive definite, even with jitter." +# diagA = np.diag(A) +# if np.any(diagA <= 0.): +# raise linalg.LinAlgError, "not pd: non-positive diagonal elements" +# jitter = diagA.mean() * 1e-6 + +# return jitchol(A+np.eye(A.shape[0])*jitter, maxtries-1) +
      +
      [docs]def jitchol(A, maxtries=5): + A = np.ascontiguousarray(A) + L, info = lapack.dpotrf(A, lower=1) + if info == 0: + return L + else: + diagA = np.diag(A) + if np.any(diagA <= 0.): + raise linalg.LinAlgError, "not pd: non-positive diagonal elements" + jitter = diagA.mean() * 1e-6 + while maxtries > 0 and np.isfinite(jitter): + try: + L = linalg.cholesky(A + np.eye(A.shape[0]) * jitter, lower=True) + except: + jitter *= 10 + finally: + maxtries -= 1 + raise linalg.LinAlgError, "not positive definite, even with jitter." + import traceback + try: raise + except: + logging.warning('\n'.join(['Added jitter of {:.10e}'.format(jitter), + ' in '+traceback.format_list(traceback.extract_stack(limit=2)[-2:-1])[0][2:]])) + import ipdb;ipdb.set_trace() + return L + + + + + +# def dtrtri(L, lower=1): +# """ +# Wrapper for lapack dtrtri function +# Inverse of L +# +# :param L: Triangular Matrix L +# :param lower: is matrix lower (true) or upper (false) +# :returns: Li, info +# """ +# L = force_F_ordered(L) +# return lapack.dtrtri(L, lower=lower) +
      +
      [docs]def dtrtrs(A, B, lower=1, trans=0, unitdiag=0): + """ + Wrapper for lapack dtrtrs function + + DTRTRS solves a triangular system of the form + + A * X = B or A**T * X = B, + + where A is a triangular matrix of order N, and B is an N-by-NRHS + matrix. A check is made to verify that A is nonsingular. + + :param A: Matrix A(triangular) + :param B: Matrix B + :param lower: is matrix lower (true) or upper (false) + :returns: Solution to A * X = B or A**T * X = B + + """ + A = np.asfortranarray(A) + #Note: B does not seem to need to be F ordered! + return lapack.dtrtrs(A, B, lower=lower, trans=trans, unitdiag=unitdiag) +
      +
      [docs]def dpotrs(A, B, lower=1): + """ + Wrapper for lapack dpotrs function + :param A: Matrix A + :param B: Matrix B + :param lower: is matrix lower (true) or upper (false) + :returns: + """ + A = force_F_ordered(A) + return lapack.dpotrs(A, B, lower=lower) +
      +
      [docs]def dpotri(A, lower=1): + """ + Wrapper for lapack dpotri function + + DPOTRI - compute the inverse of a real symmetric positive + definite matrix A using the Cholesky factorization A = + U**T*U or A = L*L**T computed by DPOTRF + + :param A: Matrix A + :param lower: is matrix lower (true) or upper (false) + :returns: A inverse + + """ + if _fix_dpotri_scipy_bug: + assert lower==1, "scipy linalg behaviour is very weird. please use lower, fortran ordered arrays" + lower = 0 + + A = force_F_ordered(A) + R, info = lapack.dpotri(A, lower=lower) #needs to be zero here, seems to be a scipy bug + + symmetrify(R) + return R, info +
      +
      [docs]def pddet(A): + """ + Determinant of a positive definite matrix, only symmetric matricies though + """ + L = jitchol(A) + logdetA = 2*sum(np.log(np.diag(L))) + return logdetA +
      +
      [docs]def trace_dot(a, b): + """ + Efficiently compute the trace of the matrix product of a and b + """ + return np.sum(a * b) +
      +
      [docs]def mdot(*args): + """ + Multiply all the arguments using matrix product rules. + The output is equivalent to multiplying the arguments one by one + from left to right using dot(). + Precedence can be controlled by creating tuples of arguments, + for instance mdot(a,((b,c),d)) multiplies a (a*((b*c)*d)). + Note that this means the output of dot(a,b) and mdot(a,b) will differ if + a or b is a pure tuple of numbers. + + """ + if len(args) == 1: + return args[0] + elif len(args) == 2: + return _mdot_r(args[0], args[1]) + else: + return _mdot_r(args[:-1], args[-1]) +
      +def _mdot_r(a, b): + """Recursive helper for mdot""" + if type(a) == types.TupleType: + if len(a) > 1: + a = mdot(*a) + else: + a = a[0] + if type(b) == types.TupleType: + if len(b) > 1: + b = mdot(*b) + else: + b = b[0] + return np.dot(a, b) + +
      [docs]def pdinv(A, *args): + """ + :param A: A DxD pd numpy array + + :rval Ai: the inverse of A + :rtype Ai: np.ndarray + :rval L: the Cholesky decomposition of A + :rtype L: np.ndarray + :rval Li: the Cholesky decomposition of Ai + :rtype Li: np.ndarray + :rval logdet: the log of the determinant of A + :rtype logdet: float64 + + """ + L = jitchol(A, *args) + logdet = 2.*np.sum(np.log(np.diag(L))) + Li = dtrtri(L) + Ai, _ = dpotri(L, lower=1) + # Ai = np.tril(Ai) + np.tril(Ai,-1).T + symmetrify(Ai) + + return Ai, L, Li, logdet + +
      +
      [docs]def dtrtri(L): + """ + Inverts a Cholesky lower triangular matrix + + :param L: lower triangular matrix + :rtype: inverse of L + + """ + + L = force_F_ordered(L) + return lapack.dtrtri(L, lower=1)[0] + +
      +
      [docs]def multiple_pdinv(A): + """ + :param A: A DxDxN numpy array (each A[:,:,i] is pd) + + :rval invs: the inverses of A + :rtype invs: np.ndarray + :rval hld: 0.5* the log of the determinants of A + :rtype hld: np.array + + """ + N = A.shape[-1] + chols = [jitchol(A[:, :, i]) for i in range(N)] + halflogdets = [np.sum(np.log(np.diag(L[0]))) for L in chols] + invs = [dpotri(L[0], True)[0] for L in chols] + invs = [np.triu(I) + np.triu(I, 1).T for I in invs] + return np.dstack(invs), np.array(halflogdets) + +
      +
      [docs]def pca(Y, input_dim): + """ + Principal component analysis: maximum likelihood solution by SVD + + :param Y: NxD np.array of data + :param input_dim: int, dimension of projection + + + :rval X: - Nxinput_dim np.array of dimensionality reduced data + :rval W: - input_dimxD mapping from X to Y + + """ + if not np.allclose(Y.mean(axis=0), 0.0): + print "Y is not zero mean, centering it locally (GPy.util.linalg.pca)" + + # Y -= Y.mean(axis=0) + + Z = linalg.svd(Y - Y.mean(axis=0), full_matrices=False) + [X, W] = [Z[0][:, 0:input_dim], np.dot(np.diag(Z[1]), Z[2]).T[:, 0:input_dim]] + v = X.std(axis=0) + X /= v; + W *= v; + return X, W.T +
      +
      [docs]def ppca(Y, Q, iterations=100): + """ + EM implementation for probabilistic pca. + + :param array-like Y: Observed Data + :param int Q: Dimensionality for reduced array + :param int iterations: number of iterations for EM + """ + from numpy.ma import dot as madot + N, D = Y.shape + # Initialise W randomly + W = np.random.randn(D, Q) * 1e-3 + Y = np.ma.masked_invalid(Y, copy=0) + mu = Y.mean(0) + Ycentered = Y - mu + try: + for _ in range(iterations): + exp_x = np.asarray_chkfinite(np.linalg.solve(W.T.dot(W), madot(W.T, Ycentered.T))).T + W = np.asarray_chkfinite(np.linalg.solve(exp_x.T.dot(exp_x), madot(exp_x.T, Ycentered))).T + except np.linalg.linalg.LinAlgError: + #"converged" + pass + return np.asarray_chkfinite(exp_x), np.asarray_chkfinite(W) +
      +
      [docs]def tdot_numpy(mat, out=None): + return np.dot(mat, mat.T, out) +
      +
      [docs]def tdot_blas(mat, out=None): + """returns np.dot(mat, mat.T), but faster for large 2D arrays of doubles.""" + if (mat.dtype != 'float64') or (len(mat.shape) != 2): + return np.dot(mat, mat.T) + nn = mat.shape[0] + if out is None: + out = np.zeros((nn, nn)) + else: + assert(out.dtype == 'float64') + assert(out.shape == (nn, nn)) + # FIXME: should allow non-contiguous out, and copy output into it: + assert(8 in out.strides) + # zeroing needed because of dumb way I copy across triangular answer + out[:] = 0.0 + + # # Call to DSYRK from BLAS + # If already in Fortran order (rare), and has the right sorts of strides I + # could avoid the copy. I also thought swapping to cblas API would allow use + # of C order. However, I tried that and had errors with large matrices: + # http://homepages.inf.ed.ac.uk/imurray2/code/tdot/tdot_broken.py + mat = np.asfortranarray(mat) + TRANS = c_char('n') + N = c_int(mat.shape[0]) + K = c_int(mat.shape[1]) + LDA = c_int(mat.shape[0]) + UPLO = c_char('l') + ALPHA = c_double(1.0) + A = mat.ctypes.data_as(ctypes.c_void_p) + BETA = c_double(0.0) + C = out.ctypes.data_as(ctypes.c_void_p) + LDC = c_int(np.max(out.strides) / 8) + dsyrk(byref(UPLO), byref(TRANS), byref(N), byref(K), + byref(ALPHA), A, byref(LDA), byref(BETA), C, byref(LDC)) + + symmetrify(out, upper=True) + + + return np.ascontiguousarray(out) +
      +
      [docs]def tdot(*args, **kwargs): + if _blas_available: + return tdot_blas(*args, **kwargs) + else: + return tdot_numpy(*args, **kwargs) +
      +
      [docs]def DSYR_blas(A, x, alpha=1.): + """ + Performs a symmetric rank-1 update operation: + A <- A + alpha * np.dot(x,x.T) + + :param A: Symmetric NxN np.array + :param x: Nx1 np.array + :param alpha: scalar + + """ + N = c_int(A.shape[0]) + LDA = c_int(A.shape[0]) + UPLO = c_char('l') + ALPHA = c_double(alpha) + A_ = A.ctypes.data_as(ctypes.c_void_p) + x_ = x.ctypes.data_as(ctypes.c_void_p) + INCX = c_int(1) + dsyr(byref(UPLO), byref(N), byref(ALPHA), + x_, byref(INCX), A_, byref(LDA)) + symmetrify(A, upper=True) +
      +
      [docs]def DSYR_numpy(A, x, alpha=1.): + """ + Performs a symmetric rank-1 update operation: + A <- A + alpha * np.dot(x,x.T) + + :param A: Symmetric NxN np.array + :param x: Nx1 np.array + :param alpha: scalar + + """ + A += alpha * np.dot(x[:, None], x[None, :]) + +
      +
      [docs]def DSYR(*args, **kwargs): + if _blas_available: + return DSYR_blas(*args, **kwargs) + else: + return DSYR_numpy(*args, **kwargs) +
      +
      [docs]def symmetrify(A, upper=False): + """ + Take the square matrix A and make it symmetrical by copting elements from the lower half to the upper + + works IN PLACE. + + note: tries to use weave, falls back to a slower numpy version + """ + if config.getboolean('weave', 'working'): + try: + symmetrify_weave(A, upper) + except: + print "\n Weave compilation failed. Falling back to (slower) numpy implementation\n" + config.set('weave', 'working', 'False') + symmetrify_numpy(A, upper) + else: + symmetrify_numpy(A, upper) + +
      +
      [docs]def symmetrify_weave(A, upper=False): + """ + Take the square matrix A and make it symmetrical by copting elements from the lower half to the upper + + works IN PLACE. + + + """ + N, M = A.shape + assert N == M + + c_contig_code = """ + int iN; + for (int i=1; i<N; i++){ + iN = i*N; + for (int j=0; j<i; j++){ + A[i+j*N] = A[iN+j]; + } + } + """ + f_contig_code = """ + int iN; + for (int i=1; i<N; i++){ + iN = i*N; + for (int j=0; j<i; j++){ + A[iN+j] = A[i+j*N]; + } + } + """ + + N = int(N) # for safe type casting + if A.flags['C_CONTIGUOUS'] and upper: + weave.inline(f_contig_code, ['A', 'N'], extra_compile_args=['-O3']) + elif A.flags['C_CONTIGUOUS'] and not upper: + weave.inline(c_contig_code, ['A', 'N'], extra_compile_args=['-O3']) + elif A.flags['F_CONTIGUOUS'] and upper: + weave.inline(c_contig_code, ['A', 'N'], extra_compile_args=['-O3']) + elif A.flags['F_CONTIGUOUS'] and not upper: + weave.inline(f_contig_code, ['A', 'N'], extra_compile_args=['-O3']) + else: + if upper: + tmp = np.tril(A.T) + else: + tmp = np.tril(A) + A[:] = 0.0 + A += tmp + A += np.tril(tmp, -1).T + +
      +
      [docs]def symmetrify_numpy(A, upper=False): + """ + Force a matrix to be symmetric + """ + triu = np.triu_indices_from(A,k=1) + if upper: + A.T[triu] = A[triu] + else: + A[triu] = A.T[triu] +
      +
      [docs]def cholupdate(L, x): + """ + update the LOWER cholesky factor of a pd matrix IN PLACE + + if L is the lower chol. of K, then this function computes L\_ + where L\_ is the lower chol of K + x*x^T + + """ + support_code = """ + #include <math.h> + """ + code = """ + double r,c,s; + int j,i; + for(j=0; j<N; j++){ + r = sqrt(L(j,j)*L(j,j) + x(j)*x(j)); + c = r / L(j,j); + s = x(j) / L(j,j); + L(j,j) = r; + for (i=j+1; i<N; i++){ + L(i,j) = (L(i,j) + s*x(i))/c; + x(i) = c*x(i) - s*L(i,j); + } + } + """ + x = x.copy() + N = x.size + weave.inline(code, support_code=support_code, arg_names=['N', 'L', 'x'], type_converters=weave.converters.blitz) +
      +
      [docs]def backsub_both_sides(L, X, transpose='left'): + """ Return L^-T * X * L^-1, assumuing X is symmetrical and L is lower cholesky""" + if transpose == 'left': + tmp, _ = dtrtrs(L, X, lower=1, trans=1) + return dtrtrs(L, tmp.T, lower=1, trans=1)[0].T + else: + tmp, _ = dtrtrs(L, X, lower=1, trans=0) + return dtrtrs(L, tmp.T, lower=1, trans=0)[0].T +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/ln_diff_erfs.html b/doc/_build/html/_modules/GPy/util/ln_diff_erfs.html new file mode 100644 index 00000000..d9e797f2 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/ln_diff_erfs.html @@ -0,0 +1,204 @@ + + + + + + + + GPy.util.ln_diff_erfs — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.ln_diff_erfs

      +# Copyright (c) 2013, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +#Only works for scipy 0.12+
      +try:
      +    from scipy.special import erfcx, erf
      +except ImportError:
      +    from scipy.special import erf
      +    from erfcx import erfcx
      +
      +import numpy as np
      +
      +
      [docs]def ln_diff_erfs(x1, x2, return_sign=False): + """Function for stably computing the log of difference of two erfs in a numerically stable manner. + :param x1 : argument of the positive erf + :type x1: ndarray + :param x2 : argument of the negative erf + :type x2: ndarray + :return: tuple containing (log(abs(erf(x1) - erf(x2))), sign(erf(x1) - erf(x2))) + + Based on MATLAB code that was written by Antti Honkela and modified by David Luengo and originally derived from code by Neil Lawrence. + """ + x1 = np.require(x1).real + x2 = np.require(x2).real + if x1.size==1: + x1 = np.reshape(x1, (1, 1)) + if x2.size==1: + x2 = np.reshape(x2, (1, 1)) + + if x1.shape==x2.shape: + v = np.zeros_like(x1) + else: + if x1.size==1: + v = np.zeros(x2.shape) + elif x2.size==1: + v = np.zeros(x1.shape) + else: + raise ValueError, "This function does not broadcast unless provided with a scalar." + + if x1.size == 1: + x1 = np.tile(x1, x2.shape) + + if x2.size == 1: + x2 = np.tile(x2, x1.shape) + + sign = np.sign(x1 - x2) + if x1.size == 1: + if sign== -1: + swap = x1 + x1 = x2 + x2 = swap + else: + I = sign == -1 + swap = x1[I] + x1[I] = x2[I] + x2[I] = swap + + with np.errstate(divide='ignore'): + # switch off log of zero warnings. + + # Case 0: arguments of different sign, no problems with loss of accuracy + I0 = np.logical_or(np.logical_and(x1>0, x2<0), np.logical_and(x2>0, x1<0)) # I1=(x1*x2)<0 + + # Case 1: x1 = x2 so we have log of zero. + I1 = (x1 == x2) + + # Case 2: Both arguments are non-negative + I2 = np.logical_and(x1 > 0, np.logical_and(np.logical_not(I0), + np.logical_not(I1))) + # Case 3: Both arguments are non-positive + I3 = np.logical_and(np.logical_and(np.logical_not(I0), + np.logical_not(I1)), + np.logical_not(I2)) + _x2 = x2.flatten() + _x1 = x1.flatten() + for group, flags in zip((0, 1, 2, 3), (I0, I1, I2, I3)): + + if np.any(flags): + if not x1.size==1: + _x1 = x1[flags] + if not x2.size==1: + _x2 = x2[flags] + if group==0: + v[flags] = np.log( erf(_x1) - erf(_x2) ) + elif group==1: + v[flags] = -np.inf + elif group==2: + v[flags] = np.log(erfcx(_x2) + -erfcx(_x1)*np.exp(_x2**2 + -_x1**2)) - _x2**2 + elif group==3: + v[flags] = np.log(erfcx(-_x1) + -erfcx(-_x2)*np.exp(_x1**2 + -_x2**2))-_x1**2 + + # TODO: switch back on log of zero warnings. + + if return_sign: + return v, sign + else: + if v.size==1: + if sign==-1: + v = v.view('complex64') + v += np.pi*1j + else: + # Need to add in a complex part because argument is negative. + v = v.view('complex64') + v[I] += np.pi*1j + + return v
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/misc.html b/doc/_build/html/_modules/GPy/util/misc.html new file mode 100644 index 00000000..2455e03c --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/misc.html @@ -0,0 +1,192 @@ + + + + + + + + GPy.util.misc — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.misc

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from config import *
      +
      +
      [docs]def chain_1(df_dg, dg_dx): + """ + Generic chaining function for first derivative + + .. math:: + \\frac{d(f . g)}{dx} = \\frac{df}{dg} \\frac{dg}{dx} + """ + return df_dg * dg_dx +
      +
      [docs]def chain_2(d2f_dg2, dg_dx, df_dg, d2g_dx2): + """ + Generic chaining function for second derivative + + .. math:: + \\frac{d^{2}(f . g)}{dx^{2}} = \\frac{d^{2}f}{dg^{2}}(\\frac{dg}{dx})^{2} + \\frac{df}{dg}\\frac{d^{2}g}{dx^{2}} + """ + return d2f_dg2*(dg_dx**2) + df_dg*d2g_dx2 +
      +
      [docs]def chain_3(d3f_dg3, dg_dx, d2f_dg2, d2g_dx2, df_dg, d3g_dx3): + """ + Generic chaining function for third derivative + + .. math:: + \\frac{d^{3}(f . g)}{dx^{3}} = \\frac{d^{3}f}{dg^{3}}(\\frac{dg}{dx})^{3} + 3\\frac{d^{2}f}{dg^{2}}\\frac{dg}{dx}\\frac{d^{2}g}{dx^{2}} + \\frac{df}{dg}\\frac{d^{3}g}{dx^{3}} + """ + return d3f_dg3*(dg_dx**3) + 3*d2f_dg2*dg_dx*d2g_dx2 + df_dg*d3g_dx3 +
      +
      [docs]def opt_wrapper(m, **kwargs): + """ + This function just wraps the optimization procedure of a GPy + object so that optimize() pickleable (necessary for multiprocessing). + """ + m.optimize(**kwargs) + return m.optimization_runs[-1] + +
      +
      [docs]def linear_grid(D, n = 100, min_max = (-100, 100)): + """ + Creates a D-dimensional grid of n linearly spaced points + + :param D: dimension of the grid + :param n: number of points + :param min_max: (min, max) list + + """ + + g = np.linspace(min_max[0], min_max[1], n) + G = np.ones((n, D)) + + return G*g[:,None] +
      +
      [docs]def kmm_init(X, m = 10): + """ + This is the same initialization algorithm that is used + in Kmeans++. It's quite simple and very useful to initialize + the locations of the inducing points in sparse GPs. + + :param X: data + :param m: number of inducing points + + """ + + # compute the distances + XXT = np.dot(X, X.T) + D = (-2.*XXT + np.diag(XXT)[:,np.newaxis] + np.diag(XXT)[np.newaxis,:]) + + # select the first point + s = np.random.permutation(X.shape[0])[0] + inducing = [s] + prob = D[s]/D[s].sum() + + for z in range(m-1): + s = np.random.multinomial(1, prob.flatten()).argmax() + inducing.append(s) + prob = D[s]/D[s].sum() + + inducing = np.array(inducing) + return X[inducing] + +### make a parameter to its corresponding array:
      +
      [docs]def param_to_array(*param): + """ +Convert an arbitrary number of parameters to :class:ndarray class objects. This is for +converting parameter objects to numpy arrays, when using scipy.weave.inline routine. +In scipy.weave.blitz there is no automatic array detection (even when the array inherits +from :class:ndarray)""" + import warnings + warnings.warn("Please use param.values, as this function will be deprecated in the next release.", DeprecationWarning) + assert len(param) > 0, "At least one parameter needed" + if len(param) == 1: + return param[0].view(np.ndarray) + return [x.view(np.ndarray) for x in param]
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/mocap.html b/doc/_build/html/_modules/GPy/util/mocap.html new file mode 100644 index 00000000..e7ef937b --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/mocap.html @@ -0,0 +1,796 @@ + + + + + + + + GPy.util.mocap — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.mocap

      +import os
      +import numpy as np
      +import math
      +from GPy.util import datasets as dat
      +import urllib2
      +
      +
      [docs]class vertex: + def __init__(self, name, id, parents=[], children=[], meta = {}): + self.name = name + self.id = id + self.parents = parents + self.children = children + self.meta = meta + + def __str__(self): + return self.name + '(' + str(self.id) + ').' +
      +
      [docs]class tree: + def __init__(self): + self.vertices = [] + self.vertices.append(vertex(name='root', id=0)) + + def __str__(self): + index = self.find_root() + return self.branch_str(index) + +
      [docs] def branch_str(self, index, indent=''): + out = indent + str(self.vertices[index]) + '\n' + for child in self.vertices[index].children: + out+=self.branch_str(child, indent+' ') + return out +
      +
      [docs] def find_children(self): + """Take a tree and set the children according to the parents. + + Takes a tree structure which lists the parents of each vertex + and computes the children for each vertex and places them in.""" + for i in range(len(self.vertices)): + self.vertices[i].children = [] + for i in range(len(self.vertices)): + for parent in self.vertices[i].parents: + if i not in self.vertices[parent].children: + self.vertices[parent].children.append(i) +
      +
      [docs] def find_parents(self): + """Take a tree and set the parents according to the children + + Takes a tree structure which lists the children of each vertex + and computes the parents for each vertex and places them in.""" + for i in range(len(self.vertices)): + self.vertices[i].parents = [] + for i in range(len(self.vertices)): + for child in self.vertices[i].children: + if i not in self.vertices[child].parents: + self.vertices[child].parents.append(i) +
      +
      [docs] def find_root(self): + """Finds the index of the root node of the tree.""" + self.find_parents() + index = 0 + while len(self.vertices[index].parents)>0: + index = self.vertices[index].parents[0] + return index +
      +
      [docs] def get_index_by_id(self, id): + """Give the index associated with a given vertex id.""" + for i in range(len(self.vertices)): + if self.vertices[i].id == id: + return i + raise ValueError('Reverse look up of id failed.') +
      +
      [docs] def get_index_by_name(self, name): + """Give the index associated with a given vertex name.""" + for i in range(len(self.vertices)): + if self.vertices[i].name == name: + return i + raise ValueError('Reverse look up of name failed.') +
      +
      [docs] def order_vertices(self): + """Order vertices in the graph such that parents always have a lower index than children.""" + + ordered = False + while ordered == False: + for i in range(len(self.vertices)): + ordered = True + for parent in self.vertices[i].parents: + if parent>i: + ordered = False + self.swap_vertices(i, parent) + + + +
      +
      [docs] def swap_vertices(self, i, j): + """ + Swap two vertices in the tree structure array. + swap_vertex swaps the location of two vertices in a tree structure array. + + :param tree: the tree for which two vertices are to be swapped. + :param i: the index of the first vertex to be swapped. + :param j: the index of the second vertex to be swapped. + :rval tree: the tree structure with the two vertex locations swapped. + + """ + store_vertex_i = self.vertices[i] + store_vertex_j = self.vertices[j] + self.vertices[j] = store_vertex_i + self.vertices[i] = store_vertex_j + for k in range(len(self.vertices)): + for swap_list in [self.vertices[k].children, self.vertices[k].parents]: + if i in swap_list: + swap_list[swap_list.index(i)] = -1 + if j in swap_list: + swap_list[swap_list.index(j)] = i + if -1 in swap_list: + swap_list[swap_list.index(-1)] = j + + +
      +
      [docs]def rotation_matrix(xangle, yangle, zangle, order='zxy', degrees=False): + + """ + + Compute the rotation matrix for an angle in each direction. + This is a helper function for computing the rotation matrix for a given set of angles in a given order. + + :param xangle: rotation for x-axis. + :param yangle: rotation for y-axis. + :param zangle: rotation for z-axis. + :param order: the order for the rotations. + + """ + if degrees: + xangle = math.radians(xangle) + yangle = math.radians(yangle) + zangle = math.radians(zangle) + + # Here we assume we rotate z, then x then y. + c1 = math.cos(xangle) # The x angle + c2 = math.cos(yangle) # The y angle + c3 = math.cos(zangle) # the z angle + s1 = math.sin(xangle) + s2 = math.sin(yangle) + s3 = math.sin(zangle) + + # see http://en.wikipedia.org/wiki/Rotation_matrix for + # additional info. + + if order=='zxy': + rot_mat = np.array([[c2*c3-s1*s2*s3, c2*s3+s1*s2*c3, -s2*c1],[-c1*s3, c1*c3, s1],[s2*c3+c2*s1*s3, s2*s3-c2*s1*c3, c2*c1]]) + else: + rot_mat = np.eye(3) + for i in range(len(order)): + if order[i]=='x': + rot_mat = np.dot(np.array([[1, 0, 0], [0, c1, s1], [0, -s1, c1]]),rot_mat) + elif order[i] == 'y': + rot_mat = np.dot(np.array([[c2, 0, -s2], [0, 1, 0], [s2, 0, c2]]),rot_mat) + elif order[i] == 'z': + rot_mat = np.dot(np.array([[c3, s3, 0], [-s3, c3, 0], [0, 0, 1]]),rot_mat) + + return rot_mat + + +# Motion capture data routines.
      +
      [docs]class skeleton(tree): + def __init__(self): + tree.__init__(self) + +
      [docs] def connection_matrix(self): + connection = np.zeros((len(self.vertices), len(self.vertices)), dtype=bool) + for i in range(len(self.vertices)): + for j in range(len(self.vertices[i].children)): + connection[i, self.vertices[i].children[j]] = True + return connection +
      +
      [docs] def to_xyz(self, channels): + raise NotImplementedError, "this needs to be implemented to use the skeleton class" + +
      +
      [docs] def finalize(self): + """After loading in a skeleton ensure parents are correct, vertex orders are correct and rotation matrices are correct.""" + + self.find_parents() + self.order_vertices() + self.set_rotation_matrices() +
      +
      [docs] def smooth_angle_channels(self, channels): + """Remove discontinuities in angle channels so that they don't cause artifacts in algorithms that rely on the smoothness of the functions.""" + for vertex in self.vertices: + for col in vertex.meta['rot_ind']: + if col: + for k in range(1, channels.shape[0]): + diff=channels[k, col]-channels[k-1, col] + if abs(diff+360.)<abs(diff): + channels[k:, col]=channels[k:, col]+360. + elif abs(diff-360.)<abs(diff): + channels[k:, col]=channels[k:, col]-360. + +# class bvh_skeleton(skeleton): +# def __init__(self): +# skeleton.__init__(self) + +# def to_xyz(self, channels): +
      +
      [docs]class acclaim_skeleton(skeleton): + def __init__(self, file_name=None): + skeleton.__init__(self) + self.documentation = [] + self.angle = 'deg' + self.length = 1.0 + self.mass = 1.0 + self.type = 'acclaim' + self.vertices[0] = vertex(name='root', id=0, + parents = [0], children=[], + meta = {'orientation': [], + 'axis': [0., 0., 0.], + 'axis_order': [], + 'C': np.eye(3), + 'Cinv': np.eye(3), + 'channels': [], + 'bodymass': [], + 'confmass': [], + 'order': [], + 'rot_ind': [], + 'pos_ind': [], + 'limits': [], + 'xyz': np.array([0., 0., 0.]), + 'rot': np.eye(3)}) + + if file_name: + self.load_skel(file_name) + +
      [docs] def to_xyz(self, channels): + rot_val = list(self.vertices[0].meta['orientation']) + for i in range(len(self.vertices[0].meta['rot_ind'])): + rind = self.vertices[0].meta['rot_ind'][i] + if rind != -1: + rot_val[i] += channels[rind] + + self.vertices[0].meta['rot'] = rotation_matrix(rot_val[0], + rot_val[1], + rot_val[2], + self.vertices[0].meta['axis_order'], + degrees=True) + # vertex based store of the xyz location + self.vertices[0].meta['xyz'] = list(self.vertices[0].meta['offset']) + + for i in range(len(self.vertices[0].meta['pos_ind'])): + pind = self.vertices[0].meta['pos_ind'][i] + if pind != -1: + self.vertices[0].meta['xyz'][i] += channels[pind] + + + for i in range(len(self.vertices[0].children)): + ind = self.vertices[0].children[i] + self.get_child_xyz(ind, channels) + + xyz = [] + for vertex in self.vertices: + xyz.append(vertex.meta['xyz']) + return np.array(xyz) + + +
      +
      [docs] def get_child_xyz(self, ind, channels): + + parent = self.vertices[ind].parents[0] + children = self.vertices[ind].children + rot_val = np.zeros(3) + for j in range(len(self.vertices[ind].meta['rot_ind'])): + rind = self.vertices[ind].meta['rot_ind'][j] + if rind != -1: + rot_val[j] = channels[rind] + else: + rot_val[j] = 0 + tdof = rotation_matrix(rot_val[0], rot_val[1], rot_val[2], + self.vertices[ind].meta['order'], + degrees=True) + + torient = rotation_matrix(self.vertices[ind].meta['axis'][0], + self.vertices[ind].meta['axis'][1], + self.vertices[ind].meta['axis'][2], + self.vertices[ind].meta['axis_order'], + degrees=True) + + torient_inv = rotation_matrix(-self.vertices[ind].meta['axis'][0], + -self.vertices[ind].meta['axis'][1], + -self.vertices[ind].meta['axis'][2], + self.vertices[ind].meta['axis_order'][::-1], + degrees=True) + + self.vertices[ind].meta['rot'] = np.dot(np.dot(np.dot(torient_inv,tdof),torient),self.vertices[parent].meta['rot']) + + + self.vertices[ind].meta['xyz'] = self.vertices[parent].meta['xyz'] + np.dot(self.vertices[ind].meta['offset'],self.vertices[ind].meta['rot']) + + for i in range(len(children)): + cind = children[i] + self.get_child_xyz(cind, channels) + +
      +
      [docs] def load_channels(self, file_name): + + fid=open(file_name, 'r') + channels = self.read_channels(fid) + fid.close() + return channels +
      +
      [docs] def load_skel(self, file_name): + + """ + Loads an ASF file into a skeleton structure. + + :param file_name: The file name to load in. + + """ + + fid = open(file_name, 'r') + self.read_skel(fid) + fid.close() + self.name = file_name + +
      +
      [docs] def read_bonedata(self, fid): + """Read bone data from an acclaim skeleton file stream.""" + + bone_count = 0 + lin = self.read_line(fid) + while lin[0]!=':': + parts = lin.split() + if parts[0] == 'begin': + bone_count += 1 + self.vertices.append(vertex(name = '', id=np.NaN, + meta={'name': [], + 'id': [], + 'offset': [], + 'orientation': [], + 'axis': [0., 0., 0.], + 'axis_order': [], + 'C': np.eye(3), + 'Cinv': np.eye(3), + 'channels': [], + 'bodymass': [], + 'confmass': [], + 'order': [], + 'rot_ind': [], + 'pos_ind': [], + 'limits': [], + 'xyz': np.array([0., 0., 0.]), + 'rot': np.eye(3)})) + lin = self.read_line(fid) + + + elif parts[0]=='id': + self.vertices[bone_count].id = int(parts[1]) + lin = self.read_line(fid) + + self.vertices[bone_count].children = [] + + elif parts[0]=='name': + self.vertices[bone_count].name = parts[1] + lin = self.read_line(fid) + + + elif parts[0]=='direction': + direction = np.array([float(parts[1]), float(parts[2]), float(parts[3])]) + lin = self.read_line(fid) + + + elif parts[0]=='length': + lgth = float(parts[1]) + lin = self.read_line(fid) + + + elif parts[0]=='axis': + self.vertices[bone_count].meta['axis'] = np.array([float(parts[1]), + float(parts[2]), + float(parts[3])]) + # order is reversed compared to bvh + self.vertices[bone_count].meta['axis_order'] = parts[-1][::-1].lower() + lin = self.read_line(fid) + + elif parts[0]=='dof': + order = [] + for i in range(1, len(parts)): + if parts[i]== 'rx': + chan = 'Xrotation' + order.append('x') + elif parts[i] =='ry': + chan = 'Yrotation' + order.append('y') + elif parts[i] == 'rz': + chan = 'Zrotation' + order.append('z') + elif parts[i] == 'tx': + chan = 'Xposition' + elif parts[i] == 'ty': + chan = 'Yposition' + elif parts[i] == 'tz': + chan = 'Zposition' + elif parts[i] == 'l': + chan = 'length' + self.vertices[bone_count].meta['channels'].append(chan) + # order is reversed compared to bvh + self.vertices[bone_count].meta['order'] = order[::-1] + lin = self.read_line(fid) + + elif parts[0]=='limits': + self.vertices[bone_count].meta['limits'] = [[float(parts[1][1:]), float(parts[2][:-1])]] + + lin = self.read_line(fid) + + while lin !='end': + parts = lin.split() + + self.vertices[bone_count].meta['limits'].append([float(parts[0][1:]), float(parts[1][:-1])]) + lin = self.read_line(fid) + self.vertices[bone_count].meta['limits'] = np.array(self.vertices[bone_count].meta['limits']) + + elif parts[0]=='end': + self.vertices[bone_count].meta['offset'] = direction*lgth + lin = self.read_line(fid) + + return lin +
      +
      [docs] def read_channels(self, fid): + """Read channels from an acclaim file.""" + bones = [[] for i in self.vertices] + num_channels = 0 + for vertex in self.vertices: + num_channels = num_channels + len(vertex.meta['channels']) + + lin = self.read_line(fid) + while lin != ':DEGREES': + lin = self.read_line(fid) + if lin == '': + raise ValueError('Could not find :DEGREES in ' + fid.name) + + counter = 0 + lin = self.read_line(fid) + while lin: + parts = lin.split() + if len(parts)==1: + frame_no = int(parts[0]) + if frame_no: + counter += 1 + if counter != frame_no: + raise ValueError('Unexpected frame number.') + else: + raise ValueError('Single bone name ...') + else: + ind = self.get_index_by_name(parts[0]) + bones[ind].append(np.array([float(channel) for channel in parts[1:]])) + lin = self.read_line(fid) + + num_frames = counter + + channels = np.zeros((num_frames, num_channels)) + + end_val = 0 + for i in range(len(self.vertices)): + vertex = self.vertices[i] + if len(vertex.meta['channels'])>0: + start_val = end_val + end_val = end_val + len(vertex.meta['channels']) + for j in range(num_frames): + channels[j, start_val:end_val] = bones[i][j] + self.resolve_indices(i, start_val) + + self.smooth_angle_channels(channels) + return channels + +
      +
      [docs] def read_documentation(self, fid): + """Read documentation from an acclaim skeleton file stream.""" + + lin = self.read_line(fid) + while lin[0] != ':': + self.documentation.append(lin) + lin = self.read_line(fid) + return lin +
      +
      [docs] def read_hierarchy(self, fid): + """Read hierarchy information from acclaim skeleton file stream.""" + + lin = self.read_line(fid) + + while lin != 'end': + parts = lin.split() + if lin != 'begin': + ind = self.get_index_by_name(parts[0]) + for i in range(1, len(parts)): + self.vertices[ind].children.append(self.get_index_by_name(parts[i])) + lin = self.read_line(fid) + lin = self.read_line(fid) + return lin +
      +
      [docs] def read_line(self, fid): + """Read a line from a file string and check it isn't either empty or commented before returning.""" + lin = '#' + while lin[0] == '#': + lin = fid.readline().strip() + if lin == '': + return lin + return lin + +
      +
      [docs] def read_root(self, fid): + """Read the root node from an acclaim skeleton file stream.""" + lin = self.read_line(fid) + while lin[0] != ':': + parts = lin.split() + if parts[0]=='order': + order = [] + for i in range(1, len(parts)): + if parts[i].lower()=='rx': + chan = 'Xrotation' + order.append('x') + elif parts[i].lower()=='ry': + chan = 'Yrotation' + order.append('y') + elif parts[i].lower()=='rz': + chan = 'Zrotation' + order.append('z') + elif parts[i].lower()=='tx': + chan = 'Xposition' + elif parts[i].lower()=='ty': + chan = 'Yposition' + elif parts[i].lower()=='tz': + chan = 'Zposition' + elif parts[i].lower()=='l': + chan = 'length' + self.vertices[0].meta['channels'].append(chan) + # order is reversed compared to bvh + self.vertices[0].meta['order'] = order[::-1] + + elif parts[0]=='axis': + # order is reversed compared to bvh + self.vertices[0].meta['axis_order'] = parts[1][::-1].lower() + elif parts[0]=='position': + self.vertices[0].meta['offset'] = [float(parts[1]), + float(parts[2]), + float(parts[3])] + elif parts[0]=='orientation': + self.vertices[0].meta['orientation'] = [float(parts[1]), + float(parts[2]), + float(parts[3])] + lin = self.read_line(fid) + return lin +
      +
      [docs] def read_skel(self, fid): + """Loads an acclaim skeleton format from a file stream.""" + lin = self.read_line(fid) + while lin: + if lin[0]==':': + if lin[1:]== 'name': + lin = self.read_line(fid) + self.name = lin + elif lin[1:]=='units': + lin = self.read_units(fid) + elif lin[1:]=='documentation': + lin = self.read_documentation(fid) + elif lin[1:]=='root': + lin = self.read_root(fid) + elif lin[1:]=='bonedata': + lin = self.read_bonedata(fid) + elif lin[1:]=='hierarchy': + lin = self.read_hierarchy(fid) + elif lin[1:8]=='version': + lin = self.read_line(fid) + continue + else: + if not lin: + self.finalize() + return + lin = self.read_line(fid) + else: + raise ValueError('Unrecognised file format') + self.finalize() +
      +
      [docs] def read_units(self, fid): + """Read units from an acclaim skeleton file stream.""" + lin = self.read_line(fid) + while lin[0] != ':': + parts = lin.split() + if parts[0]=='mass': + self.mass = float(parts[1]) + elif parts[0]=='length': + self.length = float(parts[1]) + elif parts[0]=='angle': + self.angle = parts[1] + lin = self.read_line(fid) + return lin +
      +
      [docs] def resolve_indices(self, index, start_val): + """Get indices for the skeleton from the channels when loading in channel data.""" + + channels = self.vertices[index].meta['channels'] + base_channel = start_val + rot_ind = -np.ones(3, dtype=int) + pos_ind = -np.ones(3, dtype=int) + for i in range(len(channels)): + if channels[i]== 'Xrotation': + rot_ind[0] = base_channel + i + elif channels[i]=='Yrotation': + rot_ind[1] = base_channel + i + elif channels[i]=='Zrotation': + rot_ind[2] = base_channel + i + elif channels[i]=='Xposition': + pos_ind[0] = base_channel + i + elif channels[i]=='Yposition': + pos_ind[1] = base_channel + i + elif channels[i]=='Zposition': + pos_ind[2] = base_channel + i + self.vertices[index].meta['rot_ind'] = list(rot_ind) + self.vertices[index].meta['pos_ind'] = list(pos_ind) +
      +
      [docs] def set_rotation_matrices(self): + """Set the meta information at each vertex to contain the correct matrices C and Cinv as prescribed by the rotations and rotation orders.""" + for i in range(len(self.vertices)): + self.vertices[i].meta['C'] = rotation_matrix(self.vertices[i].meta['axis'][0], + self.vertices[i].meta['axis'][1], + self.vertices[i].meta['axis'][2], + self.vertices[i].meta['axis_order'], + degrees=True) + # Todo: invert this by applying angle operations in reverse order + self.vertices[i].meta['Cinv'] = np.linalg.inv(self.vertices[i].meta['C']) + + +# Utilities for loading in x,y,z data.
      +
      [docs]def load_text_data(dataset, directory, centre=True): + """Load in a data set of marker points from the Ohio State University C3D motion capture files (http://accad.osu.edu/research/mocap/mocap_data.htm).""" + + points, point_names = parse_text(os.path.join(directory, dataset + '.txt'))[0:2] + # Remove markers where there is a NaN + present_index = [i for i in range(points[0].shape[1]) if not (np.any(np.isnan(points[0][:, i])) or np.any(np.isnan(points[0][:, i])) or np.any(np.isnan(points[0][:, i])))] + + point_names = point_names[present_index] + for i in range(3): + points[i] = points[i][:, present_index] + if centre: + points[i] = (points[i].T - points[i].mean(axis=1)).T + + # Concatanate the X, Y and Z markers together + Y = np.concatenate((points[0], points[1], points[2]), axis=1) + Y = Y/400. + connect = read_connections(os.path.join(directory, 'connections.txt'), point_names) + return Y, connect +
      +
      [docs]def parse_text(file_name): + """Parse data from Ohio State University text mocap files (http://accad.osu.edu/research/mocap/mocap_data.htm).""" + + # Read the header + fid = open(file_name, 'r') + point_names = np.array(fid.readline().split())[2:-1:3] + fid.close() + for i in range(len(point_names)): + point_names[i] = point_names[i][0:-2] + + # Read the matrix data + S = np.loadtxt(file_name, skiprows=1) + field = np.uint(S[:, 0]) + times = S[:, 1] + S = S[:, 2:] + + # Set the -9999.99 markers to be not present + S[S==-9999.99] = np.NaN + + # Store x, y and z in different arrays + points = [] + points.append(S[:, 0:-1:3]) + points.append(S[:, 1:-1:3]) + points.append(S[:, 2:-1:3]) + + return points, point_names, times +
      +
      [docs]def read_connections(file_name, point_names): + """Read a file detailing which markers should be connected to which for motion capture data.""" + + connections = [] + fid = open(file_name, 'r') + line=fid.readline() + while(line): + connections.append(np.array(line.split(','))) + connections[-1][0] = connections[-1][0].strip() + connections[-1][1] = connections[-1][1].strip() + line = fid.readline() + connect = np.zeros((len(point_names), len(point_names)),dtype=bool) + for i in range(len(point_names)): + for j in range(len(point_names)): + for k in range(len(connections)): + if connections[k][0] == point_names[i] and connections[k][1] == point_names[j]: + + connect[i,j]=True + connect[j,i]=True + break + + return connect + + +
      +skel = acclaim_skeleton() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/multioutput.html b/doc/_build/html/_modules/GPy/util/multioutput.html new file mode 100644 index 00000000..a4223407 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/multioutput.html @@ -0,0 +1,194 @@ + + + + + + + + GPy.util.multioutput — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.multioutput

      +import numpy as np
      +import warnings
      +import GPy
      +
      +
      +
      [docs]def get_slices(input_list): + num_outputs = len(input_list) + _s = [0] + [ _x.shape[0] for _x in input_list ] + _s = np.cumsum(_s) + slices = [slice(a,b) for a,b in zip(_s[:-1],_s[1:])] + return slices +
      +
      [docs]def build_XY(input_list,output_list=None,index=None): + num_outputs = len(input_list) + if output_list is not None: + assert num_outputs == len(output_list) + Y = np.vstack(output_list) + else: + Y = None + + if index is not None: + assert len(index) == num_outputs + I = np.hstack( [np.repeat(j,_x.shape[0]) for _x,j in zip(input_list,index)] ) + else: + I = np.hstack( [np.repeat(j,_x.shape[0]) for _x,j in zip(input_list,range(num_outputs))] ) + + X = np.vstack(input_list) + X = np.hstack([X,I[:,None]]) + + return X,Y,I[:,None]#slices +
      +
      [docs]def build_likelihood(Y_list,noise_index,likelihoods_list=None): + Ny = len(Y_list) + if likelihoods_list is None: + likelihoods_list = [GPy.likelihoods.Gaussian(name="Gaussian_noise_%s" %j) for y,j in zip(Y_list,range(Ny))] + else: + assert len(likelihoods_list) == Ny + #likelihood = GPy.likelihoods.mixed_noise.MixedNoise(likelihoods_list=likelihoods_list, noise_index=noise_index) + likelihood = GPy.likelihoods.mixed_noise.MixedNoise(likelihoods_list=likelihoods_list) + return likelihood + +
      +
      [docs]def ICM(input_dim, num_outputs, kernel, W_rank=1,W=None,kappa=None,name='ICM'): + """ + Builds a kernel for an Intrinsic Coregionalization Model + + :input_dim: Input dimensionality (does not include dimension of indices) + :num_outputs: Number of outputs + :param kernel: kernel that will be multiplied by the coregionalize kernel (matrix B). + :type kernel: a GPy kernel + :param W_rank: number tuples of the corregionalization parameters 'W' + :type W_rank: integer + """ + if kernel.input_dim <> input_dim: + kernel.input_dim = input_dim + warnings.warn("kernel's input dimension overwritten to fit input_dim parameter.") + + K = kernel.prod(GPy.kern.Coregionalize(1, num_outputs, active_dims=[input_dim], rank=W_rank,W=W,kappa=kappa,name='B'),name=name) + return K + +
      +
      [docs]def LCM(input_dim, num_outputs, kernels_list, W_rank=1,name='ICM'): + """ + Builds a kernel for an Linear Coregionalization Model + + :input_dim: Input dimensionality (does not include dimension of indices) + :num_outputs: Number of outputs + :param kernel: kernel that will be multiplied by the coregionalize kernel (matrix B). + :type kernel: a GPy kernel + :param W_rank: number tuples of the corregionalization parameters 'W' + :type W_rank: integer + """ + Nk = len(kernels_list) + K = ICM(input_dim,num_outputs,kernels_list[0],W_rank,name='%s%s' %(name,0)) + j = 1 + for kernel in kernels_list[1:]: + K += ICM(input_dim,num_outputs,kernel,W_rank,name='%s%s' %(name,j)) + j += 1 + return K + +
      +
      [docs]def Private(input_dim, num_outputs, kernel, output, kappa=None,name='X'): + """ + Builds a kernel for an Intrinsic Coregionalization Model + + :input_dim: Input dimensionality + :num_outputs: Number of outputs + :param kernel: kernel that will be multiplied by the coregionalize kernel (matrix B). + :type kernel: a GPy kernel + :param W_rank: number tuples of the corregionalization parameters 'W' + :type W_rank: integer + """ + K = ICM(input_dim,num_outputs,kernel,W_rank=1,kappa=kappa,name=name) + K.B.W.fix(0) + _range = range(num_outputs) + _range.pop(output) + for j in _range: + K.B.kappa[j] = 0 + K.B.kappa[j].fix() + return K
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/netpbmfile.html b/doc/_build/html/_modules/GPy/util/netpbmfile.html new file mode 100644 index 00000000..a8745650 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/netpbmfile.html @@ -0,0 +1,425 @@ + + + + + + + + GPy.util.netpbmfile — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.netpbmfile

      +#!/usr/bin/env python
      +# -*- coding: utf-8 -*-
      +# netpbmfile.py
      +
      +# Copyright (c) 2011-2013, Christoph Gohlke
      +# Copyright (c) 2011-2013, The Regents of the University of California
      +# Produced at the Laboratory for Fluorescence Dynamics.
      +# All rights reserved.
      +#
      +# Redistribution and use in source and binary forms, with or without
      +# modification, are permitted provided that the following conditions are met:
      +#
      +# * Redistributions of source code must retain the above copyright
      +#   notice, this list of conditions and the following disclaimer.
      +# * Redistributions in binary form must reproduce the above copyright
      +#   notice, this list of conditions and the following disclaimer in the
      +#   documentation and/or other materials provided with the distribution.
      +# * Neither the name of the copyright holders nor the names of any
      +#   contributors may be used to endorse or promote products derived
      +#   from this software without specific prior written permission.
      +#
      +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      +# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      +# POSSIBILITY OF SUCH DAMAGE.
      +
      +"""Read and write image data from respectively to Netpbm files.
      +
      +This implementation follows the Netpbm format specifications at
      +http://netpbm.sourceforge.net/doc/. No gamma correction is performed.
      +
      +The following image formats are supported: PBM (bi-level), PGM (grayscale),
      +PPM (color), PAM (arbitrary), XV thumbnail (RGB332, read-only).
      +
      +:Author:
      +  `Christoph Gohlke <http://www.lfd.uci.edu/~gohlke/>`_
      +
      +:Organization:
      +  Laboratory for Fluorescence Dynamics, University of California, Irvine
      +
      +:Version: 2013.01.18
      +
      +Requirements
      +------------
      +* `CPython 2.7, 3.2 or 3.3 <http://www.python.org>`_
      +* `Numpy 1.7 <http://www.numpy.org>`_
      +* `Matplotlib 1.2 <http://www.matplotlib.org>`_  (optional for plotting)
      +
      +Examples
      +--------
      +>>> im1 = numpy.array([[0, 1],[65534, 65535]], dtype=numpy.uint16)
      +>>> imsave('_tmp.pgm', im1)
      +>>> im2 = imread('_tmp.pgm')
      +>>> assert numpy.all(im1 == im2)
      +
      +"""
      +
      +from __future__ import division, print_function
      +
      +import sys
      +import re
      +import math
      +from copy import deepcopy
      +
      +import numpy
      +
      +__version__ = '2013.01.18'
      +__docformat__ = 'restructuredtext en'
      +__all__ = ['imread', 'imsave', 'NetpbmFile']
      +
      +
      +
      [docs]def imread(filename, *args, **kwargs): + """Return image data from Netpbm file as numpy array. + + `args` and `kwargs` are arguments to NetpbmFile.asarray(). + + Examples + -------- + >>> image = imread('_tmp.pgm') + + """ + try: + netpbm = NetpbmFile(filename) + image = netpbm.asarray() + finally: + netpbm.close() + return image + +
      +
      [docs]def imsave(filename, data, maxval=None, pam=False): + """Write image data to Netpbm file. + + Examples + -------- + >>> image = numpy.array([[0, 1],[65534, 65535]], dtype=numpy.uint16) + >>> imsave('_tmp.pgm', image) + + """ + try: + netpbm = NetpbmFile(data, maxval=maxval) + netpbm.write(filename, pam=pam) + finally: + netpbm.close() + +
      +
      [docs]class NetpbmFile(object): + """Read and write Netpbm PAM, PBM, PGM, PPM, files.""" + + _types = {b'P1': b'BLACKANDWHITE', b'P2': b'GRAYSCALE', b'P3': b'RGB', + b'P4': b'BLACKANDWHITE', b'P5': b'GRAYSCALE', b'P6': b'RGB', + b'P7 332': b'RGB', b'P7': b'RGB_ALPHA'} + + def __init__(self, arg=None, **kwargs): + """Initialize instance from filename, open file, or numpy array.""" + for attr in ('header', 'magicnum', 'width', 'height', 'maxval', + 'depth', 'tupltypes', '_filename', '_fh', '_data'): + setattr(self, attr, None) + if arg is None: + self._fromdata([], **kwargs) + elif isinstance(arg, basestring): + self._fh = open(arg, 'rb') + self._filename = arg + self._fromfile(self._fh, **kwargs) + elif hasattr(arg, 'seek'): + self._fromfile(arg, **kwargs) + self._fh = arg + else: + self._fromdata(arg, **kwargs) + +
      [docs] def asarray(self, copy=True, cache=False, **kwargs): + """Return image data from file as numpy array.""" + data = self._data + if data is None: + data = self._read_data(self._fh, **kwargs) + if cache: + self._data = data + else: + return data + return deepcopy(data) if copy else data +
      +
      [docs] def write(self, arg, **kwargs): + """Write instance to file.""" + if hasattr(arg, 'seek'): + self._tofile(arg, **kwargs) + else: + with open(arg, 'wb') as fid: + self._tofile(fid, **kwargs) +
      +
      [docs] def close(self): + """Close open file. Future asarray calls might fail.""" + if self._filename and self._fh: + self._fh.close() + self._fh = None +
      + def __del__(self): + self.close() + + def _fromfile(self, fh): + """Initialize instance from open file.""" + fh.seek(0) + data = fh.read(4096) + if (len(data) < 7) or not (b'0' < data[1:2] < b'8'): + raise ValueError("Not a Netpbm file:\n%s" % data[:32]) + try: + self._read_pam_header(data) + except Exception: + try: + self._read_pnm_header(data) + except Exception: + raise ValueError("Not a Netpbm file:\n%s" % data[:32]) + + def _read_pam_header(self, data): + """Read PAM header and initialize instance.""" + regroups = re.search( + b"(^P7[\n\r]+(?:(?:[\n\r]+)|(?:#.*)|" + b"(HEIGHT\s+\d+)|(WIDTH\s+\d+)|(DEPTH\s+\d+)|(MAXVAL\s+\d+)|" + b"(?:TUPLTYPE\s+\w+))*ENDHDR\n)", data).groups() + self.header = regroups[0] + self.magicnum = b'P7' + for group in regroups[1:]: + key, value = group.split() + setattr(self, unicode(key).lower(), int(value)) + matches = re.findall(b"(TUPLTYPE\s+\w+)", self.header) + self.tupltypes = [s.split(None, 1)[1] for s in matches] + + def _read_pnm_header(self, data): + """Read PNM header and initialize instance.""" + bpm = data[1:2] in b"14" + regroups = re.search(b"".join(( + b"(^(P[123456]|P7 332)\s+(?:#.*[\r\n])*", + b"\s*(\d+)\s+(?:#.*[\r\n])*", + b"\s*(\d+)\s+(?:#.*[\r\n])*" * (not bpm), + b"\s*(\d+)\s(?:\s*#.*[\r\n]\s)*)")), data).groups() + (1, ) * bpm + self.header = regroups[0] + self.magicnum = regroups[1] + self.width = int(regroups[2]) + self.height = int(regroups[3]) + self.maxval = int(regroups[4]) + self.depth = 3 if self.magicnum in b"P3P6P7 332" else 1 + self.tupltypes = [self._types[self.magicnum]] + + def _read_data(self, fh, byteorder='>'): + """Return image data from open file as numpy array.""" + fh.seek(len(self.header)) + data = fh.read() + dtype = 'u1' if self.maxval < 256 else byteorder + 'u2' + depth = 1 if self.magicnum == b"P7 332" else self.depth + shape = [-1, self.height, self.width, depth] + size = numpy.prod(shape[1:]) + if self.magicnum in b"P1P2P3": + data = numpy.array(data.split(None, size)[:size], dtype) + data = data.reshape(shape) + elif self.maxval == 1: + shape[2] = int(math.ceil(self.width / 8)) + data = numpy.frombuffer(data, dtype).reshape(shape) + data = numpy.unpackbits(data, axis=-2)[:, :, :self.width, :] + else: + data = numpy.frombuffer(data, dtype) + data = data[:size * (data.size // size)].reshape(shape) + if data.shape[0] < 2: + data = data.reshape(data.shape[1:]) + if data.shape[-1] < 2: + data = data.reshape(data.shape[:-1]) + if self.magicnum == b"P7 332": + rgb332 = numpy.array(list(numpy.ndindex(8, 8, 4)), numpy.uint8) + rgb332 *= [36, 36, 85] + data = numpy.take(rgb332, data, axis=0) + return data + + def _fromdata(self, data, maxval=None): + """Initialize instance from numpy array.""" + data = numpy.array(data, ndmin=2, copy=True) + if data.dtype.kind not in "uib": + raise ValueError("not an integer type: %s" % data.dtype) + if data.dtype.kind == 'i' and numpy.min(data) < 0: + raise ValueError("data out of range: %i" % numpy.min(data)) + if maxval is None: + maxval = numpy.max(data) + maxval = 255 if maxval < 256 else 65535 + if maxval < 0 or maxval > 65535: + raise ValueError("data out of range: %i" % maxval) + data = data.astype('u1' if maxval < 256 else '>u2') + self._data = data + if data.ndim > 2 and data.shape[-1] in (3, 4): + self.depth = data.shape[-1] + self.width = data.shape[-2] + self.height = data.shape[-3] + self.magicnum = b'P7' if self.depth == 4 else b'P6' + else: + self.depth = 1 + self.width = data.shape[-1] + self.height = data.shape[-2] + self.magicnum = b'P5' if maxval > 1 else b'P4' + self.maxval = maxval + self.tupltypes = [self._types[self.magicnum]] + self.header = self._header() + + def _tofile(self, fh, pam=False): + """Write Netbm file.""" + fh.seek(0) + fh.write(self._header(pam)) + data = self.asarray(copy=False) + if self.maxval == 1: + data = numpy.packbits(data, axis=-1) + data.tofile(fh) + + def _header(self, pam=False): + """Return file header as byte string.""" + if pam or self.magicnum == b'P7': + header = "\n".join(( + "P7", + "HEIGHT %i" % self.height, + "WIDTH %i" % self.width, + "DEPTH %i" % self.depth, + "MAXVAL %i" % self.maxval, + "\n".join("TUPLTYPE %s" % unicode(i) for i in self.tupltypes), + "ENDHDR\n")) + elif self.maxval == 1: + header = "P4 %i %i\n" % (self.width, self.height) + elif self.depth == 1: + header = "P5 %i %i %i\n" % (self.width, self.height, self.maxval) + else: + header = "P6 %i %i %i\n" % (self.width, self.height, self.maxval) + if sys.version_info[0] > 2: + header = bytes(header, 'ascii') + return header + + def __str__(self): + """Return information about instance.""" + return unicode(self.header) + +
      +if sys.version_info[0] > 2: + basestring = str + unicode = lambda x: str(x, 'ascii') + +if __name__ == "__main__": + # Show images specified on command line or all images in current directory + from glob import glob + from matplotlib import pyplot + files = sys.argv[1:] if len(sys.argv) > 1 else glob('*.p*m') + for fname in files: + try: + pam = NetpbmFile(fname) + img = pam.asarray(copy=False) + if False: + pam.write('_tmp.pgm.out', pam=True) + img2 = imread('_tmp.pgm.out') + assert numpy.all(img == img2) + imsave('_tmp.pgm.out', img) + img2 = imread('_tmp.pgm.out') + assert numpy.all(img == img2) + pam.close() + except ValueError as e: + print(fname, e) + continue + _shape = img.shape + if img.ndim > 3 or (img.ndim > 2 and img.shape[-1] not in (3, 4)): + img = img[0] + cmap = 'gray' if pam.maxval > 1 else 'binary' + pyplot.imshow(img, cmap, interpolation='nearest') + pyplot.title("%s %s %s %s" % (fname, unicode(pam.magicnum), + _shape, img.dtype)) + pyplot.show() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/normalizer.html b/doc/_build/html/_modules/GPy/util/normalizer.html new file mode 100644 index 00000000..89366e59 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/normalizer.html @@ -0,0 +1,139 @@ + + + + + + + + GPy.util.normalizer — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.normalizer

      +'''
      +Created on Aug 27, 2014
      +
      +@author: t-mazwie
      +'''
      +import logging
      +import numpy as np
      +
      +
      [docs]class Norm(object): + def __init__(self): + pass +
      [docs] def scale_by(self, Y): + """ + Use data matrix Y as normalization space to work in. + """ + raise NotImplementedError
      +
      [docs] def normalize(self, Y): + """ + Project Y into normalized space + """ + raise NotImplementedError
      +
      [docs] def inverse_mean(self, X): + """ + Project the normalized object X into space of Y + """ + raise NotImplementedError
      +
      [docs] def inverse_variance(self, var): + return var
      +
      [docs] def scaled(self): + """ + Whether this Norm object has been initialized. + """ + raise NotImplementedError
      +
      [docs]class MeanNorm(Norm): + def __init__(self): + self.mean = None +
      [docs] def scale_by(self, Y): + Y = np.ma.masked_invalid(Y, copy=False) + self.mean = Y.mean(0).view(np.ndarray)
      +
      [docs] def normalize(self, Y): + return Y-self.mean
      +
      [docs] def inverse_mean(self, X): + return X+self.mean
      +
      [docs] def scaled(self): + return self.mean is not None
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/parallel.html b/doc/_build/html/_modules/GPy/util/parallel.html new file mode 100644 index 00000000..d09d52b1 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/parallel.html @@ -0,0 +1,135 @@ + + + + + + + + GPy.util.parallel — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.parallel

      +"""
      +The module of tools for parallelization (MPI)
      +"""
      +import numpy as np
      +try:
      +    from mpi4py import MPI
      +    def get_id_within_node(comm=MPI.COMM_WORLD):
      +        rank = comm.rank
      +        nodename =  MPI.Get_processor_name()
      +        nodelist = comm.allgather(nodename)
      +        return len([i for i in nodelist[:rank] if i==nodename])
      +
      +    numpy_to_MPI_typemap = {
      +        np.dtype(np.float64) : MPI.DOUBLE,
      +        np.dtype(np.float32) : MPI.FLOAT,
      +        np.dtype(np.int)     : MPI.INT,
      +        np.dtype(np.int8)    : MPI.CHAR,
      +        np.dtype(np.uint8)   : MPI.UNSIGNED_CHAR,
      +        np.dtype(np.int32)   : MPI.INT,
      +        np.dtype(np.uint32)  : MPI.UNSIGNED_INT,
      +    }
      +except:
      +    pass
      +
      +
      [docs]def divide_data(datanum, rank, size): + assert rank<size and datanum>0 + + residue = (datanum)%size + datanum_list = np.empty((size),dtype=np.int32) + for i in xrange(size): + if i<residue: + datanum_list[i] = int(datanum/size)+1 + else: + datanum_list[i] = int(datanum/size) + if rank<residue: + size = datanum/size+1 + offset = size*rank + else: + size = datanum/size + offset = size*rank+residue + return offset, offset+size, datanum_list
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/pca.html b/doc/_build/html/_modules/GPy/util/pca.html new file mode 100644 index 00000000..58843ce1 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/pca.html @@ -0,0 +1,235 @@ + + + + + + + + GPy.util.pca — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.pca

      +'''
      +Created on 10 Sep 2012
      +
      +@author: Max Zwiessele
      +@copyright: Max Zwiessele 2012
      +'''
      +import numpy
      +try:
      +    import pylab
      +    import matplotlib
      +except:
      +    pass
      +from numpy.linalg.linalg import LinAlgError
      +from operator import setitem
      +import itertools
      +
      +
      [docs]class PCA(object): + """ + PCA module with automatic primal/dual determination. + """ + def __init__(self, X): + self.mu = None + self.sigma = None + + X = self.center(X) + + # self.X = input + if X.shape[0] >= X.shape[1]: + # print "N >= D: using primal" + self.eigvals, self.eigvectors = self._primal_eig(X) + else: + # print "N < D: using dual" + self.eigvals, self.eigvectors = self._dual_eig(X) + self.sort = numpy.argsort(self.eigvals)[::-1] + self.eigvals = self.eigvals[self.sort] + self.eigvectors = self.eigvectors[:, self.sort] + self.fracs = self.eigvals / self.eigvals.sum() + self.Q = self.eigvals.shape[0] + +
      [docs] def center(self, X): + """ + Center `X` in PCA space. + """ + X = X.copy() + inan = numpy.isnan(X) + if self.mu is None: + X_ = numpy.ma.masked_array(X, inan) + self.mu = X_.mean(0).base + self.sigma = X_.std(0).base + reduce(lambda y,x: setitem(x[0], x[1], x[2]), itertools.izip(X.T, inan.T, self.mu), None) + X = X - self.mu + X = X / numpy.where(self.sigma == 0, 1e-30, self.sigma) + return X +
      + def _primal_eig(self, X): + return numpy.linalg.eigh(numpy.einsum('ji,jk->ik',X,X)) + + def _dual_eig(self, X): + dual_eigvals, dual_eigvects = numpy.linalg.eigh(numpy.einsum('ij,kj->ik',X,X)) + relevant_dimensions = numpy.argsort(numpy.abs(dual_eigvals))[-X.shape[1]:] + eigvals = dual_eigvals[relevant_dimensions] + eigvects = dual_eigvects[:, relevant_dimensions] + eigvects = (1. / numpy.sqrt(X.shape[0] * numpy.abs(eigvals))) * X.T.dot(eigvects) + eigvects /= numpy.sqrt(numpy.diag(eigvects.T.dot(eigvects))) + return eigvals, eigvects + +
      [docs] def project(self, X, Q=None): + """ + Project X into PCA space, defined by the Q highest eigenvalues. + Y = X dot V + """ + if Q is None: + Q = self.Q + if Q > X.shape[1]: + raise IndexError("requested dimension larger then input dimension") + X = self.center(X) + return X.dot(self.eigvectors[:, :Q]) +
      +
      [docs] def plot_fracs(self, Q=None, ax=None, fignum=None): + """ + Plot fractions of Eigenvalues sorted in descending order. + """ + from GPy.plotting.matplot_dep import Tango + Tango.reset() + col = Tango.nextMedium() + if ax is None: + fig = pylab.figure(fignum) + ax = fig.add_subplot(111) + if Q is None: + Q = self.Q + ticks = numpy.arange(Q) + bar = ax.bar(ticks - .4, self.fracs[:Q], color=col) + ax.set_xticks(ticks, map(lambda x: r"${}$".format(x), ticks + 1)) + ax.set_ylabel("Eigenvalue fraction") + ax.set_xlabel("PC") + ax.set_ylim(0, ax.get_ylim()[1]) + ax.set_xlim(ticks.min() - .5, ticks.max() + .5) + try: + pylab.tight_layout() + except: + pass + return bar +
      +
      [docs] def plot_2d(self, X, labels=None, s=20, marker='o', + dimensions=(0, 1), ax=None, colors=None, + fignum=None, cmap=None, # @UndefinedVariable + ** kwargs): + """ + Plot dimensions `dimensions` with given labels against each other in + PC space. Labels can be any sequence of labels of dimensions X.shape[0]. + Labels can be drawn with a subsequent call to legend() + """ + if cmap is None: + cmap = matplotlib.cm.jet + if ax is None: + fig = pylab.figure(fignum) + ax = fig.add_subplot(111) + if labels is None: + labels = numpy.zeros(X.shape[0]) + ulabels = [] + for lab in labels: + if not lab in ulabels: + ulabels.append(lab) + nlabels = len(ulabels) + if colors is None: + colors = iter([cmap(float(i) / nlabels) for i in range(nlabels)]) + else: + colors = iter(colors) + X_ = self.project(X, self.Q)[:,dimensions] + kwargs.update(dict(s=s)) + plots = list() + for i, l in enumerate(ulabels): + kwargs.update(dict(color=colors.next(), marker=marker[i % len(marker)])) + plots.append(ax.scatter(*X_[labels == l, :].T, label=str(l), **kwargs)) + ax.set_xlabel(r"PC$_1$") + ax.set_ylabel(r"PC$_2$") + try: + pylab.tight_layout() + except: + pass + return plots
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/squashers.html b/doc/_build/html/_modules/GPy/util/squashers.html new file mode 100644 index 00000000..28e6b41d --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/squashers.html @@ -0,0 +1,110 @@ + + + + + + + + GPy.util.squashers — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.squashers

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +
      +
      [docs]def sigmoid(x): + return 1./(1.+np.exp(-x)) +
      +
      [docs]def softmax(x): + ex = np.exp(x-x.max(1)[:,None]) + return ex/ex.sum(1)[:,np.newaxis] +
      +
      [docs]def single_softmax(x): + ex = np.exp(x) + return ex/ex.sum() +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/subarray_and_sorting.html b/doc/_build/html/_modules/GPy/util/subarray_and_sorting.html new file mode 100644 index 00000000..1867c5fe --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/subarray_and_sorting.html @@ -0,0 +1,156 @@ + + + + + + + + GPy.util.subarray_and_sorting — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.subarray_and_sorting

      +'''
      +.. module:: GPy.util.subarray_and_sorting
      +
      +.. moduleauthor:: Max Zwiessele <ibinbei@gmail.com>
      +
      +'''
      +__updated__ = '2014-05-21'
      +
      +import numpy as np, logging
      +
      +
      [docs]def common_subarrays(X, axis=0): + """ + Find common subarrays of 2 dimensional X, where axis is the axis to apply the search over. + Common subarrays are returned as a dictionary of <subarray, [index]> pairs, where + the subarray is a tuple representing the subarray and the index is the index + for the subarray in X, where index is the index to the remaining axis. + + :param :class:`np.ndarray` X: 2d array to check for common subarrays in + :param int axis: axis to apply subarray detection over. + When the index is 0, compare rows -- columns, otherwise. + + Examples: + ========= + + In a 2d array: + >>> import numpy as np + >>> X = np.zeros((3,6), dtype=bool) + >>> X[[1,1,1],[0,4,5]] = 1; X[1:,[2,3]] = 1 + >>> X + array([[False, False, False, False, False, False], + [ True, False, True, True, True, True], + [False, False, True, True, False, False]], dtype=bool) + >>> d = common_subarrays(X,axis=1) + >>> len(d) + 3 + >>> X[:, d[tuple(X[:,0])]] + array([[False, False, False], + [ True, True, True], + [False, False, False]], dtype=bool) + >>> d[tuple(X[:,4])] == d[tuple(X[:,0])] == [0, 4, 5] + True + >>> d[tuple(X[:,1])] + [1] + """ + from collections import defaultdict + from itertools import count + from operator import iadd + assert X.ndim == 2 and axis in (0,1), "Only implemented for 2D arrays" + subarrays = defaultdict(list) + cnt = count() + def accumulate(x, s, c): + t = tuple(x) + col = c.next() + iadd(s[t], [col]) + return None + if axis == 0: [accumulate(x, subarrays, cnt) for x in X] + else: [accumulate(x, subarrays, cnt) for x in X.T] + return subarrays +
      +if __name__ == '__main__': + import doctest + doctest.testmod() +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/univariate_Gaussian.html b/doc/_build/html/_modules/GPy/util/univariate_Gaussian.html new file mode 100644 index 00000000..19e1e7e7 --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/univariate_Gaussian.html @@ -0,0 +1,180 @@ + + + + + + + + GPy.util.univariate_Gaussian — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.univariate_Gaussian

      +# Copyright (c) 2012, 2013 Ricardo Andrade
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +import numpy as np
      +from scipy import weave
      +
      +
      [docs]def std_norm_pdf(x): + """Standard Gaussian density function""" + return 1./np.sqrt(2.*np.pi)*np.exp(-.5*x**2) +
      +
      [docs]def std_norm_cdf(x): + """ + Cumulative standard Gaussian distribution + Based on Abramowitz, M. and Stegun, I. (1970) + """ + x_shape = np.asarray(x).shape + + if len(x_shape) == 0 or x_shape[0] == 1: + sign = np.sign(x) + x *= sign + x /= np.sqrt(2.) + t = 1.0/(1.0 + 0.3275911*x) + erf = 1. - np.exp(-x**2)*t*(0.254829592 + t*(-0.284496736 + t*(1.421413741 + t*(-1.453152027 + t*(1.061405429))))) + cdf_x = 0.5*(1.0 + sign*erf) + return cdf_x + else: + x = np.atleast_1d(x).copy() + cdf_x = np.zeros_like(x) + sign = np.ones_like(x) + neg_x_ind = x<0 + sign[neg_x_ind] = -1.0 + x[neg_x_ind] = -x[neg_x_ind] + x /= np.sqrt(2.) + t = 1.0/(1.0 + 0.3275911*x) + erf = 1. - np.exp(-x**2)*t*(0.254829592 + t*(-0.284496736 + t*(1.421413741 + t*(-1.453152027 + t*(1.061405429))))) + cdf_x = 0.5*(1.0 + sign*erf) + cdf_x = cdf_x.reshape(x_shape) + return cdf_x +
      +
      [docs]def std_norm_cdf_weave(x): + """ + Cumulative standard Gaussian distribution + Based on Abramowitz, M. and Stegun, I. (1970) + + A weave implementation of std_norm_cdf, which is faster. this is unused, + because of the difficulties of a weave dependency. (see github issue #94) + + """ + #Generalize for many x + x = np.asarray(x).copy() + cdf_x = np.zeros_like(x) + N = x.size + support_code = "#include <math.h>" + code = """ + + double sign, t, erf; + for (int i=0; i<N; i++){ + sign = 1.0; + if (x[i] < 0.0){ + sign = -1.0; + x[i] = -x[i]; + } + x[i] = x[i]/sqrt(2.0); + + t = 1.0/(1.0 + 0.3275911*x[i]); + + erf = 1. - exp(-x[i]*x[i])*t*(0.254829592 + t*(-0.284496736 + t*(1.421413741 + t*(-1.453152027 + t*(1.061405429))))); + + //return_val = 0.5*(1.0 + sign*erf); + cdf_x[i] = 0.5*(1.0 + sign*erf); + } + """ + weave.inline(code, arg_names=['x', 'cdf_x', 'N'], support_code=support_code) + return cdf_x +
      +
      [docs]def inv_std_norm_cdf(x): + """ + Inverse cumulative standard Gaussian distribution + Based on Winitzki, S. (2008) + """ + z = 2*x -1 + ln1z2 = np.log(1-z**2) + a = 8*(np.pi -3)/(3*np.pi*(4-np.pi)) + b = 2/(np.pi * a) + ln1z2/2 + inv_erf = np.sign(z) * np.sqrt( np.sqrt(b**2 - ln1z2/a) - b ) + return np.sqrt(2) * inv_erf +
      + +
      +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/GPy/util/warping_functions.html b/doc/_build/html/_modules/GPy/util/warping_functions.html new file mode 100644 index 00000000..68bf236c --- /dev/null +++ b/doc/_build/html/_modules/GPy/util/warping_functions.html @@ -0,0 +1,376 @@ + + + + + + + + GPy.util.warping_functions — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for GPy.util.warping_functions

      +# Copyright (c) 2012, GPy authors (see AUTHORS.txt).
      +# Licensed under the BSD 3-clause license (see LICENSE.txt)
      +
      +
      +import numpy as np
      +
      +
      [docs]class WarpingFunction(object): + """ + abstract function for warping + z = f(y) + """ + + def __init__(self): + raise NotImplementedError + +
      [docs] def f(self,y,psi): + """function transformation + y is a list of values (GP training data) of shpape [N,1] + """ + raise NotImplementedError +
      +
      [docs] def fgrad_y(self,y,psi): + """gradient of f w.r.t to y""" + raise NotImplementedError +
      +
      [docs] def fgrad_y_psi(self,y,psi): + """gradient of f w.r.t to y""" + raise NotImplementedError +
      +
      [docs] def f_inv(self,z,psi): + """inverse function transformation""" + raise NotImplementedError +
      + def _get_param_names(self): + raise NotImplementedError + +
      [docs] def plot(self, psi, xmin, xmax): + y = np.arange(xmin, xmax, 0.01) + f_y = self.f(y, psi) + from matplotlib import pyplot as plt + plt.figure() + plt.plot(y, f_y) + plt.xlabel('y') + plt.ylabel('f(y)') + plt.title('warping function') +
      +
      [docs]class TanhWarpingFunction(WarpingFunction): + + def __init__(self,n_terms=3): + """n_terms specifies the number of tanh terms to be used""" + self.n_terms = n_terms + self.num_parameters = 3 * self.n_terms + +
      [docs] def f(self,y,psi): + """ + transform y with f using parameter vector psi + psi = [[a,b,c]] + ::math::`f = \\sum_{terms} a * tanh(b*(y+c))` + + """ + + #1. check that number of params is consistent + assert psi.shape[0] == self.n_terms, 'inconsistent parameter dimensions' + assert psi.shape[1] == 3, 'inconsistent parameter dimensions' + + #2. exponentiate the a and b (positive!) + mpsi = psi.copy() + + #3. transform data + z = y.copy() + for i in range(len(mpsi)): + a,b,c = mpsi[i] + z += a*np.tanh(b*(y+c)) + return z + +
      +
      [docs] def f_inv(self, y, psi, iterations = 10): + """ + calculate the numerical inverse of f + + :param iterations: number of N.R. iterations + + """ + + y = y.copy() + z = np.ones_like(y) + + for i in range(iterations): + z -= (self.f(z, psi) - y)/self.fgrad_y(z,psi) + + return z + +
      +
      [docs] def fgrad_y(self, y, psi, return_precalc = False): + """ + gradient of f w.r.t to y ([N x 1]) + returns: Nx1 vector of derivatives, unless return_precalc is true, + then it also returns the precomputed stuff + """ + + mpsi = psi.copy() + + # vectorized version + + # S = (mpsi[:,1]*(y + mpsi[:,2])).T + S = (mpsi[:,1]*(y[:,:,None] + mpsi[:,2])).T + R = np.tanh(S) + D = 1-R**2 + + # GRAD = (1+(mpsi[:,0:1]*mpsi[:,1:2]*D).sum(axis=0))[:,np.newaxis] + GRAD = (1+(mpsi[:,0:1][:,:,None]*mpsi[:,1:2][:,:,None]*D).sum(axis=0)).T + + if return_precalc: + # return GRAD,S.sum(axis=1),R.sum(axis=1),D.sum(axis=1) + return GRAD, S, R, D + + + return GRAD + +
      +
      [docs] def fgrad_y_psi(self, y, psi, return_covar_chain = False): + """ + gradient of f w.r.t to y and psi + + returns: NxIx3 tensor of partial derivatives + + """ + + # 1. exponentiate the a and b (positive!) + mpsi = psi.copy() + w, s, r, d = self.fgrad_y(y, psi, return_precalc = True) + + gradients = np.zeros((y.shape[0], y.shape[1], len(mpsi), 3)) + for i in range(len(mpsi)): + a,b,c = mpsi[i] + gradients[:,:,i,0] = (b*(1.0/np.cosh(s[i]))**2).T + gradients[:,:,i,1] = a*(d[i] - 2.0*s[i]*r[i]*(1.0/np.cosh(s[i]))**2).T + gradients[:,:,i,2] = (-2.0*a*(b**2)*r[i]*((1.0/np.cosh(s[i]))**2)).T + + + if return_covar_chain: + covar_grad_chain = np.zeros((y.shape[0], y.shape[1], len(mpsi), 3)) + + for i in range(len(mpsi)): + a,b,c = mpsi[i] + covar_grad_chain[:, :, i, 0] = (r[i]).T + covar_grad_chain[:, :, i, 1] = (a*(y + c) * ((1.0/np.cosh(s[i]))**2).T) + covar_grad_chain[:, :, i, 2] = a*b*((1.0/np.cosh(s[i]))**2).T + + return gradients, covar_grad_chain + + return gradients +
      + def _get_param_names(self): + variables = ['a', 'b', 'c'] + names = sum([['warp_tanh_%s_t%i' % (variables[n],q) for n in range(3)] for q in range(self.n_terms)],[]) + return names + +
      +
      [docs]class TanhWarpingFunction_d(WarpingFunction): + + def __init__(self,n_terms=3): + """n_terms specifies the number of tanh terms to be used""" + self.n_terms = n_terms + self.num_parameters = 3 * self.n_terms + 1 + +
      [docs] def f(self,y,psi): + """ + Transform y with f using parameter vector psi + psi = [[a,b,c]] + + :math:`f = \\sum_{terms} a * tanh(b*(y+c))` + """ + + #1. check that number of params is consistent + # assert psi.shape[0] == self.n_terms, 'inconsistent parameter dimensions' + # assert psi.shape[1] == 4, 'inconsistent parameter dimensions' + mpsi = psi.copy() + d = psi[-1] + mpsi = mpsi[:self.num_parameters-1].reshape(self.n_terms, 3) + + #3. transform data + z = d*y.copy() + for i in range(len(mpsi)): + a,b,c = mpsi[i] + z += a*np.tanh(b*(y+c)) + return z + +
      +
      [docs] def f_inv(self, z, psi, max_iterations=1000, y=None): + """ + calculate the numerical inverse of f + + :param max_iterations: maximum number of N.R. iterations + + """ + + z = z.copy() + if y is None: + y = np.ones_like(z) + + it = 0 + update = np.inf + + while it == 0 or (np.abs(update).sum() > 1e-10 and it < max_iterations): + update = (self.f(y, psi) - z)/self.fgrad_y(y, psi) + y -= update + it += 1 + if it == max_iterations: + print "WARNING!!! Maximum number of iterations reached in f_inv " + + return y + +
      +
      [docs] def fgrad_y(self, y, psi, return_precalc = False): + """ + gradient of f w.r.t to y ([N x 1]) + + :returns: Nx1 vector of derivatives, unless return_precalc is true, then it also returns the precomputed stuff + + """ + + + mpsi = psi.copy() + d = psi[-1] + mpsi = mpsi[:self.num_parameters-1].reshape(self.n_terms, 3) + + # vectorized version + + S = (mpsi[:,1]*(y[:,:,None] + mpsi[:,2])).T + R = np.tanh(S) + D = 1-R**2 + + GRAD = (d + (mpsi[:,0:1][:,:,None]*mpsi[:,1:2][:,:,None]*D).sum(axis=0)).T + + if return_precalc: + return GRAD, S, R, D + + + return GRAD + +
      +
      [docs] def fgrad_y_psi(self, y, psi, return_covar_chain = False): + """ + gradient of f w.r.t to y and psi + + :returns: NxIx4 tensor of partial derivatives + + """ + + mpsi = psi.copy() + mpsi = mpsi[:self.num_parameters-1].reshape(self.n_terms, 3) + + w, s, r, d = self.fgrad_y(y, psi, return_precalc = True) + + gradients = np.zeros((y.shape[0], y.shape[1], len(mpsi), 4)) + for i in range(len(mpsi)): + a,b,c = mpsi[i] + gradients[:,:,i,0] = (b*(1.0/np.cosh(s[i]))**2).T + gradients[:,:,i,1] = a*(d[i] - 2.0*s[i]*r[i]*(1.0/np.cosh(s[i]))**2).T + gradients[:,:,i,2] = (-2.0*a*(b**2)*r[i]*((1.0/np.cosh(s[i]))**2)).T + gradients[:,:,0,3] = 1.0 + + if return_covar_chain: + covar_grad_chain = np.zeros((y.shape[0], y.shape[1], len(mpsi), 4)) + + for i in range(len(mpsi)): + a,b,c = mpsi[i] + covar_grad_chain[:, :, i, 0] = (r[i]).T + covar_grad_chain[:, :, i, 1] = (a*(y + c) * ((1.0/np.cosh(s[i]))**2).T) + covar_grad_chain[:, :, i, 2] = a*b*((1.0/np.cosh(s[i]))**2).T + covar_grad_chain[:, :, 0, 3] = y + + return gradients, covar_grad_chain + + return gradients +
      + def _get_param_names(self): + variables = ['a', 'b', 'c', 'd'] + names = sum([['warp_tanh_%s_t%i' % (variables[n],q) for n in range(3)] for q in range(self.n_terms)],[]) + names.append('warp_tanh_d') + return names
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/index.html b/doc/_build/html/_modules/index.html new file mode 100644 index 00000000..a8f23fd7 --- /dev/null +++ b/doc/_build/html/_modules/index.html @@ -0,0 +1,242 @@ + + + + + + + + Overview: module code — GPy documentation + + + + + + + + + + + + + +
      +
      +
      +
      + +

      All modules for which code is available

      + + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/multiprocessing/synchronize.html b/doc/_build/html/_modules/multiprocessing/synchronize.html new file mode 100644 index 00000000..78161be2 --- /dev/null +++ b/doc/_build/html/_modules/multiprocessing/synchronize.html @@ -0,0 +1,436 @@ + + + + + + + + multiprocessing.synchronize — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for multiprocessing.synchronize

      +#
      +# Module implementing synchronization primitives
      +#
      +# multiprocessing/synchronize.py
      +#
      +# Copyright (c) 2006-2008, R Oudkerk
      +# All rights reserved.
      +#
      +# Redistribution and use in source and binary forms, with or without
      +# modification, are permitted provided that the following conditions
      +# are met:
      +#
      +# 1. Redistributions of source code must retain the above copyright
      +#    notice, this list of conditions and the following disclaimer.
      +# 2. Redistributions in binary form must reproduce the above copyright
      +#    notice, this list of conditions and the following disclaimer in the
      +#    documentation and/or other materials provided with the distribution.
      +# 3. Neither the name of author nor the names of any contributors may be
      +#    used to endorse or promote products derived from this software
      +#    without specific prior written permission.
      +#
      +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
      +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      +# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      +# SUCH DAMAGE.
      +#
      +
      +__all__ = [
      +    'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition', 'Event'
      +    ]
      +
      +import threading
      +import os
      +import sys
      +
      +from time import time as _time, sleep as _sleep
      +
      +import _multiprocessing
      +from multiprocessing.process import current_process
      +from multiprocessing.util import Finalize, register_after_fork, debug
      +from multiprocessing.forking import assert_spawning, Popen
      +
      +# Try to import the mp.synchronize module cleanly, if it fails
      +# raise ImportError for platforms lacking a working sem_open implementation.
      +# See issue 3770
      +try:
      +    from _multiprocessing import SemLock
      +except (ImportError):
      +    raise ImportError("This platform lacks a functioning sem_open" +
      +                      " implementation, therefore, the required" +
      +                      " synchronization primitives needed will not" +
      +                      " function, see issue 3770.")
      +
      +#
      +# Constants
      +#
      +
      +RECURSIVE_MUTEX, SEMAPHORE = range(2)
      +SEM_VALUE_MAX = _multiprocessing.SemLock.SEM_VALUE_MAX
      +
      +#
      +# Base class for semaphores and mutexes; wraps `_multiprocessing.SemLock`
      +#
      +
      +class SemLock(object):
      +
      +    def __init__(self, kind, value, maxvalue):
      +        sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue)
      +        debug('created semlock with handle %s' % sl.handle)
      +        self._make_methods()
      +
      +        if sys.platform != 'win32':
      +            def _after_fork(obj):
      +                obj._semlock._after_fork()
      +            register_after_fork(self, _after_fork)
      +
      +    def _make_methods(self):
      +        self.acquire = self._semlock.acquire
      +        self.release = self._semlock.release
      +
      +    def __enter__(self):
      +        return self._semlock.__enter__()
      +
      +    def __exit__(self, *args):
      +        return self._semlock.__exit__(*args)
      +
      +    def __getstate__(self):
      +        assert_spawning(self)
      +        sl = self._semlock
      +        return (Popen.duplicate_for_child(sl.handle), sl.kind, sl.maxvalue)
      +
      +    def __setstate__(self, state):
      +        self._semlock = _multiprocessing.SemLock._rebuild(*state)
      +        debug('recreated blocker with handle %r' % state[0])
      +        self._make_methods()
      +
      +#
      +# Semaphore
      +#
      +
      +class Semaphore(SemLock):
      +
      +    def __init__(self, value=1):
      +        SemLock.__init__(self, SEMAPHORE, value, SEM_VALUE_MAX)
      +
      +    def get_value(self):
      +        return self._semlock._get_value()
      +
      +    def __repr__(self):
      +        try:
      +            value = self._semlock._get_value()
      +        except Exception:
      +            value = 'unknown'
      +        return '<Semaphore(value=%s)>' % value
      +
      +#
      +# Bounded semaphore
      +#
      +
      +class BoundedSemaphore(Semaphore):
      +
      +    def __init__(self, value=1):
      +        SemLock.__init__(self, SEMAPHORE, value, value)
      +
      +    def __repr__(self):
      +        try:
      +            value = self._semlock._get_value()
      +        except Exception:
      +            value = 'unknown'
      +        return '<BoundedSemaphore(value=%s, maxvalue=%s)>' % \
      +               (value, self._semlock.maxvalue)
      +
      +#
      +# Non-recursive lock
      +#
      +
      +class Lock(SemLock):
      +
      +    def __init__(self):
      +        SemLock.__init__(self, SEMAPHORE, 1, 1)
      +
      +    def __repr__(self):
      +        try:
      +            if self._semlock._is_mine():
      +                name = current_process().name
      +                if threading.current_thread().name != 'MainThread':
      +                    name += '|' + threading.current_thread().name
      +            elif self._semlock._get_value() == 1:
      +                name = 'None'
      +            elif self._semlock._count() > 0:
      +                name = 'SomeOtherThread'
      +            else:
      +                name = 'SomeOtherProcess'
      +        except Exception:
      +            name = 'unknown'
      +        return '<Lock(owner=%s)>' % name
      +
      +#
      +# Recursive lock
      +#
      +
      +class RLock(SemLock):
      +
      +    def __init__(self):
      +        SemLock.__init__(self, RECURSIVE_MUTEX, 1, 1)
      +
      +    def __repr__(self):
      +        try:
      +            if self._semlock._is_mine():
      +                name = current_process().name
      +                if threading.current_thread().name != 'MainThread':
      +                    name += '|' + threading.current_thread().name
      +                count = self._semlock._count()
      +            elif self._semlock._get_value() == 1:
      +                name, count = 'None', 0
      +            elif self._semlock._count() > 0:
      +                name, count = 'SomeOtherThread', 'nonzero'
      +            else:
      +                name, count = 'SomeOtherProcess', 'nonzero'
      +        except Exception:
      +            name, count = 'unknown', 'unknown'
      +        return '<RLock(%s, %s)>' % (name, count)
      +
      +#
      +# Condition variable
      +#
      +
      +class Condition(object):
      +
      +    def __init__(self, lock=None):
      +        self._lock = lock or RLock()
      +        self._sleeping_count = Semaphore(0)
      +        self._woken_count = Semaphore(0)
      +        self._wait_semaphore = Semaphore(0)
      +        self._make_methods()
      +
      +    def __getstate__(self):
      +        assert_spawning(self)
      +        return (self._lock, self._sleeping_count,
      +                self._woken_count, self._wait_semaphore)
      +
      +    def __setstate__(self, state):
      +        (self._lock, self._sleeping_count,
      +         self._woken_count, self._wait_semaphore) = state
      +        self._make_methods()
      +
      +    def __enter__(self):
      +        return self._lock.__enter__()
      +
      +    def __exit__(self, *args):
      +        return self._lock.__exit__(*args)
      +
      +    def _make_methods(self):
      +        self.acquire = self._lock.acquire
      +        self.release = self._lock.release
      +
      +    def __repr__(self):
      +        try:
      +            num_waiters = (self._sleeping_count._semlock._get_value() -
      +                           self._woken_count._semlock._get_value())
      +        except Exception:
      +            num_waiters = 'unknown'
      +        return '<Condition(%s, %s)>' % (self._lock, num_waiters)
      +
      +    def wait(self, timeout=None):
      +        assert self._lock._semlock._is_mine(), \
      +               'must acquire() condition before using wait()'
      +
      +        # indicate that this thread is going to sleep
      +        self._sleeping_count.release()
      +
      +        # release lock
      +        count = self._lock._semlock._count()
      +        for i in xrange(count):
      +            self._lock.release()
      +
      +        try:
      +            # wait for notification or timeout
      +            self._wait_semaphore.acquire(True, timeout)
      +        finally:
      +            # indicate that this thread has woken
      +            self._woken_count.release()
      +
      +            # reacquire lock
      +            for i in xrange(count):
      +                self._lock.acquire()
      +
      +    def notify(self):
      +        assert self._lock._semlock._is_mine(), 'lock is not owned'
      +        assert not self._wait_semaphore.acquire(False)
      +
      +        # to take account of timeouts since last notify() we subtract
      +        # woken_count from sleeping_count and rezero woken_count
      +        while self._woken_count.acquire(False):
      +            res = self._sleeping_count.acquire(False)
      +            assert res
      +
      +        if self._sleeping_count.acquire(False): # try grabbing a sleeper
      +            self._wait_semaphore.release()      # wake up one sleeper
      +            self._woken_count.acquire()         # wait for the sleeper to wake
      +
      +            # rezero _wait_semaphore in case a timeout just happened
      +            self._wait_semaphore.acquire(False)
      +
      +    def notify_all(self):
      +        assert self._lock._semlock._is_mine(), 'lock is not owned'
      +        assert not self._wait_semaphore.acquire(False)
      +
      +        # to take account of timeouts since last notify*() we subtract
      +        # woken_count from sleeping_count and rezero woken_count
      +        while self._woken_count.acquire(False):
      +            res = self._sleeping_count.acquire(False)
      +            assert res
      +
      +        sleepers = 0
      +        while self._sleeping_count.acquire(False):
      +            self._wait_semaphore.release()        # wake up one sleeper
      +            sleepers += 1
      +
      +        if sleepers:
      +            for i in xrange(sleepers):
      +                self._woken_count.acquire()       # wait for a sleeper to wake
      +
      +            # rezero wait_semaphore in case some timeouts just happened
      +            while self._wait_semaphore.acquire(False):
      +                pass
      +
      +#
      +# Event
      +#
      +
      +class Event(object):
      +
      +    def __init__(self):
      +        self._cond = Condition(Lock())
      +        self._flag = Semaphore(0)
      +
      +    def is_set(self):
      +        self._cond.acquire()
      +        try:
      +            if self._flag.acquire(False):
      +                self._flag.release()
      +                return True
      +            return False
      +        finally:
      +            self._cond.release()
      +
      +    def set(self):
      +        self._cond.acquire()
      +        try:
      +            self._flag.acquire(False)
      +            self._flag.release()
      +            self._cond.notify_all()
      +        finally:
      +            self._cond.release()
      +
      +    def clear(self):
      +        self._cond.acquire()
      +        try:
      +            self._flag.acquire(False)
      +        finally:
      +            self._cond.release()
      +
      +    def wait(self, timeout=None):
      +        self._cond.acquire()
      +        try:
      +            if self._flag.acquire(False):
      +                self._flag.release()
      +            else:
      +                self._cond.wait(timeout)
      +
      +            if self._flag.acquire(False):
      +                self._flag.release()
      +                return True
      +            return False
      +        finally:
      +            self._cond.release()
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_modules/unittest/case.html b/doc/_build/html/_modules/unittest/case.html new file mode 100644 index 00000000..535cf9ec --- /dev/null +++ b/doc/_build/html/_modules/unittest/case.html @@ -0,0 +1,1168 @@ + + + + + + + + unittest.case — GPy documentation + + + + + + + + + + + + + + +
      +
      +
      +
      + +

      Source code for unittest.case

      +"""Test case implementation"""
      +
      +import collections
      +import sys
      +import functools
      +import difflib
      +import pprint
      +import re
      +import types
      +import warnings
      +
      +from . import result
      +from .util import (
      +    strclass, safe_repr, unorderable_list_difference,
      +    _count_diff_all_purpose, _count_diff_hashable
      +)
      +
      +
      +__unittest = True
      +
      +
      +DIFF_OMITTED = ('\nDiff is %s characters long. '
      +                 'Set self.maxDiff to None to see it.')
      +
      +class SkipTest(Exception):
      +    """
      +    Raise this exception in a test to skip it.
      +
      +    Usually you can use TestCase.skipTest() or one of the skipping decorators
      +    instead of raising this directly.
      +    """
      +    pass
      +
      +class _ExpectedFailure(Exception):
      +    """
      +    Raise this when a test is expected to fail.
      +
      +    This is an implementation detail.
      +    """
      +
      +    def __init__(self, exc_info):
      +        super(_ExpectedFailure, self).__init__()
      +        self.exc_info = exc_info
      +
      +class _UnexpectedSuccess(Exception):
      +    """
      +    The test was supposed to fail, but it didn't!
      +    """
      +    pass
      +
      +def _id(obj):
      +    return obj
      +
      +def skip(reason):
      +    """
      +    Unconditionally skip a test.
      +    """
      +    def decorator(test_item):
      +        if not isinstance(test_item, (type, types.ClassType)):
      +            @functools.wraps(test_item)
      +            def skip_wrapper(*args, **kwargs):
      +                raise SkipTest(reason)
      +            test_item = skip_wrapper
      +
      +        test_item.__unittest_skip__ = True
      +        test_item.__unittest_skip_why__ = reason
      +        return test_item
      +    return decorator
      +
      +def skipIf(condition, reason):
      +    """
      +    Skip a test if the condition is true.
      +    """
      +    if condition:
      +        return skip(reason)
      +    return _id
      +
      +def skipUnless(condition, reason):
      +    """
      +    Skip a test unless the condition is true.
      +    """
      +    if not condition:
      +        return skip(reason)
      +    return _id
      +
      +
      +def expectedFailure(func):
      +    @functools.wraps(func)
      +    def wrapper(*args, **kwargs):
      +        try:
      +            func(*args, **kwargs)
      +        except Exception:
      +            raise _ExpectedFailure(sys.exc_info())
      +        raise _UnexpectedSuccess
      +    return wrapper
      +
      +
      +class _AssertRaisesContext(object):
      +    """A context manager used to implement TestCase.assertRaises* methods."""
      +
      +    def __init__(self, expected, test_case, expected_regexp=None):
      +        self.expected = expected
      +        self.failureException = test_case.failureException
      +        self.expected_regexp = expected_regexp
      +
      +    def __enter__(self):
      +        return self
      +
      +    def __exit__(self, exc_type, exc_value, tb):
      +        if exc_type is None:
      +            try:
      +                exc_name = self.expected.__name__
      +            except AttributeError:
      +                exc_name = str(self.expected)
      +            raise self.failureException(
      +                "{0} not raised".format(exc_name))
      +        if not issubclass(exc_type, self.expected):
      +            # let unexpected exceptions pass through
      +            return False
      +        self.exception = exc_value # store for later retrieval
      +        if self.expected_regexp is None:
      +            return True
      +
      +        expected_regexp = self.expected_regexp
      +        if not expected_regexp.search(str(exc_value)):
      +            raise self.failureException('"%s" does not match "%s"' %
      +                     (expected_regexp.pattern, str(exc_value)))
      +        return True
      +
      +
      +class TestCase(object):
      +    """A class whose instances are single test cases.
      +
      +    By default, the test code itself should be placed in a method named
      +    'runTest'.
      +
      +    If the fixture may be used for many test cases, create as
      +    many test methods as are needed. When instantiating such a TestCase
      +    subclass, specify in the constructor arguments the name of the test method
      +    that the instance is to execute.
      +
      +    Test authors should subclass TestCase for their own tests. Construction
      +    and deconstruction of the test's environment ('fixture') can be
      +    implemented by overriding the 'setUp' and 'tearDown' methods respectively.
      +
      +    If it is necessary to override the __init__ method, the base class
      +    __init__ method must always be called. It is important that subclasses
      +    should not change the signature of their __init__ method, since instances
      +    of the classes are instantiated automatically by parts of the framework
      +    in order to be run.
      +
      +    When subclassing TestCase, you can set these attributes:
      +    * failureException: determines which exception will be raised when
      +        the instance's assertion methods fail; test methods raising this
      +        exception will be deemed to have 'failed' rather than 'errored'.
      +    * longMessage: determines whether long messages (including repr of
      +        objects used in assert methods) will be printed on failure in *addition*
      +        to any explicit message passed.
      +    * maxDiff: sets the maximum length of a diff in failure messages
      +        by assert methods using difflib. It is looked up as an instance
      +        attribute so can be configured by individual tests if required.
      +    """
      +
      +    failureException = AssertionError
      +
      +    longMessage = False
      +
      +    maxDiff = 80*8
      +
      +    # If a string is longer than _diffThreshold, use normal comparison instead
      +    # of difflib.  See #11763.
      +    _diffThreshold = 2**16
      +
      +    # Attribute used by TestSuite for classSetUp
      +
      +    _classSetupFailed = False
      +
      +    def __init__(self, methodName='runTest'):
      +        """Create an instance of the class that will use the named test
      +           method when executed. Raises a ValueError if the instance does
      +           not have a method with the specified name.
      +        """
      +        self._testMethodName = methodName
      +        self._resultForDoCleanups = None
      +        try:
      +            testMethod = getattr(self, methodName)
      +        except AttributeError:
      +            raise ValueError("no such test method in %s: %s" %
      +                  (self.__class__, methodName))
      +        self._testMethodDoc = testMethod.__doc__
      +        self._cleanups = []
      +
      +        # Map types to custom assertEqual functions that will compare
      +        # instances of said type in more detail to generate a more useful
      +        # error message.
      +        self._type_equality_funcs = {}
      +        self.addTypeEqualityFunc(dict, 'assertDictEqual')
      +        self.addTypeEqualityFunc(list, 'assertListEqual')
      +        self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
      +        self.addTypeEqualityFunc(set, 'assertSetEqual')
      +        self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
      +        try:
      +            self.addTypeEqualityFunc(unicode, 'assertMultiLineEqual')
      +        except NameError:
      +            # No unicode support in this build
      +            pass
      +
      +    def addTypeEqualityFunc(self, typeobj, function):
      +        """Add a type specific assertEqual style function to compare a type.
      +
      +        This method is for use by TestCase subclasses that need to register
      +        their own type equality functions to provide nicer error messages.
      +
      +        Args:
      +            typeobj: The data type to call this function on when both values
      +                    are of the same type in assertEqual().
      +            function: The callable taking two arguments and an optional
      +                    msg= argument that raises self.failureException with a
      +                    useful error message when the two arguments are not equal.
      +        """
      +        self._type_equality_funcs[typeobj] = function
      +
      +    def addCleanup(self, function, *args, **kwargs):
      +        """Add a function, with arguments, to be called when the test is
      +        completed. Functions added are called on a LIFO basis and are
      +        called after tearDown on test failure or success.
      +
      +        Cleanup items are called even if setUp fails (unlike tearDown)."""
      +        self._cleanups.append((function, args, kwargs))
      +
      +    def setUp(self):
      +        "Hook method for setting up the test fixture before exercising it."
      +        pass
      +
      +    def tearDown(self):
      +        "Hook method for deconstructing the test fixture after testing it."
      +        pass
      +
      +    @classmethod
      +    def setUpClass(cls):
      +        "Hook method for setting up class fixture before running tests in the class."
      +
      +    @classmethod
      +    def tearDownClass(cls):
      +        "Hook method for deconstructing the class fixture after running all tests in the class."
      +
      +    def countTestCases(self):
      +        return 1
      +
      +    def defaultTestResult(self):
      +        return result.TestResult()
      +
      +    def shortDescription(self):
      +        """Returns a one-line description of the test, or None if no
      +        description has been provided.
      +
      +        The default implementation of this method returns the first line of
      +        the specified test method's docstring.
      +        """
      +        doc = self._testMethodDoc
      +        return doc and doc.split("\n")[0].strip() or None
      +
      +
      +    def id(self):
      +        return "%s.%s" % (strclass(self.__class__), self._testMethodName)
      +
      +    def __eq__(self, other):
      +        if type(self) is not type(other):
      +            return NotImplemented
      +
      +        return self._testMethodName == other._testMethodName
      +
      +    def __ne__(self, other):
      +        return not self == other
      +
      +    def __hash__(self):
      +        return hash((type(self), self._testMethodName))
      +
      +    def __str__(self):
      +        return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
      +
      +    def __repr__(self):
      +        return "<%s testMethod=%s>" % \
      +               (strclass(self.__class__), self._testMethodName)
      +
      +    def _addSkip(self, result, reason):
      +        addSkip = getattr(result, 'addSkip', None)
      +        if addSkip is not None:
      +            addSkip(self, reason)
      +        else:
      +            warnings.warn("TestResult has no addSkip method, skips not reported",
      +                          RuntimeWarning, 2)
      +            result.addSuccess(self)
      +
      +    def run(self, result=None):
      +        orig_result = result
      +        if result is None:
      +            result = self.defaultTestResult()
      +            startTestRun = getattr(result, 'startTestRun', None)
      +            if startTestRun is not None:
      +                startTestRun()
      +
      +        self._resultForDoCleanups = result
      +        result.startTest(self)
      +
      +        testMethod = getattr(self, self._testMethodName)
      +        if (getattr(self.__class__, "__unittest_skip__", False) or
      +            getattr(testMethod, "__unittest_skip__", False)):
      +            # If the class or method was skipped.
      +            try:
      +                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
      +                            or getattr(testMethod, '__unittest_skip_why__', ''))
      +                self._addSkip(result, skip_why)
      +            finally:
      +                result.stopTest(self)
      +            return
      +        try:
      +            success = False
      +            try:
      +                self.setUp()
      +            except SkipTest as e:
      +                self._addSkip(result, str(e))
      +            except KeyboardInterrupt:
      +                raise
      +            except:
      +                result.addError(self, sys.exc_info())
      +            else:
      +                try:
      +                    testMethod()
      +                except KeyboardInterrupt:
      +                    raise
      +                except self.failureException:
      +                    result.addFailure(self, sys.exc_info())
      +                except _ExpectedFailure as e:
      +                    addExpectedFailure = getattr(result, 'addExpectedFailure', None)
      +                    if addExpectedFailure is not None:
      +                        addExpectedFailure(self, e.exc_info)
      +                    else:
      +                        warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
      +                                      RuntimeWarning)
      +                        result.addSuccess(self)
      +                except _UnexpectedSuccess:
      +                    addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
      +                    if addUnexpectedSuccess is not None:
      +                        addUnexpectedSuccess(self)
      +                    else:
      +                        warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
      +                                      RuntimeWarning)
      +                        result.addFailure(self, sys.exc_info())
      +                except SkipTest as e:
      +                    self._addSkip(result, str(e))
      +                except:
      +                    result.addError(self, sys.exc_info())
      +                else:
      +                    success = True
      +
      +                try:
      +                    self.tearDown()
      +                except KeyboardInterrupt:
      +                    raise
      +                except:
      +                    result.addError(self, sys.exc_info())
      +                    success = False
      +
      +            cleanUpSuccess = self.doCleanups()
      +            success = success and cleanUpSuccess
      +            if success:
      +                result.addSuccess(self)
      +        finally:
      +            result.stopTest(self)
      +            if orig_result is None:
      +                stopTestRun = getattr(result, 'stopTestRun', None)
      +                if stopTestRun is not None:
      +                    stopTestRun()
      +
      +    def doCleanups(self):
      +        """Execute all cleanup functions. Normally called for you after
      +        tearDown."""
      +        result = self._resultForDoCleanups
      +        ok = True
      +        while self._cleanups:
      +            function, args, kwargs = self._cleanups.pop(-1)
      +            try:
      +                function(*args, **kwargs)
      +            except KeyboardInterrupt:
      +                raise
      +            except:
      +                ok = False
      +                result.addError(self, sys.exc_info())
      +        return ok
      +
      +    def __call__(self, *args, **kwds):
      +        return self.run(*args, **kwds)
      +
      +    def debug(self):
      +        """Run the test without collecting errors in a TestResult"""
      +        self.setUp()
      +        getattr(self, self._testMethodName)()
      +        self.tearDown()
      +        while self._cleanups:
      +            function, args, kwargs = self._cleanups.pop(-1)
      +            function(*args, **kwargs)
      +
      +    def skipTest(self, reason):
      +        """Skip this test."""
      +        raise SkipTest(reason)
      +
      +    def fail(self, msg=None):
      +        """Fail immediately, with the given message."""
      +        raise self.failureException(msg)
      +
      +    def assertFalse(self, expr, msg=None):
      +        """Check that the expression is false."""
      +        if expr:
      +            msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
      +            raise self.failureException(msg)
      +
      +    def assertTrue(self, expr, msg=None):
      +        """Check that the expression is true."""
      +        if not expr:
      +            msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
      +            raise self.failureException(msg)
      +
      +    def _formatMessage(self, msg, standardMsg):
      +        """Honour the longMessage attribute when generating failure messages.
      +        If longMessage is False this means:
      +        * Use only an explicit message if it is provided
      +        * Otherwise use the standard message for the assert
      +
      +        If longMessage is True:
      +        * Use the standard message
      +        * If an explicit message is provided, plus ' : ' and the explicit message
      +        """
      +        if not self.longMessage:
      +            return msg or standardMsg
      +        if msg is None:
      +            return standardMsg
      +        try:
      +            # don't switch to '{}' formatting in Python 2.X
      +            # it changes the way unicode input is handled
      +            return '%s : %s' % (standardMsg, msg)
      +        except UnicodeDecodeError:
      +            return  '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
      +
      +
      +    def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
      +        """Fail unless an exception of class excClass is raised
      +           by callableObj when invoked with arguments args and keyword
      +           arguments kwargs. If a different type of exception is
      +           raised, it will not be caught, and the test case will be
      +           deemed to have suffered an error, exactly as for an
      +           unexpected exception.
      +
      +           If called with callableObj omitted or None, will return a
      +           context object used like this::
      +
      +                with self.assertRaises(SomeException):
      +                    do_something()
      +
      +           The context manager keeps a reference to the exception as
      +           the 'exception' attribute. This allows you to inspect the
      +           exception after the assertion::
      +
      +               with self.assertRaises(SomeException) as cm:
      +                   do_something()
      +               the_exception = cm.exception
      +               self.assertEqual(the_exception.error_code, 3)
      +        """
      +        context = _AssertRaisesContext(excClass, self)
      +        if callableObj is None:
      +            return context
      +        with context:
      +            callableObj(*args, **kwargs)
      +
      +    def _getAssertEqualityFunc(self, first, second):
      +        """Get a detailed comparison function for the types of the two args.
      +
      +        Returns: A callable accepting (first, second, msg=None) that will
      +        raise a failure exception if first != second with a useful human
      +        readable error message for those types.
      +        """
      +        #
      +        # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
      +        # and vice versa.  I opted for the conservative approach in case
      +        # subclasses are not intended to be compared in detail to their super
      +        # class instances using a type equality func.  This means testing
      +        # subtypes won't automagically use the detailed comparison.  Callers
      +        # should use their type specific assertSpamEqual method to compare
      +        # subclasses if the detailed comparison is desired and appropriate.
      +        # See the discussion in http://bugs.python.org/issue2578.
      +        #
      +        if type(first) is type(second):
      +            asserter = self._type_equality_funcs.get(type(first))
      +            if asserter is not None:
      +                if isinstance(asserter, basestring):
      +                    asserter = getattr(self, asserter)
      +                return asserter
      +
      +        return self._baseAssertEqual
      +
      +    def _baseAssertEqual(self, first, second, msg=None):
      +        """The default assertEqual implementation, not type specific."""
      +        if not first == second:
      +            standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
      +            msg = self._formatMessage(msg, standardMsg)
      +            raise self.failureException(msg)
      +
      +    def assertEqual(self, first, second, msg=None):
      +        """Fail if the two objects are unequal as determined by the '=='
      +           operator.
      +        """
      +        assertion_func = self._getAssertEqualityFunc(first, second)
      +        assertion_func(first, second, msg=msg)
      +
      +    def assertNotEqual(self, first, second, msg=None):
      +        """Fail if the two objects are equal as determined by the '!='
      +           operator.
      +        """
      +        if not first != second:
      +            msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
      +                                                          safe_repr(second)))
      +            raise self.failureException(msg)
      +
      +
      +    def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None):
      +        """Fail if the two objects are unequal as determined by their
      +           difference rounded to the given number of decimal places
      +           (default 7) and comparing to zero, or by comparing that the
      +           between the two objects is more than the given delta.
      +
      +           Note that decimal places (from zero) are usually not the same
      +           as significant digits (measured from the most signficant digit).
      +
      +           If the two objects compare equal then they will automatically
      +           compare almost equal.
      +        """
      +        if first == second:
      +            # shortcut
      +            return
      +        if delta is not None and places is not None:
      +            raise TypeError("specify delta or places not both")
      +
      +        if delta is not None:
      +            if abs(first - second) <= delta:
      +                return
      +
      +            standardMsg = '%s != %s within %s delta' % (safe_repr(first),
      +                                                        safe_repr(second),
      +                                                        safe_repr(delta))
      +        else:
      +            if places is None:
      +                places = 7
      +
      +            if round(abs(second-first), places) == 0:
      +                return
      +
      +            standardMsg = '%s != %s within %r places' % (safe_repr(first),
      +                                                          safe_repr(second),
      +                                                          places)
      +        msg = self._formatMessage(msg, standardMsg)
      +        raise self.failureException(msg)
      +
      +    def assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None):
      +        """Fail if the two objects are equal as determined by their
      +           difference rounded to the given number of decimal places
      +           (default 7) and comparing to zero, or by comparing that the
      +           between the two objects is less than the given delta.
      +
      +           Note that decimal places (from zero) are usually not the same
      +           as significant digits (measured from the most signficant digit).
      +
      +           Objects that are equal automatically fail.
      +        """
      +        if delta is not None and places is not None:
      +            raise TypeError("specify delta or places not both")
      +        if delta is not None:
      +            if not (first == second) and abs(first - second) > delta:
      +                return
      +            standardMsg = '%s == %s within %s delta' % (safe_repr(first),
      +                                                        safe_repr(second),
      +                                                        safe_repr(delta))
      +        else:
      +            if places is None:
      +                places = 7
      +            if not (first == second) and round(abs(second-first), places) != 0:
      +                return
      +            standardMsg = '%s == %s within %r places' % (safe_repr(first),
      +                                                         safe_repr(second),
      +                                                         places)
      +
      +        msg = self._formatMessage(msg, standardMsg)
      +        raise self.failureException(msg)
      +
      +    # Synonyms for assertion methods
      +
      +    # The plurals are undocumented.  Keep them that way to discourage use.
      +    # Do not add more.  Do not remove.
      +    # Going through a deprecation cycle on these would annoy many people.
      +    assertEquals = assertEqual
      +    assertNotEquals = assertNotEqual
      +    assertAlmostEquals = assertAlmostEqual
      +    assertNotAlmostEquals = assertNotAlmostEqual
      +    assert_ = assertTrue
      +
      +    # These fail* assertion method names are pending deprecation and will
      +    # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
      +    def _deprecate(original_func):
      +        def deprecated_func(*args, **kwargs):
      +            warnings.warn(
      +                'Please use {0} instead.'.format(original_func.__name__),
      +                PendingDeprecationWarning, 2)
      +            return original_func(*args, **kwargs)
      +        return deprecated_func
      +
      +    failUnlessEqual = _deprecate(assertEqual)
      +    failIfEqual = _deprecate(assertNotEqual)
      +    failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
      +    failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
      +    failUnless = _deprecate(assertTrue)
      +    failUnlessRaises = _deprecate(assertRaises)
      +    failIf = _deprecate(assertFalse)
      +
      +    def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
      +        """An equality assertion for ordered sequences (like lists and tuples).
      +
      +        For the purposes of this function, a valid ordered sequence type is one
      +        which can be indexed, has a length, and has an equality operator.
      +
      +        Args:
      +            seq1: The first sequence to compare.
      +            seq2: The second sequence to compare.
      +            seq_type: The expected datatype of the sequences, or None if no
      +                    datatype should be enforced.
      +            msg: Optional message to use on failure instead of a list of
      +                    differences.
      +        """
      +        if seq_type is not None:
      +            seq_type_name = seq_type.__name__
      +            if not isinstance(seq1, seq_type):
      +                raise self.failureException('First sequence is not a %s: %s'
      +                                        % (seq_type_name, safe_repr(seq1)))
      +            if not isinstance(seq2, seq_type):
      +                raise self.failureException('Second sequence is not a %s: %s'
      +                                        % (seq_type_name, safe_repr(seq2)))
      +        else:
      +            seq_type_name = "sequence"
      +
      +        differing = None
      +        try:
      +            len1 = len(seq1)
      +        except (TypeError, NotImplementedError):
      +            differing = 'First %s has no length.    Non-sequence?' % (
      +                    seq_type_name)
      +
      +        if differing is None:
      +            try:
      +                len2 = len(seq2)
      +            except (TypeError, NotImplementedError):
      +                differing = 'Second %s has no length.    Non-sequence?' % (
      +                        seq_type_name)
      +
      +        if differing is None:
      +            if seq1 == seq2:
      +                return
      +
      +            seq1_repr = safe_repr(seq1)
      +            seq2_repr = safe_repr(seq2)
      +            if len(seq1_repr) > 30:
      +                seq1_repr = seq1_repr[:30] + '...'
      +            if len(seq2_repr) > 30:
      +                seq2_repr = seq2_repr[:30] + '...'
      +            elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
      +            differing = '%ss differ: %s != %s\n' % elements
      +
      +            for i in xrange(min(len1, len2)):
      +                try:
      +                    item1 = seq1[i]
      +                except (TypeError, IndexError, NotImplementedError):
      +                    differing += ('\nUnable to index element %d of first %s\n' %
      +                                 (i, seq_type_name))
      +                    break
      +
      +                try:
      +                    item2 = seq2[i]
      +                except (TypeError, IndexError, NotImplementedError):
      +                    differing += ('\nUnable to index element %d of second %s\n' %
      +                                 (i, seq_type_name))
      +                    break
      +
      +                if item1 != item2:
      +                    differing += ('\nFirst differing element %d:\n%s\n%s\n' %
      +                                 (i, item1, item2))
      +                    break
      +            else:
      +                if (len1 == len2 and seq_type is None and
      +                    type(seq1) != type(seq2)):
      +                    # The sequences are the same, but have differing types.
      +                    return
      +
      +            if len1 > len2:
      +                differing += ('\nFirst %s contains %d additional '
      +                             'elements.\n' % (seq_type_name, len1 - len2))
      +                try:
      +                    differing += ('First extra element %d:\n%s\n' %
      +                                  (len2, seq1[len2]))
      +                except (TypeError, IndexError, NotImplementedError):
      +                    differing += ('Unable to index element %d '
      +                                  'of first %s\n' % (len2, seq_type_name))
      +            elif len1 < len2:
      +                differing += ('\nSecond %s contains %d additional '
      +                             'elements.\n' % (seq_type_name, len2 - len1))
      +                try:
      +                    differing += ('First extra element %d:\n%s\n' %
      +                                  (len1, seq2[len1]))
      +                except (TypeError, IndexError, NotImplementedError):
      +                    differing += ('Unable to index element %d '
      +                                  'of second %s\n' % (len1, seq_type_name))
      +        standardMsg = differing
      +        diffMsg = '\n' + '\n'.join(
      +            difflib.ndiff(pprint.pformat(seq1).splitlines(),
      +                          pprint.pformat(seq2).splitlines()))
      +        standardMsg = self._truncateMessage(standardMsg, diffMsg)
      +        msg = self._formatMessage(msg, standardMsg)
      +        self.fail(msg)
      +
      +    def _truncateMessage(self, message, diff):
      +        max_diff = self.maxDiff
      +        if max_diff is None or len(diff) <= max_diff:
      +            return message + diff
      +        return message + (DIFF_OMITTED % len(diff))
      +
      +    def assertListEqual(self, list1, list2, msg=None):
      +        """A list-specific equality assertion.
      +
      +        Args:
      +            list1: The first list to compare.
      +            list2: The second list to compare.
      +            msg: Optional message to use on failure instead of a list of
      +                    differences.
      +
      +        """
      +        self.assertSequenceEqual(list1, list2, msg, seq_type=list)
      +
      +    def assertTupleEqual(self, tuple1, tuple2, msg=None):
      +        """A tuple-specific equality assertion.
      +
      +        Args:
      +            tuple1: The first tuple to compare.
      +            tuple2: The second tuple to compare.
      +            msg: Optional message to use on failure instead of a list of
      +                    differences.
      +        """
      +        self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
      +
      +    def assertSetEqual(self, set1, set2, msg=None):
      +        """A set-specific equality assertion.
      +
      +        Args:
      +            set1: The first set to compare.
      +            set2: The second set to compare.
      +            msg: Optional message to use on failure instead of a list of
      +                    differences.
      +
      +        assertSetEqual uses ducktyping to support different types of sets, and
      +        is optimized for sets specifically (parameters must support a
      +        difference method).
      +        """
      +        try:
      +            difference1 = set1.difference(set2)
      +        except TypeError, e:
      +            self.fail('invalid type when attempting set difference: %s' % e)
      +        except AttributeError, e:
      +            self.fail('first argument does not support set difference: %s' % e)
      +
      +        try:
      +            difference2 = set2.difference(set1)
      +        except TypeError, e:
      +            self.fail('invalid type when attempting set difference: %s' % e)
      +        except AttributeError, e:
      +            self.fail('second argument does not support set difference: %s' % e)
      +
      +        if not (difference1 or difference2):
      +            return
      +
      +        lines = []
      +        if difference1:
      +            lines.append('Items in the first set but not the second:')
      +            for item in difference1:
      +                lines.append(repr(item))
      +        if difference2:
      +            lines.append('Items in the second set but not the first:')
      +            for item in difference2:
      +                lines.append(repr(item))
      +
      +        standardMsg = '\n'.join(lines)
      +        self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertIn(self, member, container, msg=None):
      +        """Just like self.assertTrue(a in b), but with a nicer default message."""
      +        if member not in container:
      +            standardMsg = '%s not found in %s' % (safe_repr(member),
      +                                                  safe_repr(container))
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertNotIn(self, member, container, msg=None):
      +        """Just like self.assertTrue(a not in b), but with a nicer default message."""
      +        if member in container:
      +            standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
      +                                                        safe_repr(container))
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertIs(self, expr1, expr2, msg=None):
      +        """Just like self.assertTrue(a is b), but with a nicer default message."""
      +        if expr1 is not expr2:
      +            standardMsg = '%s is not %s' % (safe_repr(expr1),
      +                                             safe_repr(expr2))
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertIsNot(self, expr1, expr2, msg=None):
      +        """Just like self.assertTrue(a is not b), but with a nicer default message."""
      +        if expr1 is expr2:
      +            standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertDictEqual(self, d1, d2, msg=None):
      +        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
      +        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
      +
      +        if d1 != d2:
      +            standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
      +            diff = ('\n' + '\n'.join(difflib.ndiff(
      +                           pprint.pformat(d1).splitlines(),
      +                           pprint.pformat(d2).splitlines())))
      +            standardMsg = self._truncateMessage(standardMsg, diff)
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertDictContainsSubset(self, expected, actual, msg=None):
      +        """Checks whether actual is a superset of expected."""
      +        missing = []
      +        mismatched = []
      +        for key, value in expected.iteritems():
      +            if key not in actual:
      +                missing.append(key)
      +            elif value != actual[key]:
      +                mismatched.append('%s, expected: %s, actual: %s' %
      +                                  (safe_repr(key), safe_repr(value),
      +                                   safe_repr(actual[key])))
      +
      +        if not (missing or mismatched):
      +            return
      +
      +        standardMsg = ''
      +        if missing:
      +            standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
      +                                                    missing)
      +        if mismatched:
      +            if standardMsg:
      +                standardMsg += '; '
      +            standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
      +
      +        self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
      +        """An unordered sequence specific comparison. It asserts that
      +        actual_seq and expected_seq have the same element counts.
      +        Equivalent to::
      +
      +            self.assertEqual(Counter(iter(actual_seq)),
      +                             Counter(iter(expected_seq)))
      +
      +        Asserts that each element has the same count in both sequences.
      +        Example:
      +            - [0, 1, 1] and [1, 0, 1] compare equal.
      +            - [0, 0, 1] and [0, 1] compare unequal.
      +        """
      +        first_seq, second_seq = list(expected_seq), list(actual_seq)
      +        with warnings.catch_warnings():
      +            if sys.py3kwarning:
      +                # Silence Py3k warning raised during the sorting
      +                for _msg in ["(code|dict|type) inequality comparisons",
      +                             "builtin_function_or_method order comparisons",
      +                             "comparing unequal types"]:
      +                    warnings.filterwarnings("ignore", _msg, DeprecationWarning)
      +            try:
      +                first = collections.Counter(first_seq)
      +                second = collections.Counter(second_seq)
      +            except TypeError:
      +                # Handle case with unhashable elements
      +                differences = _count_diff_all_purpose(first_seq, second_seq)
      +            else:
      +                if first == second:
      +                    return
      +                differences = _count_diff_hashable(first_seq, second_seq)
      +
      +        if differences:
      +            standardMsg = 'Element counts were not equal:\n'
      +            lines = ['First has %d, Second has %d:  %r' % diff for diff in differences]
      +            diffMsg = '\n'.join(lines)
      +            standardMsg = self._truncateMessage(standardMsg, diffMsg)
      +            msg = self._formatMessage(msg, standardMsg)
      +            self.fail(msg)
      +
      +    def assertMultiLineEqual(self, first, second, msg=None):
      +        """Assert that two multi-line strings are equal."""
      +        self.assertIsInstance(first, basestring,
      +                'First argument is not a string')
      +        self.assertIsInstance(second, basestring,
      +                'Second argument is not a string')
      +
      +        if first != second:
      +            # don't use difflib if the strings are too long
      +            if (len(first) > self._diffThreshold or
      +                len(second) > self._diffThreshold):
      +                self._baseAssertEqual(first, second, msg)
      +            firstlines = first.splitlines(True)
      +            secondlines = second.splitlines(True)
      +            if len(firstlines) == 1 and first.strip('\r\n') == first:
      +                firstlines = [first + '\n']
      +                secondlines = [second + '\n']
      +            standardMsg = '%s != %s' % (safe_repr(first, True),
      +                                        safe_repr(second, True))
      +            diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
      +            standardMsg = self._truncateMessage(standardMsg, diff)
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertLess(self, a, b, msg=None):
      +        """Just like self.assertTrue(a < b), but with a nicer default message."""
      +        if not a < b:
      +            standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertLessEqual(self, a, b, msg=None):
      +        """Just like self.assertTrue(a <= b), but with a nicer default message."""
      +        if not a <= b:
      +            standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertGreater(self, a, b, msg=None):
      +        """Just like self.assertTrue(a > b), but with a nicer default message."""
      +        if not a > b:
      +            standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertGreaterEqual(self, a, b, msg=None):
      +        """Just like self.assertTrue(a >= b), but with a nicer default message."""
      +        if not a >= b:
      +            standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertIsNone(self, obj, msg=None):
      +        """Same as self.assertTrue(obj is None), with a nicer default message."""
      +        if obj is not None:
      +            standardMsg = '%s is not None' % (safe_repr(obj),)
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertIsNotNone(self, obj, msg=None):
      +        """Included for symmetry with assertIsNone."""
      +        if obj is None:
      +            standardMsg = 'unexpectedly None'
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertIsInstance(self, obj, cls, msg=None):
      +        """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
      +        default message."""
      +        if not isinstance(obj, cls):
      +            standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertNotIsInstance(self, obj, cls, msg=None):
      +        """Included for symmetry with assertIsInstance."""
      +        if isinstance(obj, cls):
      +            standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
      +            self.fail(self._formatMessage(msg, standardMsg))
      +
      +    def assertRaisesRegexp(self, expected_exception, expected_regexp,
      +                           callable_obj=None, *args, **kwargs):
      +        """Asserts that the message in a raised exception matches a regexp.
      +
      +        Args:
      +            expected_exception: Exception class expected to be raised.
      +            expected_regexp: Regexp (re pattern object or string) expected
      +                    to be found in error message.
      +            callable_obj: Function to be called.
      +            args: Extra args.
      +            kwargs: Extra kwargs.
      +        """
      +        if expected_regexp is not None:
      +            expected_regexp = re.compile(expected_regexp)
      +        context = _AssertRaisesContext(expected_exception, self, expected_regexp)
      +        if callable_obj is None:
      +            return context
      +        with context:
      +            callable_obj(*args, **kwargs)
      +
      +    def assertRegexpMatches(self, text, expected_regexp, msg=None):
      +        """Fail the test unless the text matches the regular expression."""
      +        if isinstance(expected_regexp, basestring):
      +            expected_regexp = re.compile(expected_regexp)
      +        if not expected_regexp.search(text):
      +            msg = msg or "Regexp didn't match"
      +            msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
      +            raise self.failureException(msg)
      +
      +    def assertNotRegexpMatches(self, text, unexpected_regexp, msg=None):
      +        """Fail the test if the text matches the regular expression."""
      +        if isinstance(unexpected_regexp, basestring):
      +            unexpected_regexp = re.compile(unexpected_regexp)
      +        match = unexpected_regexp.search(text)
      +        if match:
      +            msg = msg or "Regexp matched"
      +            msg = '%s: %r matches %r in %r' % (msg,
      +                                               text[match.start():match.end()],
      +                                               unexpected_regexp.pattern,
      +                                               text)
      +            raise self.failureException(msg)
      +
      +
      +class FunctionTestCase(TestCase):
      +    """A test case that wraps a test function.
      +
      +    This is useful for slipping pre-existing test functions into the
      +    unittest framework. Optionally, set-up and tidy-up functions can be
      +    supplied. As with TestCase, the tidy-up ('tearDown') function will
      +    always be called if the set-up ('setUp') function ran successfully.
      +    """
      +
      +    def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
      +        super(FunctionTestCase, self).__init__()
      +        self._setUpFunc = setUp
      +        self._tearDownFunc = tearDown
      +        self._testFunc = testFunc
      +        self._description = description
      +
      +    def setUp(self):
      +        if self._setUpFunc is not None:
      +            self._setUpFunc()
      +
      +    def tearDown(self):
      +        if self._tearDownFunc is not None:
      +            self._tearDownFunc()
      +
      +    def runTest(self):
      +        self._testFunc()
      +
      +    def id(self):
      +        return self._testFunc.__name__
      +
      +    def __eq__(self, other):
      +        if not isinstance(other, self.__class__):
      +            return NotImplemented
      +
      +        return self._setUpFunc == other._setUpFunc and \
      +               self._tearDownFunc == other._tearDownFunc and \
      +               self._testFunc == other._testFunc and \
      +               self._description == other._description
      +
      +    def __ne__(self, other):
      +        return not self == other
      +
      +    def __hash__(self):
      +        return hash((type(self), self._setUpFunc, self._tearDownFunc,
      +                     self._testFunc, self._description))
      +
      +    def __str__(self):
      +        return "%s (%s)" % (strclass(self.__class__),
      +                            self._testFunc.__name__)
      +
      +    def __repr__(self):
      +        return "<%s tec=%s>" % (strclass(self.__class__),
      +                                     self._testFunc)
      +
      +    def shortDescription(self):
      +        if self._description is not None:
      +            return self._description
      +        doc = self._testFunc.__doc__
      +        return doc and doc.split("\n")[0].strip() or None
      +
      + +
      +
      +
      + +
      +
      + + + + \ No newline at end of file diff --git a/doc/_build/html/_sources/GPy.core.parameterization.txt b/doc/_build/html/_sources/GPy.core.parameterization.txt new file mode 100644 index 00000000..4877a06d --- /dev/null +++ b/doc/_build/html/_sources/GPy.core.parameterization.txt @@ -0,0 +1,102 @@ +GPy.core.parameterization package +================================= + +Submodules +---------- + +GPy.core.parameterization.domains module +---------------------------------------- + +.. automodule:: GPy.core.parameterization.domains + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.index_operations module +------------------------------------------------- + +.. automodule:: GPy.core.parameterization.index_operations + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.lists_and_dicts module +------------------------------------------------ + +.. automodule:: GPy.core.parameterization.lists_and_dicts + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.observable_array module +------------------------------------------------- + +.. automodule:: GPy.core.parameterization.observable_array + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.param module +-------------------------------------- + +.. automodule:: GPy.core.parameterization.param + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.parameter_core module +----------------------------------------------- + +.. automodule:: GPy.core.parameterization.parameter_core + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.parameterized module +---------------------------------------------- + +.. automodule:: GPy.core.parameterization.parameterized + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.priors module +--------------------------------------- + +.. automodule:: GPy.core.parameterization.priors + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.ties_and_remappings module +---------------------------------------------------- + +.. automodule:: GPy.core.parameterization.ties_and_remappings + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.transformations module +------------------------------------------------ + +.. automodule:: GPy.core.parameterization.transformations + :members: + :undoc-members: + :show-inheritance: + +GPy.core.parameterization.variational module +-------------------------------------------- + +.. automodule:: GPy.core.parameterization.variational + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.core.parameterization + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.core.txt b/doc/_build/html/_sources/GPy.core.txt new file mode 100644 index 00000000..3c236612 --- /dev/null +++ b/doc/_build/html/_sources/GPy.core.txt @@ -0,0 +1,77 @@ +GPy.core package +================ + +Subpackages +----------- + +.. toctree:: + + GPy.core.parameterization + +Submodules +---------- + +GPy.core.gp module +------------------ + +.. automodule:: GPy.core.gp + :members: + :undoc-members: + :show-inheritance: + +GPy.core.mapping module +----------------------- + +.. automodule:: GPy.core.mapping + :members: + :undoc-members: + :show-inheritance: + +GPy.core.model module +--------------------- + +.. automodule:: GPy.core.model + :members: + :undoc-members: + :show-inheritance: + +GPy.core.sparse_gp module +------------------------- + +.. automodule:: GPy.core.sparse_gp + :members: + :undoc-members: + :show-inheritance: + +GPy.core.sparse_gp_mpi module +----------------------------- + +.. automodule:: GPy.core.sparse_gp_mpi + :members: + :undoc-members: + :show-inheritance: + +GPy.core.svigp module +--------------------- + +.. automodule:: GPy.core.svigp + :members: + :undoc-members: + :show-inheritance: + +GPy.core.symbolic module +------------------------ + +.. automodule:: GPy.core.symbolic + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.core + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.examples.txt b/doc/_build/html/_sources/GPy.examples.txt new file mode 100644 index 00000000..7fc8a123 --- /dev/null +++ b/doc/_build/html/_sources/GPy.examples.txt @@ -0,0 +1,70 @@ +GPy.examples package +==================== + +Submodules +---------- + +GPy.examples.classification module +---------------------------------- + +.. automodule:: GPy.examples.classification + :members: + :undoc-members: + :show-inheritance: + +GPy.examples.coreg_example module +--------------------------------- + +.. automodule:: GPy.examples.coreg_example + :members: + :undoc-members: + :show-inheritance: + +GPy.examples.dimensionality_reduction module +-------------------------------------------- + +.. automodule:: GPy.examples.dimensionality_reduction + :members: + :undoc-members: + :show-inheritance: + +GPy.examples.non_gaussian module +-------------------------------- + +.. automodule:: GPy.examples.non_gaussian + :members: + :undoc-members: + :show-inheritance: + +GPy.examples.regression module +------------------------------ + +.. automodule:: GPy.examples.regression + :members: + :undoc-members: + :show-inheritance: + +GPy.examples.stochastic module +------------------------------ + +.. automodule:: GPy.examples.stochastic + :members: + :undoc-members: + :show-inheritance: + +GPy.examples.tutorials module +----------------------------- + +.. automodule:: GPy.examples.tutorials + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.examples + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.inference.latent_function_inference.txt b/doc/_build/html/_sources/GPy.inference.latent_function_inference.txt new file mode 100644 index 00000000..98d16705 --- /dev/null +++ b/doc/_build/html/_sources/GPy.inference.latent_function_inference.txt @@ -0,0 +1,102 @@ +GPy.inference.latent_function_inference package +=============================================== + +Submodules +---------- + +GPy.inference.latent_function_inference.dtc module +-------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.dtc + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.exact_gaussian_inference module +----------------------------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.exact_gaussian_inference + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.expectation_propagation module +---------------------------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.expectation_propagation + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.expectation_propagation_dtc module +-------------------------------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.expectation_propagation_dtc + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.fitc module +--------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.fitc + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.inferenceX module +--------------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.inferenceX + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.laplace module +------------------------------------------------------ + +.. automodule:: GPy.inference.latent_function_inference.laplace + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.posterior module +-------------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.posterior + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.var_dtc module +------------------------------------------------------ + +.. automodule:: GPy.inference.latent_function_inference.var_dtc + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.var_dtc_gpu module +---------------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.var_dtc_gpu + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.latent_function_inference.var_dtc_parallel module +--------------------------------------------------------------- + +.. automodule:: GPy.inference.latent_function_inference.var_dtc_parallel + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.inference.latent_function_inference + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.inference.mcmc.txt b/doc/_build/html/_sources/GPy.inference.mcmc.txt new file mode 100644 index 00000000..273658b7 --- /dev/null +++ b/doc/_build/html/_sources/GPy.inference.mcmc.txt @@ -0,0 +1,30 @@ +GPy.inference.mcmc package +========================== + +Submodules +---------- + +GPy.inference.mcmc.hmc module +----------------------------- + +.. automodule:: GPy.inference.mcmc.hmc + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.mcmc.samplers module +---------------------------------- + +.. automodule:: GPy.inference.mcmc.samplers + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.inference.mcmc + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.inference.optimization.txt b/doc/_build/html/_sources/GPy.inference.optimization.txt new file mode 100644 index 00000000..a81a8e68 --- /dev/null +++ b/doc/_build/html/_sources/GPy.inference.optimization.txt @@ -0,0 +1,62 @@ +GPy.inference.optimization package +================================== + +Submodules +---------- + +GPy.inference.optimization.conjugate_gradient_descent module +------------------------------------------------------------ + +.. automodule:: GPy.inference.optimization.conjugate_gradient_descent + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.optimization.gradient_descent_update_rules module +--------------------------------------------------------------- + +.. automodule:: GPy.inference.optimization.gradient_descent_update_rules + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.optimization.optimization module +---------------------------------------------- + +.. automodule:: GPy.inference.optimization.optimization + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.optimization.scg module +------------------------------------- + +.. automodule:: GPy.inference.optimization.scg + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.optimization.sgd module +------------------------------------- + +.. automodule:: GPy.inference.optimization.sgd + :members: + :undoc-members: + :show-inheritance: + +GPy.inference.optimization.stochastics module +--------------------------------------------- + +.. automodule:: GPy.inference.optimization.stochastics + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.inference.optimization + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.inference.txt b/doc/_build/html/_sources/GPy.inference.txt new file mode 100644 index 00000000..235f804b --- /dev/null +++ b/doc/_build/html/_sources/GPy.inference.txt @@ -0,0 +1,19 @@ +GPy.inference package +===================== + +Subpackages +----------- + +.. toctree:: + + GPy.inference.latent_function_inference + GPy.inference.mcmc + GPy.inference.optimization + +Module contents +--------------- + +.. automodule:: GPy.inference + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.kern._src.psi_comp.txt b/doc/_build/html/_sources/GPy.kern._src.psi_comp.txt new file mode 100644 index 00000000..d84eeaa0 --- /dev/null +++ b/doc/_build/html/_sources/GPy.kern._src.psi_comp.txt @@ -0,0 +1,62 @@ +GPy.kern._src.psi_comp package +============================== + +Submodules +---------- + +GPy.kern._src.psi_comp.linear_psi_comp module +--------------------------------------------- + +.. automodule:: GPy.kern._src.psi_comp.linear_psi_comp + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.psi_comp.rbf_psi_comp module +------------------------------------------ + +.. automodule:: GPy.kern._src.psi_comp.rbf_psi_comp + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.psi_comp.rbf_psi_gpucomp module +--------------------------------------------- + +.. automodule:: GPy.kern._src.psi_comp.rbf_psi_gpucomp + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.psi_comp.sslinear_psi_comp module +----------------------------------------------- + +.. automodule:: GPy.kern._src.psi_comp.sslinear_psi_comp + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.psi_comp.ssrbf_psi_comp module +-------------------------------------------- + +.. automodule:: GPy.kern._src.psi_comp.ssrbf_psi_comp + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.psi_comp.ssrbf_psi_gpucomp module +----------------------------------------------- + +.. automodule:: GPy.kern._src.psi_comp.ssrbf_psi_gpucomp + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.kern._src.psi_comp + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.kern._src.txt b/doc/_build/html/_sources/GPy.kern._src.txt new file mode 100644 index 00000000..93dc0058 --- /dev/null +++ b/doc/_build/html/_sources/GPy.kern._src.txt @@ -0,0 +1,197 @@ +GPy.kern._src package +===================== + +Subpackages +----------- + +.. toctree:: + + GPy.kern._src.psi_comp + +Submodules +---------- + +GPy.kern._src.ODE_UY module +--------------------------- + +.. automodule:: GPy.kern._src.ODE_UY + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.ODE_UYC module +---------------------------- + +.. automodule:: GPy.kern._src.ODE_UYC + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.ODE_st module +--------------------------- + +.. automodule:: GPy.kern._src.ODE_st + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.ODE_t module +-------------------------- + +.. automodule:: GPy.kern._src.ODE_t + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.add module +------------------------ + +.. automodule:: GPy.kern._src.add + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.brownian module +----------------------------- + +.. automodule:: GPy.kern._src.brownian + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.coregionalize module +---------------------------------- + +.. automodule:: GPy.kern._src.coregionalize + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.hierarchical module +--------------------------------- + +.. automodule:: GPy.kern._src.hierarchical + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.independent_outputs module +---------------------------------------- + +.. automodule:: GPy.kern._src.independent_outputs + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.kern module +------------------------- + +.. automodule:: GPy.kern._src.kern + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.kernel_slice_operations module +-------------------------------------------- + +.. automodule:: GPy.kern._src.kernel_slice_operations + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.linear module +--------------------------- + +.. automodule:: GPy.kern._src.linear + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.mlp module +------------------------ + +.. automodule:: GPy.kern._src.mlp + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.periodic module +----------------------------- + +.. automodule:: GPy.kern._src.periodic + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.poly module +------------------------- + +.. automodule:: GPy.kern._src.poly + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.prod module +------------------------- + +.. automodule:: GPy.kern._src.prod + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.rbf module +------------------------ + +.. automodule:: GPy.kern._src.rbf + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.splitKern module +------------------------------ + +.. automodule:: GPy.kern._src.splitKern + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.static module +--------------------------- + +.. automodule:: GPy.kern._src.static + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.stationary module +------------------------------- + +.. automodule:: GPy.kern._src.stationary + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.symbolic module +----------------------------- + +.. automodule:: GPy.kern._src.symbolic + :members: + :undoc-members: + :show-inheritance: + +GPy.kern._src.trunclinear module +-------------------------------- + +.. automodule:: GPy.kern._src.trunclinear + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.kern._src + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.kern.txt b/doc/_build/html/_sources/GPy.kern.txt new file mode 100644 index 00000000..5a0c61c2 --- /dev/null +++ b/doc/_build/html/_sources/GPy.kern.txt @@ -0,0 +1,17 @@ +GPy.kern package +================ + +Subpackages +----------- + +.. toctree:: + + GPy.kern._src + +Module contents +--------------- + +.. automodule:: GPy.kern + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.likelihoods.txt b/doc/_build/html/_sources/GPy.likelihoods.txt new file mode 100644 index 00000000..323bb609 --- /dev/null +++ b/doc/_build/html/_sources/GPy.likelihoods.txt @@ -0,0 +1,86 @@ +GPy.likelihoods package +======================= + +Submodules +---------- + +GPy.likelihoods.bernoulli module +-------------------------------- + +.. automodule:: GPy.likelihoods.bernoulli + :members: + :undoc-members: + :show-inheritance: + +GPy.likelihoods.exponential module +---------------------------------- + +.. automodule:: GPy.likelihoods.exponential + :members: + :undoc-members: + :show-inheritance: + +GPy.likelihoods.gamma module +---------------------------- + +.. automodule:: GPy.likelihoods.gamma + :members: + :undoc-members: + :show-inheritance: + +GPy.likelihoods.gaussian module +------------------------------- + +.. automodule:: GPy.likelihoods.gaussian + :members: + :undoc-members: + :show-inheritance: + +GPy.likelihoods.likelihood module +--------------------------------- + +.. automodule:: GPy.likelihoods.likelihood + :members: + :undoc-members: + :show-inheritance: + +GPy.likelihoods.link_functions module +------------------------------------- + +.. automodule:: GPy.likelihoods.link_functions + :members: + :undoc-members: + :show-inheritance: + +GPy.likelihoods.mixed_noise module +---------------------------------- + +.. automodule:: GPy.likelihoods.mixed_noise + :members: + :undoc-members: + :show-inheritance: + +GPy.likelihoods.poisson module +------------------------------ + +.. automodule:: GPy.likelihoods.poisson + :members: + :undoc-members: + :show-inheritance: + +GPy.likelihoods.student_t module +-------------------------------- + +.. automodule:: GPy.likelihoods.student_t + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.likelihoods + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.mappings.txt b/doc/_build/html/_sources/GPy.mappings.txt new file mode 100644 index 00000000..c13642cc --- /dev/null +++ b/doc/_build/html/_sources/GPy.mappings.txt @@ -0,0 +1,46 @@ +GPy.mappings package +==================== + +Submodules +---------- + +GPy.mappings.additive module +---------------------------- + +.. automodule:: GPy.mappings.additive + :members: + :undoc-members: + :show-inheritance: + +GPy.mappings.kernel module +-------------------------- + +.. automodule:: GPy.mappings.kernel + :members: + :undoc-members: + :show-inheritance: + +GPy.mappings.linear module +-------------------------- + +.. automodule:: GPy.mappings.linear + :members: + :undoc-members: + :show-inheritance: + +GPy.mappings.mlp module +----------------------- + +.. automodule:: GPy.mappings.mlp + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.mappings + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.models.txt b/doc/_build/html/_sources/GPy.models.txt new file mode 100644 index 00000000..cb043afa --- /dev/null +++ b/doc/_build/html/_sources/GPy.models.txt @@ -0,0 +1,198 @@ +GPy.models package +================== + +Submodules +---------- + +GPy.models.bayesian_gplvm module +-------------------------------- + +.. automodule:: GPy.models.bayesian_gplvm + :members: + :undoc-members: + :show-inheritance: + +GPy.models.bayesian_gplvm_minibatch module +------------------------------------------ + +.. automodule:: GPy.models.bayesian_gplvm_minibatch + :members: + :undoc-members: + :show-inheritance: + +GPy.models.bcgplvm module +------------------------- + +.. automodule:: GPy.models.bcgplvm + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gp_classification module +----------------------------------- + +.. automodule:: GPy.models.gp_classification + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gp_coregionalized_regression module +---------------------------------------------- + +.. automodule:: GPy.models.gp_coregionalized_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gp_heteroscedastic_regression module +----------------------------------------------- + +.. automodule:: GPy.models.gp_heteroscedastic_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gp_kronecker_gaussian_regression module +-------------------------------------------------- + +.. automodule:: GPy.models.gp_kronecker_gaussian_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gp_multioutput_regression module +------------------------------------------- + +.. automodule:: GPy.models.gp_multioutput_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gp_regression module +------------------------------- + +.. automodule:: GPy.models.gp_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gp_var_gauss module +------------------------------ + +.. automodule:: GPy.models.gp_var_gauss + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gplvm module +----------------------- + +.. automodule:: GPy.models.gplvm + :members: + :undoc-members: + :show-inheritance: + +GPy.models.gradient_checker module +---------------------------------- + +.. automodule:: GPy.models.gradient_checker + :members: + :undoc-members: + :show-inheritance: + +GPy.models.mrd module +--------------------- + +.. automodule:: GPy.models.mrd + :members: + :undoc-members: + :show-inheritance: + +GPy.models.sparse_gp_classification module +------------------------------------------ + +.. automodule:: GPy.models.sparse_gp_classification + :members: + :undoc-members: + :show-inheritance: + +GPy.models.sparse_gp_coregionalized_regression module +----------------------------------------------------- + +.. automodule:: GPy.models.sparse_gp_coregionalized_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.sparse_gp_minibatch module +------------------------------------- + +.. automodule:: GPy.models.sparse_gp_minibatch + :members: + :undoc-members: + :show-inheritance: + +GPy.models.sparse_gp_multioutput_regression module +-------------------------------------------------- + +.. automodule:: GPy.models.sparse_gp_multioutput_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.sparse_gp_regression module +-------------------------------------- + +.. automodule:: GPy.models.sparse_gp_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.sparse_gplvm module +------------------------------ + +.. automodule:: GPy.models.sparse_gplvm + :members: + :undoc-members: + :show-inheritance: + +GPy.models.ss_gplvm module +-------------------------- + +.. automodule:: GPy.models.ss_gplvm + :members: + :undoc-members: + :show-inheritance: + +GPy.models.ss_mrd module +------------------------ + +.. automodule:: GPy.models.ss_mrd + :members: + :undoc-members: + :show-inheritance: + +GPy.models.svigp_regression module +---------------------------------- + +.. automodule:: GPy.models.svigp_regression + :members: + :undoc-members: + :show-inheritance: + +GPy.models.warped_gp module +--------------------------- + +.. automodule:: GPy.models.warped_gp + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.models + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.txt b/doc/_build/html/_sources/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.txt new file mode 100644 index 00000000..71826ed6 --- /dev/null +++ b/doc/_build/html/_sources/GPy.plotting.matplot_dep.latent_space_visualizations.controllers.txt @@ -0,0 +1,30 @@ +GPy.plotting.matplot_dep.latent_space_visualizations.controllers package +======================================================================== + +Submodules +---------- + +GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller module +--------------------------------------------------------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.latent_space_visualizations.controllers.axis_event_controller + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.latent_space_visualizations.controllers.imshow_controller module +----------------------------------------------------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.latent_space_visualizations.controllers.imshow_controller + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.plotting.matplot_dep.latent_space_visualizations.controllers + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.plotting.matplot_dep.latent_space_visualizations.txt b/doc/_build/html/_sources/GPy.plotting.matplot_dep.latent_space_visualizations.txt new file mode 100644 index 00000000..6e5cf4bd --- /dev/null +++ b/doc/_build/html/_sources/GPy.plotting.matplot_dep.latent_space_visualizations.txt @@ -0,0 +1,17 @@ +GPy.plotting.matplot_dep.latent_space_visualizations package +============================================================ + +Subpackages +----------- + +.. toctree:: + + GPy.plotting.matplot_dep.latent_space_visualizations.controllers + +Module contents +--------------- + +.. automodule:: GPy.plotting.matplot_dep.latent_space_visualizations + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.plotting.matplot_dep.txt b/doc/_build/html/_sources/GPy.plotting.matplot_dep.txt new file mode 100644 index 00000000..77780708 --- /dev/null +++ b/doc/_build/html/_sources/GPy.plotting.matplot_dep.txt @@ -0,0 +1,141 @@ +GPy.plotting.matplot_dep package +================================ + +Subpackages +----------- + +.. toctree:: + + GPy.plotting.matplot_dep.latent_space_visualizations + +Submodules +---------- + +GPy.plotting.matplot_dep.Tango module +------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.Tango + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.base_plots module +------------------------------------------ + +.. automodule:: GPy.plotting.matplot_dep.base_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.dim_reduction_plots module +--------------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.dim_reduction_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.img_plots module +----------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.img_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.inference_plots module +----------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.inference_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.kernel_plots module +-------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.kernel_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.mapping_plots module +--------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.mapping_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.maps module +------------------------------------ + +.. automodule:: GPy.plotting.matplot_dep.maps + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.models_plots module +-------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.models_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.netpbmfile module +------------------------------------------ + +.. automodule:: GPy.plotting.matplot_dep.netpbmfile + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.priors_plots module +-------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.priors_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.ssgplvm module +--------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.ssgplvm + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.svig_plots module +------------------------------------------ + +.. automodule:: GPy.plotting.matplot_dep.svig_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.variational_plots module +------------------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.variational_plots + :members: + :undoc-members: + :show-inheritance: + +GPy.plotting.matplot_dep.visualize module +----------------------------------------- + +.. automodule:: GPy.plotting.matplot_dep.visualize + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.plotting.matplot_dep + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.plotting.txt b/doc/_build/html/_sources/GPy.plotting.txt new file mode 100644 index 00000000..af035515 --- /dev/null +++ b/doc/_build/html/_sources/GPy.plotting.txt @@ -0,0 +1,17 @@ +GPy.plotting package +==================== + +Subpackages +----------- + +.. toctree:: + + GPy.plotting.matplot_dep + +Module contents +--------------- + +.. automodule:: GPy.plotting + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.testing.txt b/doc/_build/html/_sources/GPy.testing.txt new file mode 100644 index 00000000..45bb307f --- /dev/null +++ b/doc/_build/html/_sources/GPy.testing.txt @@ -0,0 +1,102 @@ +GPy.testing package +=================== + +Submodules +---------- + +GPy.testing.examples_tests module +--------------------------------- + +.. automodule:: GPy.testing.examples_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.fitc module +----------------------- + +.. automodule:: GPy.testing.fitc + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.index_operations_tests module +----------------------------------------- + +.. automodule:: GPy.testing.index_operations_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.inference_tests module +---------------------------------- + +.. automodule:: GPy.testing.inference_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.kernel_tests module +------------------------------- + +.. automodule:: GPy.testing.kernel_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.likelihood_tests module +----------------------------------- + +.. automodule:: GPy.testing.likelihood_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.model_tests module +------------------------------ + +.. automodule:: GPy.testing.model_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.observable_tests module +----------------------------------- + +.. automodule:: GPy.testing.observable_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.parameterized_tests module +-------------------------------------- + +.. automodule:: GPy.testing.parameterized_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.pickle_tests module +------------------------------- + +.. automodule:: GPy.testing.pickle_tests + :members: + :undoc-members: + :show-inheritance: + +GPy.testing.prior_tests module +------------------------------ + +.. automodule:: GPy.testing.prior_tests + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.testing + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.txt b/doc/_build/html/_sources/GPy.txt new file mode 100644 index 00000000..9be6dbec --- /dev/null +++ b/doc/_build/html/_sources/GPy.txt @@ -0,0 +1,26 @@ +GPy package +=========== + +Subpackages +----------- + +.. toctree:: + + GPy.core + GPy.examples + GPy.inference + GPy.kern + GPy.likelihoods + GPy.mappings + GPy.models + GPy.plotting + GPy.testing + GPy.util + +Module contents +--------------- + +.. automodule:: GPy + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/GPy.util.txt b/doc/_build/html/_sources/GPy.util.txt new file mode 100644 index 00000000..e50efdfb --- /dev/null +++ b/doc/_build/html/_sources/GPy.util.txt @@ -0,0 +1,230 @@ +GPy.util package +================ + +Submodules +---------- + +GPy.util.block_matrices module +------------------------------ + +.. automodule:: GPy.util.block_matrices + :members: + :undoc-members: + :show-inheritance: + +GPy.util.caching module +----------------------- + +.. automodule:: GPy.util.caching + :members: + :undoc-members: + :show-inheritance: + +GPy.util.classification module +------------------------------ + +.. automodule:: GPy.util.classification + :members: + :undoc-members: + :show-inheritance: + +GPy.util.config module +---------------------- + +.. automodule:: GPy.util.config + :members: + :undoc-members: + :show-inheritance: + +GPy.util.datasets module +------------------------ + +.. automodule:: GPy.util.datasets + :members: + :undoc-members: + :show-inheritance: + +GPy.util.debug module +--------------------- + +.. automodule:: GPy.util.debug + :members: + :undoc-members: + :show-inheritance: + +GPy.util.decorators module +-------------------------- + +.. automodule:: GPy.util.decorators + :members: + :undoc-members: + :show-inheritance: + +GPy.util.diag module +-------------------- + +.. automodule:: GPy.util.diag + :members: + :undoc-members: + :show-inheritance: + +GPy.util.erfcx module +--------------------- + +.. automodule:: GPy.util.erfcx + :members: + :undoc-members: + :show-inheritance: + +GPy.util.functions module +------------------------- + +.. automodule:: GPy.util.functions + :members: + :undoc-members: + :show-inheritance: + +GPy.util.gpu_init module +------------------------ + +.. automodule:: GPy.util.gpu_init + :members: + :undoc-members: + :show-inheritance: + +GPy.util.initialization module +------------------------------ + +.. automodule:: GPy.util.initialization + :members: + :undoc-members: + :show-inheritance: + +GPy.util.linalg module +---------------------- + +.. automodule:: GPy.util.linalg + :members: + :undoc-members: + :show-inheritance: + +GPy.util.linalg_gpu module +-------------------------- + +.. automodule:: GPy.util.linalg_gpu + :members: + :undoc-members: + :show-inheritance: + +GPy.util.ln_diff_erfs module +---------------------------- + +.. automodule:: GPy.util.ln_diff_erfs + :members: + :undoc-members: + :show-inheritance: + +GPy.util.misc module +-------------------- + +.. automodule:: GPy.util.misc + :members: + :undoc-members: + :show-inheritance: + +GPy.util.mocap module +--------------------- + +.. automodule:: GPy.util.mocap + :members: + :undoc-members: + :show-inheritance: + +GPy.util.mpi module +------------------- + +.. automodule:: GPy.util.mpi + :members: + :undoc-members: + :show-inheritance: + +GPy.util.multioutput module +--------------------------- + +.. automodule:: GPy.util.multioutput + :members: + :undoc-members: + :show-inheritance: + +GPy.util.netpbmfile module +-------------------------- + +.. automodule:: GPy.util.netpbmfile + :members: + :undoc-members: + :show-inheritance: + +GPy.util.normalizer module +-------------------------- + +.. automodule:: GPy.util.normalizer + :members: + :undoc-members: + :show-inheritance: + +GPy.util.parallel module +------------------------ + +.. automodule:: GPy.util.parallel + :members: + :undoc-members: + :show-inheritance: + +GPy.util.pca module +------------------- + +.. automodule:: GPy.util.pca + :members: + :undoc-members: + :show-inheritance: + +GPy.util.squashers module +------------------------- + +.. automodule:: GPy.util.squashers + :members: + :undoc-members: + :show-inheritance: + +GPy.util.subarray_and_sorting module +------------------------------------ + +.. automodule:: GPy.util.subarray_and_sorting + :members: + :undoc-members: + :show-inheritance: + +GPy.util.univariate_Gaussian module +----------------------------------- + +.. automodule:: GPy.util.univariate_Gaussian + :members: + :undoc-members: + :show-inheritance: + +GPy.util.warping_functions module +--------------------------------- + +.. automodule:: GPy.util.warping_functions + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: GPy.util + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/_sources/index.txt b/doc/_build/html/_sources/index.txt new file mode 100644 index 00000000..fec4aef1 --- /dev/null +++ b/doc/_build/html/_sources/index.txt @@ -0,0 +1,38 @@ +.. GPy documentation master file, created by + sphinx-quickstart on Fri Jan 18 17:36:01 2013. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to GPy's documentation! +=============================== + +`GPy `_ is a Gaussian Process (GP) framework written in Python, from the Sheffield machine learning group. + +The `GPy homepage `_ contains tutorials for users and further information on the project, including installation instructions. +This documentation is mostly aimed at developers interacting closely with the code-base. + +The code can be found on our `Github project page `_. It is open source and provided under the BSD license. + +.. * `Basic Gaussian process regression `_ +.. * `Interacting with models `_ +.. * `A kernel overview `_ +.. * `Writing new kernels `_ +.. * `Writing new models `_ +.. * `Parameterization handles `_ + +.. You may also be interested by some examples in the GPy/examples folder. + +Contents: + +.. toctree:: + :maxdepth: 2 + + GPy + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/_build/html/_sources/installation.txt b/doc/_build/html/_sources/installation.txt new file mode 100644 index 00000000..35352272 --- /dev/null +++ b/doc/_build/html/_sources/installation.txt @@ -0,0 +1,31 @@ +============== + Installation +============== + + +Linux +============ + + +Windows +====================== +One easy way to get a Python distribution with the required packages is to use the Anaconda environment from Continuum Analytics. + +* Download and install the free version of Anaconda according to your operating system from `their website `_. +* Open a (new) terminal window: + + * Navigate to Applications/Accessories/cmd, or + * open *anaconda Command Prompt* from windows *start* + +You should now be able to launch a Python interpreter by typing *ipython* in the terminal. In the ipython prompt, you can check your installation by importing the libraries we will need later: +:: + $ import numpy + $ import pylab + +To install the latest version of GPy, *git* is required. A *git* client on Windows can be found `here `_. It is recommened to install with the option "*Use Git from the Windows Command Prompt*". Then, GPy can be installed with the following command +:: + pip install git+https://github.com/SheffieldML/GPy.git@devel + +MacOSX +=================================== + diff --git a/doc/_build/html/_sources/kernel_implementation.txt b/doc/_build/html/_sources/kernel_implementation.txt new file mode 100644 index 00000000..c566d21d --- /dev/null +++ b/doc/_build/html/_sources/kernel_implementation.txt @@ -0,0 +1,49 @@ + +*************************** +List of implemented kernels +*************************** + +The following table shows the implemented kernels in GPy and gives the details of the implemented function for each kernel. + +==================== =========== ===== =========== ====== ======= =========== =============== ======= =========== ====== ====== ======= +NAME Dimension ARD get/set K Kdiag dK_dtheta dKdiag_dtheta dK_dX dKdiag_dX psi0 psi1 psi2 +==================== =========== ===== =========== ====== ======= =========== =============== ======= =========== ====== ====== ======= +bias n |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +Brownian 1 |tick| |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +exponential n yes |tick| |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +finite_dimensional n |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +linear n yes |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +Matern32 n yes |tick| |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +Matern52 n yes |tick| |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +periodic_exponential 1 |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +periodic_Matern32 1 |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +periodic_Matern52 1 |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +rational quadratic 1 |tick| |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +rbf n yes |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +spline 1 |tick| |tick| |tick| |tick| |tick| |tick| +-------------------- ----------- ----- ----------- ------ ------- ----------- --------------- ------- ----------- ------ ------ ------- +white n |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| |tick| +==================== =========== ===== =========== ====== ======= =========== =============== ======= =========== ====== ====== ======= + +Depending on the use, all functions may not be required + + * ``get/set, K, Kdiag``: compulsory + * ``dK_dtheta``: necessary to optimize the model + * ``dKdiag_dtheta``: sparse models, BGPLVM, GPs with uncertain inputs + * ``dK_dX``: sparse models, GPLVM, BGPLVM, GPs with uncertain inputs + * ``dKdiag_dX``: sparse models, BGPLVM, GPs with uncertain inputs + * ``psi0, psi1, psi2``: BGPLVM, GPs with uncertain inputs + +.. |tick| image:: Figures/tick.png diff --git a/doc/_build/html/_sources/modules.txt b/doc/_build/html/_sources/modules.txt new file mode 100644 index 00000000..9c698ca2 --- /dev/null +++ b/doc/_build/html/_sources/modules.txt @@ -0,0 +1,7 @@ +GPy +=== + +.. toctree:: + :maxdepth: 4 + + GPy diff --git a/doc/_build/html/_sources/tuto_GP_regression.txt b/doc/_build/html/_sources/tuto_GP_regression.txt new file mode 100644 index 00000000..29eefa72 --- /dev/null +++ b/doc/_build/html/_sources/tuto_GP_regression.txt @@ -0,0 +1,142 @@ +************************************* +Gaussian process regression tutorial +************************************* + +We will see in this tutorial the basics for building a 1 dimensional and a 2 dimensional Gaussian process regression model, also known as a kriging model. The code shown in this tutorial can be obtained at GPy/examples/tutorials.py, or by running ``GPy.examples.tutorials.tuto_GP_regression()``. + +We first import the libraries we will need: :: + + import pylab as pb + pb.ion() + import numpy as np + import GPy + +1-dimensional model +=================== + +For this toy example, we assume we have the following inputs and outputs:: + + X = np.random.uniform(-3.,3.,(20,1)) + Y = np.sin(X) + np.random.randn(20,1)*0.05 + +Note that the observations Y include some noise. + +The first step is to define the covariance kernel we want to use for the model. We choose here a kernel based on Gaussian kernel (i.e. rbf or square exponential):: + + kernel = GPy.kern.RBF(input_dim=1, variance=1., lengthscale=1.) + +The parameter ``input_dim`` stands for the dimension of the input space. The parameters ``variance`` and ``lengthscale`` are optional. Many other kernels are implemented such as: + +* linear (:py:class:`~GPy.kern.Linear`) +* exponential kernel (:py:class:`GPy.kern.Exponential`) +* Matern 3/2 (:py:class:`GPy.kern.Matern32`) +* Matern 5/2 (:py:class:`GPy.kern.Matern52`) +* spline (:py:class:`GPy.kern.Spline`) +* and many others... + +The inputs required for building the model are the observations and the kernel:: + + m = GPy.models.GPRegression(X,Y,kernel) + +By default, some observation noise is added to the modle. The functions ``print`` and ``plot`` give an insight of the model we have just build. The code:: + + print m + m.plot() + +gives the following output: :: + + Name : GP regression + Log-likelihood : -22.8178418808 + Number of Parameters : 3 + Parameters: + GP_regression. | Value | Constraint | Prior | Tied to + rbf.variance | 1.0 | +ve | | + rbf.lengthscale | 1.0 | +ve | | + Gaussian_noise.variance | 1.0 | +ve | | + +.. figure:: Figures/tuto_GP_regression_m1.png + :align: center + :height: 350px + + GP regression model before optimization of the parameters. The shaded region corresponds to ~95% confidence intervals (ie +/- 2 standard deviation). + +The default values of the kernel parameters may not be relevant for +the current data (for example, the confidence intervals seems too wide +on the previous figure). A common approach is to find the values of +the parameters that maximize the likelihood of the data. It as easy as +calling ``m.optimize`` in GPy:: + + m.optimize() + +If we want to perform some restarts to try to improve the result of the optimization, we can use the ``optimize_restart`` function:: + + m.optimize_restarts(num_restarts = 10) + +Once again, we can use ``print(m)`` and ``m.plot()`` to look at the resulting model resulting model:: + + Name : GP regression + Log-likelihood : 11.947469082 + Number of Parameters : 3 + Parameters: + GP_regression. | Value | Constraint | Prior | Tied to + rbf.variance | 0.74229417323 | +ve | | + rbf.lengthscale | 1.43020495724 | +ve | | + Gaussian_noise.variance | 0.00325654460991 | +ve | | + +.. figure:: Figures/tuto_GP_regression_m2.png + :align: center + :height: 350px + + GP regression model after optimization of the parameters. + + +2-dimensional example +===================== + +Here is a 2 dimensional example:: + + import pylab as pb + pb.ion() + import numpy as np + import GPy + + # sample inputs and outputs + X = np.random.uniform(-3.,3.,(50,2)) + Y = np.sin(X[:,0:1]) * np.sin(X[:,1:2])+np.random.randn(50,1)*0.05 + + # define kernel + ker = GPy.kern.Matern52(2,ARD=True) + GPy.kern.White(2) + + # create simple GP model + m = GPy.models.GPRegression(X,Y,ker) + + # optimize and plot + m.optimize(max_f_eval = 1000) + m.plot() + print(m) + +The flag ``ARD=True`` in the definition of the Matern kernel specifies that we want one lengthscale parameter per dimension (ie the GP is not isotropic). The output of the last two lines is:: + + Name : GP regression + Log-likelihood : 26.787156248 + Number of Parameters : 5 + Parameters: + GP_regression. | Value | Constraint | Prior | Tied to + add.Mat52.variance | 0.385463739076 | +ve | | + add.Mat52.lengthscale | (2,) | +ve | | + add.white.variance | 0.000835329608514 | +ve | | + Gaussian_noise.variance | 0.000835329608514 | +ve | | + +If you want to see the ``ARD`` parameters explicitly print them +directly:: + + >>> print m.add.Mat52.lengthscale + Index | GP_regression.add.Mat52.lengthscale | Constraint | Prior | Tied to + [0] | 1.9575587 | +ve | | N/A + [1] | 1.9689948 | +ve | | N/A + +.. figure:: Figures/tuto_GP_regression_m3.png + :align: center + :height: 350px + + Contour plot of the best predictor (posterior mean). diff --git a/doc/_build/html/_sources/tuto_creating_new_kernels.txt b/doc/_build/html/_sources/tuto_creating_new_kernels.txt new file mode 100644 index 00000000..a8197596 --- /dev/null +++ b/doc/_build/html/_sources/tuto_creating_new_kernels.txt @@ -0,0 +1,212 @@ +******************** +Creating new kernels +******************** + +We will see in this tutorial how to create new kernels in GPy. We will also give details on how to implement each function of the kernel and illustrate with a running example: the rational quadratic kernel. + +Structure of a kernel in GPy +============================ + +In GPy a kernel object is made of a list of kernpart objects, which correspond to symetric positive definite functions. More precisely, the kernel should be understood as the sum of the kernparts. In order to implement a new covariance, the following steps must be followed + + 1. implement the new covariance as a kernpart object + 2. update the constructors that allow to use the kernpart as a kern object + 3. update the __init__.py file + +Theses three steps are detailed below. + +Implementing a kernpart object +============================== + +We advise the reader to start with copy-pasting an existing kernel and to modify the new file. We will now give a description of the various functions that can be found in a kernpart object. + +**Header** + +The header is similar to all kernels: :: + + from kernpart import kernpart + import numpy as np + + class rational_quadratic(kernpart): + +**__init__(self,input_dim, param1, param2, ...)** + +The implementation of this function in mandatory. + +For all kernparts the first parameter ``input_dim`` corresponds to the dimension of the input space, and the following parameters stand for the parameterization of the kernel. + +You have to call ``super(, self).__init__(input_dim, +name)`` to make sure the input dimension and name of the kernel are +stored in the right place. These attributes are available as +``self.input_dim`` and ``self.name`` at runtime. +.. The following attributes are compulsory: ``self.input_dim`` (the dimension, integer), ``self.name`` (name of the kernel, string), ``self.num_params`` (number of parameters, integer). :: +Parameterization is done by adding +:py:class:``GPy.core.parameter.Param`` objects to ``self`` and use +them as normal numpy ``array-like``s in yout code. The parameters have +to be added by calling +:py:function:``GPy.core.parameterized:Parameterized.add_parameters`` +with the :py:class:``GPy.core.parameter.Param`` objects as arguments. + + def __init__(self,input_dim,variance=1.,lengthscale=1.,power=1.): + super(RationalQuadratic, self).__init__(input_dim, 'rat_quad') + assert input_dim == 1, "For this kernel we assume input_dim=1" + self.variance = Param('variance', variance) + self.lengthscale = Param('lengtscale', lengthscale) + self.power = Param('power', power) + self.add_parameters(self.variance, self.lengthscale, self.power) + +From now on you can use the parameters ``self.variance, +self.lengthscale, self.power`` as normal numpy ``array-like``s in your +code. Updates from the optimization routine will be done +automatically. + +**parameters_changed(self)** + +The implementation of this function is optional. + +This functions deals as a callback for each optimization iteration. If +one optimization step was successfull and the parameters (added by +:py:function:``GPy.core.parameterized:Parameterized.add_parameters``) +this callback function will be called to be able to update any +precomputations for the kernel. + + def parameters_changed(self): + # nothing todo here + + + +.. **_get_params(self)** + +.. The implementation of this function in mandatory. + +.. This function returns a one dimensional array of length ``self.num_params`` containing the value of the parameters. :: + +.. def _get_params(self): +.. return np.hstack((self.variance,self.lengthscale,self.power)) + +.. **_set_params(self,x)** + +.. The implementation of this function in mandatory. + +.. The input is a one dimensional array of length ``self.num_params`` containing the value of the parameters. The function has no output but it updates the values of the attribute associated to the parameters (such as ``self.variance``, ``self.lengthscale``, ...). :: + +.. def _set_params(self,x): +.. self.variance = x[0] +.. self.lengthscale = x[1] +.. self.power = x[2] + +.. **_get_param_names(self)** + +.. The implementation of this function in mandatory. + +.. It returns a list of strings of length ``self.num_params`` corresponding to the parameter names. :: + +.. def _get_param_names(self): +.. return ['variance','lengthscale','power'] + +**K(self,X,X2,target)** + +The implementation of this function in mandatory. + +This function is used to compute the covariance matrix associated with the inputs X, X2 (np.arrays with arbitrary number of line (say :math:`n_1`, :math:`n_2`) and ``self.input_dim`` columns). This function does not returns anything but it adds the :math:`n_1 \times n_2` covariance matrix to the kernpart to the object ``target`` (a :math:`n_1 \times n_2` np.array). This trick allows to compute the covariance matrix of a kernel containing many kernparts with a limited memory use. :: + + def K(self,X,X2,target): + if X2 is None: X2 = X + dist2 = np.square((X-X2.T)/self.lengthscale) + target += self.variance*(1 + dist2/2.)**(-self.power) + +**Kdiag(self,X,target)** + +The implementation of this function in mandatory. + +This function is similar to ``K`` but it computes only the values of the kernel on the diagonal. Thus, ``target`` is a 1-dimensional np.array of length :math:`n_1`. :: + + def Kdiag(self,X,target): + target += self.variance + + +**dK_dtheta(self,dL_dK,X,X2,target)** + +This function is required for the optimization of the parameters. + +Computes the derivative of the likelihood. As previously, the values are added to the object target which is a 1-dimensional np.array of length ``self.input_dim``. For example, if the kernel is parameterized by :math:`\sigma^2,\ \theta`, then :math:`\frac{dL}{d\sigma^2} = \frac{dL}{d K} \frac{dK}{d\sigma^2}` is added to the first element of target and :math:`\frac{dL}{d\theta} = \frac{dL}{d K} \frac{dK}{d\theta}` to the second. :: + + def dK_dtheta(self,dL_dK,X,X2,target): + if X2 is None: X2 = X + dist2 = np.square((X-X2.T)/self.lengthscale) + + dvar = (1 + dist2/2.)**(-self.power) + dl = self.power * self.variance * dist2 * self.lengthscale**(-3) * (1 + dist2/2./self.power)**(-self.power-1) + dp = - self.variance * np.log(1 + dist2/2.) * (1 + dist2/2.)**(-self.power) + + target[0] += np.sum(dvar*dL_dK) + target[1] += np.sum(dl*dL_dK) + target[2] += np.sum(dp*dL_dK) + + +**dKdiag_dtheta(self,dL_dKdiag,X,target)** + +This function is required for BGPLVM, sparse models and uncertain inputs. + +As previously, target is an ``self.num_params`` array and :math:`\frac{dL}{d Kdiag} \frac{dKdiag}{dparam}` is added to each element. :: + + def dKdiag_dtheta(self,dL_dKdiag,X,target): + target[0] += np.sum(dL_dKdiag) + # here self.lengthscale and self.power have no influence on Kdiag so target[1:] are unchanged + +**dK_dX(self,dL_dK,X,X2,target)** + +This function is required for GPLVM, BGPLVM, sparse models and uncertain inputs. + +Computes the derivative of the likelihood with respect to the inputs ``X`` (a :math:`n \times d` np.array). The result is added to target which is a :math:`n \times d` np.array. :: + + def dK_dX(self,dL_dK,X,X2,target): + """derivative of the covariance matrix with respect to X.""" + if X2 is None: X2 = X + dist2 = np.square((X-X2.T)/self.lengthscale) + + dX = -self.variance*self.power * (X-X2.T)/self.lengthscale**2 * (1 + dist2/2./self.lengthscale)**(-self.power-1) + target += np.sum(dL_dK*dX,1)[:,np.newaxis] + +**dKdiag_dX(self,dL_dKdiag,X,target)** + +This function is required for BGPLVM, sparse models and uncertain inputs. As for ``dKdiag_dtheta``, :math:`\frac{dL}{d Kdiag} \frac{dKdiag}{dX}` is added to each element of target. :: + + def dKdiag_dX(self,dL_dKdiag,X,target): + pass + +**Psi statistics** + +The psi statistics and their derivatives are required for BGPLVM and GPS with uncertain inputs. + +The expressions of the psi statistics are: + +TODO + +For the rational quadratic we have: + +TODO + +Update the constructor +====================== + +Once the required functions have been implemented as a kernpart object, the file GPy/kern/constructors.py has to be updated to allow to build a kernel based on the kernpart object. + +The following line should be added in the preamble of the file:: + + from rational_quadratic import rational_quadratic as rational_quadratic_part + +as well as the following block :: + + def rational_quadratic(input_dim,variance=1., lengthscale=1., power=1.): + part = rational_quadraticpart(input_dim,variance, lengthscale, power) + return kern(input_dim, [part]) + + +Update initialization +===================== + +The last step is to update the list of kernels imported from constructor in GPy/kern/__init__.py. + + + diff --git a/doc/_build/html/_sources/tuto_creating_new_models.txt b/doc/_build/html/_sources/tuto_creating_new_models.txt new file mode 100644 index 00000000..07f6194f --- /dev/null +++ b/doc/_build/html/_sources/tuto_creating_new_models.txt @@ -0,0 +1,100 @@ +.. _creating_new_models: + +******************* +Creating new Models +******************* + +In GPy all models inherit from the base class :py:class:`~GPy.core.parameterized.Parameterized`. :py:class:`~GPy.core.parameterized.Parameterized` is a class which allows for parameterization of objects. All it holds is functionality for tying, bounding and fixing of parameters. It also provides the functionality of searching and manipulating parameters by regular expression syntax. See :py:class:`~GPy.core.parameterized.Parameterized` for more information. + +The :py:class:`~GPy.core.model.Model` class provides parameter introspection, objective function and optimization. + +In order to fully use all functionality of +:py:class:`~GPy.core.model.Model` some methods need to be implemented +/ overridden. And the model needs to be told its parameters, such +that it can provide optimized parameter distribution and handling. +In order to explain the functionality of those methods +we will use a wrapper to the numpy ``rosen`` function, which holds +input parameters :math:`\mathbf{X}`. Where +:math:`\mathbf{X}\in\mathbb{R}^{N\times 1}`. + +Obligatory methods +================== + +:py:func:`~GPy.core.model.Model.__init__` : + Initialize the model with the given parameters. These need to + be added to the model by calling + `self.add_parameter()`, where param needs to be a + parameter handle (See parameterized_ for details).:: + + self.X = GPy.Param("input", X) + self.add_parameter(self.X) + +:py:meth:`~GPy.core.model.Model.log_likelihood` : + Returns the log-likelihood of the new model. For our example + this is just the call to ``rosen`` and as we want to minimize + it, we need to negate the objective.:: + + return -scipy.optimize.rosen(self.X) + +:py:meth:`~GPy.core.model.Model.parameters_changed` : + Updates the internal state of the model and sets the gradient of + each parameter handle in the hierarchy with respect to the + log_likelihod. Thus here we need to set the negative derivative of + the rosenbrock function for the parameters. In this case it is the + gradient for self.X.:: + + self.X.gradient = -scipy.optimize.rosen_der(self.X) + + +Here the full code for the `Rosen` class:: + + from GPy import Model, Param + import scipy + class Rosen(Model): + def __init__(self, X, name='rosenbrock'): + super(Rosen, self).__init__(name=name) + self.X = Param("input", X) + self.add_parameter(self.X) + def log_likelihood(self): + return -scipy.optimize.rosen(self.X) + def parameters_changed(self): + self.X.gradient = -scipy.optimize.rosen_der(self.X) + +In order to test the newly created model, we can check the gradients +and optimize a standard rosenbrock run:: + + >>> m = Rosen(np.array([-1,-1])) + >>> print m + Name : rosenbrock + Log-likelihood : -404.0 + Number of Parameters : 2 + Parameters: + rosenbrock. | Value | Constraint | Prior | Tied to + input | (2,) | | | + >>> m.checkgrad(verbose=True) + Name | Ratio | Difference | Analytical | Numerical + ------------------------------------------------------------------------------------------ + rosenbrock.input[[0]] | 1.000000 | 0.000000 | -804.000000 | -804.000000 + rosenbrock.input[[1]] | 1.000000 | 0.000000 | -400.000000 | -400.000000 + >>> m.optimize() + >>> print m + Name : rosenbrock + Log-likelihood : -6.52150088871e-15 + Number of Parameters : 2 + Parameters: + rosenbrock. | Value | Constraint | Prior | Tied to + input | (2,) | | | + >>> print m.input + Index | rosenbrock.input | Constraint | Prior | Tied to + [0] | 0.99999994 | | | N/A + [1] | 0.99999987 | | | N/A + >>> print m.gradient + [ -1.91169809e-06, 1.01852309e-06] + +This is the optimium for the 2D Rosenbrock function, as expected, and +the gradient of the inputs are almost zero. + +Optional methods +================ + +Currently none. diff --git a/doc/_build/html/_sources/tuto_interacting_with_models.txt b/doc/_build/html/_sources/tuto_interacting_with_models.txt new file mode 100644 index 00000000..80b2ac77 --- /dev/null +++ b/doc/_build/html/_sources/tuto_interacting_with_models.txt @@ -0,0 +1,341 @@ +.. _interacting_with_models: + +************************************* +Interacting with models +************************************* + +The GPy model class has a set of features which are +designed to make it simple to explore the parameter +space of the model. By default, the scipy optimisers +are used to fit GPy models (via model.optimize()), +for which we provide mechanisms for 'free' optimisation: +GPy can ensure that naturally positive parameters +(such as variances) remain positive. But these mechanisms +are much more powerful than simple reparameterisation, +as we shall see. + +Along this tutorial we'll use a sparse GP regression model +as example. This example can be in ``GPy.examples.regression``. +All of the examples included in GPy return an instance +of a model class, and therefore they can be called in +the following way: :: + + import numpy as np + import pylab as pb + pb.ion() + import GPy + m = GPy.examples.regression.sparse_GP_regression_1D() + +Examining the model using print +=============================== +To see the current state of the model parameters, +and the model's (marginal) likelihood just print the model :: + + print m + +The first thing displayed on the screen is the log-likelihood +value of the model with its current parameters. Below the +log-likelihood, a table with all the model's parameters +is shown. For each parameter, the table contains the name +of the parameter, the current value, and in case there are +defined: constraints, ties and prior distrbutions associated. :: + + Name : sparse gp + Log-likelihood : 588.947189413 + Number of Parameters : 8 + Parameters: + sparse_gp. | Value | Constraint | Prior | Tied to + inducing inputs | (5, 1) | | | + rbf.variance | 1.91644016819 | +ve | | + rbf.lengthscale | 2.62103621347 | +ve | | + Gaussian_noise.variance | 0.00269870373421 | +ve | | + +In this case the kernel parameters (``rbf.variance``, +``rbf.lengthscale``) as well as +the likelihood noise parameter (``Gaussian_noise.variance``), are constrained +to be positive, while the inducing inputs have no +constraints associated. Also there are no ties or prior defined. + +You can also print all subparts of the model, by printing the +subcomponents individually:: + + print m.rbf + +This will print the details of this particular parameter handle:: + + rbf. | Value | Constraint | Prior | Tied to + variance | 1.91644016819 | +ve | | + lengthscale | 2.62103621347 | +ve | | + +When you want to get a closer look into +multivalue parameters, print them directly:: + + print m.inducing_inputs + + Index | sparse_gp.inducing_inputs | Constraint | Prior | Tied to + [0 0] | 2.7189499 | | | N/A + [1 0] | 0.02006533 | | | N/A + [2 0] | -1.5299386 | | | N/A + [3 0] | -2.7001675 | | | N/A + [4 0] | 1.4654162 | | | N/A + +Interacting with Parameters: +======================= +The preferred way of interacting with parameters is to act on the +parameter handle itself. +Interacting with parameter handles is simple. The names, printed by `print m` +are accessible interactively and programatically. For example try to +set kernels (`rbf`) `lengthscale` to `.2` and print the result:: + + m.rbf.lengthscale = .2 + print m + +You should see this:: + + Name : sparse gp + Log-likelihood : 588.947189413 + Number of Parameters : 8 + Parameters: + sparse_gp. | Value | Constraint | Prior | Tied to + inducing inputs | (5, 1) | | | + rbf.variance | 1.91644016819 | +ve | | + rbf.lengthscale | 0.2 | +ve | | + Gaussian_noise.variance | 0.00269870373421 | +ve | | + +This will already have updated the model's inner state, so you can +plot it or see the changes in the posterior `m.posterior` of the model. + +Regular expressions +---------------- +The model's parameters can also be accessed through regular +expressions, by 'indexing' the model with a regular expression, +matching the parameter name. Through indexing by regular expression, +you can only retrieve leafs of the hierarchy, and you can retrieve the +values matched by calling `values()` on the returned object:: + + >>> print m['.*var'] + Index | sparse_gp.rbf.variance | Constraint | Prior | Tied to + [0] | 2.1500132 | | | N/A + ----- | sparse_gp.Gaussian_noise.variance | ---------- | ---------- | ------- + [0] | 0.0024268215 | | | N/A + >>> print m['.*var'].values() + [ 2.1500132 0.00242682] + >>> print m['rbf'] + Index | sparse_gp.rbf.variance | Constraint | Prior | Tied to + [0] | 2.1500132 | | | N/A + ----- | sparse_gp.rbf.lengthscale | ---------- | ---------- | ------- + [0] | 2.6782803 | | | N/A + +There is access to setting parameters by regular expression, +as well. Here are a few examples of how to set parameters by regular expression:: + + >>> m['.*var'] = .1 + >>> print m['.*var'] + Index | sparse_gp.rbf.variance | Constraint | Prior | Tied to + [0] | 0.1 | | | N/A + ----- | sparse_gp.Gaussian_noise.variance | ---------- | ---------- | ------- + [0] | 0.1 | | | N/A + >>> m['.*var'] = [.1, .2] + >>> print m['.*var'] + Index | sparse_gp.rbf.variance | Constraint | Prior | Tied to + [0] | 0.1 | | | N/A + ----- | sparse_gp.Gaussian_noise.variance | ---------- | ---------- | ------- + [0] | 0.2 | | | N/A + +The fact that only leaf nodes can be accesses we can print all +parameters in a flattened view, by printing the regular expression +match of matching all objects:: + + >>> print m[''] + Index | sparse_gp.inducing_inputs | Constraint | Prior | Tied to + [0 0] | -2.6716041 | | | N/A + [1 0] | -1.4665111 | | | N/A + [2 0] | -0.031010293 | | | N/A + [3 0] | 1.4563711 | | | N/A + [4 0] | 2.6803046 | | | N/A + ----- | sparse_gp.rbf.variance | ---------- | ---------- | ------- + [0] | 0.1 | | | N/A + ----- | sparse_gp.rbf.lengthscale | ---------- | ---------- | ------- + [0] | 2.6782803 | | | N/A + ----- | sparse_gp.Gaussian_noise.variance | ---------- | ---------- | ------- + [0] | 0.2 | | | N/A + +Setting and fetching parameters `parameter_array` +------------------------------------------ +Another way to interact with the model's parameters is through the +`parameter_array`. The Parameter array holds all the parameters of the +model in one place and is editable. It can be accessed through +indexing the model for example you can set all the parameters through +this mechanism:: + + >>> new_params = np.r_[[-4,-2,0,2,4], [.5,2], [.3]] + >>> print new_params + array([-4. , -2. , 0. , 2. , 4. , 0.5, 2. , 0.3]) + >>> m[:] = new_params + >>> print m + Name : sparse gp + Log-likelihood : -147.561160209 + Number of Parameters : 8 + Parameters: + sparse_gp. | Value | Constraint | Prior | Tied to + inducing inputs | (5, 1) | | | + rbf.variance | 0.5 | +sq | | + rbf.lengthscale | 2.0 | +ve | | + Gaussian_noise.variance | 0.3 | +sq | | + +Parameters themselves (leafs of the hierarchy) can be indexed and used +the same way as numpy arrays. First let us set a slice of the +`inducing_inputs`:: + + >>> m.inducing_inputs[2:, 0] = [1,3,5] + >>> print m.inducing_indputs + Index | sparse_gp.inducing_inputs | Constraint | Prior | Tied to + [0 0] | -4 | | | N/A + [1 0] | -2 | | | N/A + [2 0] | 1 | | | N/A + [3 0] | 3 | | | N/A + [4 0] | 5 | | | N/A + +Or you use the parameters as normal numpy arrays for calculations:: + + >>> precision = 1./m.Gaussian_noise.variance + array([ 3.33333333]) + +Getting the model's log likelihood +============================================= +Appart form the printing the model, the marginal +log-likelihood can be obtained by using the function +``log_likelihood()``.:: + + >>> m.log_likelihood() + array([-152.83377316]) + +If you want to ensure the log likelihood as a float, call `float()` +around it:: + + >>> float(m.log_likelihood()) + -152.83377316356177 + +Getting the model parameter's gradients +============================ +The gradients of a model can shed light on understanding the +(possibly hard) optimization process. The gradients of each parameter +handle can be accessed through their `gradient` field.:: + + >>> print m.gradient + [ 5.51170031 9.71735112 -4.20282106 -3.45667035 -1.58828165 + -2.11549358 12.40292787 -627.75467803] + >>> print m.rbf.gradient + [ -2.11549358 12.40292787] + >>> m.optimize() + >>> print m.gradient + [ -5.98046560e-04 -3.64576085e-04 1.98005930e-04 3.43381219e-04 + -6.85685104e-04 -1.28800748e-05 1.08552429e-03 2.74058081e-01] + +Adjusting the model's constraints +================================ +When we initially call the example, it was optimized and hence the +log-likelihood gradients were close to zero. However, since +we have been changing the parameters, the gradients are far from zero now. +Next we are going to show how to optimize the model setting different +restrictions on the parameters. + +Once a constraint has been set on a parameter, it is possible to remove +it with the command ``unconstrain()``, which can be called on any +parameter handle of the model. The methods `constrain()` and +`unconstrain()` return the indices which were actually unconstrained, +relative to the parameter handle the method was called on. This is +particularly handy for reporting which parameters where reconstrained, +when reconstraining a parameter, which was already constrained:: + + >>> m.rbf.variance.unconstrain() + array([0]) + >>>m.unconstrain() + array([6, 7]) + +If you want to unconstrain only a specific constraint, you can pass it +as an argument of ``unconstrain(Transformation)`` (:py:class:`~GPy.constraints.Transformation`), or call +the respective method, such as ``unconstrain_fixed()`` (or +``unfix()``) to only unfix fixed parameters.:: + + >>> m.inducing_input[0].fix() + >>> m.unfix() + >>> m.rbf.constrain_positive() + >>> print m + Name : sparse gp + Log-likelihood : 620.741066698 + Number of Parameters : 8 + Parameters: + sparse_gp. | Value | Constraint | Prior | Tied to + inducing inputs | (5, 1) | | | + rbf.variance | 1.48329711218 | +ve | | + rbf.lengthscale | 2.5430947048 | +ve | | + Gaussian_noise.variance | 0.00229714444128 | | | + +As you can see, ``unfix()`` only unfixed the inducing_input, and did +not change the positive constraint of the kernel. + +The parameter handles come with default constraints, so you will +rarely be needing to adjust the constraints of a model. In the rare +cases of needing to adjust the constraints of a model, or in need of +fixing some parameters, you can do so with the functions +``constrain_{positive|negative|bounded|fixed}()``.:: + + m['.*var'].constrain_positive() + +Available Constraints +============== + +* :py:meth:`~GPy.constraints.Logexp` +* :py:meth:`~GPy.constraints.Exponent` +* :py:meth:`~GPy.constraints.Square` +* :py:meth:`~GPy.constraints.Logistic` +* :py:meth:`~GPy.constraints.LogexpNeg` +* :py:meth:`~GPy.constraints.NegativeExponent` +* :py:meth:`~GPy.constraints.NegativeLogexp` + + +Tying Parameters +============ +Not yet implemented for GPy version 0.6.0 + + +Optimizing the model +==================== + +Once we have finished defining the constraints, +we can now optimize the model with the function +``optimize``.:: + + m.Gaussian_noise.constrain_positive() + m.rbf.constrain_positive() + m.optimize() + +By deafult, GPy uses the lbfgsb optimizer. + +Some optional parameters may be discussed here. + +* ``optimizer``: which optimizer to use, currently there are ``lbfgsb, fmin_tnc, + scg, simplex`` or any unique identifier uniquely identifying an + optimizer. Thus, you can say ``m.optimize('bfgs') for using the + ``lbfgsb`` optimizer +* ``messages``: if the optimizer is verbose. Each optimizer has its + own way of printing, so do not be confused by differing messages of + different optimizers +* ``max_iters``: Maximum number of iterations to take. Some optimizers + see iterations as function calls, others as iterations of the + algorithm. Please be advised to look into ``scipy.optimize`` for + more instructions, if the number of iterations matter, so you can + give the right parameters to ``optimize()`` +* ``gtol``: only for some optimizers. Will determine the convergence + criterion, as the tolerance of gradient to finish the optimization. + +Further Reading +=============== + +All of the mechansiams for dealing +with parameters are baked right into GPy.core.model, from which all of +the classes in GPy.models inherrit. To learn how to construct your own +model, you might want to read :ref:`creating_new_models`. If you want +to learn how to create kernels, please refer to +:ref:`creating_new_kernels` diff --git a/doc/_build/html/_sources/tuto_kernel_overview.txt b/doc/_build/html/_sources/tuto_kernel_overview.txt new file mode 100644 index 00000000..fc93491a --- /dev/null +++ b/doc/_build/html/_sources/tuto_kernel_overview.txt @@ -0,0 +1,285 @@ + +**************************** +tutorial : A kernel overview +**************************** +The aim of this tutorial is to give a better understanding of the kernel objects in GPy and to list the ones that are already implemented. The code shown in this tutorial can be obtained at GPy/examples/tutorials.py or by running ``GPy.examples.tutorials.tuto_kernel_overview()``. + +First we import the libraries we will need :: + + import pylab as pb + import numpy as np + import GPy + pb.ion() + +For most kernels, the dimension is the only mandatory parameter to define a kernel object. However, it is also possible to specify the values of the parameters. For example, the three following commands are valid for defining a squared exponential kernel (ie rbf or Gaussian) :: + + ker1 = GPy.kern.RBF(1) # Equivalent to ker1 = GPy.kern.RBF(input_dim=1, variance=1., lengthscale=1.) + ker2 = GPy.kern.RBF(input_dim=1, variance = .75, lengthscale=2.) + ker3 = GPy.kern.RBF(1, .5, .5) + +A ``print`` and a ``plot`` functions are implemented to represent kernel objects. The commands :: + + print ker2 + + ker1.plot() + ker2.plot() + ker3.plot() + +return:: + + Name | Value | Constraints | Ties + ------------------------------------------------------- + rbf_variance | 0.7500 | | + rbf_lengthscale | 2.0000 | | + +.. figure:: Figures/tuto_kern_overview_basicplot.png + :align: center + :height: 300px + +Implemented kernels +=================== + +Many kernels are already implemented in GPy. The following figure gives a summary of most of them (a comprehensive list can be list can be found `here `_): + +.. figure:: Figures/tuto_kern_overview_allkern.png + :align: center + :height: 800px + +On the other hand, it is possible to use the `sympy` package to build new kernels. This will be the subject of another tutorial. + +Operations to combine kernels +============================= + +In ``GPy``, kernel objects can be added or multiplied. In both cases, two kinds of operations are possible since one can assume that the kernels to add/multiply are defined on the same space or on different subspaces. In other words, it is possible to use two kernels :math:`k_1,\ k_2` over :math:`\mathbb{R} \times \mathbb{R}` to create + + * a kernel over :math:`\mathbb{R} \times \mathbb{R}`: :math:`k(x,y) = k_1(x,y) \times k_2(x,y)`. + +This is available in GPy via the ``add`` and ``prod`` functions. Here is a quick example :: + + k1 = GPy.kern.RBF(1,1.,2.) + k2 = GPy.kern.Matern32(1, 0.5, 0.2) + + # Product of kernels + k_prod = k1.prod(k2) + + # Sum of kernels + k_add = k1.add(k2) + +.. # plots + pb.figure(figsize=(8,8)) + pb.subplot(2,2,1) + k_prod.plot() + pb.title('prod') + pb.subplot(2,2,2) + k_prodtens.plot() + pb.title('prod') + pb.subplot(2,2,3) + k_add.plot() + pb.title('sum') + pb.subplot(2,2,4) + k_addtens.plot() + pb.title('sum') + pb.subplots_adjust(wspace=0.3, hspace=0.3) + +.. figure:: Figures/tuto_kern_overview_multadd.png + :align: center + :height: 500px + +A shortcut for ``add`` and ``prod`` is provided by the usual ``+`` and ``*`` operators. Here is another example where we create a periodic kernel with some decay :: + + k1 = GPy.kern.RBF(1,1.,2) + k2 = GPy.kern.PeriodicMatern52(1,variance=1e3, lengthscale=1, period = 1.5, lower=-5., upper = 5) + + k = k1 * k2 # equivalent to k = k1.prod(k2) + print k + + # Simulate sample paths + X = np.linspace(-5,5,501)[:,None] + Y = np.random.multivariate_normal(np.zeros(501),k.K(X),1) + +.. # plot + pb.figure(figsize=(10,4)) + pb.subplot(1,2,1) + k.plot() + pb.subplot(1,2,2) + pb.plot(X,Y.T) + pb.ylabel("Sample path") + pb.subplots_adjust(wspace=0.3) + +.. figure:: Figures/tuto_kern_overview_multperdecay.png + :align: center + :height: 300px + +In general, ``kern`` objects can be seen as a sum of ``kernparts`` objects, where the later are covariance functions defined on the same space. For example, the following code :: + + k = (k1+k2)*(k1+k2) + print k.parts[0].name, '\n', k.parts[1].name, '\n', k.parts[1].parts[0].name, '\n', k.parts[1].parts[1].name, '\n' + +returns :: + add_1 + add_2 + rbf + periodic_Matern52 + + +Constraining the parameters +=========================== + +Various constrains can be applied to the parameters of a kernel + + * ``constrain_fixed`` to fix the value of a parameter (the value will not be modified during optimisation) + * ``constrain_positive`` to make sure the parameter is greater than 0. + * ``constrain_bounded`` to impose the parameter to be in a given range. + * ``tie_params`` to impose the value of two (or more) parameters to be equal. + +When calling one of these functions, the parameters to constrain can either by specified by a regular expression that matches its name or by a number that corresponds to the rank of the parameter. Here is an example :: + + k1 = GPy.kern.RBF(1) + k2 = GPy.kern.Matern32(1) + k3 = GPy.kern.White(1) + + k = k1 + k2 + k3 + print k + + k.constrain_positive('.*var') + k.constrain_fixed(np.array([1]),1.75) + k.tie_params('.*len') + k.unconstrain('white') + k.constrain_bounded('white',lower=1e-5,upper=.5) + print k + +with output:: + + Name | Value | Constraints | Ties + --------------------------------------------------------- + rbf_variance | 1.0000 | | + rbf_lengthscale | 1.0000 | | + Mat32_variance | 1.0000 | | + Mat32_lengthscale | 1.0000 | | + white_variance | 1.0000 | | + + + Name | Value | Constraints | Ties + ---------------------------------------------------------- + rbf_variance | 1.0000 | (+ve) | + rbf_lengthscale | 1.7500 | Fixed | (0) + Mat32_variance | 1.0000 | (+ve) | + Mat32_lengthscale | 1.7500 | | (0) + white_variance | 0.3655 | (1e-05, 0.5) | + + +Example : Building an ANOVA kernel +================================== + +In two dimensions ANOVA kernels have the following form: + +.. math:: + + k_{ANOVA}(x,y) = \prod_{i=1}^2 (1 + k_i(x_i,y_i)) = 1 + k_1(x_1,y_1) + k_2(x_2,y_2) + k_1(x_1,y_1) \times k_2(x_2,y_2). + +Let us assume that we want to define an ANOVA kernel with a Matern 3/2 kernel for :math:`k_i`. As seen previously, we can define this kernel as follows :: + + k_cst = GPy.kern.Bias(1,variance=1.) + k_mat = GPy.kern.Matern52(1,variance=1.,lengthscale=3) + Kanova = (k_cst + k_mat).prod(k_cst + k_mat) + print Kanova + +Printing the resulting kernel outputs the following :: + + Name | Value | Constraints | Ties + --------------------------------------------------------------------------- + biasbias_bias_variance | 1.0000 | | (0) + biasbias_bias_variance | 1.0000 | | (3) + biasMat52_bias_variance | 1.0000 | | (0) + biasMat52_Mat52_variance | 1.0000 | | (4) + biasMat52_Mat52_lengthscale | 3.0000 | | (5) + Mat52bias_Mat52_variance | 1.0000 | | (1) + Mat52bias_Mat52_lengthscale | 3.0000 | | (2) + Mat52bias_bias_variance | 1.0000 | | (3) + Mat52Mat52_Mat52_variance | 1.0000 | | (1) + Mat52Mat52_Mat52_lengthscale | 3.0000 | | (2) + Mat52Mat52_Mat52_variance | 1.0000 | | (4) + Mat52Mat52_Mat52_lengthscale | 3.0000 | | (5) + +Note the ties between the parameters of ``Kanova`` that reflect the links between the parameters of the kernparts objects. We can illustrate the use of this kernel on a toy example:: + + # sample inputs and outputs + X = np.random.uniform(-3.,3.,(40,2)) + Y = 0.5*X[:,:1] + 0.5*X[:,1:] + 2*np.sin(X[:,:1]) * np.sin(X[:,1:]) + + # Create GP regression model + m = GPy.models.GPRegression(X,Y,Kanova) + m.plot() + +.. figure:: Figures/tuto_kern_overview_mANOVA.png + :align: center + :height: 300px + +As :math:`k_{ANOVA}` corresponds to the sum of 4 kernels, the best predictor can be splited in a sum of 4 functions + +.. math:: + + bp(x) & = k(x)^t K^{-1} Y \\ + & = (1 + k_1(x_1) + k_2(x_2) + k_1(x_1)k_2(x_2))^t K^{-1} Y \\ + & = 1^t K^{-1} Y + k_1(x_1)^t K^{-1} Y + k_2(x_2)^t K^{-1} Y + (k_1(x_1)k_2(x_2))^t K^{-1} Y + +The submodels can be represented with the option ``which_function`` of ``plot``: :: + + pb.figure(figsize=(20,3)) + pb.subplots_adjust(wspace=0.5) + axs = pb.subplot(1,5,1) + m.plot(ax=axs) + pb.subplot(1,5,2) + pb.ylabel("= ",rotation='horizontal',fontsize='30') + axs = pb.subplot(1,5,3) + m.plot(ax=axs, which_parts=[False,True,False,False]) + pb.ylabel("cst +",rotation='horizontal',fontsize='30') + axs = pb.subplot(1,5,4) + m.plot(ax=axs, which_parts=[False,False,True,False]) + pb.ylabel("+ ",rotation='horizontal',fontsize='30') + axs = pb.subplot(1,5,5) + pb.ylabel("+ ",rotation='horizontal',fontsize='30') + m.plot(ax=axs, which_parts=[False,False,False,True]) + +.. pb.savefig('tuto_kern_overview_mANOVAdec.png',bbox_inches='tight') + +.. figure:: Figures/tuto_kern_overview_mANOVAdec.png + :align: center + :height: 250px + + +.. # code + import pylab as pb + import numpy as np + import GPy + pb.ion() + + ker1 = GPy.kern.RBF(D=1) # Equivalent to ker1 = GPy.kern.RBF(D=1, variance=1., lengthscale=1.) + ker2 = GPy.kern.RBF(D=1, variance = .75, lengthscale=3.) + ker3 = GPy.kern.RBF(1, .5, .25) + + ker1.plot() + ker2.plot() + ker3.plot() + #pb.savefig("Figures/tuto_kern_overview_basicdef.png") + + kernels = [GPy.kern.RBF(1), GPy.kern.Exponential(1), GPy.kern.Matern32(1), GPy.kern.Matern52(1), GPy.kern.Brownian(1), GPy.kern.Bias(1), GPy.kern.Linear(1), GPy.kern.PeriodicExponential(1), GPy.kern.PeriodicMatern32(1), GPy.kern.PeriodicMatern52(1), GPy.kern.White(1)] + kernel_names = ["GPy.kern.RBF", "GPy.kern.Exponential", "GPy.kern.Matern32", "GPy.kern.Matern52", "GPy.kern.Brownian", "GPy.kern.Bias", "GPy.kern.Linear", "GPy.kern.PeriodicExponential", "GPy.kern.PeriodicMatern32", "GPy.kern.PeriodicMatern52", "GPy.kern.White"] + + pb.figure(figsize=(16,12)) + pb.subplots_adjust(wspace=.5, hspace=.5) + for i, kern in enumerate(kernels): + pb.subplot(3,4,i+1) + kern.plot(x=7.5,plot_limits=[0.00001,15.]) + pb.title(kernel_names[i]+ '\n') + #pb.axes([.1,.1,.8,.7]) + #pb.figtext(.5,.9,'Foo Bar', fontsize=18, ha='center') + #pb.figtext(.5,.85,'Lorem ipsum dolor sit amet, consectetur adipiscing elit',fontsize=10,ha='center') + + # actual plot for the noise + i = 11 + X = np.linspace(0.,15.,201) + WN = 0*X + WN[100] = 1. + pb.subplot(3,4,i+1) + pb.plot(X,WN,'b') diff --git a/doc/_build/html/_sources/tuto_parameterized.txt b/doc/_build/html/_sources/tuto_parameterized.txt new file mode 100644 index 00000000..507ec109 --- /dev/null +++ b/doc/_build/html/_sources/tuto_parameterized.txt @@ -0,0 +1,23 @@ +.. _parameterized: + +******************* +Parameterization handling +******************* + +Parameterization in GPy is done through so called parameter handles. The parameter handles are handles to parameters of a model of any kind. A parameter handle can be constrained, fixed, randomized and others. All parameters in GPy have a name, with which they can be accessed in the model. The most common way of accesssing a parameter programmatically though, is by variable name. + +Parameter handles +============== + +A parameter handle in GPy is a handle on a parameter, as the name suggests. A parameter can be constrained, fixed, randomized and more (See e.g. `working with models`). This gives the freedom to the model to handle parameter distribution and model updates as efficiently as possible. All parameter handles share a common memory space, which is just a flat numpy array, stored in the highest parent of a model hierarchy. +In the following we will introduce and elucidate the different parameter handles which exist in GPy. + +:py:class:`~GPy.core.parameterization.parameterized.Parameterized` +========== + +A parameterized object itself holds parameter handles and is just a summarization of the parameters below. It can use those parameters to change the internal state of the model and GPy ensures those parameters to allways hold the right value when in an optimization routine or any other update. + +:py:class:`~GPy.core.parameterization.param.Param` +=========== + +The lowest level of parameter is a numpy array. This Param class inherits all functionality of a numpy array and can simply be used as if it where a numpy array. These parameters can be accessed in the same way as a numpy array is indexed. diff --git a/doc/_build/html/_static/ajax-loader.gif b/doc/_build/html/_static/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..61faf8cab23993bd3e1560bff0668bd628642330 GIT binary patch literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nno%(3)e{?)x>&1u}A`t?OF7Z|1gRivOgXi&7IyQd1Pl zGfOfQ60;I3a`F>X^fL3(@);C=vM_KlFfb_o=k{|A33hf2a5d61U}gjg=>Rd%XaNQW zW@Cw{|b%Y*pl8F?4B9 zlo4Fz*0kZGJabY|>}Okf0}CCg{u4`zEPY^pV?j2@h+|igy0+Kz6p;@SpM4s6)XEMg z#3Y4GX>Hjlml5ftdH$4x0JGdn8~MX(U~_^d!Hi)=HU{V%g+mi8#UGbE-*ao8f#h+S z2a0-5+vc7MU$e-NhmBjLIC1v|)9+Im8x1yacJ7{^tLX(ZhYi^rpmXm0`@ku9b53aN zEXH@Y3JaztblgpxbJt{AtE1ad1Ca>{v$rwwvK(>{m~Gf_=-Ro7Fk{#;i~+{{>QtvI yb2P8Zac~?~=sRA>$6{!(^3;ZP0TPFR(G_-UDU(8Jl0?(IXu$~#4A!880|o%~Al1tN literal 0 HcmV?d00001 diff --git a/doc/_build/html/_static/basic.css b/doc/_build/html/_static/basic.css new file mode 100644 index 00000000..9fa77d88 --- /dev/null +++ b/doc/_build/html/_static/basic.css @@ -0,0 +1,599 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + width: 170px; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + width: 30px; +} + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text { +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +div.code-block-caption { + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +div.code-block-caption + div > div.highlight > pre { + margin-top: 0; +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + padding: 1em 1em 0; +} + +div.literal-block-wrapper div.highlight { + margin: 0; +} + +code.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +code.descclassname { + background-color: transparent; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/doc/_build/html/_static/classic.css b/doc/_build/html/_static/classic.css new file mode 100644 index 00000000..2da92346 --- /dev/null +++ b/doc/_build/html/_static/classic.css @@ -0,0 +1,261 @@ +/* + * default.css_t + * ~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- default theme. + * + * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: sans-serif; + font-size: 100%; + background-color: #11303d; + color: #000; + margin: 0; + padding: 0; +} + +div.document { + background-color: #1c4e63; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 230px; +} + +div.body { + background-color: #ffffff; + color: #000000; + padding: 0 20px 30px 20px; +} + +div.footer { + color: #ffffff; + width: 100%; + padding: 9px 0 9px 0; + text-align: center; + font-size: 75%; +} + +div.footer a { + color: #ffffff; + text-decoration: underline; +} + +div.related { + background-color: #133f52; + line-height: 30px; + color: #ffffff; +} + +div.related a { + color: #ffffff; +} + +div.sphinxsidebar { +} + +div.sphinxsidebar h3 { + font-family: 'Trebuchet MS', sans-serif; + color: #ffffff; + font-size: 1.4em; + font-weight: normal; + margin: 0; + padding: 0; +} + +div.sphinxsidebar h3 a { + color: #ffffff; +} + +div.sphinxsidebar h4 { + font-family: 'Trebuchet MS', sans-serif; + color: #ffffff; + font-size: 1.3em; + font-weight: normal; + margin: 5px 0 0 0; + padding: 0; +} + +div.sphinxsidebar p { + color: #ffffff; +} + +div.sphinxsidebar p.topless { + margin: 5px 10px 10px 10px; +} + +div.sphinxsidebar ul { + margin: 10px; + padding: 0; + color: #ffffff; +} + +div.sphinxsidebar a { + color: #98dbcc; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + + + +/* -- hyperlink styles ------------------------------------------------------ */ + +a { + color: #355f7c; + text-decoration: none; +} + +a:visited { + color: #355f7c; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + + + +/* -- body styles ----------------------------------------------------------- */ + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Trebuchet MS', sans-serif; + background-color: #f2f2f2; + font-weight: normal; + color: #20435c; + border-bottom: 1px solid #ccc; + margin: 20px -20px 10px -20px; + padding: 3px 0 3px 10px; +} + +div.body h1 { margin-top: 0; font-size: 200%; } +div.body h2 { font-size: 160%; } +div.body h3 { font-size: 140%; } +div.body h4 { font-size: 120%; } +div.body h5 { font-size: 110%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #c60f0f; + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + background-color: #c60f0f; + color: white; +} + +div.body p, div.body dd, div.body li { + text-align: justify; + line-height: 130%; +} + +div.admonition p.admonition-title + p { + display: inline; +} + +div.admonition p { + margin-bottom: 5px; +} + +div.admonition pre { + margin-bottom: 5px; +} + +div.admonition ul, div.admonition ol { + margin-bottom: 5px; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre { + padding: 5px; + background-color: #eeffcc; + color: #333333; + line-height: 120%; + border: 1px solid #ac9; + border-left: none; + border-right: none; +} + +code { + background-color: #ecf0f3; + padding: 0 1px 0 1px; + font-size: 0.95em; +} + +th { + background-color: #ede; +} + +.warning code { + background: #efc2c2; +} + +.note code { + background: #d6d6d6; +} + +.viewcode-back { + font-family: sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} + +div.code-block-caption { + color: #efefef; + background-color: #1c4e63; +} \ No newline at end of file diff --git a/doc/_build/html/_static/comment-bright.png b/doc/_build/html/_static/comment-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..551517b8c83b76f734ff791f847829a760ad1903 GIT binary patch literal 3500 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 A2LJ#7 literal 0 HcmV?d00001 diff --git a/doc/_build/html/_static/comment.png b/doc/_build/html/_static/comment.png new file mode 100644 index 0000000000000000000000000000000000000000..92feb52b8824c6b0f59b658b1196c61de9162a95 GIT binary patch literal 3445 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 Xn!ZpXD%P(H00000NkvXXu0mjf= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this); + }); + } + } + return this.each(function() { + highlight(this); + }); +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated == 'undefined') + return string; + return (typeof translated == 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated == 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) == 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this == '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/doc/_build/html/_static/down-pressed.png b/doc/_build/html/_static/down-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..7c30d004b71b32bb2fc06b3bd4dc8278baab0946 GIT binary patch literal 347 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~&H|6fVxZ#d zAk65bF}ngN$X?><>&kwMor^(NtW3yF87Slz;1l8sq&LUMQwy<>&kwMol#tg zK_ydLmzem(vK1>2TzUEGl*lj!N<7$PCrdoWV0 z$w0*Ap!bZ4if7h;-yfL#MC0e;t{xY+$l~DX2EWYIPet1cohf^BdG+jXhtuq&W-0|c zKPmlKv-7OTjb}T)7@fTGd9y~u4{g8An;)c2U=w=nwQ7}zVDc>n+a literal 0 HcmV?d00001 diff --git a/doc/_build/html/_static/file.png b/doc/_build/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..254c60bfbe2715ae2edca48ebccfd074deb8031d GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJXMsm#F#`j)FbFd;%$g$s6l5>) z^mS#w%FV~i&ZxO9L3Zxqw8>dd4I&zcKG){Yx14xKr0

      ZQJ$m%mv17-NAAj}g)$7-<-@JMA z_U+TRK=AR}yLa#2zkmPX!-tO_KYsf3>Hq)#%qnY_1Fd8&3GxeO2wSmci|LJf=|BO- zByV>Yl`U*PX977no-U3d5|XS39sLdkFt8q|+|QqL_#ErUf6I%zFA7b%b>3$hFGGFs zc72AL|61pRJ1(+5wNdg|xP#*`gQ~lOnTFKiIjl#S3)+QV=h{~`9{M=hx#5uZ&-tIF sG!8onYS_8EFr8v&@CavkqYey&g)1epR*Fkm0PSV)boFyt=akR{044O6bN~PV literal 0 HcmV?d00001 diff --git a/doc/_build/html/_static/jquery-1.11.1.js b/doc/_build/html/_static/jquery-1.11.1.js new file mode 100644 index 00000000..d4b67f7e --- /dev/null +++ b/doc/_build/html/_static/jquery-1.11.1.js @@ -0,0 +1,10308 @@ +/*! + * jQuery JavaScript Library v1.11.1 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-05-01T17:42Z + */ + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper window is present, + // execute the factory and get jQuery + // For environments that do not inherently posses a window with a document + // (such as Node.js), expose a jQuery-making factory as module.exports + // This accentuates the need for the creation of a real window + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +// + +var deletedIds = []; + +var slice = deletedIds.slice; + +var concat = deletedIds.concat; + +var push = deletedIds.push; + +var indexOf = deletedIds.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + version = "1.11.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1, IE<9 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: deletedIds.sort, + splice: deletedIds.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( support.ownLast ) { + for ( key in obj ) { + return hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call(obj) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Support: Android<4.1, IE<9 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( indexOf ) { + return indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + while ( j < len ) { + first[ i++ ] = second[ j++ ]; + } + + // Support: IE<9 + // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) + if ( len !== len ) { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: function() { + return +( new Date() ); + }, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v1.10.19 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-04-18 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + characterEncoding + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document (jQuery #6963) + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== strundefined && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, + doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent !== parent.top ) { + // IE11 does not have attachEvent, so all must suffer + if ( parent.addEventListener ) { + parent.addEventListener( "unload", function() { + setDocument(); + }, false ); + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", function() { + setDocument(); + }); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { + div.innerHTML = "

      "; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowclip^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (oldCache = outerCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + outerCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context !== document && context; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is no seed and only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +}); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof rootjQuery.ready !== "undefined" ? + rootjQuery.ready( selector ) : + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.extend({ + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +jQuery.fn.extend({ + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.unique( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); +var rnotwhite = (/\S+/g); + + + +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + + } else if ( !(--remaining) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend({ + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +}); + +/** + * Clean-up method for dom ready events + */ +function detach() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } +} + +/** + * The ready event handler and self cleanup method + */ +function completed() { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + + +var strundefined = typeof undefined; + + + +// Support: IE<9 +// Iteration over object's inherited properties before its own +var i; +for ( i in jQuery( support ) ) { + break; +} +support.ownLast = i !== "0"; + +// Note: most support tests are defined in their respective modules. +// false until the test is run +support.inlineBlockNeedsLayout = false; + +// Execute ASAP in case we need to set body.style.zoom +jQuery(function() { + // Minified: var a,b,c,d + var val, div, body, container; + + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { + // Return for frameset docs that don't have a body + return; + } + + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); + + if ( typeof div.style.zoom !== strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; + + support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; + if ( val ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); +}); + + + + +(function() { + var div = document.createElement( "div" ); + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +/** + * Determines whether an object can have data + */ +jQuery.acceptData = function( elem ) { + var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ], + nodeType = +elem.nodeType || 1; + + // Do not set data on non-element DOM nodes because it will not be cleared (#8335). + return nodeType !== 1 && nodeType !== 9 ? + false : + + // Nodes accept data unless otherwise specified; rejection can be conditional + !noData || noData !== true && elem.getAttribute("classid") === noData; +}; + + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /([A-Z])/g; + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + +function internalData( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements (space-suffixed to avoid Object.prototype collisions) + // throw uncatchable exceptions if you attempt to set expando properties + noData: { + "applet ": true, + "embed ": true, + // ...but Flash objects (which have this classid) *can* handle expandos + "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var i, name, data, + elem = this[0], + attrs = elem && elem.attributes; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + + +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + }; + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; +}; +var rcheckableType = (/^(?:checkbox|radio)$/i); + + + +(function() { + // Minified: var a,b,c + var input = document.createElement( "input" ), + div = document.createElement( "div" ), + fragment = document.createDocumentFragment(); + + // Setup + div.innerHTML = "
      a"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName( "tbody" ).length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = + document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + input.type = "checkbox"; + input.checked = true; + fragment.appendChild( input ); + support.appendChecked = input.checked; + + // Make sure textarea (and checkbox) defaultValue is properly cloned + // Support: IE6-IE11+ + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // #11217 - WebKit loses check when the name is after the checked attribute + fragment.appendChild( div ); + div.innerHTML = ""; + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + support.noCloneEvent = true; + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } +})(); + + +(function() { + var i, eventName, + div = document.createElement( "div" ); + + // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) + for ( i in { submit: true, change: true, focusin: true }) { + eventName = "on" + i; + + if ( !(support[ i + "Bubbles" ] = eventName in window) ) { + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + div.setAttribute( eventName, "t" ); + support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && jQuery.acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + // Support: IE < 9, Android < 4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + jQuery._removeData( doc, fix ); + } else { + jQuery._data( doc, fix, attaches ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
      ", "
      " ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
      " ], + tr: [ 2, "", "
      " ], + col: [ 2, "", "
      " ], + td: [ 3, "", "
      " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
      ", "
      " ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!support.noCloneEvent || !support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
      " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + deletedIds.push( id ); + } + } + } + } + } +}); + +jQuery.fn.extend({ + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + remove: function( selector, keepData /* Internal Use Only */ ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map(function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var arg = arguments[ 0 ]; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + arg = this.parentNode; + + jQuery.cleanData( getAll( this ) ); + + if ( arg ) { + arg.replaceChild( elem, this ); + } + }); + + // Force removal if there was no new content (e.g., from empty arguments) + return arg && (arg.length || arg.nodeType) ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + + +var iframe, + elemdisplay = {}; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var style, + elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + // getDefaultComputedStyle might be reliably used only on attached element + display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? + + // Use of this method is a temporary fix (more like optmization) until something better comes along, + // since it was removed from specification and supported only in FF + style.display : jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = (iframe || jQuery( "