Home | History | Annotate | Download | only in kernel_tests
      1 # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 # ==============================================================================
     15 """Tests for tensorflow.ops.tf.MatrixDeterminant."""
     16 
     17 from __future__ import absolute_import
     18 from __future__ import division
     19 from __future__ import print_function
     20 
     21 import numpy as np
     22 
     23 from tensorflow.python.client import session
     24 from tensorflow.python.framework import constant_op
     25 from tensorflow.python.framework import ops
     26 from tensorflow.python.ops import control_flow_ops
     27 from tensorflow.python.ops import gen_linalg_ops
     28 from tensorflow.python.ops import linalg_ops
     29 from tensorflow.python.ops import random_ops
     30 from tensorflow.python.ops import variables
     31 from tensorflow.python.platform import test
     32 
     33 
     34 class DeterminantOpTest(test.TestCase):
     35 
     36   def _compareDeterminantBase(self, matrix_x, tf_ans):
     37     out = tf_ans.eval()
     38     shape = matrix_x.shape
     39     if shape[-1] == 0 and shape[-2] == 0:
     40       np_ans = np.ones(shape[:-2]).astype(matrix_x.dtype)
     41     else:
     42       np_ans = np.array(np.linalg.det(matrix_x)).astype(matrix_x.dtype)
     43     self.assertShapeEqual(np_ans, tf_ans)
     44     self.assertAllClose(np_ans, out, atol=5e-5)
     45 
     46   def _compareLogDeterminantBase(self, matrix_x, tf_ans):
     47     sign_tf, abs_log_det_tf = tf_ans
     48     shape = matrix_x.shape
     49     if shape[-1] == 0 or shape[-2] == 0:
     50       np_sign, np_ans = (1.0, np.zeros(shape[:-2]).astype(matrix_x.dtype))
     51     else:
     52       np_sign, np_ans = np.linalg.slogdet(matrix_x)
     53       np_ans = np_ans.astype(matrix_x.dtype)
     54 
     55     self.assertShapeEqual(np_ans, abs_log_det_tf)
     56     sign_tf_val = sign_tf.eval()
     57     abs_log_det_tf_val = abs_log_det_tf.eval()
     58     self.assertAllClose(
     59         sign_tf_val * np.exp(abs_log_det_tf_val),
     60         np_sign * np.exp(np_ans),
     61         atol=5e-5)
     62 
     63   def _compareDeterminant(self, matrix_x):
     64     with self.test_session(use_gpu=True):
     65       self._compareDeterminantBase(matrix_x,
     66                                    linalg_ops.matrix_determinant(matrix_x))
     67       self._compareLogDeterminantBase(
     68           matrix_x, gen_linalg_ops._log_matrix_determinant(matrix_x))
     69 
     70   def testBasic(self):
     71     # 2x2 matrices
     72     self._compareDeterminant(np.array([[2., 3.], [3., 4.]]).astype(np.float32))
     73     self._compareDeterminant(np.array([[0., 0.], [0., 0.]]).astype(np.float32))
     74     # 5x5 matrices (Eigen forces LU decomposition)
     75     self._compareDeterminant(
     76         np.array([[2., 3., 4., 5., 6.], [3., 4., 9., 2., 0.], [
     77             2., 5., 8., 3., 8.
     78         ], [1., 6., 7., 4., 7.], [2., 3., 4., 5., 6.]]).astype(np.float32))
     79     # A multidimensional batch of 2x2 matrices
     80     self._compareDeterminant(np.random.rand(3, 4, 5, 2, 2).astype(np.float32))
     81 
     82   def testBasicDouble(self):
     83     # 2x2 matrices
     84     self._compareDeterminant(np.array([[2., 3.], [3., 4.]]).astype(np.float64))
     85     self._compareDeterminant(np.array([[0., 0.], [0., 0.]]).astype(np.float64))
     86     # 5x5 matrices (Eigen forces LU decomposition)
     87     self._compareDeterminant(
     88         np.array([[2., 3., 4., 5., 6.], [3., 4., 9., 2., 0.], [
     89             2., 5., 8., 3., 8.
     90         ], [1., 6., 7., 4., 7.], [2., 3., 4., 5., 6.]]).astype(np.float64))
     91     # A multidimensional batch of 2x2 matrices
     92     self._compareDeterminant(np.random.rand(3, 4, 5, 2, 2).astype(np.float64))
     93 
     94   def testBasicComplex64(self):
     95     # 2x2 matrices
     96     self._compareDeterminant(
     97         np.array([[2., 3.], [3., 4.]]).astype(np.complex64))
     98     self._compareDeterminant(
     99         np.array([[0., 0.], [0., 0.]]).astype(np.complex64))
    100     self._compareDeterminant(
    101         np.array([[1. + 1.j, 1. - 1.j], [-1. + 1.j, -1. - 1.j]]).astype(
    102             np.complex64))
    103     # 5x5 matrices (Eigen forces LU decomposition)
    104     self._compareDeterminant(
    105         np.array([[2., 3., 4., 5., 6.], [3., 4., 9., 2., 0.], [
    106             2., 5., 8., 3., 8.
    107         ], [1., 6., 7., 4., 7.], [2., 3., 4., 5., 6.]]).astype(np.complex64))
    108     # A multidimensional batch of 2x2 matrices
    109     self._compareDeterminant(np.random.rand(3, 4, 5, 2, 2).astype(np.complex64))
    110 
    111   def testBasicComplex128(self):
    112     # 2x2 matrices
    113     self._compareDeterminant(
    114         np.array([[2., 3.], [3., 4.]]).astype(np.complex128))
    115     self._compareDeterminant(
    116         np.array([[0., 0.], [0., 0.]]).astype(np.complex128))
    117     self._compareDeterminant(
    118         np.array([[1. + 1.j, 1. - 1.j], [-1. + 1.j, -1. - 1.j]]).astype(
    119             np.complex128))
    120     # 5x5 matrices (Eigen forces LU decomposition)
    121     self._compareDeterminant(
    122         np.array([[2., 3., 4., 5., 6.], [3., 4., 9., 2., 0.], [
    123             2., 5., 8., 3., 8.
    124         ], [1., 6., 7., 4., 7.], [2., 3., 4., 5., 6.]]).astype(np.complex128))
    125     # A multidimensional batch of 2x2 matrices
    126     self._compareDeterminant(
    127         np.random.rand(3, 4, 5, 2, 2).astype(np.complex128))
    128 
    129   def testInfiniteDeterminant(self):
    130     max_double = np.finfo("d").max
    131     huge_matrix = np.array([[max_double, 0.0], [0.0, max_double]])
    132     self._compareDeterminant(huge_matrix)
    133 
    134   def testNonSquareMatrix(self):
    135     # When the determinant of a non-square matrix is attempted we should return
    136     # an error
    137     with self.assertRaises(ValueError):
    138       linalg_ops.matrix_determinant(
    139           np.array([[1., 2., 3.], [3., 5., 4.]]).astype(np.float32))
    140 
    141   def testWrongDimensions(self):
    142     # The input to the determinant should be a 2-dimensional tensor.
    143     tensor1 = constant_op.constant([1., 2.])
    144     with self.assertRaises(ValueError):
    145       linalg_ops.matrix_determinant(tensor1)
    146 
    147   def testEmpty(self):
    148     self._compareDeterminant(np.empty([0, 2, 2]))
    149     self._compareDeterminant(np.empty([2, 0, 0]))
    150 
    151   def testConcurrentExecutesWithoutError(self):
    152     with self.test_session(use_gpu=True) as sess:
    153       matrix1 = random_ops.random_normal([5, 5], seed=42)
    154       matrix2 = random_ops.random_normal([5, 5], seed=42)
    155       det1 = linalg_ops.matrix_determinant(matrix1)
    156       det2 = linalg_ops.matrix_determinant(matrix2)
    157       det1_val, det2_val = sess.run([det1, det2])
    158       self.assertEqual(det1_val, det2_val)
    159 
    160 
    161 class MatrixDeterminantBenchmark(test.Benchmark):
    162 
    163   shapes = [
    164       (4, 4),
    165       (10, 10),
    166       (16, 16),
    167       (101, 101),
    168       (256, 256),
    169       (1000, 1000),
    170       (1024, 1024),
    171       (2048, 2048),
    172       (513, 4, 4),
    173       (513, 16, 16),
    174       (513, 256, 256),
    175   ]
    176 
    177   def _GenerateMatrix(self, shape):
    178     batch_shape = shape[:-2]
    179     shape = shape[-2:]
    180     assert shape[0] == shape[1]
    181     n = shape[0]
    182     matrix = np.ones(shape).astype(np.float32) / (
    183         2.0 * n) + np.diag(np.ones(n).astype(np.float32))
    184     return variables.Variable(np.tile(matrix, batch_shape + (1, 1)))
    185 
    186   def benchmarkMatrixDeterminantOp(self):
    187     for shape in self.shapes:
    188       with ops.Graph().as_default(), session.Session() as sess, ops.device(
    189           "/cpu:0"):
    190         matrix = self._GenerateMatrix(shape)
    191         d = linalg_ops.matrix_determinant(matrix)
    192         variables.global_variables_initializer().run()
    193         self.run_op_benchmark(
    194             sess,
    195             control_flow_ops.group(
    196                 d,),
    197             min_iters=25,
    198             name="matrix_determinant_cpu_{shape}".format(shape=shape))
    199 
    200       if test.is_gpu_available(True):
    201         with ops.Graph().as_default(), session.Session() as sess, ops.device(
    202             "/gpu:0"):
    203           matrix = self._GenerateMatrix(shape)
    204           d = linalg_ops.matrix_determinant(matrix)
    205           variables.global_variables_initializer().run()
    206           self.run_op_benchmark(
    207               sess,
    208               control_flow_ops.group(
    209                   d,),
    210               min_iters=25,
    211               name="matrix_determinant_gpu_{shape}".format(shape=shape))
    212 
    213 
    214 if __name__ == "__main__":
    215   test.main()
    216