shuffleNet是一个轻量化的CNN模型,paper链接
主要面向mobile device(有限的算力)设计。
主要有2个新的operations: pointwise group convolution 和 channel shuffle
pointwise group convolution
说到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
然后是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
ShuffleNet unit
以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