我有一个形状[None, 9, 2]
张量流的输入(None
是批量的)。
要对其执行进一步操作(例如matmul),我需要将其转换为[None, 18]
形状。怎么做?
答案 0 :(得分:37)
您可以使用tf.reshape()轻松完成,而无需了解批量大小。
x = tf.placeholder(tf.float32, shape=[None, 9,2])
shape = x.get_shape().as_list() # a list: [None, 9, 2]
dim = numpy.prod(shape[1:]) # dim = prod(9,2) = 18
x2 = tf.reshape(x, [-1, dim]) # -1 means "all"
无论批处理大小在运行时中是什么,最后一行中的-1
表示整个列。您可以在tf.reshape()中看到它。
谢谢@kbrose。对于未定义多个维度的情况,我们可以tf.shape()使用tf.reduce_prod()。
x = tf.placeholder(tf.float32, shape=[None, 3, None])
dim = tf.reduce_prod(tf.shape(x)[1:])
x2 = tf.reshape(x, [-1, dim])
tf.shape()返回一个Tensor形状,可以在运行时进行评估。可以看到tf.get_shape()和tf.shape()之间的区别in the doc。
我还尝试了另一个tf.contrib.layers.flatten()。第一种情况最简单,但它无法处理第二种情况。
答案 1 :(得分:12)
flat_inputs = tf.layers.flatten(inputs)
答案 2 :(得分:3)
您可以使用动态整形在运行时通过tf.batch
获取批量维度的值,将整个新维度集合计算为tf.reshape
。这是一个在不知道列表长度的情况下将平面列表重新整形为方形矩阵的示例。
tf.reset_default_graph()
sess = tf.InteractiveSession("")
a = tf.placeholder(dtype=tf.int32)
# get [9]
ashape = tf.shape(a)
# slice the list from 0th to 1st position
ashape0 = tf.slice(ashape, [0], [1])
# reshape list to scalar, ie from [9] to 9
ashape0_flat = tf.reshape(ashape0, ())
# tf.sqrt doesn't support int, so cast to float
ashape0_flat_float = tf.to_float(ashape0_flat)
newshape0 = tf.sqrt(ashape0_flat_float)
# convert [3, 3] Python list into [3, 3] Tensor
newshape = tf.pack([newshape0, newshape0])
# tf.reshape doesn't accept float, so convert back to int
newshape_int = tf.to_int32(newshape)
a_reshaped = tf.reshape(a, newshape_int)
sess.run(a_reshaped, feed_dict={a: np.ones((9))})
你应该看到
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]], dtype=int32)