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 """Functional tests for Stack and ParallelStack Ops."""
     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.framework import constant_op
     24 from tensorflow.python.framework import dtypes
     25 from tensorflow.python.framework import errors_impl
     26 from tensorflow.python.framework import ops
     27 from tensorflow.python.ops import array_ops
     28 from tensorflow.python.ops import gradient_checker
     29 from tensorflow.python.ops import variables
     30 from tensorflow.python.platform import test
     31 
     32 
     33 def np_split_squeeze(array, axis):
     34   axis_len = array.shape[axis]
     35   return [
     36       np.squeeze(
     37           arr, axis=(axis,)) for arr in np.split(
     38               array, axis_len, axis=axis)
     39   ]
     40 
     41 
     42 class StackOpTest(test.TestCase):
     43 
     44   def testSimple(self):
     45     np.random.seed(7)
     46     with self.test_session(use_gpu=True):
     47       for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2):
     48         for dtype in [np.bool, np.float32, np.int32, np.int64]:
     49           data = np.random.randn(*shape).astype(dtype)
     50           # Convert [data[0], data[1], ...] separately to tensorflow
     51           # TODO(irving): Remove list() once we handle maps correctly
     52           xs = list(map(constant_op.constant, data))
     53           # Stack back into a single tensorflow tensor
     54           c = array_ops.stack(xs)
     55           self.assertAllEqual(c.eval(), data)
     56 
     57   def testSimpleParallelCPU(self):
     58     np.random.seed(7)
     59     with self.test_session(use_gpu=False):
     60       for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2):
     61         data = np.random.randn(*shape).astype(np.float32)
     62         xs = list(map(constant_op.constant, data))
     63         c = array_ops.parallel_stack(xs)
     64         self.assertAllEqual(c.eval(), data)
     65 
     66   def testSimpleParallelGPU(self):
     67     np.random.seed(7)
     68     with self.test_session(use_gpu=True):
     69       for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2):
     70         data = np.random.randn(*shape).astype(np.float32)
     71         xs = list(map(constant_op.constant, data))
     72         c = array_ops.parallel_stack(xs)
     73         self.assertAllEqual(c.eval(), data)
     74 
     75   def testConst(self):
     76     np.random.seed(7)
     77     with self.test_session(use_gpu=True):
     78       for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2):
     79         for dtype in [np.bool, np.float32, np.int32, np.int64]:
     80           data = np.random.randn(*shape).astype(dtype)
     81           # Stack back into a single tensorflow tensor directly using np array
     82           c = array_ops.stack(data)
     83           # This is implemented via a Const:
     84           self.assertEqual(c.op.type, "Const")
     85           self.assertAllEqual(c.eval(), data)
     86 
     87           # Python lists also work for 1-D case:
     88           if len(shape) == 1:
     89             data_list = list(data)
     90             cl = array_ops.stack(data_list)
     91             self.assertEqual(cl.op.type, "Const")
     92             self.assertAllEqual(cl.eval(), data)
     93 
     94         # Verify that shape induction works with shapes produced via const stack
     95         a = constant_op.constant([1, 2, 3, 4, 5, 6])
     96         b = array_ops.reshape(a, array_ops.stack([2, 3]))
     97         self.assertAllEqual(b.get_shape(), [2, 3])
     98 
     99   def testConstParallelCPU(self):
    100     np.random.seed(7)
    101     with self.test_session(use_gpu=False):
    102       for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2):
    103         data = np.random.randn(*shape).astype(np.float32)
    104         if len(shape) == 1:
    105           data_list = list(data)
    106           cl = array_ops.parallel_stack(data_list)
    107           self.assertAllEqual(cl.eval(), data)
    108 
    109         data = np.random.randn(*shape).astype(np.float32)
    110         c = array_ops.parallel_stack(data)
    111         self.assertAllEqual(c.eval(), data)
    112 
    113   def testConstParallelGPU(self):
    114     np.random.seed(7)
    115     with self.test_session(use_gpu=True):
    116       for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2):
    117         data = np.random.randn(*shape).astype(np.float32)
    118         if len(shape) == 1:
    119           data_list = list(data)
    120           cl = array_ops.parallel_stack(data_list)
    121           self.assertAllEqual(cl.eval(), data)
    122 
    123         data = np.random.randn(*shape).astype(np.float32)
    124         c = array_ops.parallel_stack(data)
    125         self.assertAllEqual(c.eval(), data)
    126 
    127   def testGradientsAxis0(self):
    128     np.random.seed(7)
    129     for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2):
    130       data = np.random.randn(*shape)
    131       shapes = [shape[1:]] * shape[0]
    132       with self.test_session(use_gpu=True):
    133         # TODO(irving): Remove list() once we handle maps correctly
    134         xs = list(map(constant_op.constant, data))
    135         c = array_ops.stack(xs)
    136         err = gradient_checker.compute_gradient_error(xs, shapes, c, shape)
    137         self.assertLess(err, 1e-6)
    138 
    139   def testGradientsAxis1(self):
    140     np.random.seed(7)
    141     for shape in (2, 3), (3, 2), (4, 3, 2):
    142       data = np.random.randn(*shape)
    143       shapes = [shape[1:]] * shape[0]
    144       out_shape = list(shape[1:])
    145       out_shape.insert(1, shape[0])
    146       with self.test_session(use_gpu=True):
    147         # TODO(irving): Remove list() once we handle maps correctly
    148         xs = list(map(constant_op.constant, data))
    149         c = array_ops.stack(xs, axis=1)
    150         err = gradient_checker.compute_gradient_error(xs, shapes, c, out_shape)
    151         self.assertLess(err, 1e-6)
    152 
    153   def testZeroSizeCPU(self):
    154     # Verify that stack doesn't crash for zero size inputs
    155     with self.test_session(use_gpu=False):
    156       for shape in (0,), (3, 0), (0, 3):
    157         x = np.zeros((2,) + shape).astype(np.int32)
    158         p = array_ops.stack(list(x)).eval()
    159         self.assertAllEqual(p, x)
    160 
    161         p = array_ops.parallel_stack(list(x)).eval()
    162         self.assertAllEqual(p, x)
    163 
    164   def testZeroSizeGPU(self):
    165     # Verify that stack doesn't crash for zero size inputs
    166     with self.test_session(use_gpu=True):
    167       for shape in (0,), (3, 0), (0, 3):
    168         x = np.zeros((2,) + shape).astype(np.int32)
    169         p = array_ops.stack(list(x)).eval()
    170         self.assertAllEqual(p, x)
    171 
    172         p = array_ops.parallel_stack(list(x)).eval()
    173         self.assertAllEqual(p, x)
    174 
    175   def testAxis0DefaultCPU(self):
    176     with self.test_session(use_gpu=False):
    177       t = [constant_op.constant([1, 2, 3]), constant_op.constant([4, 5, 6])]
    178       stacked = array_ops.stack(t).eval()
    179       parallel_stacked = array_ops.parallel_stack(t).eval()
    180 
    181     expected = np.array([[1, 2, 3], [4, 5, 6]])
    182     self.assertAllEqual(stacked, expected)
    183     self.assertAllEqual(parallel_stacked, expected)
    184 
    185   def testAxis0DefaultGPU(self):
    186     with self.test_session(use_gpu=True):
    187       t = [constant_op.constant([1, 2, 3]), constant_op.constant([4, 5, 6])]
    188       stacked = array_ops.stack(t).eval()
    189       parallel_stacked = array_ops.parallel_stack(t).eval()
    190 
    191     expected = np.array([[1, 2, 3], [4, 5, 6]])
    192     self.assertAllEqual(stacked, expected)
    193     self.assertAllEqual(parallel_stacked, expected)
    194 
    195   def testAgainstNumpy(self):
    196     # For 1 to 5 dimensions.
    197     for i in range(1, 6):
    198       expected = np.random.random(np.random.permutation(i) + 1)
    199 
    200       # For all the possible axis to split it, including negative indices.
    201       for j in range(-i, i):
    202         test_arrays = np_split_squeeze(expected, j)
    203 
    204         with self.test_session(use_gpu=True):
    205           actual_pack = array_ops.stack(test_arrays, axis=j)
    206           self.assertEqual(expected.shape, actual_pack.get_shape())
    207           actual_pack = actual_pack.eval()
    208 
    209           actual_stack = array_ops.stack(test_arrays, axis=j)
    210           self.assertEqual(expected.shape, actual_stack.get_shape())
    211           actual_stack = actual_stack.eval()
    212 
    213         self.assertNDArrayNear(expected, actual_stack, 1e-6)
    214 
    215   def testDimOutOfRange(self):
    216     t = [constant_op.constant([1, 2, 3]), constant_op.constant([4, 5, 6])]
    217     with self.assertRaisesRegexp(ValueError, r"axis = 2 not in \[-2, 2\)"):
    218       array_ops.stack(t, axis=2)
    219 
    220   def testDimOutOfNegativeRange(self):
    221     t = [constant_op.constant([1, 2, 3]), constant_op.constant([4, 5, 6])]
    222     with self.assertRaisesRegexp(ValueError, r"axis = -3 not in \[-2, 2\)"):
    223       array_ops.stack(t, axis=-3)
    224 
    225 
    226 class AutomaticStackingTest(test.TestCase):
    227 
    228   def testSimple(self):
    229     with self.test_session(use_gpu=True):
    230       self.assertAllEqual(
    231           [1, 0, 2],
    232           ops.convert_to_tensor([1, constant_op.constant(0), 2]).eval())
    233       self.assertAllEqual([[0, 0, 0], [0, 1, 0], [0, 0, 0]],
    234                           ops.convert_to_tensor(
    235                               [[0, 0, 0], [0, constant_op.constant(1), 0],
    236                                [0, 0, 0]]).eval())
    237       self.assertAllEqual([[0, 0, 0], [0, 1, 0], [0, 0, 0]],
    238                           ops.convert_to_tensor(
    239                               [[0, 0, 0], constant_op.constant([0, 1, 0]),
    240                                [0, 0, 0]]).eval())
    241       self.assertAllEqual([[0, 0, 0], [0, 1, 0], [0, 0, 0]],
    242                           ops.convert_to_tensor([
    243                               constant_op.constant([0, 0, 0]),
    244                               constant_op.constant([0, 1, 0]),
    245                               constant_op.constant([0, 0, 0])
    246                           ]).eval())
    247 
    248   def testWithNDArray(self):
    249     with self.test_session(use_gpu=True):
    250       result = ops.convert_to_tensor([[[0., 0.],
    251                                        constant_op.constant([1., 1.])],
    252                                       np.array(
    253                                           [[2., 2.], [3., 3.]],
    254                                           dtype=np.float32)])
    255       self.assertAllEqual([[[0., 0.], [1., 1.]], [[2., 2.], [3., 3.]]],
    256                           result.eval())
    257 
    258   def testVariable(self):
    259     with self.test_session(use_gpu=True):
    260       v = variables.Variable(17)
    261       result = ops.convert_to_tensor([[0, 0, 0], [0, v, 0], [0, 0, 0]])
    262       v.initializer.run()
    263       self.assertAllEqual([[0, 0, 0], [0, 17, 0], [0, 0, 0]], result.eval())
    264 
    265       v.assign(38).op.run()
    266       self.assertAllEqual([[0, 0, 0], [0, 38, 0], [0, 0, 0]], result.eval())
    267 
    268   def testDtype(self):
    269     t_0 = ops.convert_to_tensor([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])
    270     self.assertEqual(dtypes.float32, t_0.dtype)
    271 
    272     t_1 = ops.convert_to_tensor([[0., 0., 0.], constant_op.constant(
    273         [0., 0., 0.], dtype=dtypes.float64), [0., 0., 0.]])
    274     self.assertEqual(dtypes.float64, t_1.dtype)
    275 
    276     t_2 = ops.convert_to_tensor(
    277         [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], dtype=dtypes.float64)
    278     self.assertEqual(dtypes.float64, t_2.dtype)
    279 
    280     with self.assertRaises(TypeError):
    281       ops.convert_to_tensor([
    282           constant_op.constant(
    283               [0., 0., 0.], dtype=dtypes.float32), constant_op.constant(
    284                   [0., 0., 0.], dtype=dtypes.float64), [0., 0., 0.]
    285       ])
    286 
    287     with self.assertRaises(TypeError):
    288       ops.convert_to_tensor(
    289           [[0., 0., 0.], constant_op.constant(
    290               [0., 0., 0.], dtype=dtypes.float64), [0., 0., 0.]],
    291           dtype=dtypes.float32)
    292 
    293     with self.assertRaises(TypeError):
    294       ops.convert_to_tensor(
    295           [constant_op.constant(
    296               [0., 0., 0.], dtype=dtypes.float64)],
    297           dtype=dtypes.float32)
    298 
    299   def testPlaceholder(self):
    300     with self.test_session(use_gpu=True):
    301       # Test using placeholder with a defined shape.
    302       ph_0 = array_ops.placeholder(dtypes.int32, shape=[])
    303       result_0 = ops.convert_to_tensor([[0, 0, 0], [0, ph_0, 0], [0, 0, 0]])
    304       self.assertAllEqual(
    305           [[0, 0, 0], [0, 1, 0], [0, 0, 0]], result_0.eval(feed_dict={ph_0: 1}))
    306       self.assertAllEqual(
    307           [[0, 0, 0], [0, 2, 0], [0, 0, 0]], result_0.eval(feed_dict={ph_0: 2}))
    308 
    309       # Test using placeholder with an undefined shape.
    310       ph_1 = array_ops.placeholder(dtypes.int32)
    311       result_1 = ops.convert_to_tensor([[0, 0, 0], [0, ph_1, 0], [0, 0, 0]])
    312       self.assertAllEqual(
    313           [[0, 0, 0], [0, 1, 0], [0, 0, 0]], result_1.eval(feed_dict={ph_1: 1}))
    314       self.assertAllEqual(
    315           [[0, 0, 0], [0, 2, 0], [0, 0, 0]], result_1.eval(feed_dict={ph_1: 2}))
    316 
    317   def testShapeErrors(self):
    318     # Static shape error.
    319     ph_0 = array_ops.placeholder(dtypes.int32, shape=[1])
    320     with self.assertRaises(ValueError):
    321       ops.convert_to_tensor([[0, 0, 0], [0, ph_0, 0], [0, 0, 0]])
    322 
    323     # Dynamic shape error.
    324     ph_1 = array_ops.placeholder(dtypes.int32)
    325     result_1 = ops.convert_to_tensor([[0, 0, 0], [0, ph_1, 0], [0, 0, 0]])
    326     with self.test_session(use_gpu=True):
    327       with self.assertRaises(errors_impl.InvalidArgumentError):
    328         result_1.eval(feed_dict={ph_1: [1]})
    329 
    330 
    331 if __name__ == "__main__":
    332   test.main()
    333