前言
YOLO10都出来为什么还要写这篇YOLO8? 首先YOLO8作为ultralytics出品的里程碑检测网络(不局限于目标检测)有必要对其深入挖掘,其次网络作者的PK数据基本基于通用的大数据集,但当在使用者自己的应用场景数据集中其实未见的新网络会更好(例如这篇paper:Precision and Adaptability of YOLOv5 and YOLOv8 in Dynamic Robotic Environments 作者研究对YOLOv5和YOLOv8模型进行了比较分析,挑战了后者在性能指标方面优越性的普遍假设。与最初的预期相反,YOLOv5模型在物体检测任务中表现出了可比性,在某些情况下甚至更高的精度。)
整个YOLO网络发展史基本从以下3点做出改进,网络结构、loss、训练方法,本文也将从这3点进行阐述;
网络结构
整个yolo8结构可参考:YOLO8总体结构图
但图中的head结构与我看的代码中的结构略有差异,具体可以参考后面的head流程图。
网络结构中的block_n这里简述为块n。
块0(ConvModule):stem,重复1次,输出P1, 降2倍
卷积模块ConvModule(pytorch的conv2d+bn+silu),卷积k=3,s=2;卷积块默认不带偏置;
卷积s=2,所以输出map分辨率下降2倍。
stage1:块1+块2
块1(ConvModule):重复1次,输出P2, 降2倍(在此已降4倍)
卷积模块ConvModule(pytorch的conv2d+bn+silu),卷积k=3,s=2;卷积块默认不带偏置;
卷积s=2,所以输出map分辨率下降2倍,输出通道数Cout=128*width。
块2:重复3*depth次Bottleneck(有shortcut),输出hwc等于块的输入;
与YOLO5相比这里每个Bottleneck的输出能跳接到模块最后输出,丰富了特征输出;结构如下图:
stage2:块3+块4
块3(ConvModule):重复1次,输出P3, 降2倍(在此已降8倍)
卷积模块ConvModule(pytorch的conv2d+bn+silu),卷积k=3,s=2;卷积块默认不带偏置;
卷积s=2,所以输出map分辨率下降2倍,输出通道数Cout=256*width。
块4:重复6*depth次Bottleneck(有shortcut),输出hwc等于块的输入
结构与块2所示流程图一致。
stage3:块5+块6
块5(ConvModule):重复1次,输出P4, 降2倍(在此已降16倍)
卷积模块ConvModule(pytorch的conv2d+bn+silu),卷积k=3,s=2;卷积块默认不带偏置;
卷积s=2,所以输出map分辨率下降2倍,输出通道数Cout=512*width。
块6:重复6*depth次Bottleneck(有shortcut),输出hwc等于块的输入
结构与块2所示流程图一致。
stage4:块7+块8+块9(SPPF)
块7(ConvModule):重复1次,输出P5, 降2倍(在此已降32倍)
卷积模块ConvModule(pytorch的conv2d+bn+silu),卷积k=3,s=2;卷积块默认不带偏置;
卷积s=2,所以输出map分辨率下降2倍,输出通道数Cout=1024*width。
块8:重复3*depth次Bottleneck(有shortcut),输出hwc等于块的输入
结构与块2所示流程图一致。
块9(SPPF,Spatial Pyramid Pooling,SPP的改良版,快速空间金字塔池化):
卷积块通道减半,串行3个55的maxpooling,concat这个4个中间结果,再卷积块,通道为指定输出的通道数(一般等于输入)。
SPPF在yolo5后期版本就已经有了,作用是实现局部特征和全局特征的featherMap级别的融合。3个size=55的串行池化,效果与SPP的55,99,13*13这3个size并行池化一致,但速度更快;
结构图如下:
以上就是整个backbone
以下就是目标检测的neck
与yolo5一样采用PAFAN结构,相比FPN,提出自底向上路径增强,用低层精确定位信号增强整个特征金字塔,缩短从底层到顶层的信息路径:
PAFAN大致结构可以参考:PAFAN
先往上融合
块10:Upsample,2倍的上采样;(分辨率1/16)
块11:Concat,块10与块6的输出在通道维度上链接(concat);
块12:C2f(结构与块2所示流程图一致),bottleneck不做shortcut;
——————
块13:Upsample,2倍的上采样;(分辨率1/8)
块14:Concat,块13与块4通道维度上链接(concat);
块15:C2f(结构与块2所示流程图一致),bottleneck不做shortcut,输出通道数Cout=256width;
输出给head
再往下融合
块16:&