Skip to main content
 首页 » 编程设计

python之tensorflow:如何用不同的条件语句设置张量的形状

2024年10月17日28txw1958

我想训练一个具有两种不同形状的输入张量的网络。每个时代选择一种类型。 这里我写了一小段代码:

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], ...))