在阅读一些深度学习的论文的时候,往往有很多卷积方式,因此本篇博客主要介绍卷积神经网络中各种卷积名称的含义,其输入输出维度如何计算
至于在Pytorch中如何使用这几种卷积,可以参考我的另一篇博客【深度学习个人笔记】Pytorch基本知识
本篇博客参考资料如下:
A guide to convolution arithmetic for deep learning
转置卷积的一个jupyter
卷积
一般说的卷积形式的过程我想不用再赘述,可以用下面这张图来很清晰地表示整个过程:
可见卷积就是通过一个卷积核(kernel)在输入的特征图(input feature map)上进行滑动,同时在每一个位置,卷积核和对应位置的乘积求和得到当前位置的输出,卷积操作的输出称为输出特征图(output feature map)
同时2维卷积可以很容易扩展到更通用的N维卷积上,一次卷积可以用如下的符号来进行表示:
$$ (n,m,k_1,k_2,...,k_N) $$
其中n表示输出特征图的数量,m表示输入特征图的数量,\( k_j \)表示第j个维度上的卷积核长度
而针对于输出的维度,可以用\( o_j \)来表示第j个维度上的卷积输出的尺寸,与以下的元素有关:
- \( i_j \):第j个维度上的输入尺寸
- \( k_j \):第j个维度上的卷积核尺寸
- \( s_j \):第j个维度上的步长
- \( p_j \):第j个维度上的零填充(zero padding)
对于步长和零填充,可以用二维卷积的一个例子很直观的进行理解,如下图所示:
采用上面提到的通用的N维卷积表示的话,则为\( N=2,i_1=i_2=5,k_1=k_2=3,s_1=s_2=2,p_1=p_2=1 \)
除了零填充和步长的特殊情况,我们还需要对多个卷积核以及多个输入特征图(即多通道)的卷积来进行理解,通过下面这张图可以很好理解这一过程:
可见这是一个(3,2,3,3)的二维卷积过程,也可以说卷积核的维度是3×2×3×3,在每一路上输入的特征图1先和第一个卷积核进行卷积,然后特征图2和第二个卷积核进行卷积,并将结果进行逐元素(elementwise)形成每一张输出的特征图
因此,我们可以总结出图像中的通道数与卷积核中的通道数要保持一致,有几个卷积核就有几个输出特征图
对于多个卷积核和多个输入特征图的卷积运算的理解非常重要,因此我这里在放一张图来表示计算过程以加深理解,可以自己算一下这张图里的结果:
卷积的输出尺寸计算
卷积的输出尺寸的计算会比较简单,这是因为第j维中卷积核尺寸、步长和零填充的选择只影响第j维的输出尺寸,不影响除了第j维度的其他维度
在这里我们只讨论2维的卷积(即\( N=2 \))、正方形的输入(\( i_1=i_2=i \))、正方形的卷积核尺寸(\( k_1=k_2=k \))、在每个维度有相等的步长(\( s_1=s_2=s \))、在每个维度有相同的零填充(\( p_1=p_2=p \))
在《A guide to convolution arithmetic for deep learning》一文中将卷积的操作进行了分类讨论,我觉得作者的思路很好,因此直接用论文中的思路进行总结:
- 没有零填充,单位步长(s=1,p=0)
下图展示了没有零填充,单位步长,且i=4,k=3的情况:
输入输出的尺寸可以用如下的公式进行计算:
$$ o=(i-k)+1 $$ 有零填充,单位步长(s=1)
下图展示了有零填充,单位步长,且i=5,k=4,p=2的情况:
输入输出的尺寸可以用如下的公式进行计算(将零填充后的特征图看作没有零填充的):
$$ o=(i-k)+2p+1 $$
对于有零填充的情况,我们可以将其分为两类:half(same) padding和full padding- half padding;使输出的尺寸等于输入的尺寸,对于任意的i且k为奇数(即\( k=2n+1,n\in \mathbb{N} \)),s=1,p=floor(k/2)=n,其输入输出关系如下所示:
$$ o=i+2\lfloor k/2\rfloor -(k-1)=i $$
- full padding:进行卷积通常会减少尺寸,但有时我们也会需要增大尺寸,对于任意的i和k,p=k-1,且s=1,其输入输出关系如下所示:
$$ o=i+2(k-1)-(k-1)=i+(k-1) $$
- 没有零填充,非单位步长(s>1,p=0)
下图展示了没有零填充,非单位步长,且i=5,k=3,s=2的情况:
输入输出的尺寸可以用如下的公式进行计算:
$$ o=\lfloor \frac{i-k}{s}\rfloor+1 $$
其中的floor的函数是考虑到按照非单位步长的滑动的最后一步不一定能到达输入的末尾,因此输入的一些部分不被纳入计算当中 - 有零填充,非单位步长
有零填充,非单位步长是最通用的情况,这里就直接给出其输入输出尺寸的公式,需要注意的是,正因为有了floor函数,对于多种输入尺寸可能有相同的输出尺寸:
$$ o=\lfloor \frac{i+2p-k}{s}\rfloor+1 $$
转置卷积(Transposed Convolution)/反卷积(Deconvolution)
对于转置卷积的讨论也只关注2维的转置卷积(即\( N=2 \))、正方形的输入(\( i_1=i_2=i \))、正方形的卷积核尺寸(\( k_1=k_2=k \))、在每个维度有相等的步长(\( s_1=s_2=s \))、在每个维度有相同的零填充(\( p_1=p_2=p \))
采用矩阵操作来表示卷积
考虑下图所示的卷积操作:
将输入和输出展开为从左到右从上到下的向量,则卷积可以表示为一个稀疏矩阵\( \textbf{C} \)如下所示,其中的非零元表示卷积核中的元素\( w_{i,j} \),其中i和j分别表示卷积核的行和列:
$$ \left [ \begin{matrix} w_{0,0}& w_{0,1} & w_{0,2} & 0 & w_{1,0} & w_{1,1} & w_{1,2} & 0 & w_{2,0} & w_{2,1} & w_{2,2} & 0 & 0 & 0 & 0 & 0 \\ 0 & w_{0,0}& w_{0,1} & w_{0,2} & 0 & w_{1,0} & w_{1,1} & w_{1,2} & 0 & w_{2,0} & w_{2,1} & w_{2,2} & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & w_{0,0}& w_{0,1} & w_{0,2} & 0 & w_{1,0} & w_{1,1} & w_{1,2} & 0 & w_{2,0} & w_{2,1} & w_{2,2} & 0 \\ 0 & 0 & 0 & 0 & 0 & w_{0,0}& w_{0,1} & w_{0,2} & 0 & w_{1,0} & w_{1,1} & w_{1,2} & 0 & w_{2,0} & w_{2,1} & w_{2,2} \end{matrix} \right ] $$
因此整个操作时将输入矩阵展平为16维的向量,并产生4维的输出,最后经过reshape得到2×2的输出矩阵
转置卷积分析
利用上面一节中的例子,现在就来思考一下如何将4维的空间映射到16维的空间,同时还需要保持卷积的连接模式,这一操作就是转置卷积
转置卷积也称为分数步长的卷积(Fractionally-strided convolution)以及反卷积(Deconvolution),其中分数步长的卷积会在论文中出现,比如下面这张图片出自《基于语义通信的低比特率图像语义编码方法》这一论文:
对于一个卷积核\( \textbf{w} \)而言,如果卷积核定义的是卷积,则前向传播和反向传播分别通过乘上\( \textbf{C} \)和\( \textbf{C}^T \)来完成;而如果卷积核定义的是转置卷积,则前向传播和反向传播分别通过乘上\( \textbf{C}^T \)和\( (\textbf{C}^T)^T=\textbf{C} \)来计算
下面就按照几种情况来看一下转置卷积如何进行计算:
- 没有零填充,单位步长,转置卷积
思考一个给定输入的转置卷积,输入是卷积在一些特征图上作用后的输出,因此转置卷积需要恢复这些特征图的形状,假定卷积采用的是3×3卷积核,卷积的输入为4×4,采用单位步长以及零填充,则转置卷积的输入就是2×2,输出为4×4
首先可以直接卷积操作对应的矩阵的转置矩阵来计算转置卷积,这是一种方法
另一种方法来获取这样的转置卷积可以采用一种等效的直接卷积(equivalent direct convolution)来进行计算,比如说对于上面的例子,采用3×3的卷积核,输入为2×2,零填充为2,步长为1,如下图所示:
可见一个输入为4×4的采用单位步长的3×3卷积核等效于输入为2×2的采用单位步长以及零填充为2的3×3卷积核,可以注意到,卷积核和步长的大小仍是一致的,只不过转置卷积的输入进行了零填充
那么我们如何理解上述过程中的零填充呢?在《A guide to convolution arithmetic for deep learning》一文中提到可以用转置卷积的连接模式(connectivity pattern)来理解,比如说等效的直接卷积的输入的左上角的像素只会对输出的左上角像素做出贡献,右上角的像素只会对输出的右上角像素做出贡献等等,为了保证这样的连接模式,输入的零填充需要保证卷积核计算的第一个位置智能接触到左上角的像素,即零填充需要等于卷积核的尺寸减一
因此输入输出的关系如下所示,即一个\( s=1,p=0 \),尺寸为k的卷积操作对应的转置卷积可以用\( k^{'}=k,s^{'}=s,p^{'}=k-1 \)的卷积来表示:
$$ o^{'}=i^{'}+(k-1) $$
有零填充,单位步长,转置卷积
现在我们已经知道一个无零填充卷积的转置等于对输入进行零填充后的卷积(transpose of a non-padded convolution is equivalent to convolving a zero padded input),因此可以设想有零填充卷积的转置等于对输入进行少量的零填充(padded
with less zeros)后的卷积
这样的例子如下图所示:
可见\( i=5,k=4,s=1,p=2 \)的卷积的转置卷积相当于\( i^{'}=6,k^{'}=k,s^{'}=1,p^{'}=1 \)
因此输入输出的关系如下所示,即一个\( s=1 \),尺寸为k,零填充为p的卷积操作对应的转置卷积可以用\( k^{'}=k,s^{'}=s,p^{'}=k-p-1 \)的卷积来表示:
$$ o^{'}=i^{'}+(k-1)-2p $$- half padding,转置卷积:half padding的卷积对应的转置卷积同样是一个half padding卷积,因为half padding的输出尺寸等于输入尺寸,对于任意的i且k为奇数(即\( k=2n+1,n\in \mathbb{N} \)),s=1,p=floor(k/2)=n对应的转置卷积为\( k^{'}=k,s^{'}=s,p^{'}=p \)的卷积,其输入输出关系如下所示:
$$ o^{'}=i^{'}+(k-1)-2p=i^{'}+2n-2n=i^{'} $$
- full padding,转置卷积:full padding的卷积对应的转置卷积其实就是上面的
没有零填充,单位步长,转置卷积
情况,即等效卷积为无零填充卷积,其输入输出关系如下所示,即一个\( s=1,p=k-1 \)的卷积的转置卷积为\( k^{'}=k,s^{'}=s,p^{'}=0 \)的卷积:
$$ o^{'}=i^{'}+(k-1)-2p=i^{'}-(k-1) $$
- 没有零填充,非单位步长,转置卷积
s>1的卷积对应的转置卷积的等效卷积是s<1的,这也是为什么转置卷积被称为分数步长的卷积
一个有助于理解分数步长的卷积的的例子如下所示,其中i=5,k=3,s=2:
可见在这个例子中0被插入在了输入的单元之间,这使得卷积核相比于单位步长移动的更慢
假定卷积是没有零填充的,同时输入的尺寸i保证了i-k是s的倍数,在这种情况下,对应的转置卷积的等效卷积为\( k^{'}=k,s^{'}=1,p^{'}=k-1 \),同时输入为在原始的输入单元之间插入s-1个零,输入输出的尺寸为:
$$ o^{'}=[(s-1)*(i^{'}-1)+i^{'}]-1+k=s(i^{'}-1)+k $$
上式可采用卷积的输入输出计算公式进行推导
- 有零填充,非单位步长,转置卷积
当卷积的输入尺寸i可以满足i+2p-k是s的倍数时,比如下图中的例子,其中i=5,k=3,s=2,p=1:
采用k,s和p的卷积,且输入尺寸i可以满足i+2p-k是s的倍数时,对应的转置卷积的等效卷积为\( k^{'}=k,s^{'}=1,p^{'}=k-p-1 \),同时输入为在原始的输入单元之间插入s-1个零,输入输出的尺寸为:
$$ o^{'}=[(s-1)*(i^{'}-1)+i^{'}]-1+k-2p=s(i^{'}-1)+k-2p $$
以上的关系对输入的尺寸i进行了限制,这种限制可以通过引入另一个参数\( a\in { 0,\ldots,s-1 } \)从而使得对于s种可能情况下都有相同的\( i^{'} \),即一个k,s和p的卷积对应的转置卷积的等效卷积为\( k^{'}=k,s^{'}=1,p^{'}=k-p-1 \),同时输入为在原始的输入单元之间插入s-1个零,而a=(i+2p-k) mod s表示添加到输入的右部和底部的0的个数,此时输入输出关系如下所示:
$$ o^{'}=s(i^{'}-1)+a+k-2p $$
(个人认为这里的添加到输入的右部和底部的零的个数不一定是一样的,只不过这里假设输入是一个正方形,如果输入的宽度和高度不一致,则添加的零的个数也不一致)
下图给出了存在a参数的例子,其中i=6,k=3,s=2,p=1:
空洞卷积
空洞卷积即dilated convolution
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。