mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-05-18 13:55:14 +02:00
fixed a bug in Neil's otherwise tidy hetero kernel.
This commit is contained in:
parent
759cf08016
commit
7ced138520
3 changed files with 48 additions and 25 deletions
|
|
@ -692,7 +692,7 @@ def kern_test(kern, X=None, X2=None, verbose=False):
|
||||||
Kern_check_dK_dtheta(kern, X=X, X2=None).checkgrad(verbose=True)
|
Kern_check_dK_dtheta(kern, X=X, X2=None).checkgrad(verbose=True)
|
||||||
pass_checks = False
|
pass_checks = False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print("Checking gradients of K(X, X2) wrt theta.")
|
print("Checking gradients of K(X, X2) wrt theta.")
|
||||||
result = Kern_check_dK_dtheta(kern, X=X, X2=X2).checkgrad(verbose=verbose)
|
result = Kern_check_dK_dtheta(kern, X=X, X2=X2).checkgrad(verbose=verbose)
|
||||||
|
|
@ -703,7 +703,7 @@ def kern_test(kern, X=None, X2=None, verbose=False):
|
||||||
Kern_check_dK_dtheta(kern, X=X, X2=X2).checkgrad(verbose=True)
|
Kern_check_dK_dtheta(kern, X=X, X2=X2).checkgrad(verbose=True)
|
||||||
pass_checks = False
|
pass_checks = False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print("Checking gradients of Kdiag(X) wrt theta.")
|
print("Checking gradients of Kdiag(X) wrt theta.")
|
||||||
result = Kern_check_dKdiag_dtheta(kern, X=X).checkgrad(verbose=verbose)
|
result = Kern_check_dKdiag_dtheta(kern, X=X).checkgrad(verbose=verbose)
|
||||||
|
|
@ -714,10 +714,15 @@ def kern_test(kern, X=None, X2=None, verbose=False):
|
||||||
Kern_check_dKdiag_dtheta(kern, X=X).checkgrad(verbose=True)
|
Kern_check_dKdiag_dtheta(kern, X=X).checkgrad(verbose=True)
|
||||||
pass_checks = False
|
pass_checks = False
|
||||||
return False
|
return 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:
|
||||||
|
|
@ -747,5 +762,5 @@ def kern_test(kern, X=None, X2=None, verbose=False):
|
||||||
Kern_check_dKdiag_dX(kern, X=X).checkgrad(verbose=True)
|
Kern_check_dKdiag_dX(kern, X=X).checkgrad(verbose=True)
|
||||||
pass_checks = False
|
pass_checks = False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return pass_checks
|
return pass_checks
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
@ -36,7 +39,7 @@ class Hetero(Kernpart):
|
||||||
C. M. (1998) Regression with Input-dependent Noise: a Gaussian
|
C. M. (1998) Regression with Input-dependent Noise: a Gaussian
|
||||||
Process Treatment In Advances in Neural Information Processing
|
Process Treatment In Advances in Neural Information Processing
|
||||||
Systems, Volume 10, pp. 493-499. MIT Press
|
Systems, Volume 10, pp. 493-499. MIT Press
|
||||||
|
|
||||||
for a Gaussian process treatment of this problem.
|
for a Gaussian process treatment of this problem.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
@ -47,7 +50,7 @@ class Hetero(Kernpart):
|
||||||
mapping = GPy.mappings.MLP(output_dim=1, hidden_dim=20, input_dim=input_dim)
|
mapping = GPy.mappings.MLP(output_dim=1, hidden_dim=20, input_dim=input_dim)
|
||||||
if not transform:
|
if not transform:
|
||||||
transform = GPy.core.transformations.logexp()
|
transform = GPy.core.transformations.logexp()
|
||||||
|
|
||||||
self.transform = transform
|
self.transform = transform
|
||||||
self.mapping = mapping
|
self.mapping = mapping
|
||||||
self.name='hetero'
|
self.name='hetero'
|
||||||
|
|
@ -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):
|
||||||
|
|
@ -76,26 +79,26 @@ class Hetero(Kernpart):
|
||||||
def _Kdiag(self, X):
|
def _Kdiag(self, X):
|
||||||
"""Helper function for computing the diagonal elements of the covariance."""
|
"""Helper function for computing the diagonal elements of the covariance."""
|
||||||
return self.mapping.f(X).flatten()**2
|
return self.mapping.f(X).flatten()**2
|
||||||
|
|
||||||
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."""
|
||||||
if X2==None or X2 is X:
|
if X2==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_dX(dL_dKdiag, X, target)
|
self.dKdiag_dX(dL_dKdiag, X, target)
|
||||||
|
|
||||||
def dKdiag_dX(self, dL_dKdiag, X, target):
|
def dKdiag_dX(self, dL_dKdiag, X, target):
|
||||||
"""Gradient of diagonal of covariance with respect to X."""
|
"""Gradient of diagonal of covariance with respect to X."""
|
||||||
target += 2.*self.mapping.df_dX(dL_dKdiag[:, None], X)*self.mapping.f(X)
|
target += 2.*self.mapping.df_dX(dL_dKdiag[:, None], X)*self.mapping.f(X)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue