tensorflow中踩过的坑

静态和动态维度

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.conv2dtf.layers.conv2d都可以用来定义一个卷积层,但是两个函数又有所不同。我个人感觉
tf.layers.conv2d应该是在tf.nn.conv2d的基础上进行封装的,因为它的参数相对而言要简单很多,最主要的参数有如下:

  • 输入tensorinput
  • 滤波器的数量filters
  • stride
  • padding

而滤波器的初始化,则完全可以自身完成。

tf.nn.conv2d函数而言,主要的参数如下:

  • 输入tensorinput
  • 滤波器tensorfilter
  • 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

猜你喜欢

转载自blog.csdn.net/weixin_33711641/article/details/87233455