user2205763
user2205763

Reputation: 1619

Organizing tensor into batches of dynamically shaped tensors

I have the following situation:

My issue is this:

What I tried:

If the tf.dynamic_partition function were to accept tensor values for num_partition, then it seems that my problem would be solved. However, I am back to square one since this is not the case.

Thank you all for your help! Let me know if anything is unclear

P.S. Here is a visual representation of the intended process:

Image batch to prediction batch

Upvotes: 2

Views: 1251

Answers (1)

user2205763
user2205763

Reputation: 1619

I ended up finding a solution to this using TensorArray and tf.while_loop:

def batch_reconstructor(tensor, partitions, batch_size):
    """
    Take a tensor of shape (batch_size, 4) and a 1-D partitions tensor as well as the scalar batch_size
    And reconstruct a TensorArray that preserves the original batching

    From the partitions, we can get the maximum amount of tensors within a batch. This will inform the padding we need to use.
    Params:
        - tensor: The tensor to convert to a batch
        - partitions: A list of batch indices. The tensor at position i corresponds to batch # partitions[i]
    """
    tfarr = tf.TensorArray(tf.int32, size=batch_size, infer_shape=False)

    _, _, count = tf.unique_with_counts(partitions)
    maximum_tensor_size = tf.cast(tf.reduce_max(count), tf.int32)

    padding_tensor_index = tf.cast(tf.gather(tf.shape(tensor), 0), tf.int32)

    padding_tensor = tf.expand_dims(tf.cast(tf.fill([4], -1), tf.float32), axis=0) # fill with [-1, -1, -1, -1]
    tensor = tf.concat([tensor, padding_tensor], axis=0)

    def cond(i, acc):
        return tf.less(i, batch_size)

    def body(i, acc):
        partition_indices = tf.reshape(tf.cast(tf.where(tf.equal(partitions, i)), tf.int32), [-1])

        partition_size = tf.gather(tf.shape(partition_indices), 0)

        # concat the partition_indices with padding_size * padding_tensor_index
        padding_size = tf.subtract(maximum_tensor_size, partition_size)
        padding_indices = tf.reshape(tf.fill([padding_size], padding_tensor_index), [-1])

        partition_indices = tf.concat([partition_indices, padding_indices], axis=0)

        return (tf.add(i, 1), acc.write(i, tf.gather(tensor, partition_indices)))

    _, reconstructed = tf.while_loop(
        cond,
        body,
        (tf.constant(0), tfarr),
        name='batch_reconstructor'
    )

    reconstructed = reconstructed.stack()
    return reconstructed

Upvotes: 1

Related Questions