查阅资料了许久,很多博客资料都对知识进行详细讲解,但一到 strides,padding 就一带而过,自己发现还是对于步长 stride 和填充 padding 这两个因素对输出张量大小的关系不是很清楚,于是自行代码实验并在此记录。
反卷积的基本资料查阅:
1、介绍了反卷积的各种详细的知识: https://blog.csdn.net/mao_xiao_feng/article/details/71713358
2、给予了动图方便理解: https://blog.csdn.net/u012938704/article/details/52838902

一、strides=[1,1,1,1],padding=”VALID” 情况

反卷积是卷积的逆过程,其参数代表了正向卷积的过程,如:注意此时的参数 padding=”VALID” 反映的是正向卷积过程不进行填充,但是在上采样反卷积过程中,是一直存在填充 0 的。
直接上代码,简单易懂。

  1. import tensorflow as tf
  2. test1 = tf.constant(1.0, shape=[1,2,2,1])
  3. w = tf.constant(1.0, shape=[3,3,1,1])
  4. result = tf.nn.conv2d_transpose(test1, w, output_shape=[1,4,4,1], strides=[1,1,1,1],padding="VALID")
  5. with tf.Session() as sess:
  6. print(sess.run(result))

我们定义了一个 shape 为[1,2,2,1]的张量 test1,即其实可以直接理解为 2×2 的矩阵,因为其他维度(batch size 和 channel)均为 1。
反卷积核为 3×3,输出通道和输入通道不变均为 1。tf.nn.conv2d_transpose反卷积(转置卷积) - 图1

此时 output_shape 只能为[1,4,4,1]了,尺寸扩大了一倍。
现在注意到了,因为其实该 tf.nn.conv2d_transpose 反卷积过程是卷积的逆过程,只有[1,4,4,1]的张量在 strides=[1,1,1,1],padding=”VALID” 情况下卷积才能得到[1,2,2,1]的结果,所以发现里面的参数都是相互联系的,互相已经进行了确认。

  1. [[[[1.]
  2. [2.]
  3. [2.]
  4. [1.]]
  5. [[2.]
  6. [4.]
  7. [4.]
  8. [2.]]
  9. [[2.]
  10. [4.]
  11. [4.]
  12. [2.]]
  13. [[1.]
  14. [2.]
  15. [2.]
  16. [1.]]]]

二、strides=[1,1,1,1],padding=”SAME” 情况

  1. import tensorflow as tf
  2. test1 = tf.constant(1.0, shape=[1,2,2,1])
  3. w = tf.constant(1.0, shape=[3,3,1,1])
  4. result = tf.nn.conv2d_transpose(test1, w, output_shape=[1,2,2,1], strides=[1,1,1,1],padding="SAME")
  5. with tf.Session() as sess:
  6. print(sess.run(result))

若 strides=[1,1,1,1],padding=”SAME” 情况,同上一样,这时候的 output_shape 只能是[1,2,2,1],只能是 2×2 的张量大小经过 3×3 卷积,并且参数 strides=[1,1,1,1],padding=“SAME”,才能得到 2×2 的张量。
tf.nn.conv2d_transpose反卷积(转置卷积) - 图2

  1. [[[[4.]
  2. [4.]]
  3. [[4.]
  4. [4.]]]]

三、strides=[1,2,2,1],padding=”VALID” 情况

当 strides 步长为 2 的时候,在进行 0 填充的时候有一点不同,它在进行填充的时候进行了一些改变,在下图中进行了表示,同时 strides 步长为 2 同样表示的是正向卷积过程的参数(正如上面第一点讨论的 padding=”VALID” 但是也进行了 0 填充),而反卷积过程中,其卷积核移动仍然是一步一步移动的。
话不多说,还是直接上代码。

  1. import tensorflow as tf
  2. test1 = tf.constant(1.0, shape=[1,2,2,1])
  3. w = tf.constant(1.0, shape=[3,3,1,1])
  4. result = tf.nn.conv2d_transpose(test1, w, output_shape=[1,5,5,1], strides=[1,2,2,1],padding="VALID")
  5. with tf.Session() as sess:
  6. print(sess.run(result))

此时发现 output_shape 只能是[1,5,5,1]了,不难理解,在 strides=[1,2,2,1],padding=”VALID” 的情况下,也只有 5×5 的张量能够得到 2×2 的张量。
tf.nn.conv2d_transpose反卷积(转置卷积) - 图3

  1. [[[[1.]
  2. [1.]
  3. [2.]
  4. [1.]
  5. [1.]]
  6. [[1.]
  7. [1.]
  8. [2.]
  9. [1.]
  10. [1.]]
  11. [[2.]
  12. [2.]
  13. [4.]
  14. [2.]
  15. [2.]]
  16. [[1.]
  17. [1.]
  18. [2.]
  19. [1.]
  20. [1.]]
  21. [[1.]
  22. [1.]
  23. [2.]
  24. [1.]
  25. [1.]]]]

四、strides=[1,2,2,1],padding=”SAME” 情况

  1. import tensorflow as tf
  2. test1 = tf.constant(1.0, shape=[1,2,2,1])
  3. w = tf.constant(1.0, shape=[3,3,1,1])
  4. result = tf.nn.conv2d_transpose(test1, w, output_shape=[1,3,3,1], strides=[1,2,2,1],padding="SAME")
  5. with tf.Session() as sess:
  6. print(sess.run(result))

tf.nn.conv2d_transpose反卷积(转置卷积) - 图4

  1. [[[[1.]
  2. [2.]
  3. [1.]]
  4. [[2.]
  5. [4.]
  6. [2.]]
  7. [[1.]
  8. [2.]
  9. [1.]]]]

彩蛋:可能大家发现了其实此时输出的张量也可以是[1,4,4,1](就不再作图了),这也正是印证了为什么当 strides,padding 等等这些参数都确定了还需要指定 out_shape,只有这样才是最后完善的!

https://blog.csdn.net/qq_42192910/article/details/89791539