shuffleNet阅读笔记

论文名称:ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices

论文链接:https://arxiv.org/abs/1707.01083

  • 摘要

shuffleNet是face++在2017年提出,目的是提高深度模型的复杂度,降低对GPU硬件的依赖,可在移动端执行。

我们知道深度学习网络在包括图像识别等多个领域发展迅速,但是随着模型的深度越来越深,模型的参数量越来越大,现如今模型一般都跑的GPU上面,那么如何能在嵌入式或者移动端使用深度学习也是目前研究比较多的领域,shufflenet便是其中一个成果。shuffleNet主要拥有两个创新点:(1)pointwise group convolution,(2)channel shuffle。

在模型效果方面,作者通过实验证明,在ImageNet classfication任务中,shuffleNet相比较于mobileNet,top-1的错误率降低了7.8个百分点。另外在移动端,在相同的精度下,shuffleNet的速度是alexNet的13倍。

与shuffleNet相关联的两个网络,一个是Xception,一个是MobileNet,有兴趣的读者可以看一下这两个网络。

1. shuffleNet策略之一:分组卷积

为了提高网络的效率,除了剪枝、量化等手段,另一个主要的手段便是在网络设计阶段在保证精度的情况下减少一定的网络参数量,分组卷积便是这样的一个手段,这里解释一下什么是分组卷积,举个例子,比如你的特征图有64个channel,分成2个组,每个组的32个特征图分别处理,最后把得到结果之后再进行合并,这就是分组卷积了,另外补充一个,depthwise separable convolution是分组卷积的一个特例,其就是特征图有几个channel,我就分为几个组,保证每个组只有一个特征图进行处理,这是在mobileNet中提出的,shuffleNet用到了分组卷积以及depthwise separable convolution。其实分组卷积在alexnet中便被使用,当时受限于GPU的显存,alex将网络分别在两个GPU上同时训练,另一个比较火的分组卷积网络便是resNeXt,resNeXt通过分组卷积,比resnet精度提高了一些,但是resNeXt的分组卷积也有一个缺点:dense 1*1卷积耗费了大量的计算,占到了总计算量的93.3%,怎么计算出来的呢?下面说明一下:

首先明确一下resnext一个unit的网络结构:如下图:

下面我们假设输入的特征图大小为d*d,来计算一下该网络结构的计算量:首先对于最上面的降维: 25611dd4 256 ∗ 1 ∗ 1 ∗ d ∗ d ∗ 4 ,中间的计算量为: 433dd4 4 ∗ 3 ∗ 3 ∗ d ∗ d ∗ 4 ,最后的输出的计算量为: 411dd256 4 ∗ 1 ∗ 1 ∗ d ∗ d ∗ 256 ,则最终pointwise所占的计算量为: 25611dd4225611dd42+433dd4 256 ∗ 1 ∗ 1 ∗ d ∗ d ∗ 4 ∗ 2 256 ∗ 1 ∗ 1 ∗ d ∗ d ∗ 4 ∗ 2 + 4 ∗ 3 ∗ 3 ∗ d ∗ d ∗ 4 = 1415 14 15 =93.3%,由此可见,如果1*1降维太多的话(channel数减少太多),1*1卷积网络的参数量就占bottleneck主导地位了。

注:分组卷积,比如原来是128维,3*3后变仍为128维,通过分组卷积分为32组,那就是输入4维,输出仍为4维,并不是输入为4维输出为128维,如果是128维,那跟没分组也没啥区别了,笔者在这就算错了一次

shuffleNet就围绕着解决上面的缺陷系统的展开了

shuffleNet是怎么操作的呢?

首先,为了解决1*1卷积在分组unit中计算量占比较大,作者提出在1*1卷积中同样使用分组卷积,但是这样会带来一个问题,就是组内的channel之间的相关性很弱,如下图(a)就是单纯的对1*1卷积(pointwise conv)进行分组操作,根据不同的颜色可以发现,其实不同组之间没有交集。那怎么解决这个问题呢?作者提出了使用shuffle操作,来帮助信息在不同的channel间进行流动。,图(b,c)显示利用shuffle操作,增加不同channel之间的关联性。具体怎么操作呢?笔者找了个代码:假设,我们将卷积层分为g组每组n个channel,则共有g*n个channel,(b,g*n,h,w),首先reshape成(b,g,n,h,w)然后transpose为(b,n,g,h,w),shuffle后在reshape成(b,n*g,h,w)channel是可微的,可以嵌入到end-to-end网络中

def channel_shuffle(data, groups):
    data = mx.sym.reshape(data, shape=(0, -4, groups, -1, -2))
    data = mx.sym.swapaxes(data, 1, 2) # 
    data = mx.sym.reshape(data, shape=(0, -3, -2))
    return data

基于此,作者设计网络如下:

作者首先设计了bottleneck unit如下图(a),作者使用3*3的depthwise convolution,然后,利用group conv替换了pointwise group convolution,在其后增加了channel shuffle operation操作,如下图(b)所示

shuffleNet实际上就是对resNeXt的1*1的pointwise-conv进行分组卷积,进一步降低参数量,然后采用Depth-wise-conv进行卷积(同样有效减少参数量),最后再使用分组卷积进行1*1的的计算,并且在最终的输出上采用concat进行叠加,减少计算量,增加channel数量

特别说明,作者使用了BN层,但是在最后的BN后面没有使用relu,这点也是Xception以及mobileNet v2所介绍的

另外为了增加stride操作,作者这里做了2个改变

  • 增加了3*3的average pooling在shortcut上面。
  • shortcut的相加变为了相乘,使得channel增加。

下面是shuffleNet每个unit的计算量的对比:(其中c代表输入channel,m代表输出channel,g代表分组卷积组数)

resnet:h*w*c*1*1*m*2 + h*w*m*3*3*m

resneXt:h*w*c*1*1*m/g*g*2 + h*w*m/g*3*3*m/g*g

shuffleNet:h*w*c/g*1*1*m/g*g*2 + h*w*m/g*3*3*1*g

化简的结果,可见shuffleNet的计算量小了很多:

resnet:hw(2cm+9m^{2})

resneXt:hw(2cm+9m^2/g)

shuffleNet:hw(2cm/g+9m)

shuffleNet网络详细结构图如下:

在每个Stage中的一个block设置stride=2,来减少特征图的大小,其他的保持特征图大小不变,bottleneck中channel输出为输入的1/4,这都与resnet保持一致,下图table中显示了不同的group的结果:

shuffleNet阅读笔记_第1张图片

对比实验
  • 1.首先针对Pointwise Group

Convolutions的效果如下图所示:【其中0.5*代表channel数为原来的0.5倍】

可见group的增加对模型的效果有一定的提升,并且实验证明,channel的增加有利于模型精度。

  • 2.针对channel shuffle的作用:

根据下表可以观察到,shuffle效果还是比较明显的

  • 3.与其他unit的对比:

  • 4.与mobileNet的对比

最后作者在mobile中进行上实验,发现group取3是精度与效率的trade-off,与不同的网络对于结果如下:

可见shuffleNet的效率还是杠杠滴

你可能感兴趣的:(图像分类,深度学习)