pytorch卷积操作nn.Conv中的groups参数用法解释

MobileNetV1《MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications》_程大海的博客-CSDN博客

《MobileNetV2: Inverted Residuals and Linear Bottlenecks》_程大海的博客-CSDN博客

《ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices》_程大海的博客-CSDN博客

pytorch中MobileNetV2分类模型的源码注解_程大海的博客-CSDN博客

pytorch卷积操作nn.Conv中的groups参数用法解释_程大海的博客-CSDN博客_pytorch中groups


最近在项目中使用到了MobileNet分类网络,MobileNet网络中使用到了深度可分离卷积操作,深度可分离卷积将传统卷积操作分成两步来处理。假设输入的特征图feature_map大小为[H, W, C],深度可分离卷积第一步使用C组NxNx1的卷积核对每个输入通道in_channel进行卷积,卷积输出结果特征图feature_map大小为[H, W, C],然后使用M个1x1xC的卷积核进行卷积操作,输出的特征图大小为[H, W, M]。深度可分离卷积的目的是减少卷积操作的参数量和计算量,从而提升运算速度。深度可分离卷积表示如下图:

pytorch卷积操作nn.Conv中的groups参数用法解释_第1张图片

在MobileNet网络中有一步是要对每个通道进行单独的卷积操作,在pytorch实现的MobileNetV2代码中用到了nn.Conv函数的groups参数来完成逐个通道的卷积操作,如下图:

pytorch卷积操作nn.Conv中的groups参数用法解释_第2张图片

查询pytorch官方文档对于groups参数的解释,看的一脸懵逼???大概能看出来这玩意是用来对输入channel和输出channel进行分组的,具体怎么分组,分组后怎么计算,还是一脸懵逼???

pytorch卷积操作nn.Conv中的groups参数用法解释_第3张图片

先大概总结一下groups参数的含义:假设卷积操作的输入通道数是in_channels,输出通道数是out_channles,分组数是groups,分组卷积就是把原本的整体卷积操作分成groups个小组来分别处理,其中每个分组的输入通道数是in_channles / groups,输出通道数是out_channles / groups,最后将所有分组的输出通道数concat,得到最终的输出通道数out_channles,所以在做分组卷积的时候,in_channels和out_channels需要被groups整除

下面就自己动手来试验一下这个参数的用法:

1、首先定义卷积操作的输入数据:

# 输入数据的维度[N, C, H, W] -> [1, 4, 1, 1]
# 输出通道数4
data = torch.arange(4, dtype=torch.float32).view(1,4, 1, 1)
print(data)

自定义的输入数据长和宽都是1,有4个通道。长下面这个样子:

pytorch卷积操作nn.Conv中的groups参数用法解释_第4张图片

2、实验groups=1场景

kernel_weight = torch.nn.Parameter(torch.arange(16, dtype=torch.float32).view(4, 4, 1, 1))
print(kernel_weight)
conv_groups_1 = nn.Conv2d(in_channels=4, out_channels=4, kernel_size=1, groups=1, bias=False)
conv_groups_1.weight = kernel_weight
conv_groups_1(data)

这里为了方便后续卷积结果的计算,我没有使用随机数产生的卷积核,使用了自定义的卷积核,并且卷积过程中没有使用bias。输出结果如下:

pytorch卷积操作nn.Conv中的groups参数用法解释_第5张图片

上图中红框中的内容是4个卷积核,绿色框中的内容是卷积结果。这些结果是怎么计算得到的呢?请看下图:

pytorch卷积操作nn.Conv中的groups参数用法解释_第6张图片

这是groups=1的场景,groups=1时只有一个分组,所有的输入通道分别和所有的卷积核进行卷积操作,生成卷积结果。下面看一下groups=2的场景。

3、实验groups=2的场景

kernel_weight_2 = torch.nn.Parameter(torch.arange(8, dtype=torch.float32).view(4, 2, 1, 1))
print(kernel_weight_2)
conv_groups_2 = nn.Conv2d(in_channels=4, out_channels=4, kernel_size=1, groups=2, bias=False)
conv_groups_2.weight = kernel_weight_2
conv_groups_2(data)

输出结果如下:

pytorch卷积操作nn.Conv中的groups参数用法解释_第7张图片

结果同上,红色框中是卷积核,绿色框中是卷积输出结果,可以发现groups=2时的卷积核通道数比groups=1时卷积核的通道数减少了一半。那上图的结果又是怎么计算出来的呢?请看下图:

pytorch卷积操作nn.Conv中的groups参数用法解释_第8张图片

这是groups=2的场景,groups=2时有2个分组,每个分组中包含2个卷积核,每组卷积核和2个输入通道进行卷积操作得到一组输出结果,将两组输出结果进行叠加得到最终的卷积结果。下面看一下groups=4的场景。

4、实验groups=4的场景

kernel_weight_4 = torch.nn.Parameter(torch.arange(4, dtype=torch.float32).view(4, 1, 1, 1))
print(kernel_weight_4)
conv_groups_4 = nn.Conv2d(in_channels=4, out_channels=4, kernel_size=1, groups=4, bias=False)
conv_groups_4.weight = kernel_weight_4
conv_groups_4(data)

输出结果如下:

pytorch卷积操作nn.Conv中的groups参数用法解释_第9张图片

结果同上,红色框中是卷积核,绿色框中是卷积输出结果,可以发现groups=4时每个卷积核只有1个通道。那上图中的结果又是怎么计算出来的呢?请看下图:

pytorch卷积操作nn.Conv中的groups参数用法解释_第10张图片

这是groups=4的场景,也是groups等于输入通道数的场景,也就是开头讲的深度分离卷积中的场景,groups=4时有4个分组,每个分组中包含1个卷积核,每组卷积核和1个输入通道进行卷积操作得到一组输出结果,将4组输出结果进行叠加得到最终的卷积结果。

你可能感兴趣的:(python编程,深度学习,pytorch,深度学习,卷积groups,nn.Conv,pytorch)