原文地址:
《ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices》
ShuffleNet的设计目标是如何利用有限的计算资源来达到最好的模型精度,这需要很好地在速度和精度之间做平衡。shufflenet通过设计更高效的网络结构来实现模型变小和变快,即通过改变模型结构来方便移动端部署
亮点:
1. 提出channel shuffle思想
2. PW Gconv的使用
3. 利用PW Gconv与DW conv更改ResNet模块结构
1. 分组卷积(Group conv)
分组卷积是将输入层的不同特征图进行分组,然后采用不同的卷积核再对各个组进行卷积,这样会降低卷积的计算量(1/g)。因为一般的卷积都是在所有的输入特征图上做卷积,可以说是全通道卷积,这是一种通道密集连接方式(channel dense connection),而分组卷积相比则是一种通道稀疏连接方式(channel sparse connection)。
计算量:
之前采用分组卷积的一些网络结构如Xception,MobileNet,ResNeXt等,因为需要采用了密集的1x1 pointwise convolution,虽然1*1的卷积可以完成升维与降维,保证group convolution之后不同组的特征图之间的信息交流,但也增加了计算量。实际上比如ResNeXt模型中1x1卷积基本上占据了93.4%的乘加运算。
解决方法:对1x1卷积采用channel sparse connection 即分组操作。
特征通信:
group convolution层另一个问题是不同组之间的特征图需要通信,否则就好像分了几个互不相干的路,大家各走各的,会降低网络的特征提取能力。
解决方法:channel shuffle。
2.channel shuffle
一般卷积操作中比如输入feature map的数量是N,该卷积层的filter数量是M,那么M个filter中的每一个filter都要和N个feature map的某个区域做卷积,然后相加作为一个卷积的结果。假设是group操作,设group为g,那么N个输入feature map就被分成g个group,M个filter就被分成g个group,然后在做卷积操作的时候,第一个group的M/g个filter中的每一个都和第一个group的N/g个输入feature map做卷积得到结果,第二个group同理,直到最后一个group,如(a)。不同的颜色代表不同的group,图中有三个group。这种操作可以大大减少计算量,因为你每个filter不再是和输入的全部feature map做卷积,而是和一个group的feature map做卷积。但是如果多个group操作叠加在一起,如(a)的两个卷积层都有group操作,显然就会产生边界效应,边界效应就是某个输出channel仅仅来自输入channel的一小部分。这样肯定是不行的,学出来的特征会非常局限。于是就有了channel shuffle来解决这个问题,先看(b),在进行GConv2之前,对其输入feature map做一个分配,也就是每个group分成几个subgroup,然后将不同group的subgroup作为GConv2的一个group的输入,使得GConv2的每一个group都能卷积输入的所有group的feature map,这和(c)的channel shuffle的思想是一样的,(c)进一步的展示了这一过程并随机,其实是“均匀地打乱”。
3. 基本单元
pointwise group convolutions,其实就是带group的卷积核为1*1的卷积,也就是说pointwise convolution是卷积核为1*1的卷积。
在ResNeXt中主要是对3*3的卷积做group操作,但是在ShuffleNet中,作者是对1*1的卷积做group的操作,因为作者认为1*1的卷积操作的计算量不可忽视。可以看(b)中的第一个1*1卷积是GConv,表示group convolution。
(a)是ResNet中的bottleneck unit,不过将原来的3*3 Conv改成3*3 DWConv,作者的ShuffleNet主要也是在这基础上做改动。首先用带group的1*1卷积代替原来的1*1卷积,同时跟一个channel shuffle操作。然后是3*3 DWConv表示depthwise separable convolution。depthwise separable convolution可以参考MobileNet。(c)添加了一个Average pooling和设置了stride=2,另外原来Resnet最后是一个Add操作,也就是元素值相加,而在(c)中是采用concat的操作,也就是按channel合并,类似googleNet的Inception操作。这样做的目的主要是降低计算量与参数大小。
注意channel shuffle后面没有接ReLU激活函数
4. ShuffleNet网络结构
可以看到开始使用的普通的3x3的卷积和max pool层。然后是三个阶段,每个阶段都是重复堆积了几个ShuffleNet的基本单元。对于每个阶段,第一个基本单元采用的是stride=2,这样特征图width和height各降低一半,而通道数增加一倍。后面的基本单元都是stride=1,特征图和通道数都保持不变。对于基本单元来说,其中瓶颈层,就是3x3卷积层的通道数为输出通道数的1/4,这和残差单元的设计理念是一样的。不过有个细节是,对于stride=2的基本单元,由于原输入会贡献一部分最终输出的通道数,那么在计算1/4时使用未concat之前的通道数。其中group(g)控制了group convolution中的分组数,分组越多,在相同计算资源下,可以使用更多的通道数,所以越大时,采用了更多的卷积核。这里给个例子,当g=3时,对于第一阶段的第一个基本单元,其输入通道数为24,输出通道数为240,但是其stride=2,那么由于原输入通过avg pool可以贡献24个通道,所以相当于左支只需要产生240-24=216通道,中间瓶颈层的通道数就为216/4=54。其他的可以以此类推。当完成三阶段后,采用global pool将特征图大小降为1x1,最后是输出类别预测值的全连接层。
5. 思想总结:
- ShuffleNet的核心就是用pointwise group convolution,channel shuffle和depthwise separable convolution代替ResNet block的相应层构成了ShuffleNet uint,达到了减少计算量和提高准确率的目的。
- channel shuffle解决了多个group convolution叠加出现的边界效应。
- pointwise group convolution和depthwise separable convolution主要减少了计算量。
参考:
仅为学习记录,侵删!