本文主要解释: (1)传统离散信号处理中的卷积维度 L = M+N -1;(2)matlab 卷积函数中的shape=full, same, valid所导致的不同卷积输出维度,和tensorflow的tf.nn.conv2d中的padding=same,valid 导致的不同输出维度;(3) pytorch中的卷积函数中设置的 padding以及torch官方给的卷积的shape计算公式(https://pytorch.org/docs/stable/nn.html)
本文主要解释这三者在计算二维卷积输出维度时的差别与联系。不想看推导您可以翻到最后直接看结论。
——————————————————————————————————————————————————
首先来将传统的离散信号处理,大多数人在学信号与系统或者数字信号处理的时候,在学离散卷积的时候,肯定都学过:如果输入的两个离散序列长度分别是M和N,那么他们卷积之后得到的离散序列长度 L=M + N -1。对于二维卷积,输入矩阵P×Q 和 M×N;卷积之后的矩阵 W×H,在两个维度方向上都满足上述公式:W = P+M-1;H = Q+N-1.
有信号处理背景的同学,在初次接触pytorch的卷积及其维度公式时,大多会感觉,怎么本来卷积的维度 L=M + N - 1,在这里就变得这么复杂了。上图中的公式,stride是指卷积时卷积核移动的步长,dilation是指卷积核元素间的距离,传统信号处理的卷积中stride=1,dilation=1,上图公式简化下来,就是H_out = H_in +2×padding - kernel_size +1;H_in对应M,kernel_size 对应N;一边是加N一边是减kernel_size 看起来似乎有些矛盾,另一个没考虑到的是padding,如果令padding=kernel_size -1,那么两个公式就一样了。其中原因,从卷积的示意图可以很直观地理解。
传统信号处理中的二维卷积,都是默认从卷积核右下角与被卷积图像左上角对齐开始。
而在pytorch中,默认从卷积核左上角与被卷积图像左上角对齐开始。输入图像通过zero padding来调节宽高,之后进行卷积操作
因此,要实现(a)中的卷积效果,在pytorch中,我们需要将padding 设置为 padding = (k-1, k-1)=(2, 2), k为kernel_size,如图(c)所示。
当然,pytorch中也可以将padding设置为其他数值。正是因为要支持不同情况的padding,比如(2,3);(0,2)等等,所以在卷积示意图中要看成从卷积核左上角与被卷图像的左上角对齐开始。
然后我们在来看文章开头提出的与shape=full, same, valid之间的关系
在matlab并不直接输入padding等于多少,而是选择上述三种方式。在tensorflow中,是选择padding='SMAE' 或者‘VALID’.
首先,选择full的话,就相当于 padding = kernel_size - 1,matlab的卷积函数中,默认的就是full,也就是满足信号处理中离散卷积的维度公式 L=M+N-1的那个。
选择same的话,就是说输入输出的矩阵维度要保持一致,那么其实我们可以用pytorch官方给的那个公式算一下,默认stride=1,dilation=1
H_out = H_in +2×padding - kernel_size +1 = H_in 得出 padding = (kerner_size - 1 ) / 2.
通常kernel size 为奇数,所以 padding算出来是整数没问题。如果kernel size 是偶数的话,这时候即使选择了same 模式,输出的矩阵维度也是和输入矩阵维度不一致的,例如 这位博主做了实验:https://blog.csdn.net/songbinxu/article/details/85328522 (这位博主用的是tensorflow 中的卷积选择 'SAME'模式,matlab具体怎样还不清楚,有兴趣可以试一下)
(看了很多博客,在讲same模式的时都只举了一个3×3卷积核例子,在输入图像上填充了一圈0, 即padding=(1,1),都没指出padding和kernel size 的具体关系hhhhhh)
第三个是valid模式,就是直接padding =0. 即不填充,然后直接 从 卷积核左上角与被卷图像的左上角对齐开始 进行卷积操作。
————————————————————————————————————————————
综上,二维离散卷积的 三种维度计算模式 之间的关系 都理清楚了。
(1) 传统信号处理中离散卷积的维度公式 L=M+N-1,对应的是padding=kernel_size -1 (M对应输入图像维度,N对应kernel size,然后默认stride=1,dilation=1),这时候 pytorch 官方的那个公式就和L = M + N -1形式一样了
(2)在matlab中,full 模式 对应padding=kernel_size -1,
(2)在matlab 和tensorflow 中 ,same 模式对应 padding = (kerner_size - 1 ) / 2, 当kernel_size 是奇数时,输出图像与输入图像的宽高相同(stride=1时),当kernel size 为偶数时,输出图像 不保持与输入图像相同,具体可以看这位博主的实验:https://blog.csdn.net/songbinxu/article/details/85328522 (matlab具体怎样还不清楚,有兴趣可以试一下)
(3)在matlab 和 tensorflow中,valid模式对应padding=0