
(二)YOLOv5/YOLOv7改进之结合PP-LCNet
3.配置yolov5/yolov7_PP-LC.yaml文件
关于YOLO算法改进及论文投稿可关注并留言博主的CSDN/QQ
论文题目:PP-LCNet: A Lightweight CPU Convolutional Neural Network


🚀 发现问题:随着模型特征提取能力的增加以及模型参数和FLOPs数量的增加,在基于移动设备的ARM架构的基础上或基于CPU设备的架构上实现快速推理速度变得困难。在这种情况下,已经提出了许多优秀的移动网络,但由于MKLDNN的限制,这些网络的速度在启用了MKLDNN的IntelCPU上并不理想。
💡 解决方法:针对此问题,作者提出了一个基于MKLDNN加速策略的轻量级CPU网络,命名为PP-LCNet,它提高了轻量级模型在多任务上的性能。论文还列出了可以在延迟几乎不变的情况下提高网络准确性的技术。通过这些改进,PP-LCNet在相同的分类推理时间下,它优于最先进的模型,准确率可以大大超过以前的网络结构。并且对于计算机视觉的下游任务,也表现非常出色,比如物体检测、语义分割等等。
PP-LCNet 在同样精度的情况下,速度远超当前所有的骨架网络!它应用在比如目标检测、语义分割等任务算法上,也可以使原本的网络有大幅度的性能提升。由下图可看出,PP-LCNet 不仅精度提升相当明显,而且比MobileNetV3快几乎3倍!!

PP-LCNet的主要贡献有以下4点:
1.更好的激活函数。
由ReLU换成了H-Swish,性能有了很大的提升,而推理时间几乎没有变化。
2.合适的位置添加SE模块
实验发现当SE模块放到最后的时候比较好,因此将SE模块放在网络最后部分,在SE层中使用的激活函数为relu和h-sigmoid。
3.更大的卷积核
作者实验发现发现在模型的最后将3x3卷积核换成5x5的效果比较好。
4.GAP后更高维度的1x1卷积层
GAP后面的维度很小,直接在他后面添加分类层会损失很多特征信息,为了增强模型的鲁棒性,在最终的GAP层之后附加了一个1280维大小的1 × 1 conv(相当于FC层),在几乎不增加推理时间的情况下存储更多的模型。


改进方法和其他模块一样,分三步走:
- class SELayer(nn.Module):
- def __init__(self, inp, oup, reduction=4):
- super(SELayer, self).__init__()
- self.avg_pool = nn.AdaptiveAvgPool2d(1)
- self.fc = nn.Sequential(
- nn.Conv2d(oup, _make_divisible(inp // reduction), 1, 1, 0,),
- nn.ReLU(),
- nn.Conv2d(_make_divisible(inp // reduction), oup, 1, 1, 0),
- HardSigmoid()
- )
-
- def forward(self, x):
- b, c, _, _ = x.size()
- y = self.avg_pool(x)
- y = self.fc(y).view(b, c, 1, 1)
- return x * y
-
-
- class DepSepConv(nn.Module):
- def __init__(self, inp, oup, kernel_size, stride, use_se):
- super(DepSepConv, self).__init__()
-
- assert stride in [1, 2]
-
- padding = (kernel_size - 1) // 2
-
- if use_se:
- self.conv = nn.Sequential(
- # dw
- nn.Conv2d(inp, inp, kernel_size, stride, padding, groups=inp, bias=False),
- nn.BatchNorm2d(inp),
- HardSwish(),
-
- # SE
- SELayer(inp, inp),
-
- # pw-linear
- nn.Conv2d(inp, oup, 1, 1, 0, bias=False),
- nn.BatchNorm2d(oup),
- HardSwish(),
-
- )
- else:
- self.conv = nn.Sequential(
- # dw
- nn.Conv2d(inp, inp, kernel_size, stride, padding, groups=inp, bias=False),
- nn.BatchNorm2d(inp),
- HardSwish(),
-
- # pw-linear
- nn.Conv2d(inp, oup, 1, 1, 0, bias=False),
- nn.BatchNorm2d(oup),
- HardSwish()
- )
-
- def forward(self, x):
- return self.conv(x)
加入DepthSepConv模块。

具体配置和之前一样。