From 6db3caf99be91664813ae621e62c3287e2af44d3 Mon Sep 17 00:00:00 2001 From: Andrew Selle Date: Thu, 14 May 2020 13:28:33 -0700 Subject: [PATCH] Update gather_op_test and unique_op_test to use subTest for easier debugging. PiperOrigin-RevId: 311595699 Change-Id: I1a8cf8b5b314aada4aeeece2603e975bc8a4ff42 --- .../python/kernel_tests/gather_op_test.py | 213 +++++++++--------- .../python/kernel_tests/unique_op_test.py | 59 ++--- 2 files changed, 142 insertions(+), 130 deletions(-) diff --git a/tensorflow/python/kernel_tests/gather_op_test.py b/tensorflow/python/kernel_tests/gather_op_test.py index 953f18bb07a..b966110963c 100644 --- a/tensorflow/python/kernel_tests/gather_op_test.py +++ b/tensorflow/python/kernel_tests/gather_op_test.py @@ -62,14 +62,15 @@ class GatherTest(test.TestCase, parameterized.TestCase): data = np.array([0, 1, 2, 3, 7, 5]) for dtype in _TEST_TYPES: for indices in 4, [1, 2, 2, 4, 5]: - params_np = self._buildParams(data, dtype) - params = constant_op.constant(params_np) - indices_tf = constant_op.constant(indices) - gather_t = array_ops.gather(params, indices_tf) - gather_val = self.evaluate(gather_t) - np_val = params_np[indices] - self.assertAllEqual(np_val, gather_val) - self.assertEqual(np_val.shape, gather_t.get_shape()) + with self.subTest(dtype=dtype, indices=indices): + params_np = self._buildParams(data, dtype) + params = constant_op.constant(params_np) + indices_tf = constant_op.constant(indices) + gather_t = array_ops.gather(params, indices_tf) + gather_val = self.evaluate(gather_t) + np_val = params_np[indices] + self.assertAllEqual(np_val, gather_val) + self.assertEqual(np_val.shape, gather_t.get_shape()) def testScalar2D(self): with self.session(use_gpu=True): @@ -77,14 +78,15 @@ class GatherTest(test.TestCase, parameterized.TestCase): [9, 10, 11], [12, 13, 14]]) for dtype in _TEST_TYPES: for axis in range(data.ndim): - params_np = self._buildParams(data, dtype) - params = constant_op.constant(params_np) - indices = constant_op.constant(2) - gather_t = array_ops.gather(params, indices, axis=axis) - gather_val = self.evaluate(gather_t) - self.assertAllEqual(np.take(params_np, 2, axis=axis), gather_val) - expected_shape = data.shape[:axis] + data.shape[axis + 1:] - self.assertEqual(expected_shape, gather_t.get_shape()) + with self.subTest(dtype=dtype, axis=axis): + params_np = self._buildParams(data, dtype) + params = constant_op.constant(params_np) + indices = constant_op.constant(2) + gather_t = array_ops.gather(params, indices, axis=axis) + gather_val = self.evaluate(gather_t) + self.assertAllEqual(np.take(params_np, 2, axis=axis), gather_val) + expected_shape = data.shape[:axis] + data.shape[axis + 1:] + self.assertEqual(expected_shape, gather_t.get_shape()) def testSimpleTwoD32(self): with self.session(use_gpu=True): @@ -92,16 +94,17 @@ class GatherTest(test.TestCase, parameterized.TestCase): [9, 10, 11], [12, 13, 14]]) for dtype in _TEST_TYPES: for axis in range(data.ndim): - params_np = self._buildParams(data, dtype) - params = constant_op.constant(params_np) - # The indices must be in bounds for any axis. - indices = constant_op.constant([0, 1, 0, 2]) - gather_t = array_ops.gather(params, indices, axis=axis) - gather_val = self.evaluate(gather_t) - self.assertAllEqual(np.take(params_np, [0, 1, 0, 2], axis=axis), - gather_val) - expected_shape = data.shape[:axis] + (4,) + data.shape[axis + 1:] - self.assertEqual(expected_shape, gather_t.get_shape()) + with self.subTest(dtype=dtype, axis=axis): + params_np = self._buildParams(data, dtype) + params = constant_op.constant(params_np) + # The indices must be in bounds for any axis. + indices = constant_op.constant([0, 1, 0, 2]) + gather_t = array_ops.gather(params, indices, axis=axis) + gather_val = self.evaluate(gather_t) + self.assertAllEqual(np.take(params_np, [0, 1, 0, 2], axis=axis), + gather_val) + expected_shape = data.shape[:axis] + (4,) + data.shape[axis + 1:] + self.assertEqual(expected_shape, gather_t.get_shape()) @test_util.run_deprecated_v1 def testHigherRank(self): @@ -112,58 +115,60 @@ class GatherTest(test.TestCase, parameterized.TestCase): for axis in range(len(shape)): params = self._buildParams(np.random.randn(*shape), dtype) indices = np.random.randint(shape[axis], size=indices_shape) - with self.cached_session(use_gpu=True) as sess: - tf_params = constant_op.constant(params) - tf_indices = constant_op.constant(indices) - # Check that both positive and negative indices for axis work. - tf_axis = constant_op.constant(axis) - tf_negative_axis = constant_op.constant(-len(shape) + axis) - gather = array_ops.gather(tf_params, tf_indices, axis=tf_axis) - gather_negative_axis = array_ops.gather( - tf_params, tf_indices, axis=tf_negative_axis) - gather_value, gather_negative_axis_value = sess.run( - [gather, gather_negative_axis]) - gather_np = np.take(params, indices, axis) - self.assertAllEqual(gather_np, gather_value) - self.assertAllEqual(gather_np, gather_negative_axis_value) - expected_shape = (params.shape[:axis] + indices.shape + - params.shape[axis + 1:]) - self.assertEqual(expected_shape, gather.shape) - self.assertEqual(expected_shape, gather_negative_axis.shape) + with self.subTest(indices_shape=indices_shape, dtype=dtype, axis=axis, + indices=indices): + with self.cached_session(use_gpu=True) as sess: + tf_params = constant_op.constant(params) + tf_indices = constant_op.constant(indices) + # Check that both positive and negative indices for axis work. + tf_axis = constant_op.constant(axis) + tf_negative_axis = constant_op.constant(-len(shape) + axis) + gather = array_ops.gather(tf_params, tf_indices, axis=tf_axis) + gather_negative_axis = array_ops.gather( + tf_params, tf_indices, axis=tf_negative_axis) + gather_value, gather_negative_axis_value = sess.run( + [gather, gather_negative_axis]) + gather_np = np.take(params, indices, axis) + self.assertAllEqual(gather_np, gather_value) + self.assertAllEqual(gather_np, gather_negative_axis_value) + expected_shape = (params.shape[:axis] + indices.shape + + params.shape[axis + 1:]) + self.assertEqual(expected_shape, gather.shape) + self.assertEqual(expected_shape, gather_negative_axis.shape) - # Test gradients - gather_grad = np.random.randn( - *gather.get_shape().as_list()).astype(dtype.as_numpy_dtype) - if dtype.is_complex: - gather_grad -= 1j * gather_grad - params_grad, indices_grad, axis_grad = gradients_impl.gradients( - gather, [tf_params, tf_indices, tf_axis], gather_grad) - self.assertEqual(indices_grad, None) - self.assertEqual(axis_grad, None) - if dtype.is_integer: - self.assertEqual(params_grad, None) - continue - # For axis 0, we are able to create an efficient IndexedSlices for - # the gradient. - if axis == 0: - self.assertEqual(type(params_grad), ops.IndexedSlices) - params_grad = ops.convert_to_tensor(params_grad) - correct_params_grad = np.zeros(shape).astype(dtype.as_numpy_dtype) - outer_dims = axis - inner_dims = len(shape) - axis - 1 - gather_grad = gather_grad.reshape( - shape[:axis] + (indices.size,) + shape[axis + 1:]) - for source_index, dest_index in enumerate(indices.flat): - dest_slice = ((slice(None),) * outer_dims + (dest_index,) + - (slice(None),) * inner_dims) - source_slice = ((slice(None),) * outer_dims + (source_index,) + + # Test gradients + gather_grad = np.random.randn( + *gather.get_shape().as_list()).astype(dtype.as_numpy_dtype) + if dtype.is_complex: + gather_grad -= 1j * gather_grad + params_grad, indices_grad, axis_grad = gradients_impl.gradients( + gather, [tf_params, tf_indices, tf_axis], gather_grad) + self.assertEqual(indices_grad, None) + self.assertEqual(axis_grad, None) + if dtype.is_integer: + self.assertEqual(params_grad, None) + continue + # For axis 0, we are able to create an efficient IndexedSlices for + # the gradient. + if axis == 0: + self.assertEqual(type(params_grad), ops.IndexedSlices) + params_grad = ops.convert_to_tensor(params_grad) + correct_params_grad = np.zeros(shape).astype(dtype.as_numpy_dtype) + outer_dims = axis + inner_dims = len(shape) - axis - 1 + gather_grad = gather_grad.reshape( + shape[:axis] + (indices.size,) + shape[axis + 1:]) + for source_index, dest_index in enumerate(indices.flat): + dest_slice = ((slice(None),) * outer_dims + (dest_index,) + (slice(None),) * inner_dims) - correct_params_grad[dest_slice] += gather_grad[source_slice] - self.assertAllClose( - correct_params_grad, - self.evaluate(params_grad), - atol=2e-6, - rtol=2e-6) + source_slice = ((slice(None),) * outer_dims + (source_index,) + + (slice(None),) * inner_dims) + correct_params_grad[dest_slice] += gather_grad[source_slice] + self.assertAllClose( + correct_params_grad, + self.evaluate(params_grad), + atol=2e-6, + rtol=2e-6) @test_util.run_deprecated_v1 def testString(self): @@ -177,12 +182,14 @@ class GatherTest(test.TestCase, parameterized.TestCase): @test_util.run_deprecated_v1 def testUInt32AndUInt64(self): for unsigned_type in (dtypes.uint32, dtypes.uint64): - params = self._buildParams( - np.array([[1, 2, 3], [7, 8, 9]]), unsigned_type) - with self.cached_session(): - self.assertAllEqual([7, 8, 9], - array_ops.gather(params, 1, axis=0).eval()) - self.assertAllEqual([1, 7], array_ops.gather(params, 0, axis=1).eval()) + with self.subTest(unsigned_type=unsigned_type): + params = self._buildParams( + np.array([[1, 2, 3], [7, 8, 9]]), unsigned_type) + with self.cached_session(): + self.assertAllEqual([7, 8, 9], + array_ops.gather(params, 1, axis=0).eval()) + self.assertAllEqual([1, 7], + array_ops.gather(params, 0, axis=1).eval()) @test_util.run_deprecated_v1 def testUnknownIndices(self): @@ -237,14 +244,15 @@ class GatherTest(test.TestCase, parameterized.TestCase): indices = 0 for bad_axis in (1, 2, -2): # Shape inference can validate axis for known params rank. - with self.assertRaisesWithPredicateMatch( - ValueError, "Shape must be at least rank . but is rank 1"): - array_ops.gather(params, indices, axis=bad_axis) - # If params rank is unknown, an op error occurs. - with self.assertRaisesOpError( - r"Expected axis in the range \[-1, 1\), but got %s" % bad_axis): - array_ops.gather(params_ph, indices, axis=bad_axis).eval( - feed_dict={params_ph: params}) + with self.subTest(bad_axis=bad_axis): + with self.assertRaisesWithPredicateMatch( + ValueError, "Shape must be at least rank . but is rank 1"): + array_ops.gather(params, indices, axis=bad_axis) + # If params rank is unknown, an op error occurs. + with self.assertRaisesOpError( + r"Expected axis in the range \[-1, 1\), but got %s" % bad_axis): + array_ops.gather(params_ph, indices, axis=bad_axis).eval( + feed_dict={params_ph: params}) @test_util.run_deprecated_v1 def testEmptySlices(self): @@ -252,20 +260,21 @@ class GatherTest(test.TestCase, parameterized.TestCase): for dtype in _TEST_TYPES: for itype in np.int32, np.int64: # Leading axis gather. - params = np.zeros((7, 0, 0), dtype=dtype.as_numpy_dtype) - indices = np.array([3, 4], dtype=itype) - gather = array_ops.gather(params, indices, axis=0) - self.assertAllEqual(gather.eval(), np.zeros((2, 0, 0))) + with self.subTest(dtype=dtype, itype=itype): + params = np.zeros((7, 0, 0), dtype=dtype.as_numpy_dtype) + indices = np.array([3, 4], dtype=itype) + gather = array_ops.gather(params, indices, axis=0) + self.assertAllEqual(gather.eval(), np.zeros((2, 0, 0))) - # Middle axis gather. - params = np.zeros((0, 7, 0), dtype=dtype.as_numpy_dtype) - gather = array_ops.gather(params, indices, axis=1) - self.assertAllEqual(gather.eval(), np.zeros((0, 2, 0))) + # Middle axis gather. + params = np.zeros((0, 7, 0), dtype=dtype.as_numpy_dtype) + gather = array_ops.gather(params, indices, axis=1) + self.assertAllEqual(gather.eval(), np.zeros((0, 2, 0))) - # Trailing axis gather. - params = np.zeros((0, 0, 7), dtype=dtype.as_numpy_dtype) - gather = array_ops.gather(params, indices, axis=2) - self.assertAllEqual(gather.eval(), np.zeros((0, 0, 2))) + # Trailing axis gather. + params = np.zeros((0, 0, 7), dtype=dtype.as_numpy_dtype) + gather = array_ops.gather(params, indices, axis=2) + self.assertAllEqual(gather.eval(), np.zeros((0, 0, 2))) @parameterized.parameters([ # batch_dims=0 (equivalent to tf.gather) diff --git a/tensorflow/python/kernel_tests/unique_op_test.py b/tensorflow/python/kernel_tests/unique_op_test.py index 7d9e875be2d..436fef8171f 100644 --- a/tensorflow/python/kernel_tests/unique_op_test.py +++ b/tensorflow/python/kernel_tests/unique_op_test.py @@ -61,17 +61,18 @@ class UniqueTest(test.TestCase): def testInt32Axis(self): for dtype in [np.int32, np.int64]: - x = np.array([[1, 0, 0], [1, 0, 0], [2, 0, 0]]) - y0, idx0 = gen_array_ops.unique_v2(x, axis=np.array([0], dtype)) - self.assertEqual(y0.shape.rank, 2) - tf_y0, tf_idx0 = self.evaluate([y0, idx0]) - y1, idx1 = gen_array_ops.unique_v2(x, axis=np.array([1], dtype)) - self.assertEqual(y1.shape.rank, 2) - tf_y1, tf_idx1 = self.evaluate([y1, idx1]) - self.assertAllEqual(tf_y0, np.array([[1, 0, 0], [2, 0, 0]])) - self.assertAllEqual(tf_idx0, np.array([0, 0, 1])) - self.assertAllEqual(tf_y1, np.array([[1, 0], [1, 0], [2, 0]])) - self.assertAllEqual(tf_idx1, np.array([0, 1, 1])) + with self.subTest(dtype=dtype): + x = np.array([[1, 0, 0], [1, 0, 0], [2, 0, 0]]) + y0, idx0 = gen_array_ops.unique_v2(x, axis=np.array([0], dtype)) + self.assertEqual(y0.shape.rank, 2) + tf_y0, tf_idx0 = self.evaluate([y0, idx0]) + y1, idx1 = gen_array_ops.unique_v2(x, axis=np.array([1], dtype)) + self.assertEqual(y1.shape.rank, 2) + tf_y1, tf_idx1 = self.evaluate([y1, idx1]) + self.assertAllEqual(tf_y0, np.array([[1, 0, 0], [2, 0, 0]])) + self.assertAllEqual(tf_idx0, np.array([0, 0, 1])) + self.assertAllEqual(tf_y1, np.array([[1, 0], [1, 0], [2, 0]])) + self.assertAllEqual(tf_idx1, np.array([0, 1, 1])) def testInt32V2(self): # This test is only temporary, once V2 is used @@ -144,26 +145,28 @@ class UniqueWithCountsTest(test.TestCase): for i in range(len(x)): self.assertEqual(x[i], tf_y[tf_idx[i]].decode('ascii')) for value, count in zip(tf_y, tf_count): - v = [1 if x[i] == value.decode('ascii') else 0 for i in range(7000)] - self.assertEqual(count, sum(v)) + with self.subTest(value=value, count=count): + v = [1 if x[i] == value.decode('ascii') else 0 for i in range(7000)] + self.assertEqual(count, sum(v)) def testInt32Axis(self): for dtype in [np.int32, np.int64]: - x = np.array([[1, 0, 0], [1, 0, 0], [2, 0, 0]]) - y0, idx0, count0 = gen_array_ops.unique_with_counts_v2( - x, axis=np.array([0], dtype)) - self.assertEqual(y0.shape.rank, 2) - tf_y0, tf_idx0, tf_count0 = self.evaluate([y0, idx0, count0]) - y1, idx1, count1 = gen_array_ops.unique_with_counts_v2( - x, axis=np.array([1], dtype)) - self.assertEqual(y1.shape.rank, 2) - tf_y1, tf_idx1, tf_count1 = self.evaluate([y1, idx1, count1]) - self.assertAllEqual(tf_y0, np.array([[1, 0, 0], [2, 0, 0]])) - self.assertAllEqual(tf_idx0, np.array([0, 0, 1])) - self.assertAllEqual(tf_count0, np.array([2, 1])) - self.assertAllEqual(tf_y1, np.array([[1, 0], [1, 0], [2, 0]])) - self.assertAllEqual(tf_idx1, np.array([0, 1, 1])) - self.assertAllEqual(tf_count1, np.array([1, 2])) + with self.subTest(dtype=dtype): + x = np.array([[1, 0, 0], [1, 0, 0], [2, 0, 0]]) + y0, idx0, count0 = gen_array_ops.unique_with_counts_v2( + x, axis=np.array([0], dtype)) + self.assertEqual(y0.shape.rank, 2) + tf_y0, tf_idx0, tf_count0 = self.evaluate([y0, idx0, count0]) + y1, idx1, count1 = gen_array_ops.unique_with_counts_v2( + x, axis=np.array([1], dtype)) + self.assertEqual(y1.shape.rank, 2) + tf_y1, tf_idx1, tf_count1 = self.evaluate([y1, idx1, count1]) + self.assertAllEqual(tf_y0, np.array([[1, 0, 0], [2, 0, 0]])) + self.assertAllEqual(tf_idx0, np.array([0, 0, 1])) + self.assertAllEqual(tf_count0, np.array([2, 1])) + self.assertAllEqual(tf_y1, np.array([[1, 0], [1, 0], [2, 0]])) + self.assertAllEqual(tf_idx1, np.array([0, 1, 1])) + self.assertAllEqual(tf_count1, np.array([1, 2])) def testInt32V2(self): # This test is only temporary, once V2 is used