卷积运算
- 这里以二维卷积为例讨论:
-
正方形输入(
i1=i2=i ) -
正方形卷积核大小(
k1=k2=k ) -
相同的步长(
s1=s2=s ) -
相同的零填充(
p1=p2=p )
第一种情况:
从输入图像的最右边开始,一个步长一个步长直到抵达图像的另外一边
输入图像的大小为:
第二种情况:
输入图像的大小为:
第三种情况: 比较特殊,名为Half padding(SAME模式)
即是输出图像大小与输入图像大小相同, 假设
满足
第四种情况: Full padding,即输出比原始图像还大的图像,
满足
第五种情况:
这种情况下输出图像大小为:
注意的是:求 下限函数解释了最后一步并不和卷积层抵达输入另外一侧相一致。也就是会遗漏一些输入像素
第六种情况:
输出图像大小为:
一个有趣的现象是:
假如
逆卷积过程
第一种情况:卷积操作
逆卷积操作
输出图像大小为:
第二种情况:明白上面非填充卷积等价于一个全零填充的逆卷积操作,因此,一般零填充的卷积操作等价于一个更少零填充的逆卷积操作。
开头结尾都减小p个,也就是:
第三种情况: 半填充的卷积(SAME模式情况下)
卷积
逆卷积表示为:
第四种情况: 既然知道一个全填充逆卷积过程对应于无填充的卷积过程,那么可以推断一个全填充卷积过程对应一个无填充卷积过程:
全填充卷积
逆卷积表示为:
第五种情况: 对于
下面有一个例子:
这可以帮助理解为什么称为分数步长卷积,因为零填充在输入的单元中,让卷积核移动的速度比一个单元步长要慢的多。
可以先假设
那么逆卷积过程
第六种情况:零填充,步长
卷积可以描述为:
与之对应的逆卷积过程表示为:
同理,
第七种情况: 零填充,步长
卷积可以描述为:
相当于对引入一个值
这种情况下:
卷积描述为:
与之对应的逆卷积过程表示为:
同理,
在Tensorflow上的思考:
tensorflow:tf.nn.conv2d_transpose
conv2d_transpose(
value, -->[batch, height, width, in_channels] for NHWC
filter, -->[height, width, output_channels, in_channels]
output_shape, -->A 1-D Tensor representing the output shape
strides, -->A list of ints
padding='SAME', -->A string, either 'VALID' or 'SAME'.
data_format='NHWC',
name=None
)
其中 在卷积过程中,padding的方式分为两种:SAME与VALID
其实SAME模式下表达为
“VALID” only ever drops the right-most columns (or bottom-most rows).
“SAME” tries to pad evenly left and right, but if the amount of columns to be added is odd, it will add the extra column to the right, as is the case in this example (the same logic applies vertically: there may be an extra row of zeros at the bottom).
而在逆卷积过程中,只不过的是
Tensorflow中逆卷积过程中两种方式均是指定卷积过程的Padding方式,可以看到源码中
Tensorflow 源码
gen_nn_ops.conv2d_backprop_input(input_sizes=output_shape_,
filter=filter,
out_backprop=value,
strides=strides,
padding=padding,
data_format=data_format,
name=name)
也就是tf.nn.conv2d_transpose 会根据制定输出大小和其他条件反推出输入大小,而该大小与真实输入大小不一致的话会出现报错。
举例子如下:
设定Valid模式下
可以反向计算出
与
InvalidArgumentError (see above for traceback): Conv2DSlowBackpropInput: Size of out_backprop doesn't match computed:
actual = 3, computed = 1
[[Node: conv2d_transpose_9 = Conv2DBackpropInput[T=DT_FLOAT, data_format="NHWC", padding="VALID", strides=[1, 2, 2, 1], use_cudnn_on_gpu=true, _device="/job:localhost/replica:0/task:0/gpu:0"](conv2d_transpose_9/output_shape, Const_19, Const_18)]]
仅设定
在SAME模式下(Half Padding):
可以反向计算出
InvalidArgumentError (see above for traceback): Conv2DSlowBackpropInput: Size of out_backprop doesn't match computed:
actual = 3, computed = 2
[[Node: conv2d_transpose_14 = Conv2DBackpropInput[T=DT_FLOAT, data_format="NHWC", padding="VALID", strides=[1, 2, 2, 1], use_cudnn_on_gpu=true, _device="/job:localhost/replica:0/task:0/gpu:0"](conv2d_transpose_14/output_shape, Const_29, Const_28)]]
仅满足
也就是当
Reference: