-
图的a图是一个带有深度可分离卷积的残差模块,这里的1×1是逐点的卷积。相比深度可分离卷积,1×1计算量较大。
-
图的b图则是基本的ShuffleNet基本单元,可以看到1×1卷积采用的是组卷积,然后进行通道的混洗,这两步可以取代1×1的逐点卷积,并且大大降低了计算量。3×3卷积仍然采用深度可分离的方式。
-
图的c图是带有降采样的ShuffleNet单元,在旁路中使用了步长为2的3×3平均池化进行降采样,在主路中3×3卷积步长为2实现降采样。另外,由于降采样时通常要伴有通道数的增加,ShuffleNet直接将两分支拼接在一起来实现了通道数的增加,而不是常规的逐点相加。
得益于组卷积与通道混洗,ShuffleNet的基本单元可以很高效地进行计算。在该基本单元的基础上,ShuffleNet的整体网络结构如下表所示。
关于ShuffleNet的整体结构,有以下3点需要注意:
-
g代表组卷积的组数,以控制卷积连接的稀疏性。组数越多,计算量越少,因此在相同的计算资源,可以使用更多的卷积核以获取更多的通道数。
-
ShuffleNet在3个阶段内使用了其特殊的基本单元,这3个阶段的第一个Block的步长为2以完成降采样,下一个阶段的通道数是上一个的两倍。
-
深度可分离卷积虽然可以有效降低计算量,但其存储访问效率较差,因此第一个卷积并没有使用ShuffleNet基本单元,而是只在后续3个阶段使用。
下面以g=3为例,从代码层面讲解ShuffleNet网络的构建。(Pytorch实现)
from torch import nn
import torch.nn.functional as F
class ShuffleNet(nn.Module):
def init(self, groups=3, in_channels=3, num_classes=1000):
super(ShuffleNet, self).init()