我想训练一个具有两种不同形状的输入张量的网络。每个时代选择一种类型。 这里我写了一小段代码:
import tensorflow as tf
import numpy as np
with tf.Session() as sess:
imgs1 = tf.placeholder(tf.float32, [4, 224, 224, 3], name = 'input_imgs1')
imgs2 = tf.placeholder(tf.float32, [4, 180, 180, 3], name = 'input_imgs2')
epoch_num_tf = tf.placeholder(tf.int32, [], name = 'input_epoch_num')
imgs = tf.cond(tf.equal(tf.mod(epoch_num_tf, 2), 0),
lambda: tf.Print(imgs2, [imgs2.get_shape()], message='(even number) input epoch number is '),
lambda: tf.Print(imgs1, [imgs1.get_shape()], message='(odd number) input epoch number is'))
print(imgs.get_shape())
for epoch in range(10):
epoch_num = np.array(epoch).astype(np.int32)
imgs1_input = np.ones([4, 224, 224, 3], dtype = np.float32)
imgs2_input = np.ones([4, 180, 180, 3], dtype = np.float32)
output = sess.run(imgs, feed_dict = {epoch_num_tf: epoch_num,
imgs1: imgs1_input,
imgs2: imgs2_input})
当我执行它时,imgs.get_shape() 的输出是 (4, ?, ?, 3) 即 imgs.get_shape()[1]=None,imgs.get_shape()[2]=None。
但我会使用 imgs.get_shape() 的输出值来定义内核 (ksize) 和步幅大小 (strides) 的 tf.nn.max_pool() 例如ksize=[1,imgs.get_shape()[1]/6, imgs.get_shape()[2]/6, 1] 在以后的代码中。 我认为 ksize 和 strides 不能支持 tf.Tensor 值。
如何解决这个问题?或者如何有条件地设置imgs的形状?
请您参考如下方法:
当您执行 print(a.get_shape()) 时,您将获得张量 a 的静态形状。假设您在上面的代码中指的是 imgs.get_shape() 而不是 a.get_shape(),则 imgs 的尺寸 1 和 2 动态变化epoch_num_tf 的值。因此,这些维度中的静态形状是未知的,TensorFlow 将其表示为None。
如果你想在后续代码中使用imgs的动态形状,你应该使用tf.shape()运算符将形状作为 tf.Tensor。例如,您可以使用 tf.shape(imgs)[2] 而不是 imgs.get_shape()[2]。
不幸的是,tf.nn.max_pool() 的ksize 和strides 参数不接受 tf.Tensor 值。 (我认为这是一个历史限制,因为这些被配置为相应内核的“属性”而不是“输入”。如果您想请求此功能,请打开 GitHub issue!)一种可能的解决方法是使用另一个 tf.cond():
imgs = ...
# Could also use `tf.equal(tf.mod(epoch_num_tf, 2), 0)` as the predicate.
pool_output = tf.cond(tf.equal(tf.shape(imgs)[2], 180),
lambda: tf.nn.max_pool(imgs, ksize=[1, 180/6, 180/6, 1], ...),
lambda: tf.nn.max_pool(imgs, ksize=[1, 224/6, 224/6, 1], ...))
