tensorflow: tf.sparse_tensor_to_dense does not have a gradient

Differentiating tf.sparse_tensor_to_dense and also tf.sparse_to_dense returns None. At the same time, a hacky way of converting a sparse tensor to a dense tensor by using tf.sparse_add works. Please see the code below:

indices = tf.placeholder(tf.int64, (None, 2))
values = tf.placeholder(tf.float32, (None,))
sparse_tensor = tf.SparseTensor(indices, values, (5, 7))
dense_tensor1 = tf.sparse_tensor_to_dense(sparse_tensor)
dense_tensor2 = tf.sparse_add(tf.zeros((5, 7)), sparse_tensor)
sum1 = tf.reduce_sum(dense_tensor1)
sum2 = tf.reduce_sum(dense_tensor2)
print tf.gradients(sum1, values)
>>> [None]
print tf.gradients(sum2, values)
>>> [tf.Tensor ...]

What related GitHub issues or StackOverflow threads have you found by searching the web for your problem?

Didn’t find anything.

Environment info

  1. A link to the pip package you installed:

pip install --user https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.11.0rc1-cp27-none-linux_x86_64.whl

  1. The output from python -c "import tensorflow; print(tensorflow.__version__)"

0.11.0rc1

If possible, provide a minimal reproducible example (We usually don’t have time to read hundreds of lines of your code)

Please see the code above.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 18 (10 by maintainers)

Most upvoted comments

Meanwhile, you guys could at least print a warning, raise an exception, deprecate this API, or add a line to the documentation. I do like Tensorflow, and I think you are doing a great job, but for people outside Google it is often very unclear which ops are “mostly deprecated” in favor of which.

This uses sparse to dense op, which is mostly deprecated in favor of scatter_nd op. That op has a gradient. We should change the sparse to dense Python wrapper to call scatter_nd.

The example provided above still does return None – added sparse_tensor_dense_matmul and sparse_to_dense to the mix because in my use case I can (with some overhead) use each of those functions.

Executed:

$ docker run -it tensorflow/tensorflow:1.4.0-py3 python3
Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> indices = tf.placeholder(tf.int64, (None, 2))
>>> values = tf.placeholder(tf.float32, (None,))
>>> sparse_tensor = tf.SparseTensor(indices, values, (5, 7))
>>> dense_tensor1 = tf.sparse_tensor_to_dense(sparse_tensor)
>>> dense_tensor2 = tf.sparse_to_dense(indices, (5, 7), values)
>>> dense_tensor3 = tf.sparse_add(tf.zeros((5, 7)), sparse_tensor)
>>> dense_tensor4 = tf.sparse_tensor_dense_matmul(sparse_tensor, tf.zeros((7, 5)))
>>> sum1 = tf.reduce_sum(dense_tensor1)
>>> sum2 = tf.reduce_sum(dense_tensor2)
>>> sum3 = tf.reduce_sum(dense_tensor3)
>>> sum4 = tf.reduce_sum(dense_tensor4)
>>> print(tf.gradients(sum1, values))
[None]
>>> print(tf.gradients(sum2, values))
[None]
>>> print(tf.gradients(sum3, values))
[<tf.Tensor 'gradients_2/SparseTensorDenseAdd_grad/GatherNd:0' shape=(?,) dtype=float32>]
>>> print(tf.gradients(sum4, values))
[<tf.Tensor 'gradients_3/SparseTensorDenseMatMul/SparseTensorDenseMatMul_grad/Sum:0' shape=(?,) dtype=float32>]

Ready to copy & run:

import tensorflow as tf
indices = tf.placeholder(tf.int64, (None, 2))
values = tf.placeholder(tf.float32, (None,))
sparse_tensor = tf.SparseTensor(indices, values, (5, 7))
dense_tensor1 = tf.sparse_tensor_to_dense(sparse_tensor)
dense_tensor2 = tf.sparse_to_dense(indices, (5, 7), values)
dense_tensor3 = tf.sparse_add(tf.zeros((5, 7)), sparse_tensor)
dense_tensor4 = tf.sparse_tensor_dense_matmul(sparse_tensor, tf.zeros((7, 5)))
sum1 = tf.reduce_sum(dense_tensor1)
sum2 = tf.reduce_sum(dense_tensor2)
sum3 = tf.reduce_sum(dense_tensor3)
sum4 = tf.reduce_sum(dense_tensor4)
print(tf.gradients(sum1, values))
print(tf.gradients(sum2, values))
print(tf.gradients(sum3, values))
print(tf.gradients(sum4, values))

BTW this op now has a gradient.

On Jun 16, 2017 2:45 PM, “Olivia” notifications@github.com wrote:

Closed #6391 https://github.com/tensorflow/tensorflow/issues/6391.

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/tensorflow/tensorflow/issues/6391#event-1127563146, or mute the thread https://github.com/notifications/unsubscribe-auth/ABtim7j8NV_YNQw3c-PZJOnLAmmWm7WSks5sEvczgaJpZM4LQSVP .

Automatically closing due to lack of recent activity. Since this issue is old at this point, please reopen the issue if it still occurs when tried with the latest version of Tensorflow. Thank you.

Here is the solution.

  1. open YOURPATH/tensorflow/python/ops/sparse_grad.py
  2. Remove line 33 ops.NotDifferentiable(“SparsetoDense”)
  3. At the end, append

@ops.RegisterGradient(“SparseToDense”) def _SparseToDenseGrad(op, grad): sparse_indices, output_shape, _, _ = op.inputs

sparse_values_grad = array_ops.gather_nd(grad, sparse_indices) default_value_grad = math_ops.reduce_sum(grad) - math_ops.reduce_sum( sparse_values_grad) return [ array_ops.zeros_like(sparse_indices), array_ops.zeros_like(output_shape), sparse_values_grad, default_value_grad ]

This implementation is from TF2.0 version.

I second that printing a warning should be in order for this. I only found a bug in my code relating to this issue by looking at the graph in tensorboard and saw that one of my variables was a different colour…