通过图+代码来理解tensorflow中反卷积

反卷积这个东西老是容易忘,而且很多文章理论讲的很详细,但反卷积实际怎么操作的却没有概念,因此想以自己喜欢的方式(直接上图和代码)写一篇,以便随时翻阅。

卷积

tf中的padding方式有两种,SAME和VALID,官方文档中好像还有个EXPLICIT方式,没了解过…先来仔细理解一下两种模式,以下所有输入矩阵与卷积核无论大小,其每个位置的值都为1:

1、SAME模式,输入4×4,卷积核2×2,步长为1:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,4,4,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d(A, w, strides=1, padding="SAME")
print(transpose_conv)

输出为:

在这里插入图片描述
蓝底为输入图像,灰底为padding的0,红框为卷积核滑动的窗口,示意图为:

在这里插入图片描述
2、VALID模式,输入4×4,卷积核2×2,步长为1:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,4,4,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d(A, w, strides=1, padding="VALID")
print(transpose_conv)

得到输出为:

在这里插入图片描述
示意图:

在这里插入图片描述
从1和2的对比可以看出,SAME模式的意思就是卷积之后的输出尺寸相对于输入图片保持不变(特指在步长为1时),并且优先在右下padding 0。

3、SAME模式,输入4×4,卷积核2×2,步长为2:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,4,4,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d(A, w, strides=2, padding="SAME")
print(transpose_conv)

输出为:

在这里插入图片描述
示意图:

在这里插入图片描述
4、VALID模式,输入4×4,卷积核2×2,步长为2:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,4,4,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d(A, w, strides=2, padding="VALID")
print(transpose_conv)

输出为:

在这里插入图片描述
示意图:

在这里插入图片描述
3和4的对比说明,在不需要补0的时候,两种模式一样。

5、SAME模式,输入5×5,卷积核2×2,步长为2:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,5,5,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d(A, w, strides=2, padding="SAME")
print(transpose_conv)

输出为:

在这里插入图片描述
示意图:

在这里插入图片描述
第五个例子说明,SAME模式不代表完全输入输出尺寸一样,也跟卷积核的步长有关系。这也是最常用的模式。

6、VALID模式,输入5×5,卷积核2×2,步长为2:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,5,5,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d(A, w, strides=2, padding="VALID")
print(transpose_conv)

输出为:

在这里插入图片描述
示意图(橙底为被抛弃的输入部分):

在这里插入图片描述

所以VALID模式是当卷积核全部被包含在输入图像中才有效,才进行卷积,如果滑动窗口会越界,就会抛弃右下的输入不进行卷积。

反卷积(转置卷积)

首先,反卷积中的padding模式与上面有所不同,比如VALID也开始补0了,SAME开始删除了。其次,反卷积里的步长与上面普通卷积的步长不是一个意思,这一点要牢记,这里的步长是扩张的意思,与上面普通卷积同一个意思的步长永远都是1,因此不需要传入这个参数。

1、输入2×2,卷积核2×2,“步长”为1,padding方式为SAME:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,2,2,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d_transpose(A, w, output_shape=[1,2,2,1], strides=1, padding="SAME")
print(transpose_conv)

输出为:

在这里插入图片描述
图解此过程(SAME模式为了让输出与输入大小一样,这时先补一圈0,然后忽略右下的0,即橙底部分):

在这里插入图片描述

2、输入2×2,卷积核2×2,“步长”为1,padding方式为VALID:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,2,2,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d_transpose(A, w, output_shape=[1,3,3,1], strides=1, padding="VALID")
print(transpose_conv)

输出为:

在这里插入图片描述

图解此过程:

在这里插入图片描述
3、输入2×2,卷积核2×2,“步长”为2,padding方式为SAME:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,2,2,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d_transpose(A, w, output_shape=[1,4,4,1], strides=2, padding="SAME")
print(transpose_conv)

输出为:

在这里插入图片描述
图解此过程:

在这里插入图片描述

4、输入2×2,卷积核2×2,“步长”为2,padding方式为VALID:

import tensorflow as tf

A = tf.constant(1.0, shape=[1,2,2,1]) # 四个维度[batch, in_height, in_width, in_channels]
w = tf.constant(1.0, shape=[2,2,1,1]) # 四个维度[filter_height, filter_width, in_channels, out_channels]
transpose_conv = tf.nn.conv2d_transpose(A, w, output_shape=[1,4,4,1], strides=2, padding="VALID")
print(transpose_conv)

输出为:

在这里插入图片描述

图解此过程:

在这里插入图片描述
例子1和2中,只有一种可能的输出,所以过程也应该没什么争议的点。但在例子3中,如果设置SAME模式输出为3×3也能输出,实现方式应该同样是忽略掉右下一行一列。但在普通卷积中SAME模式在步长不为1时,输出 = 输入 / 步长 向上取整,因此我猜测在反卷积SAME模式里,应该输出 = 输入 * 步长才是一般情况下的正确输出,即4×4;

同样的,在例子4中VALID模式设置输出为5×5也能输出,实现方式应该是在右下一行一列补0了,大家看看输出就知道了。而在上面普通卷积的3和4例中,两种模式是一样的,所以我推测在反卷积的这两个例子中输出也应该是一样的,即例子4中VALID模式输出也是4×4。

这也是为什么反卷积所需参数中多了一个输出维度,因为它并不是一个确定的值。可是我猜想既然设计需要传参了,那么两种输出都有其存在的道理,比如下采样中奇数倍的输入图像经普通卷积输出可能会是个偶数,上采样的过程一般都要和下采样对应大小的特征图进行融合,所以这两个过程所得特征图大小要一致,比如FCN,所以在这里偶数倍的输入经步长为2的反卷积得奇数倍的输出也是有存在的道理的,在设计网络的时候注意与下采样过程完全对应即可。

与空洞卷积的区别

我在第一次看到空洞卷积的图的时候,我就与反卷积混淆了,因为光从图上看好像都有一个扩张的操作,但在实际上还是有很大的区别的。

首先作用不同,反卷积主要还是用来上采样的,空洞卷积是用来代替池化增加感受野的。其次也是区别最大的一点:

在这里插入图片描述
上图是空洞卷积的示意图,(a)是普通卷积,(b)是空洞卷积,它们卷积核都是3×3,红色的点才是实际进行卷积操作的点,因此空洞卷积没有扩张的操作,只是取了更大范围的9个点来卷积,实现扩大感受野的想法,和反卷积还是非常不一样的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值