从YOLOV8检测头开始,对YOLOV8的一些理解

文章分析了YOLOV8检测头的特点,其参数量大是因为采用了解耦结构,分为Cls和Box回归分支。文章详细介绍了网络结构中的关键模块,如Conv.,C2f,SPPF等,并讨论了轻量化和解耦头在不同场景下的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        YOLOV8的检测头很有特点,它的参数量几乎占了整个模型的一半,如下图。

        而反观YOLOV5的检测头的体量就比YOLOV8的小很多。

        分析这个现象,要先从YOLOV8的网络结构入手。为了便于理解,我先列出一些复合模块的概念。

        ①Conv.

        网络中最常用到的卷积模块,由卷积层、Batch Normalization层、激活函数层(可替换)组成,输入参数含义为(输入通道数-c1, 输出通道-c2, 卷积核大小-k, 卷积核步长-s),其中主要参数都传入了模块中的卷积层,BN层只接收c2作为参数,激活函数层不需要参数。

        ②C2f.

        C2f中的一个核心模块叫做Bottleneck模块,输入参数为(输入通道数-c1, 输出通道-c2),一般情况下c1=c2,因为这个模块的作用一般是用于融合通道间的信息。要注意的是当Bottleneck模块传入的参数shortcut==True时,经过卷积得到的结果会和输入进行add操作,shortcut==False时,不会进行add操作。在Bottleneck模块定义中,默认shortcut=True,而在C2f定义中默认shortcut=False。

        综上,可以得出C2f的结构,输入参数为(输入通道数-c1, 输出通道-c2,Bottleneck模块数-n,输出通道比例-e默认为0.5)输入在经过一个卷积模块之后,输出通道数变为(c2*e*2),默认情况下为c2,经过split或chunk平均分割为两份,注意这里在送入Bottleneck模块前会提取两遍卷积输出,而后每经过一个Bottleneck模块就提取一次输出,最后将所有提取到的输出做Concat处理,得到的结果通道数就为(c2*0.5*(n+2)),最后再经过一个卷积模块,目的是将通道数转为c2。

        ③SPPF

        SPPF层输入参数为(输入通道数-c1, 输出通道-c2,池化层大小-k),将输入经过一个卷积模块压缩通道数后,连续经过3个最大池化层得到的3个输出与原输出做Concat处理,再经过一个卷积模块转换通道数,得到输出。

        ④Upsample

        上采样,采用的是反卷积,用于增大图像。


        至此,可以得出YOLOV8的backbone,未包含检测头,看上去很简单。

        我们再把YOLOV8的head加上去,但是不加最后一层检测头,网络的深度一下子大了很多。

        YOLOV8的检测头分为3个,分别以上图网络的最后3个C2f层的输出作为输入,而YOLOV8的检测头参数量大幅增加的原因是YOLOV8采用了解耦头,分为Cls分类、Box回归两个分支,并去除了Obj loss的计算分支。

        检测头中的参数中,c2=max(16, ch[0], reg_max*4),其中reg_max为计算回归损失的超参数,默认为16,所以c2=64;c3=max(ch[0], min(nc, 100)),以coco数据集(nc=80)为例,c3=100,两路计算得到的结果经过Concat后输出。

        综上,YOLOV8的总体架构如下图。YOLOV8集成的姿态估计(pose)、旋转目标检测(OBB)等功能,都是在在检测头上做出了更换,网络的主体架构不变。同时,一种轻量化的思路就是将检测头变为两个分支共享参数的结构,但相应的特征提取能力也会变弱。对于解耦头的使用,在检测类别较多的时候,特征提取能力提升较明显,因为在多类别训练中,Cls分类分支是与类别相关的,Box回归分支与类别无关(在与目标进行loss计算时,不会考虑目标的类别);而在单类检测时,Cls分类分支和Box回归分支都与类别相关,所以往往用共享参数的耦合头效果会更好。

### YOLOv8 解耦头的工作原理 YOLOv8 使用了 Decoupled-Head 设计,这种架构将分类和定位任务分离处理。传统上,在单阶段目标检测器中,分类分支和回归分支共享相同的卷积层,这可能导致两个任务之间的相互干扰[^1]。 通过引入解耦头,YOLOv8 能够更专注于各自的任务特性: - **分类子网络**:专门负责预测物体类别概率分布; - **回归子网络**:仅关注边界框坐标偏移量估计; 这样的设计有助于提高模型精度并增强鲁棒性,尤其是在复杂场景下表现更为明显。 ### 实现方式 为了实现上述功能,Decoupled Head 结构通常会增加额外的中间特征转换层来分别服务于两类不同的输出需求。具体来说: ```python class DecoupledHead(nn.Module): def __init__(self, num_classes=80, in_channels=256, feat_channels=256): super(DecoupledHead, self).__init__() # 分类分支 self.cls_convs = nn.Sequential( ConvModule(in_channels, feat_channels), ConvModule(feat_channels, feat_channels) ) self.cls_out = nn.Conv2d(feat_channels, num_classes * num_anchors, kernel_size=3) # 定位分支 self.reg_convs = nn.Sequential( ConvModule(in_channels, feat_channels), ConvModule(feat_channels, feat_channels) ) self.reg_out = nn.Conv2d(feat_channels, 4 * num_anchors, kernel_size=3) def forward(self, x): cls_feat = self.cls_convs(x) reg_feat = self.reg_convs(x) cls_score = self.cls_out(cls_feat).sigmoid() bbox_pred = self.reg_out(reg_feat) return cls_score, bbox_pred ``` 这段代码展示了如何构建一个简单的解耦头模块,其中 `ConvModule` 表示带有激活函数的标准卷积操作。对于实际应用中的 YOLOv8 来说,具体的层数、通道数以及其他超参数可能会有所不同,但基本思路保持一致。 ### 应用场景 采用 Decoupled Head 的 YOLOv8 特别适合于那些需要高精度识别的小型或密集排列的目标检测任务。由于其能够更好地平衡分类与定位性能,因此在自动驾驶汽车感知系统、无人机监控等领域有着广泛的应用前景。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值