我试图取消堆叠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
我尝试使用tf.shape(x)
推断seqlen并将其用作num
,但我得到Expected int for argument 'num' not <tf.Tensor 'strided_slice:0' shape=() dtype=int32>
答案 0 :(得分:6)
我相信这可以在别处回答,但这里有一个答案。您不能将tf.unstack
与不可推断的维度一起使用。
这是因为张量流是如何设计定义张量变换的计算图形的。每个操作都添加一个节点,每个Tensor都是节点之间的边缘。当你tf.unstack
张量时,你会产生多个新的张量(边缘)。如果从tf.unstack
操作创建的新张量的数量未定义,则计算图具有未定义的边数,这些边不能是。
不向图表添加多个新边的操作允许输入具有推断尺寸的张量(大多数操作)。
为了解决这个问题,对于批量操作的情况有两个选择,例如,当您尝试tf.unstack
时,尺寸为(batch_size, ...)
且batch_size
的张量可以推断。
我会将batch_shape
参数用于keras.topology.Input
。
生成的权重Tensors总是可以与使用不同batch_size
生成的另一个模型互换。
除非你需要访问具有不可推断维度的计算图,否则没有理由不这样做。
在您知道最大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')
当您实际提供batch_size
时,它会为第一个batch_size
索引生成未堆叠的Tesors,为其余的[]
生成{{1}}个空张贴。