⼤改ShuffleNetV2⽹络,注意⼒机制,csp,卷积裁剪
⼤改ShuffleNetV2⽹络,注意⼒机制,csp,卷积裁剪
1.背景
活动开场白台词在移动端场景中,⽬前有很多不错的轻量级⽹络可以选择,例如google的mobilenet系列,efficient lite系列,旷世的shufflenet系列,华为的ghostnet等。在这些模型中,我尤其喜欢shufflenetV2,因为它结构清晰,简洁(如下图所⽰为shufflenetv2 1.0x的结构图:红⾊标注为各个模块的flops),并且在设计之初就考虑了MAC(访存代价),使得在移动端部署的时候具有很低的延时。在多个数据集上的测试也验证了其较好的泛化性能。不过有时候为了实现在更低计算资源的嵌⼊式场景中使⽤shufflenet,或者在轻量级检测框架中使⽤shufflenet作为bakbone,那么仍然需要对shufflenet做⼀些优化。
本次实践将围绕对shufflenetV2 1.0X版本进⾏改进,包括提升精度与降低计算量两个维度。看看能否创造出⼀个⽐基线版本更优的shufflenet结构。在不加注释的情况下,下⽂的shufflenet默认指的是shufflenet v2 1.0x版本。
2、提升精度措施
结合⽬前⽐较⽕的注意⼒机制,例如net,sknet等,这⾥分别设计四个⽹络:
增加注意⼒机制的:shufflenet_⽹络
增加sk注意⼒机制的:shufflenet_sk⽹络
将3*3的depthwi卷积扩⼤为5*5:shufflenet_k5⽹络
3、降低计算量
使⽤卷积裁剪以及csp技术,分别设计两个⽹络 :
裁剪block中不重要的1*1卷积,这⾥设计⼀个shufflenet_liteconv⽹络
使⽤csp对⽹络进⾏重组,这⾥设计⼀个shufflenet_csp⽹络
shufflenet_⽹络
主要是借鉴net中的通道注意⼒机制,将其应⽤到shufflenet中。下⾯简单回顾⼀下net中的注意⼒机制:
主要有两个操作:squeeze和excitation。squeeze指的是将特征通过GAP压缩空间信息,将原来的c*h*w维度信息压缩为c*1*1. Excitation使⽤了两个全连接层,第⼀个降低维度,将c*1*1降维为c/r *1*1(带有relu激活),第⼆个fc层将特征重新映射回c*1*1(没有relu激活),然后经过sigmoid之后得到各个通道的权重系数。然后将权重系数与原来的特征相乘,从⽽得到⼀个新的特征。下⾯是attention的pytroch代码实现,⾮常的简单,就是按照上⾯的思路实现⼀遍。
class SeAttention(nn.Module):
def __init__(lf, channel_num, r=4):
""" Constructor
阿哥阿妹简谱"""
super(SeAttention, lf).__init__()
lf.channel_num = channel_num
lf.r = r
lf.inter_channel = int( float(lf.channel_num) / lf.r)
lf.fc_e1 = Linear(channel_num, lf.inter_channel)
lf.fc_e2 = Linear(lf.inter_channel, channel_num)
def forward(lf, x):
150000大写y = functional.adaptive_avg_pool2d(x, (1, 1)).squeeze()
y = lf.fc_e1(y)
y = lf.relu_e1(y)
见微知著的意思是y = lf.fc_e2(y)
y = torch.sigmoid(y).unsqueeze(-1).unsqueeze(-1)
return x*y
s hufflenet_sk⽹络
主要是借鉴了sknet中的注意⼒机制,⽤于选择⼤卷积核的输出还是⼩卷积核的输出。其原理图如下所⽰:
将特征X分别经过⼩卷积核(3*3)得到新的特征U3*3(图中黄⾊部分);另外⼀路经过⼤卷积核(5*5)得到新的特征U5*5(图中绿⾊部分)。然后加两个新的特征U相加,然后经过SE相同的squeeze和excitation得到权重向量,注意这⾥的权重向量有两个,⼀个是针对
U3*3的权重向量,另⼀个是针对U5*5的权重向量。最后⽤权重向量分别与对应的U相乘,最后相加得到新的特征输出V。主要代码如下:class SKConv(nn.Module):
def __init__(lf, in_channels):
""" Constructor纸蜻蜓的折法
Args:
in_channels: input channel dimensionality.
M: the number of branchs.
牛杂店"""
super(SKConv, lf).__init__()
天然沙滩r = 2.0
L = 32
d = max(int(in_channels / r), L)
lf.in_channels = in_channels
lf.depthwi_conv(in_channels, in_channels, kernel_size=3, dilation=1, padding=1),
nn.BatchNorm2d(in_channels),
#nn.ReLU(inplace=Fal)
)
lf.depthwi_conv(in_channels, in_channels, kernel_size=3, dilation=2, padding=2),
nn.BatchNorm2d(in_channels),
# nn.ReLU(inplace=Fal)
)
lf.fc1 = nn.Linear(in_channels, d)
lf.fc2 = nn.Linear(d, in_channels*2)
lf.softmax = nn.Softmax(dim=1)
def forward(lf, x):
U1 = lf.conv1(x)
U2 = lf.conv2(x)
U = U1 + U2
S = U.mean(-1).mean(-1)
Z1 = lf.fc1(S)
Z2 = lf.fc2(Z1)
A = lf.softmax(Z2)
V = U1 * A[:,:lf.in_chanels].unsqueeze(-1).unsqueeze(-1) + \
U2 * A[:,lf.in_channels:].unsqueeze(-1).unsqueeze(-1)
return V
shufflenet_liteconv⽹络
通过观察shufflenet的block,可以分为两种结构,⼀种是每个stage的第⼀个block,该block由于需要降采样,升维度,所以对输⼊直接复制成两份,经过branch1,和branch2之后再concat到⼀起,通道翻倍,如下图中的降采样block所⽰。另外⼀种普通的block将输⼊split 成两部分,⼀部分经过branch2的卷积提取特征后直接与branch1的部分进⾏concat。如下图中的普通block所⽰:
⼀般在DW卷积(depthwi卷积)的前或后使⽤1*1的卷积处于两种⽬的,⼀种是融合通道间的信息,弥补dw卷积对通道间信息融合功能的缺失。另⼀种是为了降维升维,例如mobilenet v2中的inverted reddual模块。⽽shufflenet中的block,在branch2中⽤了2个1*1卷积,实际上有⼀些多余,因为此处不需要进⾏升维降维的需求,那么只是为了融合dw卷积的通道间信息。实际上有⼀个1*1卷积就够了。为了剪裁的⽅便,将上图中的红⾊虚线框中的1*1卷积删除。实现shufflenet_liteconv版本。
shufflenet_k5⽹络
进⼀步观察shufflenet的计算量分布,实际上在dw卷积上的计算量占⽐是很⼩的,主要的计算量都在1*1的卷积上⾯。因此对dw卷积进⾏⼀个卷积核的扩张,既不会增加太多的计算⽐重,⼜能提升效果,何乐⽽不为呢。Shufflenet_k5将所有的3*3dw卷积替换成5*5的dw卷积,注意在pytroch实现中,需要将padding从1修改为2,这样输出的特征图才能保持与原来⼀致的分辨率。
shufflenet_csp⽹络
csp在⼤型⽹络上取得了很⼤的成功。它在每个stage,将输⼊split成两部分,⼀部分经过原来的路径,另⼀部分直接shortcut到stage的尾部,然后concat到⼀起。这既降低了计算量,⼜丰富了梯度信息,减少了梯度的重⽤,是⼀个⾮常不错的trip。在yolov4,yolov5的⽬标检测中,也引⼊了csp机制,使⽤了csp_darknet。此处将csp引⼊到shufflenet中。并且对csp做了⼀定的精简,最终使⽤csp st
age精简版本作为最终的⽹络结构。
4、实验测试
对上述:shufflenet_、shufflenet_sk、shufflenet_liteconv、shufflenet_k5、shufflenet_csp在cifar10数据集上进⾏训练,统计其最终的精度和flops,并与baline的shufflenet进⾏对⽐,结果如下表所⽰:
⽹络结构Top1实测flops (M)参数规模(M)模型⽂件⼤⼩
shufflenet(baline)0.880147.79 1.2635116K shufflenet_ 0.884147.93 1.4065676K shufflenet_sk 0.885152.34 1.5556872K shufflenet_liteconv 0.879104.770.9233736K shufflenet_k50.891155.18 1.3035268K shufflenet_csp
0.862
101.96
0.924
3776K
对其中最重要的指标flops与top1精度进⾏可视化:
5、总结
摔倒的英语