tensorflow获取tensor的shape

参考 [1],可以直接用 tensor.shape.as_list() 获得 tensor 的形状,例如:

import tensorflow as tf

ph = tf.placeholder("float32", [None, 3])
const = tf.constant([[1, 2, 3], [4, 5, 6]])

'''直接用 as_list 获得形状'''
print(ph.shape.as_list())
print(const.shape.as_list())

'''以前只会这种老方法'''
with tf.Session() as sess:
	ph_shape = tf.shape(ph)
    print("placeholder shape:", sess.run(ph_shape,
                                         feed_dict={ph: [[1, 2, 3]]}))
	c_shape = tf.shape(const)
    print("constant shape:", sess.run(c_shape))

Traps

对形状带 None 的 tensor 用了 tf.squeeze 之后,as_list 报错:

ValueError: as_list() is not defined on an unknown TensorShape.

场景是:我将一个 tensor 输入到一个模型之后,输出的形状是 [None, 1, 1, 4096],后续要输入到一个 fc 层,于是先对它用了一次 tf.squeeze,但再对 squeeze 之后的 tensor 用 as_list 就报错,而如果用 tf.squeeze 之前用 as_list 就不会
可能是因为不知道有 None 那维会不会也被 squeeze 掉吧,因为对 tf.constant 用就没事。
后来是用 tf.reshape 代替 tf.squeeze 解决的:

import tensorflow as tf
import numpy as np

'''对 constant'''
c = tf.constant([[[1, 2, 3]]])
print(c.shape.as_list())
c_squeeze = tf.squeeze(c)  # 对 constant 用 squeeze
print(c_squeeze.shape.as_list())  # 可以

'''对 placeholder'''
ph = tf.placeholder("float32", [None, 1, 1, 3])
print(ph.shape.as_list())  # squeeze 前,可以

ph_squeeze = tf.squeeze(ph)  # 对 placeholder 用 squeeze
# print(ph_squeeze.shape.as_list())  # squeeze 后,报错

ph_reshape = tf.reshape(ph, [-1, ph.shape.as_list()[-1]])  # 换成 reshape
print(ph_reshape.shape.as_list())  # 可以

'''老方法'''
with tf.Session() as sess:
	ph_squeeze_shape = tf.shape(ph_squeeze)
    print("ph_squeeze shape:", sess.run(ph_squeeze_shape,
                                        feed_dict={ph: np.zeros([1, 1, 1, 3])}))

TL;DR

起源是调用 tf.layers.dense 的时候,可以直接输入一个 tensor 和输出的维度,而不用指定输入的 shape,它就可以自动推断形状,让我想起 keras 写模型的时候也是这样的,我还以为在指定 fc 层的 weight 形状的时候用 tensor.shape[1] 这样的也行,结果在初始化 weight 的 tf.truncated_normal 处报错了。

References

  1. tf.keras.backend.int_shape

你可能感兴趣的:(机器学习,tensorflow)