mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-05-15 06:52:39 +02:00
refactored the numeric inverse into the mother class, to test Identity and Log
This commit is contained in:
parent
7bee3daac8
commit
6bea908234
2 changed files with 43 additions and 48 deletions
|
|
@ -300,12 +300,12 @@ class MiscTests(unittest.TestCase):
|
||||||
preds = m.predict(self.X)
|
preds = m.predict(self.X)
|
||||||
|
|
||||||
warp_k = GPy.kern.RBF(1)
|
warp_k = GPy.kern.RBF(1)
|
||||||
warp_f = GPy.util.warping_functions.IdentityFunction()
|
warp_f = GPy.util.warping_functions.IdentityFunction(closed_inverse=False)
|
||||||
warp_m = GPy.models.WarpedGP(self.X, self.Y, kernel=warp_k, warping_function=warp_f)
|
warp_m = GPy.models.WarpedGP(self.X, self.Y, kernel=warp_k, warping_function=warp_f)
|
||||||
warp_m.optimize()
|
warp_m.optimize()
|
||||||
warp_preds = warp_m.predict(self.X)
|
warp_preds = warp_m.predict(self.X)
|
||||||
|
|
||||||
np.testing.assert_almost_equal(preds, warp_preds)
|
np.testing.assert_almost_equal(preds, warp_preds, decimal=4)
|
||||||
|
|
||||||
def test_warped_gp_log(self):
|
def test_warped_gp_log(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -316,21 +316,16 @@ class MiscTests(unittest.TestCase):
|
||||||
Y = np.abs(self.Y)
|
Y = np.abs(self.Y)
|
||||||
logY = np.log(Y)
|
logY = np.log(Y)
|
||||||
m = GPy.models.GPRegression(self.X, logY, kernel=k)
|
m = GPy.models.GPRegression(self.X, logY, kernel=k)
|
||||||
#m.optimize()
|
m.optimize()
|
||||||
m['Gaussian_noise.variance'] = 1e-4
|
|
||||||
preds = m.predict(self.X)[0]
|
preds = m.predict(self.X)[0]
|
||||||
|
|
||||||
warp_k = GPy.kern.RBF(1)
|
warp_k = GPy.kern.RBF(1)
|
||||||
warp_f = GPy.util.warping_functions.LogFunction()
|
warp_f = GPy.util.warping_functions.LogFunction(closed_inverse=False)
|
||||||
warp_m = GPy.models.WarpedGP(self.X, Y, kernel=warp_k, warping_function=warp_f)
|
warp_m = GPy.models.WarpedGP(self.X, Y, kernel=warp_k, warping_function=warp_f)
|
||||||
warp_m.optimize()
|
warp_m.optimize()
|
||||||
warp_m['.*'] = 1.0
|
|
||||||
warp_m['Gaussian_noise.variance'] = 1e-4
|
|
||||||
warp_preds = warp_m.predict(self.X, median=True)[0]
|
warp_preds = warp_m.predict(self.X, median=True)[0]
|
||||||
#print np.exp(preds)
|
|
||||||
#print warp_preds
|
|
||||||
|
|
||||||
np.testing.assert_almost_equal(np.exp(preds), warp_preds)
|
np.testing.assert_almost_equal(np.exp(preds), warp_preds, decimal=4)
|
||||||
|
|
||||||
@unittest.skip('Comment this to plot the modified sine function')
|
@unittest.skip('Comment this to plot the modified sine function')
|
||||||
def test_warped_gp_sine(self):
|
def test_warped_gp_sine(self):
|
||||||
|
|
@ -354,19 +349,13 @@ class MiscTests(unittest.TestCase):
|
||||||
print(warp_m['.*warp.*'])
|
print(warp_m['.*warp.*'])
|
||||||
warp_m.predict_in_warped_space = False
|
warp_m.predict_in_warped_space = False
|
||||||
warp_m.plot()
|
warp_m.plot()
|
||||||
import ipdb; ipdb.set_trace()
|
|
||||||
warp_m.predict_in_warped_space = True
|
warp_m.predict_in_warped_space = True
|
||||||
warp_m.plot()
|
warp_m.plot()
|
||||||
m.plot()
|
m.plot()
|
||||||
warp_f.plot(X.min()-10, X.max()+10)
|
warp_f.plot(X.min()-10, X.max()+10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GradientTests(np.testing.TestCase):
|
class GradientTests(np.testing.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
######################################
|
######################################
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ class WarpingFunction(Parameterized):
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
super(WarpingFunction, self).__init__(name=name)
|
super(WarpingFunction, self).__init__(name=name)
|
||||||
|
self.rate = 0.1
|
||||||
|
|
||||||
def f(self, y, psi):
|
def f(self, y, psi):
|
||||||
"""function transformation
|
"""function transformation
|
||||||
|
|
@ -29,9 +30,30 @@ class WarpingFunction(Parameterized):
|
||||||
"""gradient of f w.r.t to y"""
|
"""gradient of f w.r.t to y"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def f_inv(self, z, psi):
|
def f_inv(self, z, max_iterations=100, y=None):
|
||||||
"""inverse function transformation"""
|
"""
|
||||||
raise NotImplementedError
|
Calculate the numerical inverse of f. This should be
|
||||||
|
overwritten for specific warping functions where the
|
||||||
|
inverse can be found in closed form.
|
||||||
|
|
||||||
|
:param max_iterations: maximum number of N.R. iterations
|
||||||
|
"""
|
||||||
|
|
||||||
|
z = z.copy()
|
||||||
|
y = np.ones_like(z)
|
||||||
|
|
||||||
|
it = 0
|
||||||
|
update = np.inf
|
||||||
|
while np.abs(update).sum() > 1e-10 and it < max_iterations:
|
||||||
|
fy = self.f(y)
|
||||||
|
fgrady = self.fgrad_y(y)
|
||||||
|
update = (fy - z) / fgrady
|
||||||
|
y -= self.rate * update
|
||||||
|
it += 1
|
||||||
|
if it == max_iterations:
|
||||||
|
print("WARNING!!! Maximum number of iterations reached in f_inv ")
|
||||||
|
print("Sum of roots: %.4f" % np.sum(fy - z))
|
||||||
|
return y
|
||||||
|
|
||||||
def _get_param_names(self):
|
def _get_param_names(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
@ -70,7 +92,6 @@ class TanhFunction(WarpingFunction):
|
||||||
self.link_parameter(self.psi)
|
self.link_parameter(self.psi)
|
||||||
self.link_parameter(self.d)
|
self.link_parameter(self.d)
|
||||||
self.initial_y = initial_y
|
self.initial_y = initial_y
|
||||||
self.rate = 0.1
|
|
||||||
|
|
||||||
def f(self, y):
|
def f(self, y):
|
||||||
"""
|
"""
|
||||||
|
|
@ -87,29 +108,6 @@ class TanhFunction(WarpingFunction):
|
||||||
z += a * np.tanh(b * (y + c))
|
z += a * np.tanh(b * (y + c))
|
||||||
return z
|
return z
|
||||||
|
|
||||||
def f_inv(self, z, max_iterations=100, y=None):
|
|
||||||
"""
|
|
||||||
calculate the numerical inverse of f
|
|
||||||
|
|
||||||
:param max_iterations: maximum number of N.R. iterations
|
|
||||||
"""
|
|
||||||
|
|
||||||
z = z.copy()
|
|
||||||
y = np.ones_like(z)
|
|
||||||
|
|
||||||
it = 0
|
|
||||||
update = np.inf
|
|
||||||
while np.abs(update).sum() > 1e-10 and it < max_iterations:
|
|
||||||
fy = self.f(y)
|
|
||||||
fgrady = self.fgrad_y(y)
|
|
||||||
update = (fy - z) / fgrady
|
|
||||||
y -= self.rate * update
|
|
||||||
it += 1
|
|
||||||
if it == max_iterations:
|
|
||||||
print("WARNING!!! Maximum number of iterations reached in f_inv ")
|
|
||||||
print("Sum of roots: %.4f" % np.sum(fy - z))
|
|
||||||
return y
|
|
||||||
|
|
||||||
def fgrad_y(self, y, return_precalc=False):
|
def fgrad_y(self, y, return_precalc=False):
|
||||||
"""
|
"""
|
||||||
gradient of f w.r.t to y ([N x 1])
|
gradient of f w.r.t to y ([N x 1])
|
||||||
|
|
@ -183,12 +181,16 @@ class TanhFunction(WarpingFunction):
|
||||||
|
|
||||||
class LogFunction(WarpingFunction):
|
class LogFunction(WarpingFunction):
|
||||||
"""
|
"""
|
||||||
Easy wrapper for applying a fixed warping function to
|
Easy wrapper for applying a fixed log warping function to
|
||||||
positive-only values.
|
positive-only values.
|
||||||
|
The closed_inverse flag should only be set to False for
|
||||||
|
debugging and testing purposes.
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self, closed_inverse=True):
|
||||||
self.num_parameters = 0
|
self.num_parameters = 0
|
||||||
super(LogFunction, self).__init__(name='log')
|
super(LogFunction, self).__init__(name='log')
|
||||||
|
if closed_inverse:
|
||||||
|
self.f_inv = self._f_inv
|
||||||
|
|
||||||
def f(self, y):
|
def f(self, y):
|
||||||
return np.log(y)
|
return np.log(y)
|
||||||
|
|
@ -204,7 +206,7 @@ class LogFunction(WarpingFunction):
|
||||||
return 0, 0
|
return 0, 0
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def f_inv(self, z, y=None):
|
def _f_inv(self, z, y=None):
|
||||||
return np.exp(z)
|
return np.exp(z)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -212,10 +214,14 @@ class IdentityFunction(WarpingFunction):
|
||||||
"""
|
"""
|
||||||
Identity warping function. This is for testing and sanity check purposes
|
Identity warping function. This is for testing and sanity check purposes
|
||||||
and should not be used in practice.
|
and should not be used in practice.
|
||||||
|
The closed_inverse flag should only be set to False for
|
||||||
|
debugging and testing purposes.
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self, closed_inverse=True):
|
||||||
self.num_parameters = 0
|
self.num_parameters = 0
|
||||||
super(IdentityFunction, self).__init__(name='identity')
|
super(IdentityFunction, self).__init__(name='identity')
|
||||||
|
if closed_inverse:
|
||||||
|
self.f_inv = self._f_inv
|
||||||
|
|
||||||
def f(self, y):
|
def f(self, y):
|
||||||
return y
|
return y
|
||||||
|
|
@ -231,6 +237,6 @@ class IdentityFunction(WarpingFunction):
|
||||||
return 0, 0
|
return 0, 0
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def f_inv(self, z, y=None):
|
def _f_inv(self, z, y=None):
|
||||||
return z
|
return z
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue