具有动态形状的tf.unstack

Bel*_*val 3 tensorflow

我正在尝试取消堆叠Tensor,因为我需要一个序列作为RNN的输入.我使用可变序列长度,这阻止我正确使用tf.unstack.

def MapToSequences(x):
    # x.get_shape().as_list() = [64, 1, None, 512]
    x = tf.squeeze(x)
    # tf.shape(x) = [None, None, None], at runtime would be [64, seqlen, 512]
    x = tf.transpose(x, perm=[1, 0, 2])
    # [seqlen, 64, 512]
    # Here I'd like to unstack with seqlen as num
    x = tf.unstack(x) # Cannot infer num from shape (?, ?, ?)
    return x
Run Code Online (Sandbox Code Playgroud)

我尝试使用tf.shape(x)推断seqlen并将其用作num,但我得到了Expected int for argument 'num' not <tf.Tensor 'strided_slice:0' shape=() dtype=int32>

Jos*_*ert 6

我相信这可能会在其他地方得到解答,但这里有一个答案.您不能使用tf.unstack不可推断的维度.这是因为张量流是如何设计定义张量变换的计算图形的.每个操作都添加一个节点,每个Tensor都是节点之间的边缘.当你tf.unstack使用Tensor时,你会生成多个新的张量(边缘).如果从tf.unstack操作创建的新张量的数量未定义,则计算图具有未定义的边数,这些边不能是.不向图形添加多个新边的操作允许具有推断尺寸的输入张量(大多数操作).

为了解决这个问题,有两种选择对于批处理操作非常有用,例如,当您尝试tf.unstack使用尺寸(batch_size, ...)并且batch_size可以推断的Tensor时.

选择1

我会用这个batch_shape论点来keras.topology.Input.生产的张量总是可以与另一种不同的模型互换batch_size.

除非您需要访问具有不可推断维度的计算图,否则您没有理由不应该使用此路由.

选择2

在您知道最大值的情况下,第二个选项batch_size是使用tf.dynamic_partition.

tensor = tf.placeholder(tf.float32,shape=(None,10))
partitions = tf.range(max_batch_size)
num_partitions = max_batch_size
partitioned = tf.dynamic_partition(tensor, partitions, num_partitions, name='dynamic_unstack')
Run Code Online (Sandbox Code Playgroud)

当你实际给出batch_size它时,它将为第一个batch_size索引产生未堆叠的测试器,并[]为其余索引产生空的张量.