YOLOV8增加head部分模块-BasicRFB

本文介绍了RFB模型,一种考虑尺度和离心率的卷积结构,利用轻量级主干网络提高特征提取效率,兼顾速度和精度。RFB模块包含多分支卷积和dilated卷积,与Inception思想相似但有所创新。作者还提供了在ultralytics框架下的实现步骤和模型配置示例。

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

01模型介绍

        1介绍

        本文提出RFB,将RFs的尺度、离心率纳入考虑范围,使用轻量级主干网也能提取到高判别性特征,使得检测器速度快、精度高;具体地,RFB基于RFs的不同尺度,使用不同的卷积核,设计了多分支的conv、pooling操作(makes use of multi-branch pooling with varying kernels),并通过虫洞卷积(dilated conv)来控制感受野的离心率,最后一步reshape操作后,形成生成的特征。

        2使用方法

RFB模块是一个多分支的卷积模块,它的内部结构被划分为两部分:

        1.多分支卷积层:根据RF的定义,使用多种尺寸的卷积核来实现比固定尺寸更好。具体设计:1.瓶颈结构,1x1-s2的卷积减少通道特征,然后加上一个nxn卷积。2.用5x5卷积替换为2个3x3的卷积去减少参数,这样可得到非线性结构更好的层。3.为了输出,卷积经常有stride=2或者是减少通道,所有直连层为了匹配维度用一个不带激活函数的1x1卷积层。
        2.dilated 卷积层:在保持参数量可扩大感受野,用来获取更高分辨率的特征。下图展示了两种RFB结构:RFB和RFB-s。每个分支都是一个正常卷积后面加一个dilated卷积,主要尺寸和dilated因子不同。(a)RFB整体上借鉴了Inception的思想,主要不同点在于引入了3个dilated卷积层。(b)RFB-s和RFB相比主要有两个改进,一方面用3x3的卷积层代替5x5卷积层,另一方面用1x3和3x1的卷积来代替3x3卷积,主要目的是为了减少计算量,类似Inception后期版本对Inception结构的改进。

02模型改进方法

1修改modules.py-模型使用的模块

        在ultralytics/nn/modules路径下增加一个BasicRFB.py,将以下代码复制

import torch
import torch.nn as nn

class BasicConv(nn.Module):
    def __init__(self, in_planes, out_planes, kernel_size, stride=1, padding=0, dilation=1, groups=1, relu=True):
        super(BasicConv, self).__init__()
        self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, stride=stride,
                              padding=padding, dilation=dilation, groups=groups, bias=False)
        self.bn = nn.BatchNorm2d(out_planes, eps=1e-5, momentum=0.01, affine=True)
        self.relu = nn.ReLU(inplace=True) if relu else nn.Identity()

    def forward(self, x):
        x = self.conv(x)
        x = self.bn(x)
        x = self.relu(x)
        return x

class BasicRFB(nn.Module):

    def __init__(self, in_planes, out_planes, stride=1, scale=0.1, map_reduce=8, vision=1, groups=1):
        super(BasicRFB, self).__init__()
        self.scale = scale
        self.out_channels = out_planes
        inter_planes = in_planes // map_reduce

        self.branch0 = nn.Sequential(
            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1, groups=groups, relu=False),
            BasicConv(inter_planes, 2 * inter_planes, kernel_size=(3, 3), stride=stride, padding=(1, 1), groups=groups),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=vision + 1,
                      dilation=vision + 1, relu=False, groups=groups)
        )
        self.branch1 = nn.Sequential(
            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1, groups=groups, relu=False),
            BasicConv(inter_planes, 2 * inter_planes, kernel_size=(3, 3), stride=stride, padding=(1, 1), groups=groups),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=vision + 2,
                      dilation=vision + 2, relu=False, groups=groups)
        )
        self.branch2 = nn.Sequential(
            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1, groups=groups, relu=False),
            BasicConv(inter_planes, (inter_planes // 2) * 3, kernel_size=3, stride=1, padding=1, groups=groups),
            BasicConv((inter_planes // 2) * 3, 2 * inter_planes, kernel_size=3, stride=stride, padding=1,
                      groups=groups),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=vision + 4,
                      dilation=vision + 4, relu=False, groups=groups)
        )

        self.ConvLinear = BasicConv(6 * inter_planes, out_planes, kernel_size=1, stride=1, relu=False)
        self.shortcut = BasicConv(in_planes, out_planes, kernel_size=1, stride=stride, relu=False)
        self.relu = nn.ReLU(inplace=False)

    def forward(self, x):
        x0 = self.branch0(x)
        x1 = self.branch1(x)
        x2 = self.branch2(x)

        out = torch.cat((x0, x1, x2), 1)
        out = self.ConvLinear(out)
        short = self.shortcut(x)
        out = out * self.scale + short
        out = self.relu(out)

        return out

2修改tasks.py-增加模型中使用的模块

       在ultralytics/nn/tasks.py中,保证能够导入类,在最后面加入class 的BasicRFB名称,

from ultralytics.nn.modules import (AIFI, C1, C2, C3, C3TR, SPP, SPPF, Bottleneck, BottleneckCSP, C2f, C3Ghost, C3x,
                                    Classify, Concat, Conv, ConvTranspose, Detect, DWConv, DWConvTranspose2d, Focus,
                                    GhostBottleneck, GhostConv, HGBlock, HGStem, Pose, RepC3, RepConv, RTDETRDecoder,
                                    Segment,CBAM,BasicRFB)

3修改def parse_model-解析参数

        还是在ultralytics/nn/tasks.py中,在最后面加入BasicRFB,保证能读入名称

 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
                 BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x,BasicRFB)

