Revision 291ae6c7dbfcbded27c604f136982a5067d14b8e authored by thevincentadam on 20 January 2020, 12:17:20 UTC, committed by thevincentadam on 20 January 2020, 12:17:20 UTC
1 parent 5dc31b8
expectations.py
``````# Copyright 2018 the GPflow authors.
#
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#
# Unless required by applicable law or agreed to in writing, software
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and

from ..probability_distributions import DiagonalGaussian, Gaussian, MarkovGaussian
from . import dispatch

def expectation(p, obj1, obj2=None, nghp=None):
"""
Compute the expectation <obj1(x) obj2(x)>_p(x)
Uses multiple-dispatch to select an analytical implementation,
if one is available. If not, it falls back to quadrature.

:type p: (mu, cov) tuple or a `ProbabilityDistribution` object
:type obj1: kernel, mean function, (kernel, inducing_variable), or None
:type obj2: kernel, mean function, (kernel, inducing_variable), or None
:param int nghp: passed to `_quadrature_expectation` to set the number
of Gauss-Hermite points used: `num_gauss_hermite_points`
:return: a 1-D, 2-D, or 3-D tensor containing the expectation

Allowed combinations

- Psi statistics:
>>> eKdiag = expectation(p, kernel)  (N)  # Psi0
>>> eKxz = expectation(p, (kernel, inducing_variable))  (NxM)  # Psi1
>>> exKxz = expectation(p, identity_mean, (kernel, inducing_variable))  (NxDxM)
>>> eKzxKxz = expectation(p, (kernel, inducing_variable), (kernel, inducing_variable))  (NxMxM)  # Psi2

- kernels and mean functions:
>>> eKzxMx = expectation(p, (kernel, inducing_variable), mean)  (NxMxQ)
>>> eMxKxz = expectation(p, mean, (kernel, inducing_variable))  (NxQxM)

- only mean functions:
>>> eMx = expectation(p, mean)  (NxQ)
>>> eM1x_M2x = expectation(p, mean1, mean2)  (NxQ1xQ2)
.. note:: mean(x) is 1xQ (row vector)

- different kernels. This occurs, for instance, when we are calculating Psi2 for Sum kernels:
>>> eK1zxK2xz = expectation(p, (kern1, inducing_variable), (kern2, inducing_variable))  (NxMxM)
"""
p, obj1, feat1, obj2, feat2 = _init_expectation(p, obj1, obj2)
try:
return dispatch.expectation(p, obj1, feat1, obj2, feat2, nghp=nghp)
except NotImplementedError as error:
return dispatch.quadrature_expectation(p, obj1, feat1, obj2, feat2, nghp=nghp)

"""
Compute the expectation <obj1(x) obj2(x)>_p(x)
Uses Gauss-Hermite quadrature for approximate integration.

:type p: (mu, cov) tuple or a `ProbabilityDistribution` object
:type obj1: kernel, mean function, (kernel, inducing_variable), or None
:type obj2: kernel, mean function, (kernel, inducing_variable), or None
:param int num_gauss_hermite_points: passed to `_quadrature_expectation` to set
the number of Gauss-Hermite points used
:return: a 1-D, 2-D, or 3-D tensor containing the expectation
"""
print(f"2. p={p}, obj1={obj1}, obj2={obj2}")
p, obj1, feat1, obj2, feat2 = _init_expectation(p, obj1, obj2)
return dispatch.quadrature_expectation(p, obj1, feat1, obj2, feat2, nghp=nghp)

def _init_expectation(p, obj1, obj2):
if isinstance(p, tuple):
mu, cov = p
classes = [DiagonalGaussian, Gaussian, MarkovGaussian]
p = classes[cov.ndim - 2](*p)

obj1, feat1 = obj1 if isinstance(obj1, tuple) else (obj1, None)
obj2, feat2 = obj2 if isinstance(obj2, tuple) else (obj2, None)
return p, obj1, feat1, obj2, feat2
``````

Computing file changes ...