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 array_ops.""" 16from __future__ import absolute_import 17from __future__ import division 18from __future__ import print_function 19 20import re 21import time 22import unittest 23 24import numpy as np 25 26from tensorflow.python.client import session 27from tensorflow.python.eager import context 28from tensorflow.python.eager import def_function 29from tensorflow.python.framework import constant_op 30from tensorflow.python.framework import dtypes 31from tensorflow.python.framework import errors 32from tensorflow.python.framework import errors_impl 33from tensorflow.python.framework import ops 34from tensorflow.python.framework import sparse_tensor 35from tensorflow.python.framework import tensor_shape 36from tensorflow.python.framework import tensor_spec 37from tensorflow.python.framework import test_ops 38from tensorflow.python.framework import test_util 39from tensorflow.python.ops import array_ops 40from tensorflow.python.ops import gen_array_ops 41from tensorflow.python.ops import gradients_impl 42from tensorflow.python.ops import init_ops 43from tensorflow.python.ops import math_ops 44from tensorflow.python.ops import resource_variable_ops 45from tensorflow.python.ops import state_ops 46from tensorflow.python.ops import variable_scope 47from tensorflow.python.ops import variables 48from tensorflow.python.platform import test as test_lib 49 50 51@test_util.run_all_in_graph_and_eager_modes 52class BatchMatrixTransposeTest(test_util.TensorFlowTestCase): 53 54 def testNonBatchMatrix(self): 55 matrix = [[1, 2, 3], [4, 5, 6]] # Shape (2, 3) 56 expected_transposed = [[1, 4], [2, 5], [3, 6]] # Shape (3, 2) 57 transposed = array_ops.matrix_transpose(matrix) 58 self.assertEqual((3, 2), transposed.get_shape()) 59 self.assertAllEqual(expected_transposed, transposed) 60 61 def testConjugate(self): 62 m = [[1 + 1j, 2 + 2j, 3 + 3j], [4 + 4j, 5 + 5j, 6 + 6j]] 63 expected_transposed = [[1 - 1j, 4 - 4j], [2 - 2j, 5 - 5j], [3 - 3j, 6 - 6j]] 64 matrix = ops.convert_to_tensor(m) 65 transposed = array_ops.matrix_transpose(matrix, conjugate=True) 66 self.assertEqual((3, 2), transposed.get_shape()) 67 self.assertAllEqual(expected_transposed, transposed) 68 69 def testBatchMatrix(self): 70 matrix_0 = [[1, 2, 3], [4, 5, 6]] 71 matrix_0_t = [[1, 4], [2, 5], [3, 6]] 72 matrix_1 = [[11, 22, 33], [44, 55, 66]] 73 matrix_1_t = [[11, 44], [22, 55], [33, 66]] 74 batch_matrix = [matrix_0, matrix_1] # Shape (2, 2, 3) 75 expected_transposed = [matrix_0_t, matrix_1_t] # Shape (2, 3, 2) 76 transposed = array_ops.matrix_transpose(batch_matrix) 77 self.assertEqual((2, 3, 2), transposed.get_shape()) 78 self.assertAllEqual(expected_transposed, transposed) 79 80 def testNonBatchMatrixDynamicallyDefined(self): 81 # needs explicit `constant` because lists are not automatically 82 # converted to sensors when applying `transpose` below 83 matrix = constant_op.constant([[1, 2, 3], [4, 5, 6]]) # Shape (2, 3) 84 expected_transposed = [[1, 4], [2, 5], [3, 6]] # Shape (3, 2) 85 @def_function.function(input_signature= 86 [tensor_spec.TensorSpec 87 (shape=None, dtype=dtypes.int32)]) 88 def transpose(matrix): 89 self.assertIs(matrix.shape.ndims, None) 90 return array_ops.matrix_transpose(matrix) 91 self.assertAllEqual(expected_transposed, transpose(matrix)) 92 93 def testBatchMatrixDynamicallyDefined(self): 94 matrix_0 = [[1, 2, 3], [4, 5, 6]] 95 matrix_0_t = [[1, 4], [2, 5], [3, 6]] 96 matrix_1 = [[11, 22, 33], [44, 55, 66]] 97 matrix_1_t = [[11, 44], [22, 55], [33, 66]] 98 # needs explicit `constant` because lists are not automatically 99 # converted to sensors when applying `transpose` below 100 batch_matrix = constant_op.constant([matrix_0, matrix_1]) # Shape (2, 2, 3) 101 expected_transposed = [matrix_0_t, matrix_1_t] # Shape (2, 3, 2) 102 @def_function.function(input_signature= 103 [tensor_spec.TensorSpec 104 (shape=None, dtype=dtypes.int32)]) 105 def transpose(matrix): 106 self.assertIs(matrix.shape.ndims, None) 107 return array_ops.matrix_transpose(matrix) 108 self.assertAllEqual(expected_transposed, transpose(batch_matrix)) 109 110 def testTensorWithStaticRankLessThanTwoRaisesBecauseNotAMatrix(self): 111 vector = [1, 2, 3] 112 with self.assertRaisesRegexp(ValueError, "should be a "): 113 array_ops.matrix_transpose(vector) 114 115 116class BooleanMaskTest(test_util.TensorFlowTestCase): 117 118 def setUp(self): 119 self.rng = np.random.RandomState(42) 120 121 def CheckVersusNumpy(self, ndims_mask, arr_shape, make_mask=None, axis=None): 122 """Check equivalence between boolean_mask and numpy masking.""" 123 if make_mask is None: 124 make_mask = lambda shape: self.rng.randint(0, 2, size=shape).astype(bool) 125 arr = np.random.rand(*arr_shape) 126 mask = make_mask(arr_shape[:ndims_mask]) 127 if axis is not None: 128 mask = make_mask(arr_shape[axis:ndims_mask + axis]) 129 if axis is None or axis == 0: 130 masked_arr = arr[mask] 131 elif axis == 1: 132 masked_arr = arr[:, mask] 133 elif axis == 2: 134 masked_arr = arr[:, :, mask] 135 with self.cached_session(): 136 masked_tensor = array_ops.boolean_mask(arr, mask, axis=axis) 137 138 # Leading dimension size of masked_tensor is always unknown until runtime 139 # since we don't how many elements will be kept. 140 leading = 1 if axis is None else axis + 1 141 self.assertAllEqual(masked_tensor.get_shape()[leading:], 142 masked_arr.shape[leading:]) 143 144 self.assertAllClose(masked_arr, masked_tensor.eval()) 145 146 @test_util.run_deprecated_v1 147 def testMaskDim1ArrDim2Axis1(self): 148 ndims_mask = 1 149 for arr_shape in [(1, 1), (2, 2), (2, 5)]: 150 self.CheckVersusNumpy(ndims_mask, arr_shape, axis=1) 151 152 @test_util.run_deprecated_v1 153 def testMaskDim2ArrDim2Axis1(self): 154 ndims_mask = 2 155 for arr_shape in [(1, 1), (2, 2), (2, 5)]: 156 self.CheckVersusNumpy(ndims_mask, arr_shape, axis=1) 157 158 @test_util.run_deprecated_v1 159 def testMaskDim1ArrDim1(self): 160 ndims_mask = 1 161 for arr_shape in [(1,), (2,), (3,), (10,)]: 162 self.CheckVersusNumpy(ndims_mask, arr_shape) 163 164 @test_util.run_deprecated_v1 165 def testMaskDim1ArrDim2(self): 166 ndims_mask = 1 167 for arr_shape in [(1, 1), (2, 2), (2, 5)]: 168 self.CheckVersusNumpy(ndims_mask, arr_shape) 169 170 @test_util.run_deprecated_v1 171 def testMaskDim2ArrDim2(self): 172 ndims_mask = 2 173 for arr_shape in [(1, 1), (2, 2), (2, 5)]: 174 self.CheckVersusNumpy(ndims_mask, arr_shape) 175 176 @test_util.run_deprecated_v1 177 def testMaskDim2ArrDim3(self): 178 ndims_mask = 2 179 for arr_shape in [(1, 1, 1), (1, 2, 2), (2, 2, 1)]: 180 self.CheckVersusNumpy(ndims_mask, arr_shape) 181 182 @test_util.run_deprecated_v1 183 def testEmptyInput2D(self): 184 mask = np.array([True, False]) 185 arr = np.array([[], []]).astype(np.float32) 186 numpy_result = arr[mask] 187 tf_result = array_ops.boolean_mask(arr, mask) 188 self.assertAllEqual(numpy_result.shape[1:], tf_result.get_shape()[1:]) 189 with self.cached_session(): 190 self.assertAllClose(numpy_result, tf_result.eval()) 191 192 def testEmptyInput1D(self): 193 mask = np.array([]).astype(bool) 194 arr = np.array([]).astype(np.float32) 195 numpy_result = arr[mask] 196 tf_result = array_ops.boolean_mask(arr, mask) 197 self.assertAllEqual(numpy_result.shape[1:], tf_result.get_shape()[1:]) 198 with self.cached_session(): 199 self.assertAllClose(numpy_result, tf_result.eval()) 200 201 @test_util.run_deprecated_v1 202 def testEmptyOutput(self): 203 make_mask = lambda shape: np.zeros(shape, dtype=bool) 204 for ndims_mask in range(1, 4): 205 for ndims_arr in range(ndims_mask, ndims_mask + 3): 206 for _ in range(3): 207 arr_shape = np.random.randint(1, 5, size=ndims_arr) 208 self.CheckVersusNumpy(ndims_mask, arr_shape, make_mask=make_mask) 209 210 @test_util.run_deprecated_v1 211 def testWorksWithDimensionsEqualToNoneDuringGraphBuild(self): 212 # The rank of the mask tensor must be specified. This is explained 213 # in the docstring as well. 214 with self.cached_session() as sess: 215 ph_tensor = array_ops.placeholder(dtypes.int32, shape=None) 216 ph_mask = array_ops.placeholder(dtypes.bool, shape=[None]) 217 218 arr = np.array([[1, 2], [3, 4]]) 219 mask = np.array([False, True]) 220 221 masked_tensor = sess.run( 222 array_ops.boolean_mask(ph_tensor, ph_mask), 223 feed_dict={ 224 ph_tensor: arr, 225 ph_mask: mask 226 }) 227 np.testing.assert_allclose(masked_tensor, arr[mask]) 228 229 @test_util.run_deprecated_v1 230 def testMaskDimensionsSetToNoneRaises(self): 231 # The rank of the mask tensor must be specified. This is explained 232 # in the docstring as well. 233 with self.cached_session(): 234 tensor = array_ops.placeholder(dtypes.int32, shape=[None, 2]) 235 mask = array_ops.placeholder(dtypes.bool, shape=None) 236 with self.assertRaisesRegexp(ValueError, "dimensions must be specified"): 237 array_ops.boolean_mask(tensor, mask) 238 239 def testMaskHasMoreDimsThanTensorRaises(self): 240 mask = [[True, True], [False, False]] 241 tensor = [1, 2, 3, 4] 242 with self.cached_session(): 243 with self.assertRaisesRegexp(ValueError, "incompatible"): 244 array_ops.boolean_mask(tensor, mask).eval() 245 246 def testMaskIsScalarRaises(self): 247 mask = True 248 tensor = 1 249 with self.cached_session(): 250 with self.assertRaisesRegexp(ValueError, "mask.*scalar"): 251 array_ops.boolean_mask(tensor, mask).eval() 252 253 def testMaskShapeDifferentThanFirstPartOfTensorShapeRaises(self): 254 mask = [True, True, True] 255 tensor = [[1, 2], [3, 4]] 256 with self.cached_session(): 257 with self.assertRaisesRegexp(ValueError, "incompatible"): 258 array_ops.boolean_mask(tensor, mask).eval() 259 260 261@test_util.run_all_in_graph_and_eager_modes 262class OperatorShapeTest(test_util.TensorFlowTestCase): 263 264 def testExpandScalar(self): 265 scalar = "hello" 266 scalar_expanded = array_ops.expand_dims(scalar, [0]) 267 self.assertEqual(scalar_expanded.get_shape(), (1,)) 268 269 def testSqueezeScalar(self): 270 scalar = "hello" 271 scalar_squeezed = array_ops.squeeze(scalar, ()) 272 self.assertEqual(scalar_squeezed.get_shape(), ()) 273 274 def testSqueezeMatrix(self): 275 matrix = [[1, 2, 3]] 276 matrix_squeezed = array_ops.squeeze(matrix, [0]) 277 self.assertEqual(matrix_squeezed.get_shape(), (3)) 278 279 with self.assertRaisesRegexp( 280 Exception, "Can not squeeze dim.1., expected a dimension of 1, got 3"): 281 matrix_squeezed = array_ops.squeeze(matrix, [1]) 282 283 def testSqueezeScalarDim(self): 284 matrix = [[1, 2, 3]] 285 matrix_squeezed = array_ops.squeeze(matrix, 0) 286 self.assertEqual(matrix_squeezed.get_shape(), (3)) 287 288 def testExpandDimsWithNonScalarDim(self): 289 with self.assertRaisesRegexp(Exception, 290 "must be a tensor with a single value"): 291 array_ops.expand_dims(1, axis=[0, 1]) 292 293 294class ReverseV2Test(test_util.TensorFlowTestCase): 295 296 @test_util.run_deprecated_v1 297 def testReverse0DimAuto(self): 298 x_np = 4 299 for use_gpu in [False, True]: 300 with self.cached_session(use_gpu=use_gpu): 301 x_tf = array_ops.reverse_v2(x_np, []).eval() 302 self.assertAllEqual(x_tf, x_np) 303 304 def _reverse1DimAuto(self, np_dtype): 305 x_np = np.array([1, 200, 3, 40, 5], dtype=np_dtype) 306 307 for use_gpu in [False, True]: 308 for axis_dtype in [dtypes.int32, dtypes.int64]: 309 with self.cached_session(use_gpu=use_gpu): 310 x_tf = array_ops.reverse_v2(x_np, 311 constant_op.constant( 312 [0], dtype=axis_dtype)).eval() 313 self.assertAllEqual(x_tf, np.asarray(x_np)[::-1]) 314 315 def _reverse2DimAuto(self, np_dtype): 316 x_np = np.array([[1, 200, 3], [4, 5, 60]], dtype=np_dtype) 317 318 for reverse_f in [array_ops.reverse_v2, array_ops.reverse]: 319 for use_gpu in [False, True]: 320 for axis_dtype in [dtypes.int32, dtypes.int64]: 321 with self.cached_session(use_gpu=use_gpu): 322 x_tf_1 = reverse_f(x_np, constant_op.constant( 323 [0], dtype=axis_dtype)).eval() 324 x_tf_2 = reverse_f(x_np, constant_op.constant( 325 [-2], dtype=axis_dtype)).eval() 326 x_tf_3 = reverse_f(x_np, constant_op.constant( 327 [1], dtype=axis_dtype)).eval() 328 x_tf_4 = reverse_f(x_np, constant_op.constant( 329 [-1], dtype=axis_dtype)).eval() 330 x_tf_5 = reverse_f(x_np, 331 constant_op.constant([1, 0], 332 dtype=axis_dtype)).eval() 333 self.assertAllEqual(x_tf_1, np.asarray(x_np)[::-1, :]) 334 self.assertAllEqual(x_tf_2, np.asarray(x_np)[::-1, :]) 335 self.assertAllEqual(x_tf_3, np.asarray(x_np)[:, ::-1]) 336 self.assertAllEqual(x_tf_4, np.asarray(x_np)[:, ::-1]) 337 self.assertAllEqual(x_tf_5, np.asarray(x_np)[::-1, ::-1]) 338 339 # This test covers the axis validation in the shape function 340 # (no eval()) 341 @test_util.run_deprecated_v1 342 def testInvalidAxis(self): 343 x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32) 344 with self.assertRaisesRegexp(ValueError, 345 "is out of valid range"): 346 array_ops.reverse_v2(x_np, [-30]) 347 with self.assertRaisesRegexp(ValueError, 348 "is out of valid range"): 349 array_ops.reverse_v2(x_np, [2]) 350 with self.assertRaisesRegexp(ValueError, 351 "axis 0 specified more than once"): 352 array_ops.reverse_v2(x_np, [0, -2]) 353 354 # This is the version of reverse that uses axis indices rather than 355 # bool tensors 356 # TODO(b/32254538): Change this test to use array_ops.reverse 357 # 358 # Note: this test passes placeholder as constant axis is validated 359 # in shape function (see testInvalidAxis) 360 @test_util.run_deprecated_v1 361 def testInvalid(self): 362 x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32) 363 axis = array_ops.placeholder(dtypes.int32) 364 with self.cached_session(): 365 with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, 366 "is out of valid range"): 367 array_ops.reverse_v2(x_np, axis).eval(feed_dict={axis: [-30]}) 368 with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, 369 "is out of valid range"): 370 array_ops.reverse_v2(x_np, axis).eval(feed_dict={axis: [2]}) 371 with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, 372 "axis 0 specified more than once"): 373 array_ops.reverse_v2(x_np, axis).eval(feed_dict={axis: [0, -2]}) 374 375 @test_util.run_deprecated_v1 376 def testReverse1DimAuto(self): 377 for dtype in [ 378 np.uint8, np.int8, np.uint16, np.int16, np.int32, np.int64, np.bool, 379 np.float16, np.float32, np.float64, np.complex64, np.complex128, 380 np.array(b"").dtype.type 381 ]: 382 self._reverse1DimAuto(dtype) 383 384 @test_util.run_deprecated_v1 385 def testReverse2DimAuto(self): 386 for dtype in [ 387 np.uint8, np.int8, np.uint16, np.int16, np.int32, np.int64, np.bool, 388 np.float16, np.float32, np.float64, np.complex64, np.complex128, 389 np.array(b"").dtype.type 390 ]: 391 self._reverse2DimAuto(dtype) 392 393 @test_util.run_deprecated_v1 394 def testUnknownDims(self): 395 reverse_v2 = array_ops.reverse_v2 396 data_t = array_ops.placeholder(dtypes.float32) 397 axis_known_t = array_ops.placeholder(dtypes.int32, shape=[3]) 398 reverse_known_t = reverse_v2(data_t, axis_known_t) 399 # Unlike V1 we cannot know this anymore 400 self.assertEqual(None, reverse_known_t.get_shape().ndims) 401 402 axis_unknown_t = array_ops.placeholder(dtypes.int32) 403 reverse_unknown_t = reverse_v2(data_t, axis_unknown_t) 404 self.assertIs(None, reverse_unknown_t.get_shape().ndims) 405 406 data_2d_t = array_ops.placeholder(dtypes.float32, shape=[None, None]) 407 axis_2d_t = array_ops.placeholder(dtypes.int32, shape=[3]) 408 reverse_2d_t = reverse_v2(data_2d_t, axis_2d_t) 409 self.assertEqual(2, reverse_2d_t.get_shape().ndims) 410 411 @test_util.run_deprecated_v1 412 def testReverseRowsOf3Channels(self): 413 """Tests optimized code for reversing rows with last dim size = 3.""" 414 with self.session(use_gpu=True): 415 for reverse_f in [array_ops.reverse_v2, array_ops.reverse]: 416 for outer_size in (1, 2): 417 for middle_size in list(range(50)) + [100000]: 418 x_np = np.reshape( 419 np.arange(outer_size * middle_size * 3, dtype=np.float32), 420 newshape=(outer_size, middle_size, 3)) 421 x_tf = reverse_f(x_np, [1]).eval() 422 np_answer = x_np[:, ::-1, :] 423 self.assertAllEqual(x_tf, np_answer) 424 425 @test_util.run_deprecated_v1 426 def testReverseRowsOf4Channels(self): 427 with self.session(use_gpu=True): 428 for reverse_f in [array_ops.reverse_v2, array_ops.reverse]: 429 for outer_size in (1, 2): 430 for middle_size in list(range(50)) + [100000]: 431 x_np = np.reshape( 432 np.arange(outer_size * middle_size * 4, dtype=np.float32), 433 newshape=(outer_size, middle_size, 4)) 434 x_tf = reverse_f(x_np, [1]).eval() 435 np_answer = x_np[:, ::-1, :] 436 self.assertAllEqual(x_tf, np_answer) 437 438 def testReverseColumnsOf3Channels(self): 439 with self.session(use_gpu=True): 440 for reverse_f in [array_ops.reverse_v2, array_ops.reverse]: 441 for outer_size in list(range(50)) + [100000]: 442 for middle_size in (1, 2): 443 x_np = np.reshape( 444 np.arange(outer_size * middle_size * 3, dtype=np.float32), 445 newshape=(outer_size, middle_size, 3)) 446 x_tf = reverse_f(x_np, [0]).eval() 447 np_answer = x_np[::-1, :, :] 448 self.assertAllEqual(x_tf, np_answer) 449 450 451class MeshgridTest(test_util.TensorFlowTestCase): 452 453 def _compareDiff(self, x, y, use_gpu): 454 for index in ("ij", "xy"): 455 numpy_out = np.meshgrid(x, y, indexing=index) 456 tf_out = array_ops.meshgrid(x, y, indexing=index) 457 with self.cached_session(use_gpu=use_gpu): 458 for xx, yy in zip(numpy_out, tf_out): 459 self.assertAllEqual(xx, yy.eval()) 460 461 def _compareDiffType(self, n, np_dtype, use_gpu): 462 inputs = [] 463 for index in ("ij", "xy"): 464 for _ in range(n): 465 x = np.linspace(-10, 10, 5).astype(np_dtype) 466 if np_dtype in (np.complex64, np.complex128): 467 x += 1j 468 inputs.append(x) 469 numpy_out = np.meshgrid(*inputs, indexing=index) 470 with self.cached_session(use_gpu=use_gpu): 471 tf_out = array_ops.meshgrid(*inputs, indexing=index) 472 for x_np, x_tf in zip(numpy_out, tf_out): 473 self.assertAllEqual(x_np, x_tf.eval()) 474 475 @test_util.run_deprecated_v1 476 def testCompare(self): 477 for t in (np.float16, np.float32, np.float64, np.int32, np.int64, 478 np.complex64, np.complex128): 479 self._compareDiffType(2, t, False) 480 self._compareDiffType(3, t, False) 481 482 x = [1, 2, 3] 483 y = [4, 5] 484 485 a = [[1, 1], [1, 1]] 486 487 self._compareDiff(x, y, False) 488 self._compareDiff(x, a, False) 489 490 491class StridedSliceChecker(object): 492 """Check a given tensor against the numpy result.""" 493 494 REF_TENSOR = np.arange(1, 19, dtype=np.float32).reshape(3, 2, 3) 495 REF_TENSOR_ALIGNED = np.arange(1, 97, dtype=np.float32).reshape(3, 4, 8) 496 497 def __init__(self, test, x, tensor_type=dtypes.int32, check_type_infer=True): 498 self.x_np = np.array(x).astype(tensor_type.as_numpy_dtype) 499 if tensor_type.is_bool: 500 self.x_np = np.array(x % 3).astype(np.bool) 501 # Give the value a non-zero imaginary component for complex types. 502 if tensor_type.is_complex: 503 self.x_np -= 1j * self.x_np 504 self.test = test 505 self.x = constant_op.constant(self.x_np, dtype=tensor_type) 506 self.check_type_infer = check_type_infer 507 508 def __getitem__(self, spec): 509 op = self.x.__getitem__(spec) 510 511 def eval_if_tensor(x): 512 try: 513 return x.eval() 514 except AttributeError: 515 return x 516 517 if isinstance(spec, bool) or \ 518 (isinstance(spec, ops.Tensor) and spec.dtype == dtypes.bool) or \ 519 (isinstance(spec, np.ndarray) and spec.dtype == bool) or \ 520 (isinstance(spec, (list, tuple)) and np.asarray(spec).dtype == bool): 521 tensor = op.eval() 522 np_spec = eval_if_tensor(spec) 523 self.test.assertAllEqual(self.x_np[np_spec], tensor) 524 return tensor 525 526 if not isinstance(spec, (list, tuple)): 527 spec = [spec] 528 529 tensor = op.eval() 530 531 # Make a numpy spec that pre-evals the tensors 532 np_specs = [] 533 534 for s in spec: 535 if isinstance(s, slice): 536 start = eval_if_tensor(s.start) 537 stop = eval_if_tensor(s.stop) 538 step = eval_if_tensor(s.step) 539 np_specs.append(slice(start, stop, step)) 540 else: 541 np_specs.append(eval_if_tensor(s)) 542 543 self.test.assertAllEqual(self.x_np[tuple(np_specs)], tensor) 544 if self.check_type_infer: 545 self.test.assertAllEqual(tensor.shape, op.get_shape()) 546 return tensor 547 548 549STRIDED_SLICE_TYPES = [ 550 dtypes.int32, dtypes.int64, dtypes.int16, dtypes.int8, dtypes.float32, 551 dtypes.float64, dtypes.complex64, dtypes.complex128, dtypes.bool 552] 553 554 555class StridedSliceTest(test_util.TensorFlowTestCase): 556 """Test the strided slice operation with variants of slices.""" 557 558 @test_util.run_deprecated_v1 559 def test_basic_slice(self): 560 for tensor_type in STRIDED_SLICE_TYPES: 561 with self.cached_session(use_gpu=True): 562 checker = StridedSliceChecker( 563 self, StridedSliceChecker.REF_TENSOR, tensor_type=tensor_type) 564 _ = checker[:, :, :] 565 # Various ways of representing identity slice 566 _ = checker[:, :, :] 567 _ = checker[::, ::, ::] 568 _ = checker[::1, ::1, ::1] 569 # Not zero slice 570 _ = checker[::1, ::5, ::2] 571 # Reverse in each dimension independently 572 _ = checker[::-1, :, :] 573 _ = checker[:, ::-1, :] 574 _ = checker[:, :, ::-1] 575 ## negative index tests i.e. n-2 in first component 576 _ = checker[-2::-1, :, ::1] 577 # negative index tests i.e. n-2 in first component, non-unit stride 578 _ = checker[-2::-1, :, ::2] 579 580 # Check rank-0 examples 581 checker2 = StridedSliceChecker(self, 5, tensor_type=tensor_type) 582 _ = checker2[None] 583 _ = checker2[...] 584 _ = checker2[tuple()] 585 586 def testInt64GPU(self): 587 if not test_util.is_gpu_available(): 588 self.skipTest("No GPU available") 589 590 with test_util.force_gpu(): 591 x = constant_op.constant([1., 2., 3.]) 592 begin = constant_op.constant([2], dtype=dtypes.int64) 593 end = constant_op.constant([3], dtype=dtypes.int64) 594 strides = constant_op.constant([1], dtype=dtypes.int64) 595 s = array_ops.strided_slice(x, begin, end, strides) 596 self.assertAllEqual([3.], self.evaluate(s)) 597 598 @test_util.assert_no_new_pyobjects_executing_eagerly 599 @test_util.assert_no_garbage_created 600 def testTensorSliceEagerMemory(self): 601 with context.eager_mode(): 602 inputs = constant_op.constant( 603 [[[1], [2], [3], [4]]], dtype=dtypes.float32) 604 # Tests that slicing an EagerTensor doesn't leak memory 605 inputs[0] # pylint: disable=pointless-statement 606 607 @test_util.assert_no_new_pyobjects_executing_eagerly 608 @test_util.assert_no_garbage_created 609 def testVariableSliceEagerMemory(self): 610 with context.eager_mode(): 611 v = variables.Variable([1., 2.]) 612 v[0] # pylint: disable=pointless-statement 613 614 @test_util.run_deprecated_v1 615 def testDegenerateSlices(self): 616 with self.session(use_gpu=True): 617 checker = StridedSliceChecker(self, StridedSliceChecker.REF_TENSOR) 618 # degenerate by offering a forward interval with a negative stride 619 _ = checker[0:-1:-1, :, :] 620 # degenerate with a reverse interval with a positive stride 621 _ = checker[-1:0, :, :] 622 # empty interval in every dimension 623 _ = checker[-1:0, 2:2, 2:3:-1] 624 # empty first dimension only (used to break for aligned tensors). 625 checker = StridedSliceChecker(self, 626 StridedSliceChecker.REF_TENSOR_ALIGNED) 627 _ = checker[1:0] 628 629 @test_util.run_deprecated_v1 630 def testEllipsis(self): 631 with self.session(use_gpu=True): 632 raw = [[[[[1, 2], [3, 4], [5, 6]]], [[[7, 8], [9, 10], [11, 12]]]]] 633 checker = StridedSliceChecker(self, raw) 634 635 _ = checker[0:] 636 # implicit ellipsis 637 _ = checker[0:, ...] 638 # ellipsis alone 639 _ = checker[...] 640 # ellipsis at end 641 _ = checker[0:1, ...] 642 # ellipsis at begin 643 _ = checker[..., 0:1] 644 # ellipsis at middle 645 _ = checker[0:1, ..., 0:1] 646 # multiple ellipses not allowed 647 with self.assertRaisesRegexp(ValueError, "Multiple ellipses"): 648 _ = checker[..., :, ...].eval() 649 650 @test_util.run_deprecated_v1 651 def testShrink(self): 652 with self.session(use_gpu=True): 653 raw = [[[[[1, 2, 4, 5], [5, 6, 7, 8], [9, 10, 11, 12]]], 654 [[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]]]] 655 checker = StridedSliceChecker(self, raw) 656 _ = checker[:, :, :, :, 3] 657 _ = checker[..., 3] 658 _ = checker[:, 0] 659 _ = checker[:, :, 0] 660 661 @test_util.run_deprecated_v1 662 def testBothNewAxisAndShrink(self): 663 with self.session(use_gpu=True): 664 ones = array_ops.placeholder(shape=[2, 2], dtype=dtypes.int16) 665 self.assertAllEqual( 666 ones[array_ops.newaxis, :, 0].eval( 667 feed_dict={ones: [[1, 1], [1, 1]]}), 668 [[1, 1]]) 669 670 @test_util.run_deprecated_v1 671 def testTensorIndexing(self): 672 with self.session(use_gpu=True): 673 raw = [[[[[1, 2, 4, 5], [5, 6, 7, 8], [9, 10, 11, 12]]], 674 [[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]]]] 675 checker = StridedSliceChecker(self, raw, check_type_infer=False) 676 bar = constant_op.constant(2) 677 bar2 = constant_op.constant(3) 678 _ = checker[..., bar:bar2] 679 _ = checker[..., bar] 680 _ = checker[..., 3] 681 _ = checker[..., 2 ** 64 // 2**63] # Test longs in Python 2 682 683 def testTensorIndexingTypeError(self): 684 with self.session(use_gpu=True): 685 checker = StridedSliceChecker(self, StridedSliceChecker.REF_TENSOR) 686 expected = re.escape(array_ops._SLICE_TYPE_ERROR) 687 with self.assertRaisesRegexp(TypeError, expected): 688 _ = checker["foo"] 689 with self.assertRaisesRegexp(TypeError, expected): 690 _ = checker[constant_op.constant("foo")] 691 with self.assertRaisesRegexp(TypeError, expected): 692 _ = checker[0.0] 693 with self.assertRaisesRegexp(TypeError, expected): 694 _ = checker[constant_op.constant(0.0)] 695 with self.assertRaisesRegexp(TypeError, expected): 696 _ = checker[constant_op.constant([1, 2, 3])] 697 with self.assertRaisesRegexp(TypeError, expected): 698 _ = checker[[2.1, -0.7, 1.5]] 699 700 @test_util.run_deprecated_v1 701 def testExpand(self): 702 with self.session(use_gpu=True): 703 raw = [[[[[1, 2, 4, 5], [5, 6, 7, 8], [9, 10, 11, 12]]], 704 [[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]]]] 705 checker = StridedSliceChecker(self, raw) 706 # new axis (followed by implicit ellipsis) 707 _ = checker[np.newaxis] 708 # newaxis after ellipsis 709 _ = checker[..., np.newaxis] 710 # newaxis in between ellipsis and explicit range 711 _ = checker[..., np.newaxis, :] 712 _ = checker[:, ..., np.newaxis, :, :] 713 # Reverse final dimension with new axis 714 _ = checker[:, :, np.newaxis, :, 2::-1] 715 # Ellipsis in middle of two newaxis 716 _ = checker[np.newaxis, ..., np.newaxis] 717 718 @test_util.run_deprecated_v1 719 def testExpandVariable(self): 720 with self.session(use_gpu=True): 721 x = variables.Variable(7, dtype=dtypes.int32) 722 x.initializer.run() 723 y = x[None].eval() 724 self.assertEqual(y.shape, (1,)) 725 self.assertAllEqual(y, (7,)) 726 727 @test_util.run_deprecated_v1 728 def testOptimizedCases(self): 729 with self.session(use_gpu=True): 730 checker = StridedSliceChecker(self, 731 StridedSliceChecker.REF_TENSOR_ALIGNED) 732 # Identity 733 _ = checker[:] 734 # Identity 735 _ = checker[...] 736 # Identity 737 _ = checker[np.newaxis, ..., np.newaxis] 738 # First axis slice 739 _ = checker[1:] 740 # First axis slice 741 _ = checker[np.newaxis, 1:] 742 743 def testMasks(self): 744 with self.session(use_gpu=True): 745 scalar = np.array(0) 746 # Test tensor type mask 747 checker = StridedSliceChecker(self, StridedSliceChecker.REF_TENSOR) 748 _ = checker[checker.x > 2] 749 _ = checker[checker.x <= 5] 750 _ = checker[ops.convert_to_tensor(scalar)] 751 752 # Test numpy array type mask 753 raw = np.array([[[[[1, 2, 4, 5], [5, 6, 7, 8], [9, 10, 11, 12]]], 754 [[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 755 24]]]]]) 756 checker1 = StridedSliceChecker(self, raw) 757 _ = checker1[raw >= 4] 758 _ = checker1[raw < 19] 759 _ = checker1[scalar] 760 761 # Test boolean and non boolean cases 762 mask = np.array([True, False, True]) 763 raw1 = np.array([[1, 2, 4, 5], [5, 6, 7, 8], [9, 10, 11, 12]]) 764 checker2 = StridedSliceChecker(self, raw1) 765 _ = checker2[mask] 766 _ = checker2[ops.convert_to_tensor(mask)] 767 768 769class StridedSliceShapeChecker(object): 770 771 def __init__(self, x): 772 self.x = x 773 774 def __getitem__(self, spec): 775 op = self.x.__getitem__(spec) 776 return op.get_shape() 777 778 779class StridedSliceShapeTest(test_util.TensorFlowTestCase): 780 """Test the shape inference of StridedSliceShapes.""" 781 782 @test_util.run_deprecated_v1 783 def testUnknown(self): 784 with self.session(use_gpu=True): 785 uncertain_tensor = array_ops.placeholder(dtypes.float32) 786 a = StridedSliceShapeChecker(uncertain_tensor) 787 a_slice_shape = a[...] 788 self.assertAllEqual(a_slice_shape.ndims, None) 789 790 def tensorShapeEqual(self, x, y): 791 self.assertTrue(x is not None and y is not None or x is None and y is None) 792 self.assertEqual(x.as_list(), y.as_list()) 793 794 @test_util.run_deprecated_v1 795 def testTensorShapeUncertain(self): 796 with self.session(use_gpu=True): 797 uncertain_tensor = array_ops.placeholder( 798 dtypes.float32, shape=(5, None, 7)) 799 a = StridedSliceShapeChecker(uncertain_tensor) 800 self.tensorShapeEqual(a[3:5], tensor_shape.TensorShape([2, None, 7])) 801 self.tensorShapeEqual(a[3:5, :, 4], tensor_shape.TensorShape([2, None])) 802 self.tensorShapeEqual(a[3:5, 3:4, 4], tensor_shape.TensorShape([2, None])) 803 self.tensorShapeEqual(a[3:5, :, 5:10], 804 tensor_shape.TensorShape([2, None, 2])) 805 self.tensorShapeEqual(a[3:5, :, 50:3], 806 tensor_shape.TensorShape([2, None, 0])) 807 self.tensorShapeEqual(a[3:5, :, array_ops.newaxis, 50:3,], 808 tensor_shape.TensorShape([2, None, 1, 0])) 809 self.tensorShapeEqual(a[1:5:2, :, array_ops.newaxis, 50:3,], 810 tensor_shape.TensorShape([2, None, 1, 0])) 811 self.tensorShapeEqual(a[:5:3, :, array_ops.newaxis, 50:3,], 812 tensor_shape.TensorShape([2, None, 1, 0])) 813 self.tensorShapeEqual(a[:2:3, :, array_ops.newaxis, 50:3,], 814 tensor_shape.TensorShape([1, None, 1, 0])) 815 self.tensorShapeEqual(a[::-1, :, array_ops.newaxis, ::-2], 816 tensor_shape.TensorShape([5, None, 1, 4])) 817 818 @test_util.run_deprecated_v1 819 def testTensorValuedIndexShape(self): 820 with self.session(use_gpu=True): 821 defined_shape_tensor = array_ops.placeholder( 822 dtypes.float32, shape=(5, 3, 7)) 823 index_value = array_ops.placeholder(dtypes.int32, shape=()) 824 a = StridedSliceShapeChecker(defined_shape_tensor) 825 self.tensorShapeEqual(a[index_value], tensor_shape.TensorShape([3, 7])) 826 self.tensorShapeEqual(a[index_value, ::-1], 827 tensor_shape.TensorShape([3, 7])) 828 self.tensorShapeEqual(a[index_value, ::-2], 829 tensor_shape.TensorShape([2, 7])) 830 other_scalar = array_ops.placeholder(dtypes.int32, shape=()) 831 self.tensorShapeEqual(a[index_value, other_scalar:2], 832 tensor_shape.TensorShape([None, 7])) 833 834 835class GradSliceChecker(object): 836 """Tests that we can compute a gradient for var^2.""" 837 838 def __init__(self, test, sess, var, varnp): 839 self.test = test 840 self.sess = sess 841 self.val = var * var 842 self.var = var 843 self.varnp = varnp 844 845 def __getitem__(self, spec): 846 slice_var = self.var[spec] 847 slice_val = self.val[spec] 848 849 # compute analytic 2nd derivative 850 analytic_grad2 = 2 * slice_val 851 852 dy = variables.Variable( 853 array_ops.ones_like(slice_var, dtype=dtypes.float32)) 854 assign = dy.assign(slice_var) 855 slice_val_grad, = gradients_impl.gradients(slice_val, self.var, grad_ys=dy) 856 slice_val_grad2, = gradients_impl.gradients( 857 slice_val_grad, dy, grad_ys=self.var) 858 self.sess.run(assign) 859 slice_val_grad_evaled, slice_val_grad2_evaled = ( 860 self.sess.run([slice_val_grad, slice_val_grad2])) 861 analytic_grad2_evaled = analytic_grad2.eval() 862 self.test.assertAllEqual(slice_val_grad2_evaled, analytic_grad2_evaled) 863 864 # compute analytic gradient for slice 865 np_val_grad = (2 * self.varnp * self.varnp) 866 np_sliceval_grad = np.zeros(self.var.get_shape()) 867 if isinstance(spec, ops.Tensor): 868 spec = self.sess.run([spec]) 869 np_sliceval_grad[spec] = np_val_grad[spec] 870 # verify gradient 871 self.test.assertAllEqual(slice_val_grad_evaled, np_sliceval_grad) 872 873 874class StridedSliceGradTest(test_util.TensorFlowTestCase): 875 """Test that strided slice's custom gradient produces correct gradients.""" 876 877 @test_util.run_deprecated_v1 878 def testGradient(self): 879 with self.session(use_gpu=True) as sess: 880 var = variables.Variable( 881 array_ops.reshape( 882 math_ops.range(1, 97, 1, dtype=dtypes.float32), shape=(6, 4, 4))) 883 init = variables.global_variables_initializer() 884 sess.run(init) 885 886 raw = np.array(range(1, 97, 1)).reshape((6, 4, 4)) 887 grad = GradSliceChecker(self, sess, var, raw) 888 _ = grad[2:6:2, 1:3, 1:3] 889 _ = grad[3:0:-2, 1:3, 1:3] 890 _ = grad[3:0:-2, array_ops.newaxis, 1:3, 2, array_ops.newaxis] 891 _ = grad[3:0:-2, 1:3, 2] 892 _ = grad[:, -1, :] 893 _ = grad[:, -2, :] 894 with self.assertRaisesRegexp(ValueError, "out of bounds"): 895 _ = grad[:, -200, :] 896 with self.assertRaisesRegexp(ValueError, "out of bounds"): 897 _ = grad[:, 200, :] 898 899 # Test numpy array type mask 900 _ = grad[raw > 51] 901 # Test tensor type mask 902 _ = grad[ops.convert_to_tensor(raw) <= 76] 903 904 def testGradientZero(self): 905 with self.session(use_gpu=True) as sess: 906 var = variables.Variable(8.) 907 init = variables.global_variables_initializer() 908 sess.run(init) 909 grad = GradSliceChecker(self, sess, var, np.array(8)) 910 _ = grad[tuple()] 911 912 @test_util.run_deprecated_v1 913 def testInt64Indices(self): 914 with self.session(use_gpu=True) as sess: 915 a = math_ops.range(3, dtype=dtypes.float32) 916 index = constant_op.constant(1, dtype=dtypes.int64) 917 b = 2. * a[index] 918 grad, = gradients_impl.gradients(b, a) 919 self.assertAllEqual(self.evaluate(grad), [0., 2., 0.]) 920 921 922class StridedSliceGradTypeTest(test_util.TensorFlowTestCase): 923 """Test varied index types and host located memory.""" 924 925 @test_util.run_deprecated_v1 926 def testHostVsDevice(self): 927 with self.session(use_gpu=True) as sess: 928 var2 = variables.Variable( 929 array_ops.reshape( 930 math_ops.cast(math_ops.range(1, 5, 1), dtypes.float32), 931 shape=(4, 1, 1))) 932 varshape = variables.Variable([6, 4, 4], dtype=dtypes.int32) 933 self.evaluate(variables.global_variables_initializer()) 934 begin = constant_op.constant([0, 0, 0]) 935 end = constant_op.constant([4, 1, 1]) 936 strides = constant_op.constant([1, 1, 1]) 937 foo = array_ops.strided_slice_grad(varshape, begin, end, strides, var2) 938 sess.run(foo) 939 940 @test_util.run_deprecated_v1 941 def testInt64Shape(self): 942 with self.session(use_gpu=True) as sess: 943 original_dy = array_ops.reshape( 944 math_ops.cast(math_ops.range(1, 5, 1), dtypes.float32), 945 shape=(4, 1, 1)) 946 original_shape = constant_op.constant([6, 4, 4], dtype=dtypes.int64) 947 self.evaluate(variables.global_variables_initializer()) 948 begin = constant_op.constant([0, 0, 0], dtype=dtypes.int64) 949 end = constant_op.constant([4, 1, 1], dtype=dtypes.int64) 950 strides = constant_op.constant([1, 1, 1], dtype=dtypes.int64) 951 dx = array_ops.strided_slice_grad(original_shape, begin, end, strides, 952 original_dy) 953 sess.run(dx) 954 955 @test_util.run_deprecated_v1 956 def testMixedIndexTypes(self): 957 with self.session(use_gpu=True) as sess: 958 original_dy = array_ops.reshape( 959 math_ops.cast(math_ops.range(1, 5, 1), dtypes.float32), 960 shape=(4, 1, 1)) 961 original_shape = constant_op.constant([6, 4, 4], dtype=dtypes.int64) 962 self.evaluate(variables.global_variables_initializer()) 963 begin = constant_op.constant([0, 0, 0], dtype=dtypes.int32) 964 end = constant_op.constant([4, 1, 1], dtype=dtypes.int64) 965 strides = constant_op.constant([1, 1, 1], dtype=dtypes.int64) 966 with self.assertRaisesRegexp( 967 TypeError, "Input 'begin' of 'StridedSliceGrad' Op has type int32" 968 " that does not match type int64 of argument 'shape'"): 969 dx = array_ops.strided_slice_grad(original_shape, begin, end, strides, 970 original_dy) 971 sess.run(dx) 972 973 974class BenchmarkSlice(object): 975 976 def __init__(self, tensor): 977 self.tensor = tensor 978 979 def __getitem__(self, x): 980 return self.tensor[x] 981 982 983class StridedSliceBenchmark(test_lib.Benchmark): 984 """Benchmark new strided slice operation on non-trivial case.""" 985 986 def run_and_time(self, slice_op): 987 variables.global_variables_initializer().run() 988 for _ in range(10): 989 _ = slice_op.eval() 990 iters = 1000 991 t0 = time.time() 992 for _ in range(iters): 993 slice_op.eval() 994 t1 = time.time() 995 self.report_benchmark(iters=iters, wall_time=(t1 - t0) / 1000.0) 996 997 def make_variable(self): 998 n = 256 999 shape = (n, n, n) 1000 items = n**3 1001 var = variables.Variable( 1002 array_ops.reshape(math_ops.linspace(1., float(items), items), shape), 1003 dtype=dtypes.float32) 1004 return var 1005 1006 def benchmark_strided_slice_skip(self): 1007 with session.Session(): 1008 var = self.make_variable() 1009 helper = BenchmarkSlice(var) 1010 slice_op = helper[::2, ::1, ::2] 1011 self.run_and_time(slice_op) 1012 1013 def benchmark_strided_slice_easy(self): 1014 with session.Session(): 1015 var = self.make_variable() 1016 helper = BenchmarkSlice(var) 1017 slice_op = helper[3::1, 3::1, 3::1] 1018 self.run_and_time(slice_op) 1019 1020 def benchmark_slice_easy(self): 1021 with session.Session(): 1022 var = self.make_variable() 1023 slice_op = var[3::1, 3::1, 3::1] 1024 self.run_and_time(slice_op) 1025 1026 1027class StridedSliceAssignChecker(object): 1028 1029 def __init__(self, test, x, tensor_type=dtypes.float32, use_resource=False): 1030 self.tensor_type = tensor_type 1031 self.test = test 1032 self._use_resource = use_resource 1033 1034 self.x_np = np.array(x).astype(tensor_type.as_numpy_dtype) 1035 # Give the value a non-zero imaginary component for complex types. 1036 if tensor_type.is_complex: 1037 self.x_np -= 1j * self.x_np 1038 self.x = constant_op.constant(self.x_np, dtype=tensor_type) 1039 1040 def __setitem__(self, index, value): 1041 value = np.array(value).astype(self.tensor_type.as_numpy_dtype) 1042 # Give the value a non-zero imaginary component for complex types. 1043 if self.tensor_type.is_complex: 1044 value -= 1j * value 1045 1046 with self.test.test_session(use_gpu=True) as sess: 1047 if self._use_resource: 1048 var = resource_variable_ops.ResourceVariable(self.x) 1049 else: 1050 var = variables.Variable(self.x) 1051 sess.run(variables.variables_initializer([var])) 1052 val = sess.run(var[index].assign(value)) 1053 # val_copy is used to check that tf.assign works equivalently to the 1054 # assign method above. 1055 val_copy = sess.run(state_ops.assign(var[index], value)) 1056 valnp = np.copy(self.x_np) 1057 valnp[index] = np.array(value) 1058 self.test.assertAllEqual(val, valnp) 1059 self.test.assertAllEqual(val_copy, valnp) 1060 1061 1062class SliceAssignTest(test_util.TensorFlowTestCase): 1063 1064 @test_util.run_deprecated_v1 1065 def testInvalidSlice(self): 1066 with self.cached_session() as sess: 1067 foo = constant_op.constant([1, 2, 3]) 1068 with self.assertRaisesRegexp(ValueError, "Sliced assignment" 1069 " is only supported for variables"): 1070 bar = foo[:2].assign(constant_op.constant([1, 2])) 1071 sess.run(bar) 1072 1073 def doTestSliceAssign(self, use_resource): 1074 for dtype in STRIDED_SLICE_TYPES: 1075 checker = StridedSliceAssignChecker( 1076 self, [[1, 2, 3], [4, 5, 6]], 1077 use_resource=use_resource, 1078 tensor_type=dtype) 1079 # Check if equal 1080 checker[:] = [[10, 20, 30], [40, 50, 60]] 1081 # Check trivial (1,1) shape tensor 1082 checker[1:2, 1:2] = [[66]] 1083 # shrinks shape changes 1084 checker[1:2, 1] = [66] 1085 checker[1, 1:2] = [66] 1086 checker[1, 1] = 66 1087 # newaxis shape changes 1088 checker[:, None, :] = [[[10, 20, 30]], [[40, 50, 50]]] 1089 # shrink and newaxis 1090 checker[None, None, 0, 0:1] = [[[99]]] 1091 # Non unit strides 1092 checker[::1, ::-2] = [[3, 33], [4, 44]] 1093 # degenerate interval 1094 checker[8:10, 0] = [] 1095 checker[8:10, 8:10] = [[]] 1096 # Assign vector to scalar (rank-0) using newaxis 1097 checker2 = StridedSliceAssignChecker(self, 222) 1098 checker2[()] = 6 # no indices 1099 checker2[...] = 6 # ellipsis 1100 checker2[None] = [6] # new axis 1101 1102 @test_util.run_deprecated_v1 1103 @test_util.disable_xla("b/123559667") 1104 def testSliceAssign(self): 1105 self.doTestSliceAssign(use_resource=False) 1106 1107 @test_util.run_deprecated_v1 1108 @test_util.disable_xla("b/123559667") 1109 def testSliceAssignResource(self): 1110 self.doTestSliceAssign(use_resource=True) 1111 1112 @test_util.run_deprecated_v1 1113 def testUninitialized(self): 1114 with self.assertRaisesRegexp( 1115 errors.FailedPreconditionError, 1116 "Attempting to use uninitialized value Variable"): 1117 with self.cached_session() as sess: 1118 v = variables.VariableV1([1, 2]) 1119 sess.run(v[:].assign([1, 2])) 1120 1121 def testTypeError(self): 1122 init_val = constant_op.constant([1, 2], dtype=dtypes.int32) 1123 too_small_val = constant_op.constant([3, 4], dtype=dtypes.int8) 1124 too_large_val = constant_op.constant([3, 4], dtype=dtypes.int64) 1125 v = variables.VariableV1(init_val) 1126 with self.assertRaises(TypeError): 1127 v[:].assign(too_small_val) 1128 with self.assertRaises(TypeError): 1129 v[:].assign(too_large_val) 1130 1131 @test_util.run_deprecated_v1 1132 def testTypeErrorResource(self): 1133 init_val = constant_op.constant([1, 2], dtype=dtypes.int32) 1134 too_small_val = constant_op.constant([3, 4], dtype=dtypes.int8) 1135 too_large_val = constant_op.constant([3, 4], dtype=dtypes.int64) 1136 v = resource_variable_ops.ResourceVariable(init_val) 1137 with self.cached_session() as sess: 1138 self.evaluate(v.initializer) 1139 with self.assertRaises(ValueError): 1140 sess.run(v[:].assign(too_large_val)) 1141 with self.assertRaises(ValueError): 1142 sess.run(v[:].assign(too_small_val)) 1143 1144 1145class ShapeSizeRankTest(test_util.TensorFlowTestCase): 1146 1147 @test_util.run_in_graph_and_eager_modes 1148 def testDenseShape(self): 1149 t_value = [[0, 42], [24, 0]] 1150 self.assertAllEqual((2, 2), self.evaluate(array_ops.shape(t_value))) 1151 self.assertEqual(4, self.evaluate(array_ops.size(t_value))) 1152 self.assertEqual(2, self.evaluate(array_ops.rank(t_value))) 1153 1154 t = constant_op.constant(t_value) 1155 self.assertAllEqual((2, 2), self.evaluate(array_ops.shape(t))) 1156 self.assertEqual(4, self.evaluate(array_ops.size(t))) 1157 self.assertEqual(2, self.evaluate(array_ops.rank(t))) 1158 1159 @test_util.run_in_graph_and_eager_modes 1160 def testSparseShape(self): 1161 sp_value = sparse_tensor.SparseTensorValue( 1162 indices=((0, 1), (1, 0)), values=(42, 24), dense_shape=(2, 2)) 1163 self.assertAllEqual((2, 2), self.evaluate(array_ops.shape(sp_value))) 1164 self.assertEqual(4, self.evaluate(array_ops.size(sp_value))) 1165 self.assertEqual(2, self.evaluate(array_ops.rank(sp_value))) 1166 1167 sp = sparse_tensor.SparseTensor.from_value(sp_value) 1168 self.assertAllEqual((2, 2), self.evaluate(array_ops.shape(sp))) 1169 self.assertEqual(4, self.evaluate(array_ops.size(sp))) 1170 self.assertEqual(2, self.evaluate(array_ops.rank(sp))) 1171 1172 @test_util.run_in_graph_and_eager_modes 1173 def testSizeDtype(self): 1174 tensor = [1] 1175 self.assertEqual(dtypes.int32, self.evaluate(array_ops.size(tensor)).dtype) 1176 self.assertEqual( 1177 dtypes.int64, 1178 self.evaluate(array_ops.size(tensor, out_type=dtypes.int64)).dtype) 1179 1180 1181class SequenceMaskTest(test_util.TensorFlowTestCase): 1182 1183 def testExceptions(self): 1184 with self.cached_session(): 1185 with self.assertRaisesRegexp(ValueError, "maxlen must be scalar"): 1186 array_ops.sequence_mask([10, 20], [10, 20]) 1187 1188 @test_util.run_deprecated_v1 1189 def testOneDimensionalWithMaxlen(self): 1190 with self.cached_session(): 1191 res = array_ops.sequence_mask(constant_op.constant([1, 3, 2]), 5) 1192 self.assertAllEqual(res.get_shape(), [3, 5]) 1193 self.assertAllEqual( 1194 res.eval(), 1195 [[True, False, False, False, False], [True, True, True, False, False], 1196 [True, True, False, False, False]]) 1197 1198 @test_util.run_deprecated_v1 1199 def testOneDimensionalDtypeWithoutMaxlen(self): 1200 with self.cached_session(): 1201 # test dtype and default maxlen: 1202 res = array_ops.sequence_mask(constant_op.constant([0, 1, 4]), 1203 dtype=dtypes.float32) 1204 self.assertAllEqual(res.get_shape().as_list(), [3, 4]) 1205 self.assertAllEqual( 1206 res.eval(), 1207 [[0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]]) 1208 1209 @test_util.run_deprecated_v1 1210 def testOneDimensionalWithoutMaxlen(self): 1211 with self.cached_session(): 1212 res = array_ops.sequence_mask( 1213 constant_op.constant([0, 1, 4])) 1214 self.assertAllEqual(res.get_shape().as_list(), [3, 4]) 1215 self.assertAllEqual( 1216 res.eval(), 1217 [[False, False, False, False], 1218 [True, False, False, False], 1219 [True, True, True, True]]) 1220 1221 def testTwoDimensional(self): 1222 with self.cached_session(): 1223 res = array_ops.sequence_mask(constant_op.constant([[1, 3, 2]]), 5) 1224 self.assertAllEqual(res.get_shape(), [1, 3, 5]) 1225 self.assertAllEqual(res.eval(), [[[True, False, False, False, False], [ 1226 True, True, True, False, False 1227 ], [True, True, False, False, False]]]) 1228 1229 # test dtype and default maxlen: 1230 res = array_ops.sequence_mask( 1231 constant_op.constant([[0, 1, 4], [1, 2, 3]]), dtype=dtypes.float32) 1232 self.assertAllEqual(res.get_shape().as_list(), [2, 3, 4]) 1233 self.assertAllEqual( 1234 res.eval(), 1235 [[[0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]], 1236 [[1.0, 0.0, 0.0, 0.0], [1.0, 1.0, 0.0, 0.0], [1.0, 1.0, 1.0, 0.0]]]) 1237 1238 @test_util.run_deprecated_v1 1239 def testUnknownShape(self): 1240 lengths = array_ops.placeholder(dtype=dtypes.int32) 1241 res = array_ops.sequence_mask(lengths) 1242 self.assertEqual(res.shape, None) 1243 1244 @test_util.run_deprecated_v1 1245 def testDtypes(self): 1246 1247 def check_dtypes(lengths_dtype, maxlen_dtype): 1248 res = array_ops.sequence_mask( 1249 constant_op.constant([1, 3, 2], dtype=lengths_dtype), 1250 constant_op.constant(5, dtype=maxlen_dtype)) 1251 self.assertAllEqual(res.get_shape(), [3, 5]) 1252 self.assertAllEqual( 1253 res.eval(), 1254 [[True, False, False, False, False], [True, True, True, False, False], 1255 [True, True, False, False, False]]) 1256 1257 with self.cached_session(): 1258 check_dtypes(dtypes.int32, dtypes.int32) 1259 check_dtypes(dtypes.int32, dtypes.int64) 1260 check_dtypes(dtypes.int64, dtypes.int32) 1261 check_dtypes(dtypes.int64, dtypes.int64) 1262 1263 1264class ConcatSliceResourceTest(test_util.TensorFlowTestCase): 1265 1266 @test_util.run_in_graph_and_eager_modes 1267 @test_util.run_deprecated_v1 1268 def testConcatSlice(self): 1269 r1 = test_ops.stub_resource_handle_op(container="a", shared_name="b") 1270 r2 = test_ops.stub_resource_handle_op(container="a", shared_name="c") 1271 c = array_ops.stack([r1, r2]) 1272 s = array_ops.strided_slice(c, [1], [2]) 1273 self.evaluate(test_ops.resource_create_op(s)) 1274 with self.assertRaises(errors.AlreadyExistsError): 1275 self.evaluate(test_ops.resource_create_op(r2)) 1276 1277 1278class IdentityTest(test_util.TensorFlowTestCase): 1279 1280 def testEagerIdentity(self): 1281 with context.eager_mode(): 1282 ctx = context.context() 1283 if not ctx.num_gpus(): 1284 self.skipTest("No GPUs found") 1285 1286 def _test(x, y, device): 1287 self.assertAllEqual(x.numpy(), y.numpy()) 1288 self.assertTrue(device in y.device.lower()) 1289 1290 with test_util.force_gpu(): 1291 a = constant_op.constant([[2], [3]], dtype=dtypes.float32) 1292 with test_util.force_gpu(): 1293 b = array_ops.identity(a) 1294 _test(a, b, "gpu") 1295 with test_util.force_cpu(): 1296 c = array_ops.identity(b) 1297 _test(b, c, "cpu") 1298 with test_util.force_cpu(): 1299 d = array_ops.identity(c) 1300 _test(c, d, "cpu") 1301 with test_util.force_gpu(): 1302 e = array_ops.identity(d) 1303 _test(d, e, "gpu") 1304 1305 1306class PadTest(test_util.TensorFlowTestCase): 1307 1308 def testEager(self): 1309 with context.eager_mode(): 1310 t = constant_op.constant([[1, 2, 3], [4, 5, 6]]) 1311 paddings = constant_op.constant([[ 1312 1, 1313 1, 1314 ], [2, 2]]) 1315 padded = array_ops.pad(t, paddings, "CONSTANT") 1316 self.assertAllEqual(padded.numpy(), 1317 [[0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 2, 3, 0, 0], 1318 [0, 0, 4, 5, 6, 0, 0], [0, 0, 0, 0, 0, 0, 0]]) 1319 1320 1321class InvertPermutationTest(test_util.TensorFlowTestCase): 1322 1323 @test_util.run_deprecated_v1 1324 def testInvertPermutation(self): 1325 for dtype in [dtypes.int32, dtypes.int64]: 1326 with self.cached_session(use_gpu=True): 1327 x = constant_op.constant([3, 4, 0, 2, 1], dtype=dtype) 1328 y = array_ops.invert_permutation(x) 1329 self.assertAllEqual(y.get_shape(), [5]) 1330 self.assertAllEqual(y.eval(), [2, 4, 3, 0, 1]) 1331 1332 1333class UnravelIndexTest(test_util.TensorFlowTestCase): 1334 1335 # TODO(b/73086570): Reenable test. 1336 @unittest.skip("Test does not pass internally.") 1337 def testUnravelIndex(self): 1338 with self.cached_session(): 1339 for dtype in [dtypes.int32, dtypes.int64]: 1340 indices_1 = constant_op.constant(1621, dtype=dtype) 1341 dims_1 = constant_op.constant([6, 7, 8, 9], dtype=dtype) 1342 out_1 = array_ops.unravel_index(indices_1, dims_1) 1343 self.assertAllEqual(out_1.eval(), [3, 1, 4, 1]) 1344 1345 indices_2 = constant_op.constant([1621], dtype=dtype) 1346 dims_2 = constant_op.constant([6, 7, 8, 9], dtype=dtype) 1347 out_2 = array_ops.unravel_index(indices_2, dims_2) 1348 self.assertAllEqual(out_2.eval(), [[3], [1], [4], [1]]) 1349 1350 indices_3 = constant_op.constant([22, 41, 37], dtype=dtype) 1351 dims_3 = constant_op.constant([7, 6], dtype=dtype) 1352 out_3 = array_ops.unravel_index(indices_3, dims_3) 1353 self.assertAllEqual(out_3.eval(), [[3, 6, 6], [4, 5, 1]]) 1354 1355 1356class GuaranteeConstOpTest(test_util.TensorFlowTestCase): 1357 1358 @test_util.run_deprecated_v1 1359 def testSimple(self): 1360 with self.cached_session(): 1361 a = array_ops.constant(10) 1362 guarantee_a = array_ops.guarantee_const(a) 1363 self.assertEqual(10, guarantee_a.eval()) 1364 1365 @test_util.run_deprecated_v1 1366 def testVariables(self): 1367 with self.cached_session() as sess: 1368 for use_resource in [False, True]: 1369 a = variable_scope.get_variable( 1370 "var_{}".format(use_resource), [], 1371 initializer=init_ops.constant_initializer(10.0), 1372 use_resource=use_resource) 1373 guarantee_a = array_ops.guarantee_const(a) 1374 self.evaluate(variables.global_variables_initializer()) 1375 self.assertEqual(10.0, guarantee_a.eval()) 1376 1377 @test_util.run_deprecated_v1 1378 def testResourceRejection(self): 1379 with self.cached_session() as sess: 1380 a = variable_scope.get_variable( 1381 "resource_var", [], 1382 initializer=init_ops.constant_initializer(10.0), 1383 use_resource=True) 1384 guarantee_a = array_ops.guarantee_const(a.handle) 1385 self.evaluate(variables.global_variables_initializer()) 1386 with self.assertRaisesWithPredicateMatch(errors.InvalidArgumentError, 1387 "cannot be a resource variable"): 1388 guarantee_a.eval() 1389 1390 1391class SnapshotOpTest(test_util.TensorFlowTestCase): 1392 1393 @test_util.run_deprecated_v1 1394 def testInvertPermutation(self): 1395 for dtype in [dtypes.int32, dtypes.int64, dtypes.float32, dtypes.float64]: 1396 with self.cached_session(use_gpu=True): 1397 x = constant_op.constant([0, 1, 2, 3], dtype=dtype) 1398 y = gen_array_ops.snapshot(x) 1399 self.assertAllEqual(y.eval(), [0, 1, 2, 3]) 1400 1401 1402@test_util.run_all_in_graph_and_eager_modes 1403class SortedSearchTest(test_util.TensorFlowTestCase): 1404 1405 def testUpperBoundFloatHandCoded(self): 1406 cdf = np.array([0, .2, .5, .6, .8, 1.], dtype=np.float32) 1407 arr = np.array([.04, .99, .53, .58, .31, .01, .79, .8, .21], 1408 dtype=np.float32) 1409 result = np.searchsorted(cdf, arr, side="right") 1410 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="right")) 1411 self.assertAllEqual(result, tf_result) 1412 1413 def testUpperBoundFloatRandomNd(self): 1414 dim_size = 7 1415 for d in range(1, 5): 1416 shape = [dim_size] * d 1417 cdf = np.cumsum( 1418 np.random.uniform(size=shape).astype(np.float32), axis=(d - 1)) 1419 arr = np.random.uniform(size=shape).astype(np.float32) * dim_size 1420 1421 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="right")) 1422 1423 cdf = cdf.reshape([-1, dim_size]) 1424 arr = arr.reshape([-1, dim_size]) 1425 result = np.zeros(arr.shape, dtype=np.int32) 1426 for i in range(dim_size**(d - 1)): 1427 result[i, :] = np.searchsorted(cdf[i, :], arr[i, :], side="right") 1428 1429 result = result.reshape(shape) 1430 1431 self.assertAllEqual(result, tf_result) 1432 1433 def testUpperBoundFloatUneven(self): 1434 batch_size = 7 1435 size_search_array = 1000 1436 size_values = 47 1437 cdf = np.cumsum( 1438 np.random.uniform(size=[batch_size, size_search_array]).astype( 1439 np.float32), 1440 axis=1) 1441 arr = np.random.uniform(size=[batch_size, size_values]).astype( 1442 np.float32) * size_search_array 1443 1444 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="right")) 1445 1446 result = np.zeros(arr.shape, dtype=np.int32) 1447 for i in range(batch_size): 1448 result[i, :] = np.searchsorted(cdf[i, :], arr[i, :], side="right") 1449 1450 self.assertAllEqual(result, tf_result) 1451 1452 def testLowerBoundFloatHandCoded(self): 1453 cdf = np.array([0, .2, .5, .6, .8, 1.], dtype=np.float32) 1454 arr = np.array([.04, .99, .53, .58, .31, .01, .79, .8, .21], 1455 dtype=np.float32) 1456 result = np.searchsorted(cdf, arr, side="left") 1457 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="left")) 1458 self.assertAllEqual(result, tf_result) 1459 1460 def testLowerBoundFloatRandomNd(self): 1461 dim_size = 7 1462 for d in range(1, 5): 1463 shape = [dim_size] * d 1464 cdf = np.cumsum( 1465 np.random.uniform(size=shape).astype(np.float32), axis=(d - 1)) 1466 arr = np.random.uniform(size=shape).astype(np.float32) * dim_size 1467 1468 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="left")) 1469 1470 cdf = cdf.reshape([-1, dim_size]) 1471 arr = arr.reshape([-1, dim_size]) 1472 result = np.zeros(arr.shape, dtype=np.int32) 1473 for i in range(dim_size**(d - 1)): 1474 result[i, :] = np.searchsorted(cdf[i, :], arr[i, :], side="left") 1475 1476 result = result.reshape(shape) 1477 1478 self.assertAllEqual(result, tf_result) 1479 1480 def testLowerBoundFloatUneven(self): 1481 batch_size = 7 1482 size_search_array = 1000 1483 size_values = 47 1484 cdf = np.cumsum( 1485 np.random.uniform(size=[batch_size, size_search_array]).astype( 1486 np.float32), 1487 axis=1) 1488 arr = np.random.uniform(size=[batch_size, size_values]).astype( 1489 np.float32) * size_search_array 1490 1491 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="left")) 1492 1493 result = np.zeros(arr.shape, dtype=np.int32) 1494 for i in range(batch_size): 1495 result[i, :] = np.searchsorted(cdf[i, :], arr[i, :], side="left") 1496 1497 self.assertAllEqual(result, tf_result) 1498 1499 def testUpperBoundIntHandCoded(self): 1500 cdf = np.array([0, 20, 50, 60, 80, 100], dtype=np.int64) 1501 arr = np.array([4, 99, 53, 58, 31, 1, 79, 8, 21], dtype=np.int64) 1502 result = np.searchsorted(cdf, arr, side="right") 1503 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="right")) 1504 self.assertAllEqual(result, tf_result) 1505 1506 def testUpperBoundIntRandomNd(self): 1507 dim_size = 7 1508 for d in range(1, 5): 1509 shape = [dim_size] * d 1510 cdf = np.cumsum( 1511 np.random.randint(low=0, high=10, size=shape).astype(np.int64), 1512 axis=(d - 1)) 1513 arr = np.random.randint( 1514 low=0, high=10 * dim_size, size=shape).astype(np.int64) 1515 1516 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="right")) 1517 1518 cdf = cdf.reshape([-1, dim_size]) 1519 arr = arr.reshape([-1, dim_size]) 1520 result = np.zeros(arr.shape, dtype=np.int32) 1521 for i in range(dim_size**(d - 1)): 1522 result[i, :] = np.searchsorted(cdf[i, :], arr[i, :], side="right") 1523 1524 result = result.reshape(shape) 1525 1526 self.assertAllEqual(result, tf_result) 1527 1528 def testUpperBoundIntUneven(self): 1529 batch_size = 7 1530 size_search_array = 1000 1531 size_values = 47 1532 cdf = np.cumsum( 1533 np.random.randint(low=0, high=10, 1534 size=[batch_size, 1535 size_search_array]).astype(np.int64), 1536 axis=1) 1537 arr = np.random.randint( 1538 low=0, high=10 * size_search_array, size=[batch_size, 1539 size_values]).astype(np.int64) 1540 1541 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="right")) 1542 1543 result = np.zeros(arr.shape, dtype=np.int32) 1544 for i in range(batch_size): 1545 result[i, :] = np.searchsorted(cdf[i, :], arr[i, :], side="right") 1546 1547 self.assertAllEqual(result, tf_result) 1548 1549 def testLowerBoundIntHandCoded(self): 1550 cdf = np.array([0, 20, 50, 60, 80, 100], dtype=np.int64) 1551 arr = np.array([4, 99, 53, 58, 31, 1, 79, 8, 21], dtype=np.int64) 1552 result = np.searchsorted(cdf, arr, side="left") 1553 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="left")) 1554 self.assertAllEqual(result, tf_result) 1555 1556 def testLowerBoundIntRandomNd(self): 1557 dim_size = 7 1558 for d in range(1, 5): 1559 shape = [dim_size] * d 1560 cdf = np.cumsum( 1561 np.random.randint(low=0, high=10, size=shape).astype(np.int64), 1562 axis=(d - 1)) 1563 arr = np.random.randint( 1564 low=0, high=10 * dim_size, size=shape).astype(np.int64) 1565 1566 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="left")) 1567 1568 cdf = cdf.reshape([-1, dim_size]) 1569 arr = arr.reshape([-1, dim_size]) 1570 result = np.zeros(arr.shape, dtype=np.int32) 1571 for i in range(dim_size**(d - 1)): 1572 result[i, :] = np.searchsorted(cdf[i, :], arr[i, :], side="left") 1573 1574 result = result.reshape(shape) 1575 1576 self.assertAllEqual(result, tf_result) 1577 1578 def testLowerBoundIntUneven(self): 1579 batch_size = 7 1580 size_search_array = 1000 1581 size_values = 47 1582 cdf = np.cumsum( 1583 np.random.randint(low=0, high=10, 1584 size=[batch_size, 1585 size_search_array]).astype(np.int64), 1586 axis=1) 1587 arr = np.random.randint( 1588 low=0, high=10 * size_search_array, size=[batch_size, 1589 size_values]).astype(np.int64) 1590 1591 tf_result = self.evaluate(array_ops.searchsorted(cdf, arr, side="left")) 1592 1593 result = np.zeros(arr.shape, dtype=np.int32) 1594 for i in range(batch_size): 1595 result[i, :] = np.searchsorted(cdf[i, :], arr[i, :], side="left") 1596 1597 self.assertAllEqual(result, tf_result) 1598 1599 1600if __name__ == "__main__": 1601 test_lib.main() 1602