japreiss
japreiss

Reputation: 11251

constructing a TensorFlow tensor that behaves as empty when passed to tf.concat()

I am constructing a computation graph with topology that varies based on some hyperparameters. At some point, a concatenation takes place:

c = tf.concat([a, b], axis=-1)

The tensor a has shape (None, m). The tensor b has shape (None, n) where n depends on the hyperparameters. For one value of the hyperparameters, the tensor b should be conceptually empty, e.g. we want c and a to be the same.

I can build the graph successfully with the following:

b = tf.placeholder(tf.float32, (None, 0), name="Empty")

but then, if I run a session, TensorFlow raises an InvalidArgumentError stating:

You must feed a value for placeholder tensor 'Empty' with dtype float and shape [?,0]

Is there any way to construct a tensor that will behave as empty in the concat operation, but does not require feeding a spurious input?

Obviously, I'm aware that I could just add a special case, wrapper, etc. in the code where I construct the graph. I'm hoping to avoid that.

Full code:

import tensorflow as tf
import numpy as np

a = tf.placeholder(tf.float32, (None, 10))
b = tf.placeholder(tf.float32, (None, 0), name="Empty")
c = tf.concat([a, b], axis=-1)
assert c.shape.as_list() == [None, 10]

with tf.Session() as sess:
    a_feed = np.zeros((100, 10))
    c = sess.run(c, {a : a_feed})

Upvotes: 4

Views: 5167

Answers (3)

Xavier Wang
Xavier Wang

Reputation: 1

As the message indicates, you also have to feed b

with tf.Session() as sess:
    a_feed = np.zeros((100, 10))
    b_feed = np.zeros((100, 0)) 
    c = sess.run(c, {a : a_feed, b: b_feed})

It passes on my computer.

Upvotes: 0

dopexxx
dopexxx

Reputation: 2636

If you were not to use tf.placeholder() to feed your data, but tf.Estimator, then the solution is trivial, since you could just define:

b = tf.zeros([a.shape[0].value, 0])

So, in case the shape of a is known,

c = tf.concat([a,b],axis=-1)
assert c.shape == a.shape

will always succceed.

Upvotes: 1

kempy
kempy

Reputation: 616

You can use tf.placeholder_with_default which does not require the placeholder to be fed.

import tensorflow as tf
import numpy as np

# Hparams
batch_size = 100
a_dim = 10
b_dim = 0

# Placeholder for a which is required to be fed.
a = tf.placeholder(tf.float32, (None, a_dim))

# Placeholder for b, which doesn't have to be fed.
b_default = np.zeros((batch_size, b_dim), dtype=np.float32)
b = tf.placeholder_with_default(
    b_default, (None, b_dim), name="Empty"
)
c = tf.concat([a, b], axis=-1)
assert c.shape.as_list() == [None, a_dim + b_dim]

with tf.Session() as sess:
    a_feed = np.zeros((batch_size, a_dim))
    b_feed = np.ones((batch_size, b_dim))
    c_out = sess.run(c, {a : a_feed})
    # You can optionally feed in b:
    # c_out = sess.run(c, {a : a_feed, b : b_feed})
    print(c_out)

Upvotes: 0

Related Questions