YOLO目标检测创新改进与实战案例专栏
专栏目录: YOLO有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例
专栏链接: YOLO基础解析+创新改进+实战案例
摘要
文章介绍了基于互补搜索技术组合以及新颖架构设计的MobileNets下一代,MobileNetV3。通过结合硬件感知的网络架构搜索(NAS)和NetAdapt算法,MobileNetV3针对手机CPU进行了优化,随后通过新颖的架构进步得到了改进。本文开始探索自动化搜索算法和网络设计如何共同作用,以利用互补方法提升整体艺术状态。通过这一过程,我们创建了两个新的MobileNet模型以供发布:面向高资源和低资源使用案例的MobileNetV3-Large和MobileNetV3-Small。这些模型随后被适配并应用于对象检测和语义分割任务。对于语义分割(或任何密集像素预测)任务,我们提出了一种新的高效分割解码器Lite Reduced Atrous Spatial Pyramid Pooling(LR-ASPP)。我们为移动分类、检测和分割实现了新的艺术状态水平。MobileNetV3-Large在ImageNet分类上的准确率比MobileNetV2高3.2%,同时减少了20%的延迟。与具有可比延迟的MobileNetV2模型相比,MobileNetV3-Small的准确率提高了6.6%。在COCO检测上,MobileNetV3-Large检测的速度比MobileNetV2快25%左右,准确率大致相同。在Cityscapes分割上,MobileNetV3-Large LR-ASPP比MobileNetV2 R-ASPP快34%,准确率相似。
创新点
MobileNetV3的创新点包括:
结合互补搜索技术和新颖架构设计:通过结合硬件感知的网络架构搜索(NAS)和NetAdapt算法,以及新颖的架构设计,实现了MobileNetV3的优化。
高效的分割解码器:提出了新的高效分割解码器Lite Reduced Atrous Spatial Pyramid Pooling(LR-ASPP),用于对象检测和语义分割任务。
高性能的MobileNetV3-Large和MobileNetV3-Small模型:针对高和低资源使用情况进行优化,在移动分类、检测和分割任务中取得了最新的技术成果。
引入了新颖的架构设计,包括反转残差结构和线性瓶颈层。
提高了准确性和性能:MobileNetV3-Large在ImageNet分类任务中比MobileNetV2准确性提高了3.2%,同时降低了20%的延迟;MobileNetV3-Small比MobileNetV2模型准确性提高了6.6%,延迟相当;MobileNetV3-Large在COCO检测中比MobileNetV2快25%以上,准确性相当;MobileNetV3-Large LR-ASPP在Cityscapes分割中比MobileNetV2 R-ASPP快34%,准确性相当。
yolov8 引入
class MobileNetV3_InvertedResidual(nn.Module):
# MobileNetV3的倒置残差模块初始化
def __init__(self, inp, oup, hidden_dim, kernel_size, stride, use_se, use_hs):
super(MobileNetV3_InvertedResidual, self).__init__()
# 断言stride值有效,确保步长为1或2
assert stride in [1, 2]
# 判断是否使用恒等映射,条件是步长为1且输入输出通道数相等
self.identity = stride == 1 and inp == oup
if inp == hidden_dim:
# 如果输入通道数等于隐藏层通道数,直接在隐藏层上操作
self.conv = nn.Sequential(
# 深度可分离卷积
nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim, bias=False),
nn.BatchNorm2d(hidden_dim),
# 根据use_hs选择Hardswish或ReLU激活函数
nn.Hardswish() if use_hs else nn.ReLU(),
# 根据use_se决定是否使用SEBlock
SeBlock(hidden_dim) if use_se else nn.Sequential(),
# 1x1卷积用于改变通道数
nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
)
else:
# 如果输入通道数不等于隐藏层通道数,使用1x1卷积改变通道数
self.conv = nn.Sequential(
# 使用1x1卷积层改变输入通道数至隐藏层通道数
nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
nn.BatchNorm2d(hidden_dim),
# 根据是否使用Hardswish激活函数选择相应激活函数
nn.Hardswish() if use_hs else nn.ReLU(),
# 深度可分离卷积,使用指定的核大小和步长,以及分组卷积来减少参数量和计算复杂度
nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim, bias=False),
nn.BatchNorm2d(hidden_dim),
# 根据use_se标志决定是否在模块中加入SE块
SeBlock(hidden_dim) if use_se else nn.Sequential(),
# 再次根据是否使用Hardswish激活函数选择相应激活函数
nn.Hardswish() if use_hs else nn.ReLU(),
# 使用1x1卷积层改变通道数至输出通道数
nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
)
def forward(self, x):
# 前向传播函数
y = self.conv(x) # 通过定义的卷积结构处理输入
if self.identity:
# 如果identity为True,则表示使用恒等映射,直接将输入和输出相加
return x + y
else:
# 如果不使用恒等映射,则直接返回卷积后的结果
return y
task与yaml配置
详见:https://blog.csdn.net/shangyanaf/article/details/136891204