1. 概念
Deconvolutional Networks, Zeiler, CVPR 2010
首先我们要厘清这两个概念, 就是Deconvolution和Convolutional Sparse Coding
很多人在谈这两个问题的时候使用的都是Deconvolution, 有一点混淆
我觉得混淆的原因在于它出现的时候就把这两个概念没有分开
Deconvolution和Convolutional Sparse Coding都出自我们上面贴的这篇paper, 名字叫Deconvolutional Networks, 其实讲的却是Convolutional Sparse Coding, 其实Deconvolution只是实现卷积稀疏编码的一个手段

https://www.zhihu.com/question/43609045?sort=created
Decovolution
https://blog.csdn.net/qiusuoxiaozi/article/details/77269740
这篇里面提到的两篇文章对Deconvolution这个问题讲的比较清楚
Deconvolution很多人翻成"反卷积"或者"逆卷积"我觉得容易引起误会, 其实它叫转置卷积(Transposed Convolution)更合适, 说白了就是从用卷积结果乘以展平的卷积核转置得到卷积前结果的过程
举个栗子, 4x4输入, Kernal大小3x3, p=0, s=1, 输出是2x2
更多动图可以看https://github.com/vdumoulin/conv_arithmetic

输入的矩阵可以展开为16维向量, 记作x
输出的矩阵可以展开为4维向量, 记作y
卷积运算就可以用矩阵乘积来表示y = Cx
C就是如下的稀疏矩阵

怎么算出来的呢, 我们来推导一下

所以x′ = C^T y′, 这个就是Deconvolution
转置卷积的过程可以看下面这个图

上面是stride=0的情况, 如果stride≠1, 情况看起来会稍微复杂一点
5x5输入, Kernal大小3x3, p=0, s=2, 输出是2x2, 那Transposed Convolution的推导就是这样
转置卷积的过程变成了下面这个图

当stride≠1的时候, 转置卷积的卷积核就变成了一个带"洞"的卷积, 这时候给它起了个名字叫fractional stride convolution(微步卷积), 为什么带洞? 其实我理解就是为了使卷积的步长变为正向卷积的1/s倍, 核将以一个更小的步伐移动, 比如正向的stride=2, 那转置的stride=0.5, 这就是说图像上动了一个pixel, 卷积核只能动0.5个pixel, 就是要过去两个pixel卷积核才能动一步
转置卷积其实就是一种特殊的卷积形式, 转置卷积可以用作解码(从深度信息解回图像大小)

上面这个图像就是Deconvolution一个非常重要的应用, GAN生成图像
但是只能还原shape大小, 不能还原原value值
按照CS231n中的说法, 我们可以把它看作Learnable Upsampling, 有一点要注意, Deconvolution并不一定比Bicubic这些cheap upsampling方法的效果要好
https://distill.pub/2016/deconv-checkerboard/
容易产生Checkerboard Artifacts
Deconvolution有一个重要应用就是可视化Feature, https://blog.csdn.net/tina_ttl/article/details/52048765
Convolutional Sparse Coding
刚才说了, Deconvolution和Convolutional Sparse Coding之所以会混淆, 是因为Zeiler是在同一篇paper里提出的两个概念
那Convolutional Sparse Coding又是什么呢, 就是用卷积做Sparse Coding
Sparse Coding就是用一组过完备基来表示向量, 得到的向量具有一定的稀疏性, 在Deconvolutional Networks中, 就是用Deconvolution的权重来作为这组过完备基, 为保证稀疏性, 优化的目标函数和一般的网络就不一样

通常, 我们训练网络最终就是要结果尽量接近样本值, 但是Convolutional Sparse Coding呢, 不止要结果尽量接近样本值, 还要结果尽量稀疏, 就是高亮的那部分
所以, 训练的时候也要比训练一般的神经网络复杂, 要交替优化差异项和正则项
一般是先固定filter学习feature map, 然后再固定feature map学习filter, iterally, 这个可以参考Sc训练字典的方法
Convolutional Sparse Coding比之前的Sc的好处就是Inference的时候会更快, 因为之前Sc在训练阶段把输入数据集的超完备基学到了, 在测试阶段还是要通过凸优化的方法去求其特征值
所以说白了, Convolutional Sparse Coding就是用CNN的结构来训练稀疏表达的字典, 与一般的CNN的差异就是目标函数不止要差异尽量小, 还要feature具有稀疏性, 而Deconvolution根据我们上面的分析, 本质上就是一种特殊的卷积, 只不过它能放大图像的大小, 从空间压缩的feature还原到原图大小, 所以常被用在encoder-decoder结构中, 还有一个重大的用途就是Visualization of Networks
就是我们常引用的那篇
Zeller et al., “Visualizing and understanding convolutional networks”. ECCV 2014
2. Pytorch中的ConvTranspose2d
https://ptorch.com/docs/8/torch-nn

Pytorch或者Keras中的ConvTranspose2d就是我们之前说的Deconvolution, 和Conv2d不同的是, 多了一个output_padding参数, 那这个参数是什么意思呢?https://www.jianshu.com/p/01577e86e506
首先要确立这个概念, 就是Transpose conv就是conv的转置, 就是说Transpose conv和conv还是一个过程
所以stride,padding, dilation还是Conv2D的含义
这个公式用来计算输入输出的形状关系

- o:
output size
- i:
input size
- p:
padding size
- k:
kernel size
- s:
stride size
建立在Conv2D和TranposeConv2D只是同一过程从两个方向去理解, 那当我们去计算TransposeConv2D的输出维度的时候, 实际上就是在知道输出维度的情况下, 反推输入维度
s=1
当s=1时, o与i是一一对应的关系, 那此时在一定的padding, kernel情况下, 我们要根据input大小算output大小, 就是用上面那个公式从o反推i

栗子1, k=3, p=2, o=7, i=?

栗子2, k=3, p=1, o=5, i=?

举这两个栗子为了说明什么呢?就是在TransposeConv2D里, padding和在Conv中是一样的, 都是加在待卷积图上的, 不同的是, 在Conv2D中, 待卷积图是input, 在TransposeConv2D中, 待卷积图是output
s≠1
s≠1的时候, 那个向下取整就不能忽略掉了, 这个时候就出现一个问题, 就是input和output不是一一对应关系, 一个output可能对应着好多个input
比如k=2, s=2, p=0, i=4 => o=2
而k=2, s=2, p=0, i=5 => o=2
这两种情况下, output的大小都是2, 那问题来了, 在TransposeConv2D中, 如果input size=2, output size究竟是4还是5呢?
已知o的情况下, 我们可以得到s个i的解

为了解决上面我们说的在TransposeConv2D中的尴尬的input和output 1对多问题, 就有了这个output_padding
output_padding就是给i(0)后面加的那个东西

也就是说, 如果output_padding=0, 那就认为向下取整实际上没有用, 比如k=2, s=2, p=0, i=4 => o=2为这种情况, +n就是在待卷积图上再加上n行n列, 比如k=2, s=2, p=0, i=5 => o=2这种情况就是给i=4加上n=1的行列
不管是padding还是output_padding, 我们都可以理解成是给待卷积图上额外加的, 这样比较容易理解, 但是padding=1是在整个外圈加一圈(相当于加两行两列), output_padding=1就是给待卷积图加上1行1列
网友评论