提交 9036e6dd authored 作者: Thomas George's avatar Thomas George

more test cases + some small changes

上级 a8996904
...@@ -284,8 +284,6 @@ class GpuCholesky(Op): ...@@ -284,8 +284,6 @@ class GpuCholesky(Op):
# Input matrix. # Input matrix.
A = inputs[0] A = inputs[0]
assert(len(A.shape) == 2)
l, n = A.shape l, n = A.shape
if l != n: if l != n:
raise ValueError('A must be a square matrix') raise ValueError('A must be a square matrix')
...@@ -333,7 +331,6 @@ class GpuCholesky(Op): ...@@ -333,7 +331,6 @@ class GpuCholesky(Op):
# cusolver leaves the elements in the matrix outside the considered # cusolver leaves the elements in the matrix outside the considered
# upper or lower triangle unchanged, so we need to put zeros outside # upper or lower triangle unchanged, so we need to put zeros outside
# the triangle # the triangle
# Note : we should probably check for c or f order in triu instead of here
if self.lower: if self.lower:
tril(L) tril(L)
else: else:
......
...@@ -120,14 +120,14 @@ class TestGpuCholesky(unittest.TestCase): ...@@ -120,14 +120,14 @@ class TestGpuCholesky(unittest.TestCase):
utt.seed_rng() utt.seed_rng()
def get_gpu_cholesky_func(self, lower=True, inplace=False): def get_gpu_cholesky_func(self, lower=True, inplace=False):
""" Helper function to compile function from GPU Cholesky op. """ # Helper function to compile function from GPU Cholesky op.
A = theano.tensor.matrix("A", dtype="float32") A = theano.tensor.matrix("A", dtype="float32")
cholesky_op = GpuCholesky(lower=lower, inplace=inplace) cholesky_op = GpuCholesky(lower=lower, inplace=inplace)
chol_A = cholesky_op(A) chol_A = cholesky_op(A)
return theano.function([A], chol_A, accept_inplace=inplace, mode=mode_with_gpu) return theano.function([A], chol_A, accept_inplace=inplace, mode=mode_with_gpu)
def compare_gpu_cholesky_to_numpy(self, A_val, lower=True, inplace=False): def compare_gpu_cholesky_to_numpy(self, A_val, lower=True, inplace=False):
""" Helper function to compare op output to numpy.cholesky output. """ # Helper function to compare op output to numpy.cholesky output.
chol_A_val = numpy.linalg.cholesky(A_val) chol_A_val = numpy.linalg.cholesky(A_val)
if not lower: if not lower:
chol_A_val = chol_A_val.T chol_A_val = chol_A_val.T
...@@ -137,77 +137,55 @@ class TestGpuCholesky(unittest.TestCase): ...@@ -137,77 +137,55 @@ class TestGpuCholesky(unittest.TestCase):
utt.assert_allclose(chol_A_res, chol_A_val) utt.assert_allclose(chol_A_res, chol_A_val)
def test_invalid_input_fail_non_square(self): def test_invalid_input_fail_non_square(self):
""" Invalid Cholesky input test with non-square matrix as input. """ # Invalid Cholesky input test with non-square matrix as input.
A_val = numpy.random.normal(size=(3, 2)).astype("float32") A_val = numpy.random.normal(size=(3, 2)).astype("float32")
fn = self.get_gpu_cholesky_func(True, False) fn = self.get_gpu_cholesky_func(True, False)
self.assertRaises(ValueError, fn, A_val) self.assertRaises(ValueError, fn, A_val)
def test_invalid_input_fail_vector(self): def test_invalid_input_fail_vector(self):
""" Invalid Cholesky input test with vector as input. """ # Invalid Cholesky input test with vector as input.
def invalid_input_func(): def invalid_input_func():
A = theano.tensor.vector("A", dtype="float32") A = theano.tensor.vector("A", dtype="float32")
GpuCholesky(lower=True, inplace=False)(A) GpuCholesky(lower=True, inplace=False)(A)
self.assertRaises(AssertionError, invalid_input_func) self.assertRaises(AssertionError, invalid_input_func)
def test_invalid_input_fail_tensor3(self): def test_invalid_input_fail_tensor3(self):
""" Invalid Cholesky input test with 3D tensor as input. """ # Invalid Cholesky input test with 3D tensor as input.
def invalid_input_func(): def invalid_input_func():
A = theano.tensor.tensor3("A", dtype="float32") A = theano.tensor.tensor3("A", dtype="float32")
GpuCholesky(lower=True, inplace=False)(A) GpuCholesky(lower=True, inplace=False)(A)
self.assertRaises(AssertionError, invalid_input_func) self.assertRaises(AssertionError, invalid_input_func)
def test_diag_chol(self): def test_diag_chol(self):
""" Diagonal matrix input Cholesky test. """ # Diagonal matrix input Cholesky test.
# make sure all diagonal elements are positive so positive-definite # make sure all diagonal elements are positive so positive-definite
A_val = numpy.diag(numpy.random.uniform(size=5).astype("float32") + 1) for lower in [True, False]:
self.compare_gpu_cholesky_to_numpy(A_val, lower=True, inplace=False) for inplace in [True, False]:
A_val = numpy.diag(numpy.random.uniform(size=5).astype("float32") + 1)
self.compare_gpu_cholesky_to_numpy(A_val, lower=lower, inplace=inplace)
def test_dense_chol_lower(self): def test_dense_chol_lower(self):
""" Dense matrix input lower-triangular Cholesky test. """ # Dense matrix input lower-triangular Cholesky test.
M_val = numpy.random.normal(size=(3, 3)).astype("float32") for lower in [True, False]:
# A = M.dot(M) will be positive definite for all non-singular M for inplace in [True, False]:
A_val = M_val.dot(M_val.T) M_val = numpy.random.normal(size=(3, 3)).astype("float32")
self.compare_gpu_cholesky_to_numpy(A_val, lower=True, inplace=False) # A = M.dot(M) will be positive definite for all non-singular M
A_val = M_val.dot(M_val.T)
def test_dense_chol_upper(self): self.compare_gpu_cholesky_to_numpy(A_val, lower=lower, inplace=inplace)
""" Dense matrix input upper-triangular Cholesky test. """
M_val = numpy.random.normal(size=(3, 3)).astype("float32")
# A = M.dot(M) will be positive definite for all non-singular M
A_val = M_val.dot(M_val.T)
self.compare_gpu_cholesky_to_numpy(A_val, lower=False, inplace=False)
def test_diag_chol_inplace(self):
""" Diagonal matrix input inplace Cholesky test. """
# make sure all diagonal elements are positive so positive-definite
A_val = numpy.diag(numpy.random.uniform(size=5).astype("float32") + 1)
self.compare_gpu_cholesky_to_numpy(A_val, lower=True, inplace=True)
def test_dense_chol_lower_inplace(self):
""" Dense matrix input lower-triangular inplace Cholesky test. """
M_val = numpy.random.normal(size=(3, 3)).astype("float32")
# A = M.dot(M) will be positive definite for all non-singular M
A_val = M_val.dot(M_val.T)
self.compare_gpu_cholesky_to_numpy(A_val, lower=True, inplace=True)
def test_dense_chol_upper_inplace(self):
""" Dense matrix input upper-triangular inplace Cholesky test. """
M_val = numpy.random.normal(size=(3, 3)).astype("float32")
# A = M.dot(M) will be positive definite for all non-singular M
A_val = M_val.dot(M_val.T)
self.compare_gpu_cholesky_to_numpy(A_val, lower=False, inplace=True)
def test_invalid_input_fail_non_symmetric(self): def test_invalid_input_fail_non_symmetric(self):
""" Invalid Cholesky input test with non-symmetric input. # Invalid Cholesky input test with non-symmetric input.
(Non-symmetric real input must also be non-positive definite). """ # (Non-symmetric real input must also be non-positive definite).
A_val = numpy.random.normal(size=(3, 3)).astype("float32") A_val = None
# double-check random A_val is asymmetric - the probability of this while True:
# not being the case even with finite precision should be negligible A_val = numpy.random.normal(size=(3, 3)).astype("float32")
assert not numpy.allclose(A_val, A_val.T) if not numpy.allclose(A_val, A_val.T):
break
fn = self.get_gpu_cholesky_func(True, False) fn = self.get_gpu_cholesky_func(True, False)
self.assertRaises(LinAlgError, fn, A_val) self.assertRaises(LinAlgError, fn, A_val)
def test_invalid_input_fail_negative_definite(self): def test_invalid_input_fail_negative_definite(self):
""" Invalid Cholesky input test with negative-definite input. """ # Invalid Cholesky input test with negative-definite input.
M_val = numpy.random.normal(size=(3, 3)).astype("float32") M_val = numpy.random.normal(size=(3, 3)).astype("float32")
# A = -M.dot(M) will be negative definite for all non-singular M # A = -M.dot(M) will be negative definite for all non-singular M
A_val = -M_val.dot(M_val.T) A_val = -M_val.dot(M_val.T)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论