1、反卷积原理
反卷积原理不太好用文字描述,这里直接以一个简单例子描述反卷积。
假设输入如下:
[[1,0,1],
[0,2,1],
[1,1,0]]
反卷积卷积核如下:
[[ 1, 0, 1],
[-1, 1, 0],
[ 0,-1, 0]]
现在通过strides=2来进行反卷积,使得尺寸由原来的3*3变为6*6.那么在Tensorflow框架中,反卷积的过程如下(不同框架在裁剪这步可能不一样):
其实通过绘制的这张图,就已经把原理讲的很清楚,大致步骤就是,先填充0,然后进行卷积,卷积过程和上一篇讲述的一致。最后一步还要进行裁剪。
2、代码实现
上一篇文章我们只针对输出通道数为1进行代码实现,在这篇文章中,反卷积我们将输出通道设置为多个,这样更符合实际场景。
先定义输入和卷积核:
input_data=[[[1,0,1],
[0,2,1],
[1,1,0]],
[[2,0,2],
[0,1,0],
[1,0,0]],
[[1,1,1],
[2,2,0],
[1,1,1]],
[[1,1,2],
[1,0,1],
[0,2,2]]]
weights_data=[
[[[ 1, 0, 1],
[-1, 1, 0],
[ 0,-1, 0]],
[[-1, 0, 1],
[ 0, 0, 1],
[ 1, 1, 1]],
[[ 0, 1, 1],
[ 2, 0, 1],
[ 1, 2, 1]],
[[ 1, 1, 1],
[ 0, 2, 1],
[ 1, 0, 1]]],
[[[ 1, 0, 2],
[-2, 1, 1],
[ 1,-1, 0]],
[[-1, 0, 1],
[-1, 2, 1],
[ 1, 1, 1]],
[[ 0, 0, 0],
[ 2, 2, 1],
[ 1,-1, 1]],
[[ 2, 1, 1],
[ 0,-1, 1],
[ 1, 1, 1]]]
]
上面定义的输入核卷积核,在接下的运算过程如下图所示:
可以看到实际上,反卷积和卷积基本一致,差别在于,反卷积需要填充过程,并在最后一步需要裁剪。
有几点需要注意:
1、每个卷积核需要旋转180°后,再传入tf.nn.conv2d_transpose函数中,因为tf.nn.conv2d_transpose内部会旋转180°,所以提前旋转,再经内部旋转后,能包传卷积核和我们使用的卷积核的数据排列一致。
2、我们定义的输入的shape为[c, h, w]需要转为tensorflow所使用的[n, h, w, c]。
3、我们定义的卷积核shape为[out_c, in_c, h, w]需要转为tensorflow反卷积中所使用的[h, w, out_c, in_c]
感谢作者:https://www.jianshu.com/p/f0674e48894c