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 various tensorflow.ops.tf."""
     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.core.framework import node_def_pb2
     24 from tensorflow.python.framework import constant_op
     25 from tensorflow.python.framework import dtypes
     26 from tensorflow.python.framework import errors_impl
     27 from tensorflow.python.framework import importer
     28 from tensorflow.python.framework import sparse_tensor
     29 from tensorflow.python.ops import array_ops
     30 from tensorflow.python.ops import gradient_checker
     31 from tensorflow.python.ops import gradients_impl
     32 from tensorflow.python.platform import test
     33 
     34 
     35 # TODO(zongheng): it'd be great to factor out this function and various random
     36 # SparseTensor gen funcs.
     37 def _sparsify(x, thresh=0.5, index_dtype=np.int64):
     38   x[x < thresh] = 0
     39 
     40   non_zero = np.where(x)
     41   x_indices = np.vstack(non_zero).astype(index_dtype).T
     42   x_values = x[non_zero]
     43   x_shape = x.shape
     44 
     45   return sparse_tensor.SparseTensor(
     46       indices=x_indices, values=x_values, dense_shape=x_shape), len(x_values)
     47 
     48 
     49 class ShapeOpsTest(test.TestCase):
     50 
     51   def _compareShape(self, x, use_gpu=False):
     52     np_ans = np.array(np.shape(x))
     53     with self.test_session(use_gpu=use_gpu):
     54       tf_ans = array_ops.shape(x)
     55       tf_ans_64 = array_ops.shape(x, out_type=dtypes.int64)
     56       result = tf_ans.eval()
     57       result_64 = tf_ans_64.eval()
     58     self.assertAllEqual(np_ans, result)
     59     self.assertAllEqual(np_ans, result_64)
     60     self.assertShapeEqual(np_ans, tf_ans)
     61 
     62   def _compareShapeSparse(self, x_np, use_gpu=False):
     63     np_ans = np.array(np.shape(x_np))
     64     x_tf, unused_nnz = _sparsify(x_np)
     65     with self.test_session(use_gpu=use_gpu):
     66       tf_ans = array_ops.shape(x_tf)
     67       result = tf_ans.eval()
     68     self.assertAllEqual(np_ans, result)
     69     self.assertShapeEqual(np_ans, tf_ans)
     70 
     71   def _compareShapeN(self, x, use_gpu=False):
     72     np_ans = np.array(np.shape(x))
     73     with self.test_session(use_gpu=use_gpu) as sess:
     74       tf_ans = array_ops.shape_n([x, x, x])
     75       tf_ans_64 = array_ops.shape_n([x, x, x], out_type=dtypes.int64)
     76       result = sess.run(tf_ans)
     77       result_64 = sess.run(tf_ans_64)
     78     for i in range(3):
     79       self.assertAllEqual(np_ans, result[i])
     80       self.assertAllEqual(np_ans, result_64[i])
     81       self.assertShapeEqual(np_ans, tf_ans[i])
     82 
     83   def _compareRank(self, x, use_gpu=False):
     84     np_ans = np.asarray(np.ndim(x))
     85     with self.test_session(use_gpu=use_gpu):
     86       tf_ans = array_ops.rank(x)
     87       result = tf_ans.eval()
     88     self.assertAllEqual(np_ans, result)
     89     self.assertShapeEqual(np_ans, tf_ans)
     90 
     91   def _compareRankSparse(self, x_np, use_gpu=False):
     92     np_ans = np.asarray(np.ndim(x_np))
     93     x_tf, unused_nnz = _sparsify(x_np)
     94     with self.test_session(use_gpu=use_gpu):
     95       tf_ans = array_ops.rank(x_tf)
     96       result = tf_ans.eval()
     97     self.assertAllEqual(np_ans, result)
     98     self.assertShapeEqual(np_ans, tf_ans)
     99 
    100   def _compareSize(self, x, use_gpu=False):
    101     np_ans = np.asarray(np.size(x))
    102     with self.test_session(use_gpu=use_gpu):
    103       tf_ans = array_ops.size(x)
    104       result = tf_ans.eval()
    105       tf_ans_64 = array_ops.size(x, out_type=dtypes.int64)
    106       result_64 = tf_ans_64.eval()
    107     self.assertAllEqual(np_ans, result)
    108     self.assertAllEqual(np_ans, result_64)
    109     self.assertShapeEqual(np_ans, tf_ans)
    110 
    111   def _compareSizeSparse(self, x_np, use_gpu=False):
    112     np_ans = np.asarray(np.size(x_np))
    113     x_tf, unused_nnz = _sparsify(x_np)
    114     with self.test_session(use_gpu=use_gpu):
    115       tf_ans = array_ops.size(x_tf)
    116       result = tf_ans.eval()
    117     self.assertAllEqual(np_ans, result)
    118     self.assertShapeEqual(np_ans, tf_ans)
    119 
    120   def _testCpu(self, x):
    121     self._compareShape(x, use_gpu=False)
    122     self._compareShapeN(x, use_gpu=False)
    123     self._compareRank(x, use_gpu=False)
    124     self._compareSize(x, use_gpu=False)
    125     self._compareShapeSparse(x, use_gpu=False)
    126     self._compareRankSparse(x, use_gpu=False)
    127     self._compareSizeSparse(x, use_gpu=False)
    128 
    129   def _testGpu(self, x):
    130     self._compareShape(x, use_gpu=True)
    131     self._compareShapeN(x, use_gpu=True)
    132     self._compareRank(x, use_gpu=True)
    133     self._compareSize(x, use_gpu=True)
    134     self._compareShapeSparse(x, use_gpu=True)
    135     self._compareRankSparse(x, use_gpu=True)
    136     self._compareSizeSparse(x, use_gpu=True)
    137 
    138   def _testAll(self, x):
    139     self._testCpu(x)
    140     self._testGpu(x)
    141 
    142   def testBasic(self):
    143     self._testAll(np.random.randn(2))
    144     self._testAll(np.random.randn(2, 3))
    145     self._testAll(np.random.randn(2, 3, 5))
    146     self._testAll(np.random.randn(2, 3, 5, 7))
    147     self._testAll(np.random.randn(2, 3, 5, 7, 11))
    148     self._testAll(np.random.randn(2, 3, 5, 7, 11, 13))
    149 
    150   def testBool(self):
    151     self._testAll(np.random.choice((False, True), size=(2,)))
    152     self._testAll(np.random.choice((False, True), size=(2, 3)))
    153     self._testAll(np.random.choice((False, True), size=(2, 3, 5)))
    154     self._testAll(np.random.choice((False, True), size=(2, 3, 5, 7)))
    155     self._testAll(np.random.choice((False, True), size=(2, 3, 5, 7, 11)))
    156     self._testAll(np.random.choice((False, True), size=(2, 3, 5, 7, 11, 13)))
    157 
    158   # Disabled because it takes too long to run, but manually verified
    159   # as passing at time of writing.
    160   def _test64BitOutput(self):
    161     with self.test_session():
    162       inp = array_ops.zeros([2**31])
    163       num_elements = array_ops.size_internal(
    164           inp, optimize=False, out_type=dtypes.int64)
    165       self.assertEqual(2**31, num_elements.eval())
    166 
    167     # Too large for tf.int32 output.
    168     with self.assertRaises(errors_impl.InvalidArgumentError):
    169       with self.test_session():
    170         inp = array_ops.zeros([2**31])
    171         num_elements = array_ops.size_internal(
    172             inp, optimize=False, out_type=dtypes.int32)
    173         self.assertEqual(2**31, num_elements.eval())
    174 
    175   def _compareExpandDims(self, x, dim, use_gpu):
    176     np_ans = np.expand_dims(x, axis=dim)
    177     with self.test_session(use_gpu=use_gpu):
    178       tensor = array_ops.expand_dims(x, dim)
    179       tf_ans = tensor.eval()
    180     self.assertShapeEqual(np_ans, tensor)
    181     self.assertAllEqual(np_ans, tf_ans)
    182 
    183   def _compareExpandDimsAll(self, x, dim):
    184     self._compareExpandDims(x, dim, False)
    185     self._compareExpandDims(x, dim, True)
    186 
    187   def testExpandDims(self):
    188     self._compareExpandDimsAll(np.zeros([2]), 0)
    189     self._compareExpandDimsAll(np.zeros([2]), 1)
    190     self._compareExpandDimsAll(np.zeros([2]), -1)
    191 
    192     self._compareExpandDimsAll(np.zeros([2, 3]), 0)
    193     self._compareExpandDimsAll(np.zeros([2, 3]), 1)
    194     self._compareExpandDimsAll(np.zeros([2, 3]), 2)
    195     self._compareExpandDimsAll(np.zeros([2, 3]), -1)
    196     self._compareExpandDimsAll(np.zeros([2, 3]), -2)
    197 
    198     self._compareExpandDimsAll(np.zeros([2, 3, 5]), 0)
    199     self._compareExpandDimsAll(np.zeros([2, 3, 5]), 1)
    200     self._compareExpandDimsAll(np.zeros([2, 3, 5]), 2)
    201     self._compareExpandDimsAll(np.zeros([2, 3, 5]), 3)
    202 
    203     self._compareExpandDimsAll(np.zeros([2, 3, 5]), -1)
    204     self._compareExpandDimsAll(np.zeros([2, 3, 5]), -2)
    205     self._compareExpandDimsAll(np.zeros([2, 3, 5]), -3)
    206     self._compareExpandDimsAll(np.zeros([2, 3, 5]), -4)
    207 
    208   def testExpandDimsBool(self):
    209     choice = lambda s: np.random.choice((False, True), size=s)
    210     self._compareExpandDimsAll(choice([2]), 0)
    211     self._compareExpandDimsAll(choice([2]), 1)
    212     self._compareExpandDimsAll(choice([2]), -1)
    213 
    214     self._compareExpandDimsAll(choice([2, 3]), 0)
    215     self._compareExpandDimsAll(choice([2, 3]), 1)
    216     self._compareExpandDimsAll(choice([2, 3]), 2)
    217     self._compareExpandDimsAll(choice([2, 3]), -1)
    218     self._compareExpandDimsAll(choice([2, 3]), -2)
    219 
    220     self._compareExpandDimsAll(choice([2, 3, 5]), 0)
    221     self._compareExpandDimsAll(choice([2, 3, 5]), 1)
    222     self._compareExpandDimsAll(choice([2, 3, 5]), 2)
    223     self._compareExpandDimsAll(choice([2, 3, 5]), 3)
    224 
    225     self._compareExpandDimsAll(choice([2, 3, 5]), -1)
    226     self._compareExpandDimsAll(choice([2, 3, 5]), -2)
    227     self._compareExpandDimsAll(choice([2, 3, 5]), -3)
    228     self._compareExpandDimsAll(choice([2, 3, 5]), -4)
    229 
    230   def testExpandDimsErrors(self):
    231     with self.test_session():
    232       self.assertRaises(ValueError, array_ops.expand_dims,
    233                         np.zeros([2, 3, 5]), -5)
    234       self.assertRaises(ValueError, array_ops.expand_dims,
    235                         [False, True, True], -5)
    236       self.assertRaises(ValueError, array_ops.expand_dims,
    237                         np.zeros([2, 3, 5]), 4)
    238       self.assertRaises(ValueError, array_ops.expand_dims,
    239                         [False, True, True], 4)
    240 
    241   def testExpandDimsGradient(self):
    242     with self.test_session():
    243       inp = constant_op.constant(
    244           np.random.rand(4, 2).astype("f"), dtype=dtypes.float32)
    245       squeezed = array_ops.expand_dims(inp, 1)
    246 
    247       err = gradient_checker.compute_gradient_error(inp, [4, 2], squeezed,
    248                                                     [4, 1, 2])
    249     self.assertLess(err, 1e-3)
    250 
    251   def testExpandDimsScalar(self):
    252     with self.test_session():
    253       inp = constant_op.constant(7)
    254       self.assertAllEqual([7], array_ops.expand_dims(inp, 0).eval())
    255       self.assertAllEqual([7], array_ops.expand_dims(inp, -1).eval())
    256 
    257       inp = constant_op.constant(True)
    258       self.assertAllEqual([True], array_ops.expand_dims(inp, 0).eval())
    259       self.assertAllEqual([True], array_ops.expand_dims(inp, -1).eval())
    260 
    261   def testExpandDimsDimType(self):
    262     for dtype in [dtypes.int32, dtypes.int64]:
    263       x = np.zeros([2])
    264       np_ans = np.expand_dims(x, axis=0)
    265       with self.test_session(use_gpu=True):
    266         tensor = array_ops.expand_dims(x, constant_op.constant(0, dtype))
    267         tf_ans = tensor.eval()
    268       self.assertShapeEqual(np_ans, tensor)
    269       self.assertAllEqual(np_ans, tf_ans)
    270 
    271   def _compareSqueeze(self, x, squeeze_dims, use_gpu):
    272     with self.test_session(use_gpu=use_gpu):
    273       if squeeze_dims:
    274         np_ans = np.squeeze(x, axis=tuple(squeeze_dims))
    275         tensor = array_ops.squeeze(x, squeeze_dims)
    276         tf_ans = tensor.eval()
    277       else:
    278         np_ans = np.squeeze(x)
    279         tensor = array_ops.squeeze(x)
    280         tf_ans = tensor.eval()
    281     self.assertShapeEqual(np_ans, tensor)
    282     self.assertAllEqual(np_ans, tf_ans)
    283 
    284   def _compareSqueezeAll(self, x, squeeze_dims=None):
    285     if squeeze_dims is None:
    286       squeeze_dims = []
    287     self._compareSqueeze(x, squeeze_dims, False)
    288     self._compareSqueeze(x, squeeze_dims, True)
    289 
    290   def testSqueeze(self):
    291     # Nothing to squeeze.
    292     self._compareSqueezeAll(np.zeros([2]))
    293     self._compareSqueezeAll(np.zeros([2, 3]))
    294 
    295     # Squeeze the middle element away.
    296     self._compareSqueezeAll(np.zeros([2, 1, 2]))
    297 
    298     # Squeeze on both ends.
    299     self._compareSqueezeAll(np.zeros([1, 2, 1, 3, 1]))
    300 
    301   def testSqueezeBool(self):
    302     choice = lambda s: np.random.choice((False, True), size=s)
    303     # Nothing to squeeze.
    304     self._compareSqueezeAll(choice([2]))
    305     self._compareSqueezeAll(choice([2, 3]))
    306 
    307     # Squeeze the middle element away.
    308     self._compareSqueezeAll(choice([2, 1, 2]))
    309 
    310     # Squeeze on both ends.
    311     self._compareSqueezeAll(choice([1, 2, 1, 3, 1]))
    312 
    313   def testSqueezeSpecificDimension(self):
    314     # Positive squeeze dim index.
    315     self._compareSqueezeAll(np.zeros([1, 2, 1, 3, 1]), [0])
    316     self._compareSqueezeAll(np.zeros([1, 2, 1, 3, 1]), [2, 4])
    317     self._compareSqueezeAll(np.zeros([1, 2, 1, 3, 1]), [0, 4, 2])
    318 
    319     # Negative squeeze dim index.
    320     self._compareSqueezeAll(np.zeros([1, 2, 1, 3, 1]), [-1])
    321     self._compareSqueezeAll(np.zeros([1, 2, 1, 3, 1]), [-3, -5])
    322     self._compareSqueezeAll(np.zeros([1, 2, 1, 3, 1]), [-3, -5, -1])
    323 
    324   def testSqueezeSpecificDimensionBool(self):
    325     choice = lambda s: np.random.choice((False, True), size=s)
    326     # Positive squeeze dim index.
    327     self._compareSqueezeAll(choice([1, 2, 1, 3, 1]), [0])
    328     self._compareSqueezeAll(choice([1, 2, 1, 3, 1]), [2, 4])
    329     self._compareSqueezeAll(choice([1, 2, 1, 3, 1]), [0, 4, 2])
    330 
    331     # Negative squeeze dim index.
    332     self._compareSqueezeAll(choice([1, 2, 1, 3, 1]), [-1])
    333     self._compareSqueezeAll(choice([1, 2, 1, 3, 1]), [-3, -5])
    334     self._compareSqueezeAll(choice([1, 2, 1, 3, 1]), [-3, -5, -1])
    335 
    336   def testSqueezeAllOnes(self):
    337     # Numpy squeezes a 1 element tensor into a zero dimensional tensor.
    338     # Verify that we do the same.
    339     for use_gpu in [False, True]:
    340       with self.test_session(use_gpu=use_gpu):
    341         tensor = array_ops.squeeze(np.zeros([1, 1, 1]), [])
    342         self.assertEqual(np.shape(1), tensor.get_shape())
    343         tf_ans = tensor.eval()
    344         self.assertEqual(np.shape(1), tf_ans.shape)
    345 
    346   def testSqueezeAllOnesBool(self):
    347     # Numpy squeezes a 1 element tensor into a zero dimensional tensor.
    348     # Verify that we do the same.
    349     for use_gpu in [False, True]:
    350       with self.test_session(use_gpu=use_gpu):
    351         tensor = array_ops.squeeze([[[False]]], [])
    352         self.assertEqual(np.shape(1), tensor.get_shape())
    353         tf_ans = tensor.eval()
    354         self.assertEqual(np.shape(1), tf_ans.shape)
    355 
    356   def testSqueezeOnlyOnes(self):
    357     for use_gpu in [False, True]:
    358       with self.test_session(use_gpu=use_gpu):
    359         input_1x1x3 = np.zeros([1, 1, 3])
    360         self._compareSqueezeAll(input_1x1x3)
    361         self._compareSqueezeAll(input_1x1x3, [0])
    362         self._compareSqueezeAll(input_1x1x3, [1])
    363         self.assertRaises(ValueError, array_ops.squeeze, input_1x1x3, [2])
    364 
    365   def testSqueezeErrors(self):
    366     for use_gpu in [False, True]:
    367       with self.test_session(use_gpu=use_gpu):
    368         self.assertRaises(ValueError, array_ops.squeeze,
    369                           np.zeros([1, 2, 1]), [-4])
    370         self.assertRaises(ValueError, array_ops.squeeze,
    371                           np.zeros([1, 2, 1]), [0, -4])
    372         self.assertRaises(ValueError, array_ops.squeeze,
    373                           np.zeros([1, 2, 1]), [3])
    374         self.assertRaises(ValueError, array_ops.squeeze,
    375                           np.zeros([1, 2, 1]), [2, 3])
    376 
    377   def testSqueezeGradient(self):
    378     with self.test_session():
    379       inp = np.random.rand(4, 2).astype("f")
    380       a = array_ops.reshape(inp, [4, 1, 2])
    381       squeezed = array_ops.squeeze(a, [])
    382 
    383       err = gradient_checker.compute_gradient_error(a, [4, 1, 2], squeezed,
    384                                                     [4, 2])
    385     self.assertLess(err, 1e-3)
    386 
    387   def testSqueezeGradientWithSqueezeDims(self):
    388     with self.test_session():
    389       inp = np.random.rand(4, 2).astype("f")
    390       a = array_ops.reshape(inp, [4, 1, 2, 1])
    391       squeezed = array_ops.squeeze(a, [1])
    392 
    393       err = gradient_checker.compute_gradient_error(a, [4, 1, 2, 1], squeezed,
    394                                                     [4, 2, 1])
    395     self.assertLess(err, 1e-3)
    396 
    397   def testSqueezeWithUnknownShape(self):
    398     with self.test_session():
    399       a = array_ops.placeholder(dtypes.float32, shape=[2, None])
    400 
    401       squeezed = array_ops.squeeze(a, [1])
    402       self.assertEqual([2], squeezed.get_shape().as_list())
    403 
    404       squeezed = array_ops.squeeze(a)
    405       self.assertEqual(None, squeezed.get_shape())
    406 
    407       self.assertRaises(ValueError, array_ops.squeeze, a, [0])
    408       self.assertRaises(ValueError, array_ops.squeeze, a, [100])
    409 
    410 
    411 class TileTest(test.TestCase):
    412 
    413   def testScalar(self):
    414     for use_gpu in False, True:
    415       with self.test_session(use_gpu=use_gpu):
    416         a = constant_op.constant(7, shape=[], dtype=dtypes.float32)
    417         tiled = array_ops.tile(a, [])
    418         result = tiled.eval()
    419       self.assertEqual(result.shape, ())
    420       self.assertEqual([], tiled.get_shape())
    421       self.assertEqual(7, result)
    422 
    423   def testSimple(self):
    424     # multiples could be int32 or int64
    425     for dtype in [dtypes.int32, dtypes.int64]:
    426       with self.test_session(use_gpu=True):
    427         inp = np.random.rand(4, 1).astype(np.float32)
    428         a = constant_op.constant(inp)
    429         tiled = array_ops.tile(a, constant_op.constant([1, 4], dtype=dtype))
    430         result = tiled.eval()
    431       self.assertEqual(result.shape, (4, 4))
    432       self.assertEqual([4, 4], tiled.get_shape())
    433       self.assertTrue((result == np.tile(inp, (1, 4))).all())
    434 
    435   def testIdentityTileAndGrad(self):
    436     with self.test_session():
    437       inp = np.random.rand(4, 1).astype(np.float32)
    438       a = constant_op.constant(inp)
    439       tiled = array_ops.tile(a, [1, 1])
    440       result = tiled.eval()
    441     self.assertEqual(result.shape, (4, 1))
    442     self.assertEqual([4, 1], tiled.get_shape())
    443     self.assertTrue((result == np.tile(inp, (1, 1))).all())
    444 
    445   def testEmpty(self):
    446     with self.test_session():
    447       inp = np.random.rand(2, 3).astype(np.float32)
    448       a = constant_op.constant(inp)
    449       tiled = array_ops.tile(a, [5, 0])
    450       result = tiled.eval()
    451     self.assertEqual(result.shape, (10, 0))
    452     self.assertEqual([10, 0], tiled.get_shape())
    453 
    454   def testUnknownInputShape(self):
    455     """Importing can call _TileShape without shape of <multiples> known."""
    456     with self.test_session():
    457       inp = array_ops.placeholder(dtypes.float32)  # unknown shape
    458       multiples = constant_op.constant([1, 2, 3, 4], dtype=np.int32)
    459       tiled = array_ops.tile(inp, multiples)
    460       gdef = tiled.graph.as_graph_def()
    461 
    462       # Move the tile op to the start of the graph so that shapes of its inputs
    463       # are not available when the shape function runs on import.
    464       swapped = False
    465       for i, n in enumerate(gdef.node):
    466         if n.op == "Tile":
    467           # Swap tile op to be first in gdef.node
    468           assert i != 0
    469           new_node = node_def_pb2.NodeDef()
    470           new_node.CopyFrom(gdef.node[i])
    471           gdef.node[i].CopyFrom(gdef.node[0])
    472           gdef.node[0].CopyFrom(new_node)
    473           swapped = True
    474       assert swapped
    475 
    476       tiled_imported, = importer.import_graph_def(
    477           gdef, return_elements=[tiled.name])
    478       self.assertEqual(4, tiled_imported.get_shape().ndims)
    479 
    480   def testTypes(self):
    481     types_to_test = {
    482         "bool": (dtypes.bool, bool),
    483         "float32": (dtypes.float32, float),
    484         "float64": (dtypes.float64, float),
    485         "complex64": (dtypes.complex64, complex),
    486         "complex128": (dtypes.complex128, complex),
    487         "uint8": (dtypes.uint8, int),
    488         "int32": (dtypes.int32, int),
    489         "int64": (dtypes.int64, int),
    490         bytes: (dtypes.string, bytes)
    491     }
    492     for dtype_np, (dtype_tf, cast) in types_to_test.items():
    493       with self.test_session(use_gpu=True):
    494         inp = np.random.rand(4, 1).astype(dtype_np)
    495         a = constant_op.constant(
    496             [cast(x) for x in inp.ravel(order="C")],
    497             shape=[4, 1],
    498             dtype=dtype_tf)
    499         tiled = array_ops.tile(a, [1, 4])
    500         result = tiled.eval()
    501       self.assertEqual(result.shape, (4, 4))
    502       self.assertEqual([4, 4], tiled.get_shape())
    503       self.assertAllEqual(result, np.tile(inp, (1, 4)))
    504 
    505   def testInvalidDim(self):
    506     with self.test_session():
    507       inp = np.random.rand(4, 1).astype("f")
    508       a = constant_op.constant(
    509           [float(x) for x in inp.ravel(order="C")],
    510           shape=[4, 1],
    511           dtype=dtypes.float32)
    512       # Wrong length of multiples.
    513       with self.assertRaises(ValueError):
    514         array_ops.tile(a, [1, 4, 2])
    515       # Wrong rank for multiples.
    516       with self.assertRaises(ValueError):
    517         array_ops.tile(a, [[2, 3], [3, 4]]).eval()
    518 
    519   def _RunAndVerifyResult(self, rank, use_gpu):
    520     with self.test_session(use_gpu=use_gpu):
    521       # Random dims of given rank
    522       input_shape = np.random.randint(1, 4, size=rank)
    523       inp = np.random.rand(*input_shape).astype("f")
    524       a = constant_op.constant(
    525           [float(x) for x in inp.ravel(order="C")],
    526           shape=input_shape,
    527           dtype=dtypes.float32)
    528       multiples = np.random.randint(1, 4, size=rank).astype(np.int32)
    529       tiled = array_ops.tile(a, multiples)
    530       result = tiled.eval()
    531     self.assertTrue((np.array(multiples) * np.array(inp.shape) == np.array(
    532         result.shape)).all())
    533     self.assertAllEqual(result, np.tile(inp, tuple(multiples)))
    534     self.assertShapeEqual(result, tiled)
    535 
    536   def testRandom(self):
    537     # test low rank, like 5
    538     for _ in range(5):
    539       self._RunAndVerifyResult(5, use_gpu=False)
    540     for _ in range(5):
    541       self._RunAndVerifyResult(5, use_gpu=True)
    542     # test high rank, like 10
    543     for _ in range(5):
    544       self._RunAndVerifyResult(10, use_gpu=False)
    545     for _ in range(5):
    546       self._RunAndVerifyResult(10, use_gpu=True)
    547 
    548   def testGradientSimpleReduction(self):
    549     with self.test_session():
    550       inp = np.random.rand(4, 1).astype("f")
    551       a = constant_op.constant(
    552           [float(x) for x in inp.flatten()], shape=[4, 1], dtype=dtypes.float32)
    553       tiled = array_ops.tile(a, [1, 4])
    554       grad_shape = [4, 4]
    555       grad_inp = np.random.rand(*grad_shape).astype("f")
    556       grad_tensor = constant_op.constant(
    557           [float(x) for x in grad_inp.flatten()], shape=grad_shape)
    558       grad = gradients_impl.gradients([tiled], [a], [grad_tensor])[0]
    559       self.assertShapeEqual(inp, grad)
    560       result = grad.eval()
    561     self.assertAllClose(np.sum(grad_inp, axis=1).reshape(4, 1), result, 1e-3)
    562 
    563   def testGradientStridedReduction(self):
    564     with self.test_session():
    565       inp = np.random.rand(4, 2).astype("f")
    566       a = constant_op.constant(
    567           [float(x) for x in inp.flatten()], shape=[4, 2], dtype=dtypes.float32)
    568       tiled = array_ops.tile(a, [1, 2])
    569       grad_shape = [4, 4]
    570       grad_inp = np.random.rand(*grad_shape).astype("f")
    571       grad_tensor = constant_op.constant(
    572           [float(x) for x in grad_inp.flatten()], shape=grad_shape)
    573       grad = gradients_impl.gradients([tiled], [a], [grad_tensor])[0]
    574       self.assertShapeEqual(inp, grad)
    575       result = grad.eval()
    576     expected_shape = [4, 2]
    577     expected = np.zeros(expected_shape)
    578     expected[:, 0] = grad_inp[:, 0] + grad_inp[:, 2]
    579     expected[:, 1] = grad_inp[:, 1] + grad_inp[:, 3]
    580     self.assertTrue((np.abs(expected - result) < 1e-3).all())
    581 
    582   def testGradientSimpleReductionOnGPU(self):
    583     with self.test_session(use_gpu=True):
    584       inp = np.random.rand(4, 1).astype("f")
    585       a = constant_op.constant(
    586           [float(x) for x in inp.flatten()], shape=[4, 1], dtype=dtypes.float32)
    587       tiled = array_ops.tile(a, [1, 4])
    588       grad_shape = [4, 4]
    589       grad_inp = np.random.rand(*grad_shape).astype("f")
    590       grad_tensor = constant_op.constant(
    591           [float(x) for x in grad_inp.flatten()], shape=grad_shape)
    592       grad = gradients_impl.gradients([tiled], [a], [grad_tensor])[0]
    593       result = grad.eval()
    594     self.assertAllClose(np.sum(grad_inp, axis=1).reshape(4, 1), result, 1e-3)
    595 
    596   def testGradientStridedReductionOnGPU(self):
    597     with self.test_session(use_gpu=True):
    598       inp = np.random.rand(4, 2).astype("f")
    599       a = constant_op.constant(
    600           [float(x) for x in inp.flatten()], shape=[4, 2], dtype=dtypes.float32)
    601       tiled = array_ops.tile(a, [1, 2])
    602       grad_shape = [4, 4]
    603       grad_inp = np.random.rand(*grad_shape).astype("f")
    604       grad_tensor = constant_op.constant(
    605           [float(x) for x in grad_inp.flatten()], shape=grad_shape)
    606       grad = gradients_impl.gradients([tiled], [a], [grad_tensor])[0]
    607       result = grad.eval()
    608     expected_shape = [4, 2]
    609     expected = np.zeros(expected_shape)
    610     expected[:, 0] = grad_inp[:, 0] + grad_inp[:, 2]
    611     expected[:, 1] = grad_inp[:, 1] + grad_inp[:, 3]
    612     self.assertAllClose(expected, result, 1e-3)
    613 
    614   def _RunAndVerifyGradientResult(self, input_shape, multiples):
    615     for use_gpu in False, True:
    616       with self.test_session(use_gpu=use_gpu):
    617         # Random values
    618         inp = np.asarray(np.random.rand(*input_shape))
    619         a = constant_op.constant(inp, dtype=dtypes.float64)
    620         tiled = array_ops.tile(a, multiples)
    621         grad_shape = list(np.array(multiples) * np.array(inp.shape))
    622         err = gradient_checker.compute_gradient_error(
    623             a, list(input_shape), tiled, grad_shape, x_init_value=inp)
    624       print("tile(float) error = ", err)
    625       self.assertLess(err, 1e-3)
    626 
    627   def testGradientRandomScalar(self):
    628     self._RunAndVerifyGradientResult([], [])
    629 
    630   def testGradientRandom(self):
    631     self._RunAndVerifyGradientResult([2, 2, 1, 1, 3], [1, 1, 1, 1, 1])
    632     self._RunAndVerifyGradientResult([2, 2, 1, 1, 3], [1, 2, 1, 3, 1])
    633     self._RunAndVerifyGradientResult([2, 3, 1, 1, 3], [3, 1, 1, 2, 2])
    634     self._RunAndVerifyGradientResult([2, 1, 3, 3, 2], [1, 3, 3, 1, 2])
    635 
    636   def testGradientStridedReductionGC(self):
    637     with self.test_session():
    638       inp = np.random.rand(4, 2).astype("f")
    639       a = constant_op.constant(
    640           [float(x) for x in inp.flatten()], shape=[4, 2], dtype=dtypes.float32)
    641       tiled = array_ops.tile(a, [1, 2])
    642       err = gradient_checker.compute_gradient_error(a, [4, 2], tiled, [4, 4])
    643     self.assertLess(err, 1e-3)
    644 
    645   def testShapeFunctionEdgeCases(self):
    646     # Unknown multiples shape.
    647     inp = constant_op.constant(0.0, shape=[4, 4, 4, 4])
    648     tiled = array_ops.tile(inp, array_ops.placeholder(dtypes.int32))
    649     self.assertEqual([None, None, None, None], tiled.get_shape().as_list())
    650 
    651     # Unknown input shape.
    652     inp = array_ops.placeholder(dtypes.float32)
    653     tiled = array_ops.tile(inp, [2, 2, 2, 2])
    654     self.assertEqual([None, None, None, None], tiled.get_shape().as_list())
    655 
    656     # Unknown input and multiples shape.
    657     inp = array_ops.placeholder(dtypes.float32)
    658     tiled = array_ops.tile(inp, array_ops.placeholder(dtypes.int32))
    659     self.assertIs(None, tiled.get_shape().ndims)
    660 
    661     # Known input and partially known multiples.
    662     inp = constant_op.constant(0.0, shape=[1, 1])
    663     tiled = array_ops.tile(inp, [array_ops.placeholder(dtypes.int32), 7])
    664     self.assertEqual([None, 7], tiled.get_shape().as_list())
    665 
    666     # Mismatched input rank and multiples length.
    667     inp = array_ops.placeholder(dtypes.float32, shape=[None, None])
    668     with self.assertRaises(ValueError):
    669       tiled = array_ops.tile(
    670           inp, array_ops.placeholder(
    671               dtypes.int32, shape=[3]))
    672 
    673 
    674 if __name__ == "__main__":
    675   test.main()
    676