fixed a bug in Neil's otherwise tidy hetero kernel.

This commit is contained in:
James Hensman 2013-09-20 15:35:27 +01:00
parent 759cf08016
commit 7ced138520
3 changed files with 48 additions and 25 deletions

View file

@ -717,7 +717,12 @@ def kern_test(kern, X=None, X2=None, verbose=False):
if verbose: if verbose:
print("Checking gradients of K(X, X) wrt X.") print("Checking gradients of K(X, X) wrt X.")
result = Kern_check_dK_dX(kern, X=X, X2=None).checkgrad(verbose=verbose) try:
result = Kern_check_dK_dX(kern, X=X, X2=None).checkgrad(verbose=verbose)
except NotImplementedError:
result=True
if verbose:
print("dK_dX not implemented for " + kern.name)
if result and verbose: if result and verbose:
print("Check passed.") print("Check passed.")
if not result: if not result:
@ -728,7 +733,12 @@ def kern_test(kern, X=None, X2=None, verbose=False):
if verbose: if verbose:
print("Checking gradients of K(X, X2) wrt X.") print("Checking gradients of K(X, X2) wrt X.")
result = Kern_check_dK_dX(kern, X=X, X2=X2).checkgrad(verbose=verbose) try:
result = Kern_check_dK_dX(kern, X=X, X2=X2).checkgrad(verbose=verbose)
except NotImplementedError:
result=True
if verbose:
print("dK_dX not implemented for " + kern.name)
if result and verbose: if result and verbose:
print("Check passed.") print("Check passed.")
if not result: if not result:
@ -739,7 +749,12 @@ def kern_test(kern, X=None, X2=None, verbose=False):
if verbose: if verbose:
print("Checking gradients of Kdiag(X) wrt X.") print("Checking gradients of Kdiag(X) wrt X.")
result = Kern_check_dKdiag_dX(kern, X=X).checkgrad(verbose=verbose) try:
result = Kern_check_dKdiag_dX(kern, X=X).checkgrad(verbose=verbose)
except NotImplementedError:
result=True
if verbose:
print("dK_dX not implemented for " + kern.name)
if result and verbose: if result and verbose:
print("Check passed.") print("Check passed.")
if not result: if not result:

View file

@ -10,9 +10,12 @@ import GPy
class Hetero(Kernpart): class Hetero(Kernpart):
""" """
TODO: Need to constrain the function outputs positive (still thinking of best way of doing this!!! Yes, intend to use transformations, but what's the *best* way). Currently just squaring output. TODO: Need to constrain the function outputs
positive (still thinking of best way of doing this!!! Yes, intend to use
transformations, but what's the *best* way). Currently just squaring output.
Heteroschedastic noise which depends on input location. See, for example, this paper by Goldberg et al. Heteroschedastic noise which depends on input location. See, for example,
this paper by Goldberg et al.
.. math:: .. math::
@ -20,15 +23,15 @@ class Hetero(Kernpart):
where :math:`\sigma^2(x)` is a function giving the variance as a function of input space and :math:`\delta_{i,j}` is the Kronecker delta function. where :math:`\sigma^2(x)` is a function giving the variance as a function of input space and :math:`\delta_{i,j}` is the Kronecker delta function.
The parameters are the parameters of \sigma^2(x) which is a The parameters are the parameters of \sigma^2(x) which is a
function that can be specified by the user, by default an function that can be specified by the user, by default an
multi-layer peceptron is used. multi-layer peceptron is used.
:param input_dim: the number of input dimensions :param input_dim: the number of input dimensions
:type input_dim: int :type input_dim: int
:param mapping: the mapping that gives the lengthscale across the input space (by default GPy.mappings.MLP is used with 20 hidden nodes). :param mapping: the mapping that gives the lengthscale across the input space (by default GPy.mappings.MLP is used with 20 hidden nodes).
:type mapping: GPy.core.Mapping :type mapping: GPy.core.Mapping
:rtype: Kernpart object :rtype: Kernpart object
See this paper: See this paper:
@ -66,7 +69,7 @@ class Hetero(Kernpart):
def K(self, X, X2, target): def K(self, X, X2, target):
"""Return covariance between X and X2.""" """Return covariance between X and X2."""
if X2==None or X2 is X: if (X2 is None) or (X2 is X):
target[np.diag_indices_from(target)] += self._Kdiag(X) target[np.diag_indices_from(target)] += self._Kdiag(X)
def Kdiag(self, X, target): def Kdiag(self, X, target):
@ -79,13 +82,13 @@ class Hetero(Kernpart):
def dK_dtheta(self, dL_dK, X, X2, target): def dK_dtheta(self, dL_dK, X, X2, target):
"""Derivative of the covariance with respect to the parameters.""" """Derivative of the covariance with respect to the parameters."""
if X2==None or X2 is X: if (X2 is None) or (X2 is X):
dL_dKdiag = dL_dK.flat[::dL_dK.shape[0]+1] dL_dKdiag = dL_dK.flat[::dL_dK.shape[0]+1]
self.dKdiag_dtheta(dL_dKdiag, X, target) self.dKdiag_dtheta(dL_dKdiag, X, target)
def dKdiag_dtheta(self, dL_dKdiag, X, target): def dKdiag_dtheta(self, dL_dKdiag, X, target):
"""Gradient of diagonal of covariance with respect to parameters.""" """Gradient of diagonal of covariance with respect to parameters."""
target += 2.*self.mapping.df_dtheta(dL_dKdiag[:, None], X)*self.mapping.f(X) target += 2.*self.mapping.df_dtheta(dL_dKdiag[:, None]*self.mapping.f(X), X)
def dK_dX(self, dL_dK, X, X2, target): def dK_dX(self, dL_dK, X, X2, target):
"""Derivative of the covariance matrix with respect to X.""" """Derivative of the covariance matrix with respect to X."""

View file

@ -58,6 +58,8 @@ class Kernpart(object):
raise NotImplementedError raise NotImplementedError
def dK_dX(self, dL_dK, X, X2, target): def dK_dX(self, dL_dK, X, X2, target):
raise NotImplementedError raise NotImplementedError
def dKdiag_dX(self, dL_dK, X, target):
raise NotImplementedError
@ -97,6 +99,9 @@ class Kernpart_stationary(Kernpart):
# wrt lengthscale is 0. # wrt lengthscale is 0.
target[0] += np.sum(dL_dKdiag) target[0] += np.sum(dL_dKdiag)
def dKdiag_dX(self, dL_dK, X, target):
pass # true for all stationary kernels
class Kernpart_inner(Kernpart): class Kernpart_inner(Kernpart):
def __init__(self,input_dim): def __init__(self,input_dim):