Search code examples
pythontensorflowsparse-matrix

Tensorflow sparse to dense operations failing when placeholder provided shape


I'm having an issue multiplying a sparse tensor (a sparse placeholder) by a dense tensor in Tensorflow. I am also encountering problems converting a sparse tensor to a dense tensor directly. I've searched but so far haven't found an example of this problem.

TL;DR

The computation works if the sparse placeholder has its shape argument set to None, but if I provide a shape like (3,3) it fails.

Here is the code that works:

import tensorflow as tf
import numpy as np

matrix_place = tf.placeholder(tf.float32, name="foo", shape=(3,2))
sparse_place = tf.sparse_placeholder(tf.float32, name="bar", shape=None) # Note shape is None

mul_result = tf.sparse_tensor_dense_matmul(sparse_place, matrix_place)

matrix_input = np.ones((3,2))
sparse_input = tf.SparseTensorValue([[0,0], [1,1], [2,2]], [1, 2, 3], (3, 3))

with tf.Session() as sess:
    result = sess.run(mul_result, feed_dict={sparse_place: sparse_input, matrix_place: matrix_input})
    print(result)

Output (as expected):

[[1. 1.]
 [2. 2.]
 [3. 3.]]

Now, if I change this line:

sparse_place = tf.sparse_placeholder(tf.float32, name="bar", shape=None)

to this:

sparse_place = tf.sparse_placeholder(tf.float32, name="bar", shape=(3,3))

(which matches the shape of the tf.SparseTenorValue(...) that I'm feeding in), I get the following error:

Traceback (most recent call last):
  File "testing_sparse3.py", line 13, in <module>
    result = sess.run(mul_result, feed_dict={sparse_place: sparse_input, matrix_place: matrix_input})
  File "C:\Anaconda3\envs\tensorflow-cpu\lib\site-packages\tensorflow\python\client\session.py", line 905, in run
    run_metadata_ptr)
  File "C:\Anaconda3\envs\tensorflow-cpu\lib\site-packages\tensorflow\python\client\session.py", line 1115, in _run
    raise ValueError('Tensor %s may not be fed.' % subfeed_t)
ValueError: Tensor Tensor("bar/shape:0", shape=(2,), dtype=int64) may not be fed.

Things I've Tried

If I switch from matrix multiplication (which involves 2 tensors):

sparse_place = tf.sparse_placeholder(tf.float32, name="bar", shape=(3,3))

mul_result = tf.sparse_tensor_dense_matmul(sparse_place, matrix_place)

to simply summing the elements of the sparse tensor (which only involves the sparse tensor):

sparse_place = tf.sparse_placeholder(tf.float32, name="bar", shape=(3,3))

mul_result = tf.sparse_tensor_reduce_sum(sparse_place)

it does not produce an error and gives the correct result. But if I try to convert the sparse tensor to a dense tensor (an op which also only involves the sparse tensor):

sparse_place = tf.sparse_placeholder(tf.float32, name="bar", shape=(3,3))

mul_result = tf.sparse_tensor_to_dense(sparse_place)

the error returns.

I did see a related issue but it appears to have been merged already. I tried converting the indices/values/shape passed to tf.SparseTensorValue into numpy arrays with dtypes int64/float32/int64 respectively, but the problem persisted. I also tried converting the (3,3) shape passed to the sparse placeholder into a numpy int64 array but that also failed.

Any ideas? Am I missing something very obvious? I am using Python 3.5 and Tensorflow v1.6.0 (CPU) on Windows.

Thanks!


Solution

  • When you say shape = (3, 3) TensorFlow treats that shape as a constant for shape inference, and disallows feeding that shape tensor. We should probably detect that you're feeding its actual value and let it pass. File a github issue.