静态和动态维度
TensorFlow: Shapes and dynamic dimensions一文中,对张量的静态和动态维度做了描述。
- 使用tf.get_shape()获取静态维度
- 使用tf.shape获取动态维度
如果你的placeholder输入的维度都是固定的情况下,使用get_shape()。但是很多情况下,我们希望想训练得到的网络可以用于任意大小的图像,这时你的placeholder就的输入维度都是[None,None,None,color_dim]这样的,在这种情况下,后续网络中如果需要得到tensor的维度,则需要使用tf.shape。
tf.nn.conv2d和tf.layers.conv2d
tf.nn.conv2d
和tf.layers.conv2d
都可以用来定义一个卷积层,但是两个函数又有所不同。我个人感觉
tf.layers.conv2d
应该是在tf.nn.conv2d
的基础上进行封装的,因为它的参数相对而言要简单很多,最主要的参数有如下:
- 输入tensor
input
- 滤波器的数量
filters
stride
padding
而滤波器的初始化,则完全可以自身完成。
对tf.nn.conv2d
函数而言,主要的参数如下:
- 输入tensor
input
- 滤波器tensor
filter
stride
padding
主要区别就在于,使用tf.nn.conv2d的时候,用户需要自己初始化滤波器tensor,而不是自动初始化。除此之外,两者还有一个十分重要的区别:
-
tf.layers.conv2d
在初始化滤波器的时候,只需要给出滤波器个数,其实也就是输出结果的featue map个数,也就是缺省认为输入函数的tensor的feature map 数量是已知的。 -
tf.nn.conv2d
在初始化滤波器的时候,filter参数的维度为:[filter_height, filter_width, in_channels, out_channels]
,相当于显式的(in_chann)告知了输入tensor的feature map个数。
在定义u-net的时候,需要使用tf.slice
函数取出一个tensor的一部分,虽然这个tensor的维度是(?, ?, ?, 512)维度,但是使用tf.slice以后,输出的tensor则变成了(?, ?, ?, ?)维度,继续将这样的一个tensor输入tf.layers.conv2d
则会下面的错误:
The channel dimension of the inputs should be defined. Found `None`.
但是将这个tensor给tf.nn.conv2d
则不会产生相同的错误,因为在定义filter
的时候,定义了in_channels
,相当于纠正了tf.slice的错误。
所以,在定义一些较为复杂网络graph的时候,最好还是使用tf.nn.conv2d
,而不是使用tf.layers.conv2d
。
网友评论