关于Conv2d的用法先看以下链接:Conv2d_马鹏森的博客-CSDN博客
注意:首先需要知道的是groups的值必须能整除in_channels和out_channels
前置知识:卷积参数量的计算公式是:(输入通道数 * 输出通道数 * k^2 )/ groups
历史由来:group conv
最早出现在AlexNet
中,因为显卡显存不够,只好把网络分在两块卡里,于是产生了这种结构;Alex认为group conv
的方式能够增加 filter之间的对角相关性,而且能够减少训练参数,不容易过拟合,这类似于正则的效果。
1.当设置group=1时:
conv = nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=1)
conv.weight.data.size()
返回:
torch.Size([6, 6, 1, 1])
另一个例子:
conv = nn.Conv2d(in_channels=6, out_channels=3, kernel_size=1, groups=1)
conv.weight.data.size()
返回:
torch.Size([3, 6, 1, 1])
可见第一个值为out_channels的大小,第二个值为in_channels的大小,后面两个值为kernel_size
2.当设置为group=2时
conv = nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=2)
conv.weight.data.size()
返回:
torch.Size([6, 3, 1, 1])
3.当设置group=3时
conv = nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=3)
conv.weight.data.size()
返回:
torch.Size([6, 2, 1, 1])
4.当设置group=4时
conv = nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=4)
conv.weight.data.size()
报错:
ValueError: in_channels must be divisible by groups
groups的值必须能整除in_channels,同样也要求groups的值必须能整除out_channels
总结:其实就是将输入通道数变为 输入通道数/groups,输出通道数不变,总共计算groups次
不分组:
可以看到不分组卷积总共需要的参数量是:
以此类推。当然,以上都是均匀分组的,不均分也是可以的。至于分组卷积有什么好处,很明显,可以节省参数量。假设不使用分组时,卷积核的参数量为:
其中 分别表示卷积核宽度,输入通道数,输出通道数。如果使用分组卷积,分为
组,则卷积核参数量为:
也就是说分几组,参数量就为原来的几分之几。当然偏置值是不会被节省的,都是 个。
分组卷积时,每个分组对其它分组的特征图不可见,这实际上就等价于把网络进行分支,也就是把输入的特征图以通道维度拆开来分别进行卷积,然后再将卷积结果拼接起来。分几组就等于分几个支。
分组卷积和深度可分离卷积 - 颀周 - 博客园