From a7af12e6ea9bbe3c240bb512c96494573c785904 Mon Sep 17 00:00:00 2001 From: Jayanth Koushik Date: Mon, 23 Oct 2017 15:58:17 -0400 Subject: [PATCH 1/7] fix: dev: cython import errors This commit fixes issues observed in Windows where some cython modules are successfully imported, and some are not. This causes the global config cython.working to be inconsistent, which causes import errors when unavailable cython modules are tried to be imported (example https://github.com/SheffieldML/GPy/issues/266). This commit uses a separate flag for each module to fix the issue. --- GPy/kern/src/coregionalize.py | 11 +++++++---- GPy/kern/src/stationary.py | 7 ++++--- GPy/testing/cython_tests.py | 18 +++++++++++------- GPy/testing/kernel_tests.py | 8 ++++---- GPy/util/choleskies.py | 9 ++++++--- 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/GPy/kern/src/coregionalize.py b/GPy/kern/src/coregionalize.py index 197d7ece..704d0370 100644 --- a/GPy/kern/src/coregionalize.py +++ b/GPy/kern/src/coregionalize.py @@ -6,11 +6,14 @@ import numpy as np from ...core.parameterization import Param from paramz.transformations import Logexp from ...util.config import config # for assesing whether to use cython + try: from . import coregionalize_cython - config.set('cython', 'working', 'True') + cython_coregionalize_working = True except ImportError: - config.set('cython', 'working', 'False') + print('warning in coregionalize: failed to import cython module: falling back to numpy') + cython_coregionalize_working = False + class Coregionalize(Kern): """ @@ -61,7 +64,7 @@ class Coregionalize(Kern): self.B = np.dot(self.W, self.W.T) + np.diag(self.kappa) def K(self, X, X2=None): - if config.getboolean('cython', 'working'): + if cython_coregionalize_working and config.getboolean('cython', 'working'): return self._K_cython(X, X2) else: return self._K_numpy(X, X2) @@ -92,7 +95,7 @@ class Coregionalize(Kern): index2 = np.asarray(X2, dtype=np.int) #attempt to use cython for a nasty double indexing loop: fall back to numpy - if config.getboolean('cython', 'working'): + if cython_coregionalize_working and config.getboolean('cython', 'working'): dL_dK_small = self._gradient_reduce_cython(dL_dK, index, index2) else: dL_dK_small = self._gradient_reduce_numpy(dL_dK, index, index2) diff --git a/GPy/kern/src/stationary.py b/GPy/kern/src/stationary.py index 4e8ddb77..81681d60 100644 --- a/GPy/kern/src/stationary.py +++ b/GPy/kern/src/stationary.py @@ -14,9 +14,10 @@ from paramz.transformations import Logexp try: from . import stationary_cython + cython_stationary_working = True except ImportError: print('warning in stationary: failed to import cython module: falling back to numpy') - config.set('cython', 'working', 'false') + cython_stationary_working = False class Stationary(Kern): @@ -196,7 +197,7 @@ class Stationary(Kern): tmp = dL_dr*self._inv_dist(X, X2) if X2 is None: X2 = X - if config.getboolean('cython', 'working'): + if cython_stationary_working and config.getboolean('cython', 'working'): self.lengthscale.gradient = self._lengthscale_grads_cython(tmp, X, X2) else: self.lengthscale.gradient = self._lengthscale_grads_pure(tmp, X, X2) @@ -239,7 +240,7 @@ class Stationary(Kern): """ Given the derivative of the objective wrt K (dL_dK), compute the derivative wrt X """ - if config.getboolean('cython', 'working'): + if cython_stationary_working and config.getboolean('cython', 'working'): return self._gradients_X_cython(dL_dK, X, X2) else: return self._gradients_X_pure(dL_dK, X, X2) diff --git a/GPy/testing/cython_tests.py b/GPy/testing/cython_tests.py index c4bca5cd..c777aae0 100644 --- a/GPy/testing/cython_tests.py +++ b/GPy/testing/cython_tests.py @@ -2,21 +2,25 @@ import numpy as np import scipy as sp from GPy.util import choleskies import GPy -from ..util.config import config import unittest try: - from ..util import linalg_cython from ..util import choleskies_cython - config.set('cython', 'working', 'True') + choleskies_cython_working = True except ImportError: - config.set('cython', 'working', 'False') + choleskies_cython_working = False + +try: + from ..kern.src import stationary_cython + stationary_cython_working = True +except ImportError: + stationary_cython_working = False """ These tests make sure that the pure python and cython codes work the same """ -@unittest.skipIf(not config.getboolean('cython', 'working'),"Cython modules have not been built on this machine") +@unittest.skipIf(not choleskies_cython_working,"Cython cholesky module has not been built on this machine") class CythonTestChols(np.testing.TestCase): def setUp(self): self.flat = np.random.randn(45,5) @@ -30,7 +34,7 @@ class CythonTestChols(np.testing.TestCase): A2 = choleskies._triang_to_flat_cython(self.triang) np.testing.assert_allclose(A1, A2) -@unittest.skipIf(not config.getboolean('cython', 'working'),"Cython modules have not been built on this machine") +@unittest.skipIf(not stationary_cython_working,"Cython stationary module has not been built on this machine") class test_stationary(np.testing.TestCase): def setUp(self): self.k = GPy.kern.RBF(10) @@ -60,7 +64,7 @@ class test_stationary(np.testing.TestCase): g2 = self.k._lengthscale_grads_cython(self.dKxz, self.X, self.Z) np.testing.assert_allclose(g1, g2) -@unittest.skipIf(not config.getboolean('cython', 'working'),"Cython modules have not been built on this machine") +@unittest.skipIf(not choleskies_cython_working,"Cython cholesky module has not been built on this machine") class test_choleskies_backprop(np.testing.TestCase): def setUp(self): a =np.random.randn(10,12) diff --git a/GPy/testing/kernel_tests.py b/GPy/testing/kernel_tests.py index 053fce35..e5bc5683 100644 --- a/GPy/testing/kernel_tests.py +++ b/GPy/testing/kernel_tests.py @@ -14,10 +14,10 @@ from ..util.config import config verbose = 0 try: - from ..util import linalg_cython - config.set('cython', 'working', 'True') + from ..util import choleskies_cython + cython_choleskies_working = True except ImportError: - config.set('cython', 'working', 'False') + cython_choleskies_working = False class Kern_check_model(GPy.core.Model): @@ -618,7 +618,7 @@ class KernelTestsNonContinuous(unittest.TestCase): kern = GPy.kern.Coregionalize(1, output_dim=3, active_dims=[-1]) self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose, fixed_X_dims=-1)) -@unittest.skipIf(not config.getboolean('cython', 'working'),"Cython modules have not been built on this machine") +@unittest.skipIf(not cython_choleskies_working,"Cython choleskies module has not been built on this machine") class Coregionalize_cython_test(unittest.TestCase): """ Make sure that the coregionalize kernel work with and without cython enabled diff --git a/GPy/util/choleskies.py b/GPy/util/choleskies.py index 2676b6e6..54a7ea74 100644 --- a/GPy/util/choleskies.py +++ b/GPy/util/choleskies.py @@ -4,11 +4,14 @@ import numpy as np from . import linalg from .config import config + try: from . import choleskies_cython - config.set('cython', 'working', 'True') + cython_choleskies_working = True except ImportError: - config.set('cython', 'working', 'False') + print('warning in choleskies: failed to import cython module: falling back to numpy') + cython_choleskies_working = False + def safe_root(N): i = np.sqrt(N) @@ -100,7 +103,7 @@ def indexes_to_fix_for_low_rank(rank, size): return np.setdiff1d(np.arange((size**2+size)/2), keep) -if config.getboolean('cython', 'working'): +if cython_choleskies_working and config.getboolean('cython', 'working'): triang_to_flat = _triang_to_flat_cython flat_to_triang = _flat_to_triang_cython backprop_gradient = choleskies_cython.backprop_gradient_par_c From 6605b736d8231b495c10ce3210ac7d92d6cf4313 Mon Sep 17 00:00:00 2001 From: Jayanth Koushik Date: Mon, 23 Oct 2017 16:22:42 -0400 Subject: [PATCH 2/7] Use correct cython check in kernel_tests.py --- GPy/testing/kernel_tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GPy/testing/kernel_tests.py b/GPy/testing/kernel_tests.py index e5bc5683..5f418674 100644 --- a/GPy/testing/kernel_tests.py +++ b/GPy/testing/kernel_tests.py @@ -14,10 +14,10 @@ from ..util.config import config verbose = 0 try: - from ..util import choleskies_cython - cython_choleskies_working = True + from ..kern.src import coregionalize_cython + cython_coregionalize_working = True except ImportError: - cython_choleskies_working = False + cython_coregionalize_working = False class Kern_check_model(GPy.core.Model): @@ -618,7 +618,7 @@ class KernelTestsNonContinuous(unittest.TestCase): kern = GPy.kern.Coregionalize(1, output_dim=3, active_dims=[-1]) self.assertTrue(check_kernel_gradient_functions(kern, X=self.X, X2=self.X2, verbose=verbose, fixed_X_dims=-1)) -@unittest.skipIf(not cython_choleskies_working,"Cython choleskies module has not been built on this machine") +@unittest.skipIf(not cython_coregionalize_working,"Cython coregionalize module has not been built on this machine") class Coregionalize_cython_test(unittest.TestCase): """ Make sure that the coregionalize kernel work with and without cython enabled From 928559216cdb2d7e2261fab8e89bc929502069c9 Mon Sep 17 00:00:00 2001 From: Jayanth Koushik Date: Thu, 16 Nov 2017 20:29:49 -0500 Subject: [PATCH 3/7] Refactor checking for cython availability --- GPy/kern/src/coregionalize.py | 8 ++++---- GPy/kern/src/stationary.py | 8 ++++---- GPy/util/choleskies.py | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/GPy/kern/src/coregionalize.py b/GPy/kern/src/coregionalize.py index 704d0370..0c471cb3 100644 --- a/GPy/kern/src/coregionalize.py +++ b/GPy/kern/src/coregionalize.py @@ -9,10 +9,10 @@ from ...util.config import config # for assesing whether to use cython try: from . import coregionalize_cython - cython_coregionalize_working = True + use_coregionalize_cython = config.getboolean('cython', 'working') except ImportError: print('warning in coregionalize: failed to import cython module: falling back to numpy') - cython_coregionalize_working = False + use_coregionalize_cython = False class Coregionalize(Kern): @@ -64,7 +64,7 @@ class Coregionalize(Kern): self.B = np.dot(self.W, self.W.T) + np.diag(self.kappa) def K(self, X, X2=None): - if cython_coregionalize_working and config.getboolean('cython', 'working'): + if use_coregionalize_cython: return self._K_cython(X, X2) else: return self._K_numpy(X, X2) @@ -95,7 +95,7 @@ class Coregionalize(Kern): index2 = np.asarray(X2, dtype=np.int) #attempt to use cython for a nasty double indexing loop: fall back to numpy - if cython_coregionalize_working and config.getboolean('cython', 'working'): + if use_coregionalize_cython: dL_dK_small = self._gradient_reduce_cython(dL_dK, index, index2) else: dL_dK_small = self._gradient_reduce_numpy(dL_dK, index, index2) diff --git a/GPy/kern/src/stationary.py b/GPy/kern/src/stationary.py index 81681d60..90172049 100644 --- a/GPy/kern/src/stationary.py +++ b/GPy/kern/src/stationary.py @@ -14,10 +14,10 @@ from paramz.transformations import Logexp try: from . import stationary_cython - cython_stationary_working = True + use_stationary_cython = config.getboolean('cython', 'working') except ImportError: print('warning in stationary: failed to import cython module: falling back to numpy') - cython_stationary_working = False + use_stationary_cython = False class Stationary(Kern): @@ -197,7 +197,7 @@ class Stationary(Kern): tmp = dL_dr*self._inv_dist(X, X2) if X2 is None: X2 = X - if cython_stationary_working and config.getboolean('cython', 'working'): + if use_stationary_cython: self.lengthscale.gradient = self._lengthscale_grads_cython(tmp, X, X2) else: self.lengthscale.gradient = self._lengthscale_grads_pure(tmp, X, X2) @@ -240,7 +240,7 @@ class Stationary(Kern): """ Given the derivative of the objective wrt K (dL_dK), compute the derivative wrt X """ - if cython_stationary_working and config.getboolean('cython', 'working'): + if use_stationary_cython: return self._gradients_X_cython(dL_dK, X, X2) else: return self._gradients_X_pure(dL_dK, X, X2) diff --git a/GPy/util/choleskies.py b/GPy/util/choleskies.py index 54a7ea74..acc4ad7a 100644 --- a/GPy/util/choleskies.py +++ b/GPy/util/choleskies.py @@ -7,10 +7,10 @@ from .config import config try: from . import choleskies_cython - cython_choleskies_working = True + use_choleskies_cython = config.getboolean('cython', 'working') except ImportError: print('warning in choleskies: failed to import cython module: falling back to numpy') - cython_choleskies_working = False + use_choleskies_cython = False def safe_root(N): @@ -103,7 +103,7 @@ def indexes_to_fix_for_low_rank(rank, size): return np.setdiff1d(np.arange((size**2+size)/2), keep) -if cython_choleskies_working and config.getboolean('cython', 'working'): +if use_choleskies_cython: triang_to_flat = _triang_to_flat_cython flat_to_triang = _flat_to_triang_cython backprop_gradient = choleskies_cython.backprop_gradient_par_c From 46d3b6ce5ce9e23d0f2d2b942d36b3c84acb8e61 Mon Sep 17 00:00:00 2001 From: Jayanth Koushik Date: Thu, 15 Feb 2018 14:04:47 -0500 Subject: [PATCH 4/7] Don't override global cython config in tests --- GPy/testing/cython_tests.py | 6 ++++-- GPy/testing/kernel_tests.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/GPy/testing/cython_tests.py b/GPy/testing/cython_tests.py index c777aae0..dc41c44a 100644 --- a/GPy/testing/cython_tests.py +++ b/GPy/testing/cython_tests.py @@ -4,15 +4,17 @@ from GPy.util import choleskies import GPy import unittest +from ..util.config import config + try: from ..util import choleskies_cython - choleskies_cython_working = True + choleskies_cython_working = config.getboolean('cython', 'working') except ImportError: choleskies_cython_working = False try: from ..kern.src import stationary_cython - stationary_cython_working = True + stationary_cython_working = config.getboolean('cython', 'working') except ImportError: stationary_cython_working = False diff --git a/GPy/testing/kernel_tests.py b/GPy/testing/kernel_tests.py index 5f418674..7f89ae4e 100644 --- a/GPy/testing/kernel_tests.py +++ b/GPy/testing/kernel_tests.py @@ -15,7 +15,7 @@ verbose = 0 try: from ..kern.src import coregionalize_cython - cython_coregionalize_working = True + cython_coregionalize_working = config.getboolean('cython', 'working') except ImportError: cython_coregionalize_working = False From 1aab04188566f658d417b0531ae6a306ff492189 Mon Sep 17 00:00:00 2001 From: Jayanth Koushik Date: Thu, 15 Feb 2018 17:17:25 -0500 Subject: [PATCH 5/7] Fix cython check in linalg --- GPy/util/linalg.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/GPy/util/linalg.py b/GPy/util/linalg.py index cad3b352..406c19a6 100644 --- a/GPy/util/linalg.py +++ b/GPy/util/linalg.py @@ -11,8 +11,11 @@ from scipy.linalg import lapack, blas from .config import config import logging -if config.getboolean('cython', 'working'): +try: from . import linalg_cython + use_linalg_cython = config.getboolean('cython', 'working') +except ImportError: + use_linalg_cython = False def force_F_ordered_symmetric(A): """ @@ -358,7 +361,7 @@ def symmetrify(A, upper=False): note: tries to use cython, falls back to a slower numpy version """ - if config.getboolean('cython', 'working'): + if use_linalg_cython: _symmetrify_cython(A, upper) else: _symmetrify_numpy(A, upper) From 64c125573ecb5ccb2437ad58b796881b97713874 Mon Sep 17 00:00:00 2001 From: Jayanth Koushik Date: Thu, 15 Feb 2018 17:18:03 -0500 Subject: [PATCH 6/7] Use explicity cython/numpy variants in coregionalize test --- GPy/testing/kernel_tests.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/GPy/testing/kernel_tests.py b/GPy/testing/kernel_tests.py index 7f89ae4e..a0fc5a3d 100644 --- a/GPy/testing/kernel_tests.py +++ b/GPy/testing/kernel_tests.py @@ -631,32 +631,25 @@ class Coregionalize_cython_test(unittest.TestCase): def test_sym(self): dL_dK = np.random.randn(self.N1, self.N1) - GPy.util.config.config.set('cython', 'working', 'True') - K_cython = self.k.K(self.X) + K_cython = self.k._K_cython(self.X) self.k.update_gradients_full(dL_dK, self.X) grads_cython = self.k.gradient.copy() - GPy.util.config.config.set('cython', 'working', 'False') - K_numpy = self.k.K(self.X) + K_numpy = self.k._K_numpy(self.X) self.k.update_gradients_full(dL_dK, self.X) grads_numpy = self.k.gradient.copy() self.assertTrue(np.allclose(K_numpy, K_cython)) self.assertTrue(np.allclose(grads_numpy, grads_cython)) - #reset the cython state for any other tests - GPy.util.config.config.set('cython', 'working', 'true') - def test_nonsym(self): dL_dK = np.random.randn(self.N1, self.N2) - GPy.util.config.config.set('cython', 'working', 'True') - K_cython = self.k.K(self.X, self.X2) + K_cython = self.k._K_cython(self.X, self.X2) self.k.gradient = 0. self.k.update_gradients_full(dL_dK, self.X, self.X2) grads_cython = self.k.gradient.copy() - GPy.util.config.config.set('cython', 'working', 'False') - K_numpy = self.k.K(self.X, self.X2) + K_numpy = self.k._K_numpy(self.X, self.X2) self.k.gradient = 0. self.k.update_gradients_full(dL_dK, self.X, self.X2) grads_numpy = self.k.gradient.copy() @@ -664,9 +657,6 @@ class Coregionalize_cython_test(unittest.TestCase): self.assertTrue(np.allclose(K_numpy, K_cython)) self.assertTrue(np.allclose(grads_numpy, grads_cython)) - #reset the cython state for any other tests - GPy.util.config.config.set('cython', 'working', 'true') - class KernelTestsProductWithZeroValues(unittest.TestCase): From 08801c555496ed6b6e4da9eb52cb08baf487cf67 Mon Sep 17 00:00:00 2001 From: Jayanth Koushik Date: Thu, 15 Feb 2018 21:26:32 -0500 Subject: [PATCH 7/7] Ensure numpy version is used in coregionalize cython test --- GPy/testing/kernel_tests.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/GPy/testing/kernel_tests.py b/GPy/testing/kernel_tests.py index a0fc5a3d..a78ef69a 100644 --- a/GPy/testing/kernel_tests.py +++ b/GPy/testing/kernel_tests.py @@ -636,7 +636,14 @@ class Coregionalize_cython_test(unittest.TestCase): grads_cython = self.k.gradient.copy() K_numpy = self.k._K_numpy(self.X) + # Nasty hack to ensure the numpy version is used for update_gradients + # If this test is running, cython is working, so override the cython + # function with the numpy function + _gradient_reduce_cython = self.k._gradient_reduce_cython + self.k._gradient_reduce_cython = self.k._gradient_reduce_numpy self.k.update_gradients_full(dL_dK, self.X) + # Undo hack + self.k._gradient_reduce_cython = _gradient_reduce_cython grads_numpy = self.k.gradient.copy() self.assertTrue(np.allclose(K_numpy, K_cython)) @@ -651,7 +658,12 @@ class Coregionalize_cython_test(unittest.TestCase): K_numpy = self.k._K_numpy(self.X, self.X2) self.k.gradient = 0. + # Same hack as in test_sym (Line 639) + _gradient_reduce_cython = self.k._gradient_reduce_cython + self.k._gradient_reduce_cython = self.k._gradient_reduce_numpy self.k.update_gradients_full(dL_dK, self.X, self.X2) + # Undo hack + self.k._gradient_reduce_cython = _gradient_reduce_cython grads_numpy = self.k.gradient.copy() self.assertTrue(np.allclose(K_numpy, K_cython))