diff --git a/GPy/kern/_src/kern.py b/GPy/kern/_src/kern.py index dbe4c1f8..7d17f4da 100644 --- a/GPy/kern/_src/kern.py +++ b/GPy/kern/_src/kern.py @@ -27,25 +27,28 @@ class Kern(Parameterized): Do not instantiate. """ 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 - 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 isinstance(self.active_dims, slice): - self.active_dims = slice(self.active_dims.start or 0, self.active_dims.stop or self.input_dim, self.active_dims.step or 1) - active_dim_size = int(np.round((self.active_dims.stop-self.active_dims.start)/self.active_dims.step)) - elif isinstance(self.active_dims, np.ndarray): - 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) - active_dim_size = self.active_dims.size - 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) + if self.active_dims is not None and self.input_dim is not None: + 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 isinstance(self.active_dims, slice): + self.active_dims = slice(self.active_dims.start or 0, self.active_dims.stop or self.input_dim, self.active_dims.step or 1) + active_dim_size = int(np.round((self.active_dims.stop-self.active_dims.start)/self.active_dims.step)) + elif isinstance(self.active_dims, np.ndarray): + #assert np.all(self.active_dims >= 0), 'active dimensions need to be positive. negative indexing is not allowed' + 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 = self.active_dims.size + 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.useGPU = self._support_GPU and useGPU @Cache_this(limit=10) 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): """ @@ -205,9 +208,10 @@ class CombinationKernel(Kern): return self._parameters_ 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)) - input_dim = active_dims.max()+1 + (len(np.r_[extra_dims]) if extra_dims is not None else 0) - active_dims = slice(0, input_dim, 1) + #active_dims = reduce(np.union1d, (np.r_[x.active_dims] for x in kernels), np.array([], dtype=int)) + #active_dims = np.array(np.concatenate((active_dims, extra_dims if extra_dims is not None else [])), dtype=int) + input_dim = [k.input_dim for k in kernels] + active_dims = None return input_dim, active_dims def input_sensitivity(self): diff --git a/GPy/kern/_src/kernel_slice_operations.py b/GPy/kern/_src/kernel_slice_operations.py index a4bb8f62..30b27eea 100644 --- a/GPy/kern/_src/kernel_slice_operations.py +++ b/GPy/kern/_src/kernel_slice_operations.py @@ -33,8 +33,8 @@ class _Slice_wrap(object): def __init__(self, k, X, X2=None): self.k = k self.shape = X.shape - if 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])) + if (self.k.active_dims is not None) and (self.k._sliced_X == 0): + #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.X2 = self.k._slice_X(X2) if X2 is not None else X2 self.ret = True diff --git a/GPy/testing/kernel_tests.py b/GPy/testing/kernel_tests.py index 91683edc..65998ad2 100644 --- a/GPy/testing/kernel_tests.py +++ b/GPy/testing/kernel_tests.py @@ -260,7 +260,6 @@ class KernelGradientTestsContinuous(unittest.TestCase): self.assertTrue(check_kernel_gradient_functions(k, X=self.X, X2=self.X2, verbose=verbose)) 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.randomize() 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): 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() - 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.randomize() # assert it runs: @@ -303,46 +302,25 @@ class KernelGradientTestsContinuous(unittest.TestCase): k.randomize() 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): def setUp(self): 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.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.matern self.sumkern.randomize() def test_active_dims(self): - self.assertEqual(self.sumkern.input_dim, 10) - self.assertEqual(self.sumkern.active_dims, slice(0, 10, 1)) + #self.assertEqual(self.sumkern.input_dim, 10) + #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): 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))) @@ -365,7 +343,7 @@ class KernelTestsNonContinuous(unittest.TestCase): self.X2 = np.random.randn((N0+N1)*2, self.D+1) self.X2[:(N0*2), -1] = 0 self.X2[(N0*2):, -1] = 1 - + def test_IndependentOutputs(self): k = GPy.kern.RBF(self.D) kern = GPy.kern.IndependentOutputs(k, -1, 'ind_single') @@ -373,7 +351,7 @@ class KernelTestsNonContinuous(unittest.TestCase): k = [GPy.kern.RBF(1, active_dims=[1], name='rbf1'), GPy.kern.RBF(self.D, name='rbf012'), GPy.kern.RBF(2, active_dims=[0,2], name='rbf02')] kern = GPy.kern.IndependentOutputs(k, -1, name='ind_split') self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose, fixed_X_dims=-1)) - + def test_ODE_UY(self): kern = GPy.kern.ODE_UY(2, active_dims=[0, self.D]) X = self.X[self.X[:,-1]!=2]