mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-05-27 14:25:16 +02:00
bug fix: slicing can now be turned of by passing None as active_dims
This commit is contained in:
parent
d2f73f13ec
commit
a57ca26c89
3 changed files with 34 additions and 52 deletions
|
|
@ -27,25 +27,28 @@ class Kern(Parameterized):
|
||||||
Do not instantiate.
|
Do not instantiate.
|
||||||
"""
|
"""
|
||||||
super(Kern, self).__init__(name=name, *a, **kw)
|
super(Kern, self).__init__(name=name, *a, **kw)
|
||||||
self.active_dims = active_dims if active_dims is not None else slice(0, input_dim)
|
self.active_dims = active_dims# if active_dims is not None else slice(0, input_dim, 1)
|
||||||
self.input_dim = input_dim
|
self.input_dim = input_dim
|
||||||
assert isinstance(self.active_dims, (slice, list, tuple, np.ndarray)), 'active_dims needs to be an array-like or slice object over dimensions, {} given'.format(self.active_dims.__class__)
|
if self.active_dims is not None and self.input_dim is not None:
|
||||||
if isinstance(self.active_dims, slice):
|
assert isinstance(self.active_dims, (slice, list, tuple, np.ndarray)), 'active_dims needs to be an array-like or slice object over dimensions, {} given'.format(self.active_dims.__class__)
|
||||||
self.active_dims = slice(self.active_dims.start or 0, self.active_dims.stop or self.input_dim, self.active_dims.step or 1)
|
if isinstance(self.active_dims, slice):
|
||||||
active_dim_size = int(np.round((self.active_dims.stop-self.active_dims.start)/self.active_dims.step))
|
self.active_dims = slice(self.active_dims.start or 0, self.active_dims.stop or self.input_dim, self.active_dims.step or 1)
|
||||||
elif isinstance(self.active_dims, np.ndarray):
|
active_dim_size = int(np.round((self.active_dims.stop-self.active_dims.start)/self.active_dims.step))
|
||||||
assert self.active_dims.ndim == 1, 'only flat indices allowed, given active_dims.shape={}, provide only indexes to the dimensions of the input'.format(self.active_dims.shape)
|
elif isinstance(self.active_dims, np.ndarray):
|
||||||
active_dim_size = self.active_dims.size
|
#assert np.all(self.active_dims >= 0), 'active dimensions need to be positive. negative indexing is not allowed'
|
||||||
else:
|
assert self.active_dims.ndim == 1, 'only flat indices allowed, given active_dims.shape={}, provide only indexes to the dimensions (columns) of the input'.format(self.active_dims.shape)
|
||||||
active_dim_size = len(self.active_dims)
|
active_dim_size = self.active_dims.size
|
||||||
assert active_dim_size == self.input_dim, "input_dim={} does not match len(active_dim)={}, active_dims={}".format(self.input_dim, active_dim_size, self.active_dims)
|
else:
|
||||||
|
active_dim_size = len(self.active_dims)
|
||||||
|
assert active_dim_size == self.input_dim, "input_dim={} does not match len(active_dim)={}, active_dims={}".format(self.input_dim, active_dim_size, self.active_dims)
|
||||||
self._sliced_X = 0
|
self._sliced_X = 0
|
||||||
|
|
||||||
self.useGPU = self._support_GPU and useGPU
|
self.useGPU = self._support_GPU and useGPU
|
||||||
|
|
||||||
@Cache_this(limit=10)
|
@Cache_this(limit=10)
|
||||||
def _slice_X(self, X):
|
def _slice_X(self, X):
|
||||||
return X[:, self.active_dims]
|
if self.active_dims is not None:
|
||||||
|
return X[:, self.active_dims]
|
||||||
|
return X
|
||||||
|
|
||||||
def K(self, X, X2):
|
def K(self, X, X2):
|
||||||
"""
|
"""
|
||||||
|
|
@ -205,9 +208,10 @@ class CombinationKernel(Kern):
|
||||||
return self._parameters_
|
return self._parameters_
|
||||||
|
|
||||||
def get_input_dim_active_dims(self, kernels, extra_dims = None):
|
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 = reduce(np.union1d, (np.r_[x.active_dims] for x in kernels), np.array([], dtype=int))
|
||||||
input_dim = active_dims.max()+1 + (len(np.r_[extra_dims]) if extra_dims is not None else 0)
|
#active_dims = np.array(np.concatenate((active_dims, extra_dims if extra_dims is not None else [])), dtype=int)
|
||||||
active_dims = slice(0, input_dim, 1)
|
input_dim = [k.input_dim for k in kernels]
|
||||||
|
active_dims = None
|
||||||
return input_dim, active_dims
|
return input_dim, active_dims
|
||||||
|
|
||||||
def input_sensitivity(self):
|
def input_sensitivity(self):
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ class _Slice_wrap(object):
|
||||||
def __init__(self, k, X, X2=None):
|
def __init__(self, k, X, X2=None):
|
||||||
self.k = k
|
self.k = k
|
||||||
self.shape = X.shape
|
self.shape = X.shape
|
||||||
if self.k._sliced_X == 0:
|
if (self.k.active_dims is not None) and (self.k._sliced_X == 0):
|
||||||
assert X.shape[1] > max(np.r_[self.k.active_dims]), "At least {} dimensional X needed".format(max(np.r_[self.k.active_dims]))
|
#assert X.shape[1] > len(np.r_[self.k.active_dims]), "At least {} dimensional X needed".format(len(np.r_[self.k.active_dims]))
|
||||||
self.X = self.k._slice_X(X)
|
self.X = self.k._slice_X(X)
|
||||||
self.X2 = self.k._slice_X(X2) if X2 is not None else X2
|
self.X2 = self.k._slice_X(X2) if X2 is not None else X2
|
||||||
self.ret = True
|
self.ret = True
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,6 @@ class KernelGradientTestsContinuous(unittest.TestCase):
|
||||||
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
||||||
|
|
||||||
def test_Prod3(self):
|
def test_Prod3(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.RBF(2, active_dims=[0,4]) * GPy.kern.Linear(self.D))
|
k = (GPy.kern.RBF(2, active_dims=[0,4]) * GPy.kern.Linear(self.D))
|
||||||
k.randomize()
|
k.randomize()
|
||||||
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
||||||
|
|
@ -274,7 +273,7 @@ class KernelGradientTestsContinuous(unittest.TestCase):
|
||||||
def test_Add_dims(self):
|
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 = GPy.kern.Matern32(2, active_dims=[2,self.D]) + GPy.kern.RBF(2, active_dims=[0,4]) + GPy.kern.Linear(self.D)
|
||||||
k.randomize()
|
k.randomize()
|
||||||
self.assertRaises(AssertionError, k.K, self.X)
|
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 = 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()
|
k.randomize()
|
||||||
# assert it runs:
|
# assert it runs:
|
||||||
|
|
@ -303,46 +302,25 @@ class KernelGradientTestsContinuous(unittest.TestCase):
|
||||||
k.randomize()
|
k.randomize()
|
||||||
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
||||||
|
|
||||||
#TODO: turn off grad checkingwrt X for indexed kernels like coregionalize
|
|
||||||
# class KernelGradientTestsContinuous1D(unittest.TestCase):
|
|
||||||
# def setUp(self):
|
|
||||||
# self.N, self.D = 100, 1
|
|
||||||
# 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]
|
|
||||||
#
|
|
||||||
# def test_PeriodicExponential(self):
|
|
||||||
# k = GPy.kern.PeriodicExponential(self.D)
|
|
||||||
# k.randomize()
|
|
||||||
# self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
|
||||||
#
|
|
||||||
# def test_PeriodicMatern32(self):
|
|
||||||
# k = GPy.kern.PeriodicMatern32(self.D)
|
|
||||||
# k.randomize()
|
|
||||||
# self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
|
||||||
#
|
|
||||||
# def test_PeriodicMatern52(self):
|
|
||||||
# k = GPy.kern.PeriodicMatern52(self.D)
|
|
||||||
# k.randomize()
|
|
||||||
# self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose))
|
|
||||||
|
|
||||||
|
|
||||||
class KernelTestsMiscellaneous(unittest.TestCase):
|
class KernelTestsMiscellaneous(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
N, D = 100, 10
|
N, D = 100, 10
|
||||||
self.X = np.linspace(-np.pi, +np.pi, N)[:,None] * np.ones(D)
|
self.X = np.linspace(-np.pi, +np.pi, N)[:,None] * np.random.uniform(-10,10,D)
|
||||||
self.rbf = GPy.kern.RBF(2, active_dims=slice(0,4,2))
|
self.rbf = GPy.kern.RBF(2, active_dims=slice(0,4,2))
|
||||||
self.linear = GPy.kern.Linear(2, active_dims=(3,9))
|
self.linear = GPy.kern.Linear(2, active_dims=(3,9))
|
||||||
self.matern = GPy.kern.Matern32(3, active_dims=np.array([2,4,9]))
|
self.matern = GPy.kern.Matern32(3, active_dims=np.array([1,7,9]))
|
||||||
self.sumkern = self.rbf + self.linear
|
self.sumkern = self.rbf + self.linear
|
||||||
self.sumkern += self.matern
|
self.sumkern += self.matern
|
||||||
self.sumkern.randomize()
|
self.sumkern.randomize()
|
||||||
|
|
||||||
def test_active_dims(self):
|
def test_active_dims(self):
|
||||||
self.assertEqual(self.sumkern.input_dim, 10)
|
#self.assertEqual(self.sumkern.input_dim, 10)
|
||||||
self.assertEqual(self.sumkern.active_dims, slice(0, 10, 1))
|
#self.assertEqual(list(self.sumkern.active_dims), [0,1,2,3,7,9])
|
||||||
|
# test the automatic dim detection expression for slices:
|
||||||
|
start, stop = 0, 277
|
||||||
|
for i in range(start,stop,7):
|
||||||
|
for j in range(1,4):
|
||||||
|
GPy.kern.Kern(int(np.round((i+1)/j)), slice(0, i+1, j), "testkern")
|
||||||
|
|
||||||
def test_which_parts(self):
|
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.matern]), self.linear.K(self.X)+self.matern.K(self.X)))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue