shuffleNet是一个轻量化的CNN模型,paper链接
主要面向mobile device(有限的算力)设计。
主要有2个新的operations: pointwise group convolution 和 channel shuffle
说到pointwise group convolution,不得不先提到group convolution,
它是在AlexNet中第一次提到,详细介绍见这篇文章

channel分成了G个组,每个组的卷积核尺寸为C/G * K * K, C是input channel数量。
output channel数量为N,分到每个组的channel就为N/G,所以每个组需要N/G个卷积核。
大概就是这个意思。
再说一下pointwise convolution, 它就是1x1卷积。
pointwise group convolution, 就是卷积核的大小是1x1,再加上上面的分组操作。
后面再说它用在哪。
然后是channel shuffle的提出,为什么要shuffle。

因为面临有限的计算资源下,小网络channel受限的问题,
这时可以用稀疏的channel,group convolution就是一个例子,
但是group convolution有一个副作用,就是一个特定的output channel只和一小部分的input channel有关,信息量变少了。
想增加信息量可以通过group卷积时,把每个group进一步分成sub group, 多加一些group的信息进来,

这种从不同的sub group里采样的做法,等效于channel shuffle.
具体怎么shuffle,

channel数转为矩阵,矩阵转置再压平。而且channel shuffle是可导的,因此可用在back propagation,
也就是能嵌入到网络结构中。
def channel_shuffle(x, groups):
# type: (torch.Tensor, int) -> torch.Tensor
batchsize, num_channels, height, width = x.data.size()
channels_per_group = num_channels // groups
# reshape
#channel变为groups x channels_per_group
x = x.view(batchsize, groups, channels_per_group, height, width)
#转置为channels_per_group x groups
x = torch.transpose(x, 1, 2).contiguous()
# flatten
x = x.view(batchsize, -1, height, width)
return x
以bottleneck为例

左边的是bottleneck结构,中间的把1x1卷积换成1x1 分组卷积,紧跟一个channel shuffle,
最后一个1x1 分组卷积不再跟channel shuffle. 这是stride = 1的情况。
右边的是stride=2的情况,在residual的部分加上了3x3 average pooling,
同时用channel concat 代替了直接add.
整个shuffleNet的结构如下

stage2的第一个1x1 layer没有用分组卷积,因为channel比较少。
这个是用于imageNet分类的。
分组卷积只用在bottleneck里。

分组的效果比较

其中ShuffleNet sx表示channel缩放了多少倍

output channel缩放了s倍,就意味着filter个数缩放了s倍,

后面有实验证明channel shuffle能降低error
