本文翻译自: 《Understanding static and dynamic shapes》, 如有侵权请联系删除, 仅限于学术交流, 请勿商用。 如有谬误, 请联系指出。
TensorFlow中的张量具有静态形状属性, 该属性在图形构造期间确定。 静态形状可能未指定。 例如, 我们可以定义一个形状张量[None, 128]:
import tensorflow as tf
a = tf.placeholder(tf.float32, [None, 128])
这意味着第一个维度可以是任何大小, 并将在 Session.run()
期间动态确定。 您可以按如下方式查询Tensor的静态形状:
static_shape = a.shape.as_list() # returns [None, 128]
要获得张量的动态形状, 可以调用 tf.shape
方法, 它返回一个给定张量代表的形状:
dynamic_shape = tf.shape(a)
可以使用 Tensor.set_shape()
方法设置张量的静态形状:
a.set_shape([32, 128]) # static shape of a is [32, 128]
a.set_shape([None, 128]) # first dimension of a is determined dynamically
您可以使用 tf.reshape
函数动态重塑给定的张量:
a = tf.reshape(a, [32, 128])
一个在可用时返回静态形状, 不可用时返回动态形状的函数会很方便。 一个比较好的程序实现如下:
def get_shape(tensor):
static_shape = tensor.shape.as_list()
dynamic_shape = tf.unstack(tf.shape(tensor))
dims = [s[1] if s[0] is None else s[0]
for s in zip(static_shape, dynamic_shape)]
return dims
现在假设我们想通过将第二维和第三维折叠成一个来将三维张量转换为二维张量。 我们可以使用 get_shape()
函数来做到这一点:
b = tf.placeholder(tf.float32, [None, 10, 32])
shape = get_shape(b)
b = tf.reshape(b, [shape[0], shape[1] * shape[2]])
值得注意的是, 无论形状是否静态指定, 这都有效。
事实上, 我们可以编写一个通用的 reshape()
函数来折叠任何维度列表:
import tensorflow as tf
import numpy as np
def reshape(tensor, dims_list):
shape = get_shape(tensor)
dims_prod = []
for dims in dims_list:
if isinstance(dims, int):
dims_prod.append(shape[dims])
elif all([isinstance(shape[d], int) for d in dims]):
dims_prod.append(np.prod([shape[d] for d in dims]))
else:
dims_prod.append(tf.prod([shape[d] for d in dims]))
tensor = tf.reshape(tensor, dims_prod)
return tensor
然后折叠第二个维度就会变得非常容易:
b = tf.placeholder(tf.float32, [None, 10, 32])
b = reshape(b, [0, [1, 2]])