4修改yolov8_BasicRFB.yaml-模型的配置文件

        在ultralytics/models/v8/.yaml文件中,复制增加一个名称yolov8_BasicRFB.yaml文件,

把以下复制在其中。

# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
 
# Parameters
nc: 1  # 模型识别的类别数量
scales: # 模型的大小  model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
 
# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, Conv, [64, 3, 2]]  # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8
  - [-1, 6, C2f, [256, True]]
  - [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16
  - [-1, 6, C2f, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32
  - [-1, 3, C2f, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]]  # 9
 
# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f, [512]]  # 12
 
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f, [256]]  # 15 (P3/8-small)
  - [-1, 1, BasicRFB, [256]]  # 16 
 
  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f, [512]]  # 19 (P4/16-medium)
  - [-1, 1, BasicRFB, [512]]  # 20 
 
  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f, [1024]]  # 23 (P5/32-large)
  - [-1, 1, BasicRFB, [1024]]  # 24 
 
  - [[16, 20, 24], 1, Detect, [nc]]  # Detect(P3, P4, P5)

5模型调用

        在模型调用中将模型配置文件改为设置的ymal文件

from ultralytics import YOLO
if __name__ == '__main__':
    model = YOLO("ultralytics/models/v8/yolov8x_BasicRFB.yaml").train(**{'cfg': 'ultralytics/yolo/cfg/break.yaml'})

YOLOv12 并未在当前主流的 YOLO 版本中被明确提及或发布。根据已知的 YOLO 发展历程,从 YOLOv1 到 YOLOv8 的演变过程已经涵盖了多个重要版本,并且每个版本都有其特定的技术改进和架构变化[^1]。然而,截至目前,YOLO 系列的主要版本为 YOLOv1 至 YOLOv8,以及一些由社区开发的变体(如 PP-YOLOYOLOX 等)[^3]。 如果提到 YOLOv12,可能是指某个非官方实现或社区扩展版本。为了查找 YOLOv12 的网络结构图,建议参考以下步骤: ### 1. 官方文档和代码库 首先检查 Ultralytics 的官方 GitHub 仓库或其他权威来源,确认是否存在名为 YOLOv12 的版本。Ultralytics 是目前 YOLO 系列的主要维护者之一,其代码库通常包含最新的模型定义和架构信息[^4]。 ### 2. 社区资源 如果没有找到官方的 YOLOv12,可以搜索相关社区资源,例如 ArXiv 上的论文、技术博客或第三方实现。某些社区可能会基于现有 YOLO 版本进行扩展或优化,并将其命名为 YOLOv12。 ### 3. 模型架构推测 假设 YOLOv12 是对现有版本的延续,可以从最近的 YOLOv8 或其他变体中推测其架构特点: - **主干网络**:可能采用更先进的主干架构,例如 EfficientNet、RegNet 或 Swin Transformer。 - **颈部设计**:可能引入更高效的特征融合机制,例如改进的 PANet 或 BiFPN。 - **头部设计**:可能支持更多的任务类型(如分割、关键点检测),并优化边界框回归策略。 - **训练技巧**:可能结合自监督学习、知识蒸馏等技术以提升性能。 以下是基于 YOLOv5 的输出结构示例代码,展示如何定义多尺度输出层: ```python import torch import torch.nn as nn class YOLOv12Head(nn.Module): def __init__(self, num_classes=80, anchors=[(10, 13), (16, 30), (33, 23)]): super(YOLOv12Head, self).__init__() self.num_classes = num_classes self.anchors = anchors self.output_channels = len(anchors) * (5 + num_classes) self.conv1 = nn.Conv2d(256, self.output_channels, kernel_size=1) self.conv2 = nn.Conv2d(512, self.output_channels, kernel_size=1) self.conv3 = nn.Conv2d(1024, self.output_channels, kernel_size=1) def forward(self, x): p3, p4, p5 = x out_p3 = self.conv1(p3) out_p4 = self.conv2(p4) out_p5 = self.conv3(p5) return [out_p3, out_p4, out_p5] ``` ###
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值