def test_shape_expand_first_dim(self): input_data = ragged_factory_ops.constant([[0, 1, 2], [], [3]]) actual = ragged_conversion_ops.ragged_to_dense(input_data, shape=[4, 4]) self.assertAllEqual( actual, [[0, 1, 2, 0], [0, 0, 0, 0], [3, 0, 0, 0], [0, 0, 0, 0]]) self.assertEqual(actual.shape.as_list(), [4, 4])
def test_skip_eager_shape_half_limit_tensor_shape(self): # Eager would produce a shape of [2, 4] input_data = ragged_factory_ops.constant([[0, 1, 2, 3], [], [4], []]) actual = ragged_conversion_ops.ragged_to_dense( input_data, shape=tensor_shape.TensorShape([2, None])) result = actual.shape.as_list() # This is equal to [2, 4] in eager, or [2, None] in non-eager. self.assertEqual(result[0], 2)
def test_empty_tensor_with_shape(self): input_data = RaggedTensor.from_value_rowids( values=constant_op.constant([], dtype=dtypes.int64), value_rowids=constant_op.constant([], dtype=dtypes.int64), nrows=constant_op.constant(2, dtype=dtypes.int64), validate=True) actual = ragged_conversion_ops.ragged_to_dense(input_data, default_value=3, shape=[2, 3]) self.assertAllEqual(actual, [[3, 3, 3], [3, 3, 3]])
def _compare_to_reference(self, ragged_tensor, expected=None, default_value=None): treatment = ragged_conversion_ops.ragged_to_dense( ragged_tensor, default_value=default_value) control = ragged_tensor.to_tensor(default_value=default_value) self.assertAllEqual(control, treatment) if expected is not None: self.assertAllEqual(expected, treatment)
def testRaggedTensorToTensor(self, rt_input, expected, ragged_rank=None, default=None, expected_shape=None): rt1 = ragged_factory_ops.constant(rt_input, ragged_rank=ragged_rank) dt1 = ragged_conversion_ops.ragged_to_dense(rt1, default_value=default) rt2 = rebuild_ragged_tensor_with_value_rowids(rt1) dt2 = ragged_conversion_ops.ragged_to_dense(rt2, default_value=default) for (rt, dt) in [(rt1, dt1), (rt2, dt2)]: self.assertIsInstance(dt, ops.Tensor) self.assertEqual(rt.dtype, dt.dtype) self.assertTrue(dt.shape.is_compatible_with(rt.shape)) if expected_shape is not None: expected = np.ndarray(expected_shape, buffer=np.array(expected)) self.assertAllEqual(dt, expected)
def test_broadcast_default_no_placeholder(self): # Again, this functionality is not supported. It fails more gracefully # when creating the op. input_data = ragged_factory_ops.constant([[[[1, 2], [3, 4]]], []], ragged_rank=1) # default_value has a 2 x 1 dimension. default_value = constant_op.constant([[5], [6]], shape=None) actual = ragged_conversion_ops.ragged_to_dense( input_data, default_value=default_value) expected = [[[[1, 2], [3, 4]]], [[[5, 5], [6, 6]]]] self.assertAllEqual(actual, expected)
def test_broadcast_default(self): # This test is commented out. The functionality here is not supported. # The dense dimension here is 2 x 2 input_data = ragged_factory_ops.constant([[[[1, 2], [3, 4]]], []], ragged_rank=1) # This placeholder has a 2 x 1 dimension. default_value = make_placeholder([[5], [6]]) actual = ragged_conversion_ops.ragged_to_dense( input_data, default_value=default_value) expected = [[[[1, 2], [3, 4]]], [[[5, 5], [6, 6]]]] self.assertAllEqual(actual, expected)
def testError(self, rt_input, error, error_type=(ValueError, errors.InvalidArgumentError), default=None, ragged_rank=None, shape=None): rt = ragged_factory_ops.constant(rt_input, ragged_rank=ragged_rank) with self.assertRaisesRegexp(error_type, error): self.evaluate( ragged_conversion_ops.ragged_to_dense(rt, default_value=default, shape=shape)) rt_placeholder = nest.map_structure(make_placeholder, rt, expand_composites=True) with self.assertRaisesRegexp(error_type, error): self.evaluate( ragged_conversion_ops.ragged_to_dense(rt_placeholder, default_value=default, shape=shape))
def run_benchmark(self, shape=(100, 100), ragged_rank=None, dtype=dtypes.float32, fill=None, default_shape=(), output_shape=None, min_iters=1000): """Run a benchmark with the specified configuraiton parameters. Args: shape: Bounding box for the input ragged tensor. ragged_rank: Ragged rank for the input ragged tensor. Defauts to `len(shape)-1`. dtype: Data type for the input ragged tensor. fill: How full each dimension should be (0-1). Corresponds 1:1 with `shape`. Defaults to 0.8 for each dimension. default_shape: Shape for the default (padding) value. output_shape: Output shape -- ragged tensor will be padded or cropped to this shape. min_iters: Minimum iterations for benchmark. """ if ragged_rank is None: ragged_rank = len(shape) - 1 if fill is None: fill = [0.8 for _ in shape] # Build the inputs for the op. rt_input = self._generateRaggedTensor(shape, ragged_rank, dtype, fill) default_value = constant_op.constant(self._generateRaggedTensor( default_shape, 0, dtype), dtype=dtype) mbs = np.prod(shape) / (2**20) with session.Session(config=benchmark.benchmark_config()) as sess: extras = { 'shape': shape, 'ragged_rank': ragged_rank, 'dtype': dtype, 'fill': fill, 'default_shape': default_shape } rt = ragged_factory_ops.constant(rt_input, dtype, ragged_rank=ragged_rank) # Inputs for with_splits: splits_rt_placeholder = ragged_factory_ops.placeholder( dtype, ragged_rank, shape[ragged_rank + 1:]) splits_feed_dict = {splits_rt_placeholder: sess.run(rt)} # Inputs for with_rowids: rowids_feed_dict = {} rowids_rt_placeholder = rebuild_ragged_tensor_with_value_rowids( rt, rowids_feed_dict, sess) # Common arguments for benchmarks: run_op_benchmark_kwargs = dict(sess=sess, store_memory_usage=True, min_iters=min_iters, burn_iters=max(5, min_iters // 10), mbs=mbs, extras=extras) ragged_to_dense_with_splits = ragged_conversion_ops.ragged_to_dense( splits_rt_placeholder, default_value=default_value) self.run_op_benchmark(op_or_tensor=ragged_to_dense_with_splits.op, name='ragged_to_dense_with_splits', feed_dict=splits_feed_dict, **run_op_benchmark_kwargs) ragged_to_tensor_with_splits = splits_rt_placeholder.to_tensor( default_value=default_value) self.run_op_benchmark(op_or_tensor=ragged_to_tensor_with_splits.op, name='ragged_to_tensor_with_splits', feed_dict=splits_feed_dict, **run_op_benchmark_kwargs) ragged_to_dense_with_rowids = ragged_conversion_ops.ragged_to_dense( rowids_rt_placeholder, default_value=default_value) self.run_op_benchmark(op_or_tensor=ragged_to_dense_with_rowids.op, name='ragged_to_dense_with_rowids', feed_dict=rowids_feed_dict, **run_op_benchmark_kwargs) ragged_to_tensor_with_rowids = rowids_rt_placeholder.to_tensor( default_value=default_value) self.run_op_benchmark(op_or_tensor=ragged_to_tensor_with_rowids.op, name='ragged_to_tensor_with_rowids', feed_dict=rowids_feed_dict, **run_op_benchmark_kwargs)
def test_gradient(self, shape, rt_value, rt_grad, default_value, default_grad, output_value, output_grad, ragged_rank=None): """Tests that ragged_to_dense generates the right gradient. Args: shape: The `shape` arg for `ragged_to_dense`. rt_value: The `rt_input` arg for `ragged_to_dense`. rt_grad: The expected gradient for `rt_value`. Corresponds 1:1 with `rt_value`. default_value: The `default_value` arg for `ragged_to_dense`. default_grad: The expected gradient for `default_value`. Corresponds 1:1 with `default_value`. output_value: The expected output of `ragged_to_dense`. output_grad: The gradient for the output (used to generate the gradients `rt_grad` and `default_grad`). Corresponds 1:1 with `output_value`. ragged_rank: Ragged rank for `rt_value`. """ if context.executing_eagerly(): return rt_value = ragged_factory_ops.constant(rt_value, dtype=dtypes.float32, ragged_rank=ragged_rank) rt_grad = ragged_factory_ops.constant(rt_grad, dtype=dtypes.float32, ragged_rank=ragged_rank) default_value = constant_op.constant(default_value, dtype=dtypes.float32) default_grad = constant_op.constant(default_grad, dtype=dtypes.float32) output_value = constant_op.constant(output_value, dtype=dtypes.float32, shape=shape) output_grad = constant_op.constant(output_grad, dtype=dtypes.float32, shape=shape) shape = tensor_shape.as_shape(shape) # There are different code paths for ragged_to_dense, depending on whether # the RaggedTensor was created from row_splits or value_rowids. Make sure # that we test both. for partition_type in ['row_splits', 'value_rowids']: # There are different code paths when computing the gradient for # default_value, depending on whether shape info is statically available; # make sure that we test all code paths. for shape_info in ['known', 'unknown_dims', 'unknown_rank']: rt_val = self.rt_with_partition_type(rt_value, partition_type) rt_val = self.wrap_in_placeholder(rt_val, shape_info) default_val = self.wrap_in_placeholder(default_value, shape_info) shape_val = self.wrap_in_placeholder(shape, shape_info) out = ragged_conversion_ops.ragged_to_dense( rt_val, default_val, shape_val) self.assertAllClose(out, output_value) actual_flat_values_grad, actual_default_grad = gradients_impl.gradients( ys=out, xs=(rt_value.flat_values, default_value), grad_ys=output_grad) self.assertIsInstance(actual_flat_values_grad, indexed_slices.IndexedSlices) actual_flat_values_grad = ops.convert_to_tensor( actual_flat_values_grad) actual_values_grad = rt_value.with_flat_values( actual_flat_values_grad) self.assertAllClose(actual_values_grad, rt_grad) self.assertAllClose(actual_default_grad, default_grad)
def test_shape_limit_shape_is_tensor_int32(self): input_data = ragged_factory_ops.constant([[0, 1, 2, 3], [], [4], []]) actual = ragged_conversion_ops.ragged_to_dense( input_data, shape=constant_op.constant([2, 3], dtype=dtypes.int32)) self.assertAllEqual(actual, [[0, 1, 2], [0, 0, 0]]) self.assertEqual(actual.shape.as_list(), [2, 3])
def test_shape_half_limit_tensor_shape(self): input_data = ragged_factory_ops.constant([[0, 1, 2, 3], [], [4], []]) actual = ragged_conversion_ops.ragged_to_dense( input_data, shape=tensor_shape.TensorShape([2, None])) self.assertAllEqual(actual, [[0, 1, 2, 3], [0, 0, 0, 0]])
def test_shape_limit_tuple(self): input_data = ragged_factory_ops.constant([[0, 1, 2, 3], [], [4], []]) actual = ragged_conversion_ops.ragged_to_dense(input_data, shape=(2, 3)) self.assertAllEqual(actual, [[0, 1, 2], [0, 0, 0]]) self.assertEqual(actual.shape.as_list(), [2, 3])
def testDocStringExamples(self): """Example from ragged_to_tensor.__doc__.""" rt = ragged_factory_ops.constant([[9, 8, 7], [], [6, 5], [4]]) dt = ragged_conversion_ops.ragged_to_dense(rt) self.assertAllEqual(dt, [[9, 8, 7], [0, 0, 0], [6, 5, 0], [4, 0, 0]])
def testError(self, rt_input, default, error, ragged_rank=None): rt = ragged_factory_ops.constant(rt_input, ragged_rank=ragged_rank) with self.assertRaisesRegexp(error[0], error[1]): ragged_conversion_ops.ragged_to_dense(rt, default_value=default)