ShuffleNetv1:An Extremely Efficient Convolutional Neural Network for Mobile Devices

ShuffleNetv1通过channel shuffle解决分组卷积后,特征无法交流的情况

什么是ShuffleNetv1?

  • ShuffleNetv1-20230408141120
  • ResNeXt 提出的分组卷积(GroupConvolution),可以在降低模型参数量的同时,提升模型的预测效果,但是分组后的特征完全不进行交流,虽然可以通过 1x1 卷积缓解,但是 1x1 卷积需要计算量很大,不是理想的方法
  • ShuffleNetv1通过使用 channel shuffle 操作弥补分组间的信息交流,使得网络可以尽情使用分组卷积

ShuffleNetv1的网络结构?

  • ShuffleNetv1-20230408141120-1
  • 3个不同的Stage组成网络结构,最后一列显示不同的分组其层的输出通道

ShuffleNetv1的基础单元Units?

  • ShuffleNetv1-20230408141121
  • 图a:深度可分离卷积+残差连接,这在MobileNetv2上被作为基础单元
  • 图b:ShuffleNetv1的基础单元,经过该单元后,特征图分辨率不变,使用add进行特征融合
  • 图c:ShuffleNetv1的下采样单元,经过该单元后,特征图分辨率减半,使用concat进行特征融合

ShuffleNetv1如何实现通道混淆(channel shuffle)?

  • ShuffleNetv1-20230408141121-1
  • 假定将输入层分为 g 组,总通道数为 g * n,首先你将通道那个维度拆分为 (g, n) 两个维度,然后将这两个维度转置变成 (n, g),最后重新 reshape 成一个维度 g * n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def channel_shuffle(x, groups):
"""
Parameters
x: Input tensor of with `channels_last` data format
groups: int number of groups per channel
Returns
channel shuffled output tensor
Examples
Example for a 1D Array with 3 groups
>>> d = np.array([0,1,2,3,4,5,6,7,8])
>>> x = np.reshape(d, (3,3))
>>> x = np.transpose(x, [1,0])
>>> x = np.reshape(x, (9,))
'[0 1 2 3 4 5 6 7 8] --> [0 3 6 1 4 7 2 5 8]'
"""
height, width, in_channels = x.shape.as_list()[1:]
channels_per_group = in_channels // groups
x = K.reshape(x, [-1, height, width, groups, channels_per_group])
x = K.permute_dimensions(x, (0, 1, 2, 4, 3)) # transpose
x = K.reshape(x, [-1, height, width, in_channels])
return x