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