ToB企服应用市场:ToB评测及商务社交产业平台

标题: YOLO v8目标检测(一)—网络模子与构建 [打印本页]

作者: 卖不甜枣    时间: 2024-10-16 12:39
标题: YOLO v8目标检测(一)—网络模子与构建
YOLO V8目标检测

   在之前的文章中报告了在win11系统中如何部署并使用YOLO V8项目举行预测和训练,经过一段时间的目标检测源代码的学习来报告YOLO v8网络模子的构建、预测、匹配、训练等一下几个方法来报告YOLO v8网络。
  YOLO v8网络布局

v8网络团体概述

YOLO V8在网络布局上的改进点主要体现在了一下几个方面:
   YOLO v8网络定义的基础模块都基础在moudle模块下的nn模块中
  CBS模块

CBS模块是最基本的一个网络模块可以说是Yolo v7中的基础卷积模块 。CBS模块由三个部分拼接组成。在最后通过画图软件给出CBS模块的直观表现。

CBS模块也就是三个拼接层的缩写,在ultralytics/nn/modules/conv.py的路径下面,该文件定义了所有的卷积布局。和网络的起始布局等。
  1. class Conv(nn.Module):
  2.     """Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""
  3.     default_act = nn.SiLU()  # default activation
  4.     # 使用卷积模块时候的构造函数
  5.     #c1 :输入通道的数量。c2 :输出通道的数量。k :卷积核的大小。s :卷积的步长。p :填充的大小,如果为 None ,则使用 autopad 函数自动计算。
  6.     #g :卷积的分组数量。d :卷积的扩张系数。act :激活函数,如果为 True ,使用默认的 SiLU 激活函数;如果是 nn.Module 类型的实例,则使用该激活函数;否则使用恒等激活函数 nn.Identity
  7.     def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
  8.         """Initialize Conv layer with given arguments including activation."""
  9.         super().__init__()
  10.         self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
  11.         self.bn = nn.BatchNorm2d(c2)
  12.         self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
  13.     def forward(self, x):
  14.         """Apply convolution, batch normalization and activation to input tensor."""
  15.         return self.act(self.bn(self.conv(x)))
复制代码


Bottleneck模块

Bottleneck 类定义了一个尺度的瓶颈模块。这是深度神经网络中常见的架构组件,特别是在筹划用于图像分类、目标检测等任务的模子。
   ultralytics/nn/modules/block.py
  构造函数设置了以下层:

  1. # Bottleneck模块
  2. class Bottleneck(nn.Module):
  3.     """Standard bottleneck."""
  4.     def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):
  5.         """Initializes a bottleneck module with given input/output channels, shortcut option, group, kernels, and
  6.         expansion.
  7.         """
  8.         super().__init__()
  9.         c_ = int(c2 * e)  # hidden channels(中间隐藏层的通道数)
  10.         self.cv1 = Conv(c1, c_, k[0], 1)
  11.         self.cv2 = Conv(c_, c2, k[1], 1, g=g)
  12.         self.add = shortcut and c1 == c2
  13.     def forward(self, x):
  14.         """'forward()' applies the YOLO FPN to input data."""
  15.         return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
复制代码
在backbone部分使用残差连接的方式,在head部分不使用残差连接的方式。

总结:Bottleneck 模块通过先减少通道数,然后再增加回原始通道数的方式来处置惩罚输入张量。
C2f模块

   经过c2f模块并不改变通道数量,C2代表的是两个conv布局。C2f 类定义了一个更快的 CSP(Cross Stage Partial)瓶颈层实现,该层只使用了两个卷积层。
  
  1. # C2f模块
  2. class C2f(nn.Module):
  3.     """Faster Implementation of CSP Bottleneck with 2 convolutions."""
  4.     def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
  5.         """Initialize CSP bottleneck layer with two convolutions with arguments ch_in, ch_out, number, shortcut, groups,
  6.         expansion.
  7.         """
  8.         super().__init__()
  9.         self.c = int(c2 * e)  # hidden channels
  10.         self.cv1 = Conv(c1, 2 * self.c, 1, 1)
  11.         self.cv2 = Conv((2 + n) * self.c, c2, 1)  # optional act=FReLU(c2)
  12.         self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
  13.     def forward(self, x):
  14.         """Forward pass through C2f layer."""
  15.         y = list(self.cv1(x).chunk(2, 1)) # 经过chunk操作分为两部分y0 y1
  16.         y.extend(m(y[-1]) for m in self.m) # 将y1送入bottleneck进行处理 extend拓展两个bottleneck部分
  17.         return self.cv2(torch.cat(y, 1))
  18.     def forward_split(self, x):
  19.         """Forward pass using split() instead of chunk()."""
  20.         y = list(self.cv1(x).split((self.c, self.c), 1))
  21.         y.extend(m(y[-1]) for m in self.m)
  22.         return self.cv2(torch.cat(y, 1))
复制代码

SPPF模块

快速-空间金字塔池化 (SPPF)层是backbone的最后一个模块,也可以看作是neck模块。
使用1 * 1的CBL和maxpooling,对输入举行特性提取和特性融合与SPP不同之处在于增加特性由浅入深的提取过程。
   Spp部分主要使用在yolo v3+spp的部分中和yolo v4的网络中。
  SPP全称为空间金字塔池化布局,主要是为了解决两个问题
  
  


SPPF的三个maxpooling之间使用了串联的连接方式,在举行连接之后再次进入CBL模块中举行使用。
  1. class SPPF(nn.Module):
  2.     """Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher."""
  3.     def __init__(self, c1, c2, k=5): # k:池化和大小为5
  4.         """
  5.         Initializes the SPPF layer with given input/output channels and kernel size.
  6.         This module is equivalent to SPP(k=(5, 9, 13)).
  7.         """
  8.         super().__init__()
  9.         c_ = c1 // 2  # hidden channels
  10.         self.cv1 = Conv(c1, c_, 1, 1)
  11.         self.cv2 = Conv(c_ * 4, c2, 1, 1)
  12.         self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
  13.     def forward(self, x):
  14.         """Forward pass through Ghost Convolution block."""
  15.         y = [self.cv1(x)]
  16.         y.extend(self.m(y[-1]) for _ in range(3))
  17.         return self.cv2(torch.cat(y, 1))
复制代码
特点:经过maxpooling不改变特性图的大小。
Detect模块

Detect 类是 YOLOv8 模子中的关键部分,负责将特性图转换为最终的检测输出,包罗边界框和种别概率。这个类通过多个卷积层和自定义层处置惩罚输入特性图,最终天生用于目标检测的输出。
Detect模块中包罗了推理解码等许多部分,这里只对模子布局的部分来举行说明。
  1. class Detect(nn.Module):
  2.     """YOLOv8 Detect head for detection models."""
  3.     dynamic = False  # force grid reconstruction
  4.     export = False  # export mode
  5.     end2end = False  # end2end
  6.     max_det = 300  # max_det
  7.     shape = None
  8.     anchors = torch.empty(0)  # init
  9.     strides = torch.empty(0)  # init
  10.     def __init__(self, nc=80, ch=()): # nc :类别数量。ch :每个检测层的通道数。
  11.         """Initializes the YOLOv8 detection layer with specified number of classes and channels."""
  12.         super().__init__()
  13.         self.nc = nc  # number of classes
  14.         self.nl = len(ch)  # number of detection layers 检测层的数量
  15.         self.reg_max = 16  # DFL channels (ch[0] // 16 to scale 4/8/12/16/20 for n/s/m/l/x) DFL(Distribution Focal Loss)通道数
  16.         self.no = nc + self.reg_max * 4  # number of outputs per anchor
  17.         self.stride = torch.zeros(self.nl)  # strides computed during build
  18.         c2, c3 = max((16, ch[0] // 4, self.reg_max * 4)), max(ch[0], min(self.nc, 100))  # channels
  19.         self.cv2 = nn.ModuleList( #解耦头的上部分操作dfi + ciou
  20.             nn.Sequential(Conv(x, c2, 3), Conv(c2, c2, 3), nn.Conv2d(c2, 4 * self.reg_max, 1)) for x in ch
  21.         )
  22.         # 解耦头的下部分bce
  23.         self.cv3 = nn.ModuleList(nn.Sequential(Conv(x, c3, 3), Conv(c3, c3, 3), nn.Conv2d(c3, self.nc, 1)) for x in ch)
  24.         self.dfl = DFL(self.reg_max) if self.reg_max > 1 else nn.Identity() #dfl输入16
  25.         if self.end2end:
  26.             self.one2one_cv2 = copy.deepcopy(self.cv2)
  27.             self.one2one_cv3 = copy.deepcopy(self.cv3)
  28.     def forward(self, x):
  29.         """Concatenates and returns predicted bounding boxes and class probabilities."""
  30.         if self.end2end:
  31.             return self.forward_end2end(x)
  32.         # 循环遍历 self.nl (检测层的数量)。
  33.         # 对于每个特征图,通过两个卷积层( self.cv2[i] 和 self.cv3[i] )处理,然后将结果沿着通道维度拼接。
  34.         for i in range(self.nl): # 三个尺度每个尺度做拼接操作
  35.             x[i] = torch.cat((self.cv2[i](x[i]), self.cv3[i](x[i])), 1)
  36.         if self.training:  # Training path
  37.             return x # 训练模式直接返回
  38.         y = self._inference(x) # 预测模式执行后面的推理操作
  39.         return y if self.export else (y, x)
复制代码

V8网络架构

[code]# Ultralytics YOLO




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4