I have some code that runs fine in eager mode, which processes a list of tensors. The length of the list is known at runtime only, and the list elements have different shapes (e.g. different row number but same number of cols), also known at runtime. I would like to write a graph version of this code.
To avoid re-tracing at each call with different list length / element dimensions I would like to use an input_signature with None at the dynamic dimensions. A list of tensors is not an acceptable signature, so I tried two different options:
Using a
RaggedTensor, and aRaggedTensorSpecin theinput_signature, but the problem is thatNonein that case already means a ragged axis, and there is no value I can use for dimensions that are not ragged but not known yet.Using a
TensorArray(withinfer_shape=False), but I get an error when using aTensorArraySpecin theinput_signatureand calling the function (maybe it is not possible to use aTensorArraySpechere at all ?).
Here is a minimal example:
a = tf.constant([[1, 2, 3],
[4, 5, 6]], dtype=tf.float32) #Shape [2, 3]
b = tf.constant([[7, 8, 9]], dtype=tf.float32) #Shape [1, 3]
#Version with ragged tensor
values = tf.concat([a, b], axis=0)
lens = tf.stack([tf.shape(t)[0] for t in [a, b]])
ragged_tensor = tf.RaggedTensor.from_row_lengths(values, lens)
ragged_tensor.shape #TensorShape([2, None, 3])
#ragged_tensor represents a list of 2 tensors of shape [None, 3] (the 2 can vary but the 3 is fixed)
@tf.function(input_signature=(tf.RaggedTensorSpec(shape=[None, None, 3], dtype=tf.float32),))
def myFunc(x):
return tf.math.reduce_sum(x)
myFunc(ragged_tensor) #ValueError
#Version with tensor array
array = tf.TensorArray(tf.float32, size=2, infer_shape=False, element_shape=[None, 3])
array = array.write(0, a)
array = array.write(1, b)
#array represents a list of 2 tensors of shape [None, 3] (the 2 can vary but the 3 is fixed)
@tf.function(input_signature=(tf.TensorArraySpec(element_shape=[None, 3], dtype=tf.float32, infer_shape=False),))
def myFunc1(x):
return tf.math.reduce_sum(x.concat())
myFunc1(array) #TypeError
The full error messages:
ValueError: Incompatible CompositeTensor TypeSpecs: RaggedTensorSpec(TensorShape([None, None, 3]), tf.float32, 2, tf.int64) vs. RaggedTensorSpec(TensorShape([2, None, 3]), tf.float32, 1, tf.int32) -- Types are not compatible: 2 vs 1
TypeError:If shallow structure is a sequence, input must also be a sequence. Input has type: <class 'tensorflow.python.ops.tensor_array_ops.TensorArray'>
How can I make it work ?