parser

yolov5s.yaml



- nc: 80 # number of classes
- depth_multiple: 0.33 # model depth multiple 模型深度倍数 和number有关,要乘
- width_multiple: 0.50 # layer channel multiple 层级通道倍数 和args有关,要乘
- yolov5s.yaml

- yolov5m.yaml

- yolov5l.yaml

- yolov5x.yaml

yolov5n.yaml、yolov5l.yaml、yolov5m.yaml、yolov5s.yaml、yolov5x.yaml只有这两个倍数变化,模型越复杂,倍数越大。 - [from, number, module, args]
- [-1, 1, Focus, [64, 3]
from=-1:从上一层过来的 - [-1, 10], 1, Concat, [1]
from=[-1,10]:从22层和10层过来 - [-1, 3, C3, [128]]
number=3,第2层有3个C3模块 - module:
conv:卷积层
C3:
SPP:
nn.Upsample:
Concat:
Detect: - args:给module传的参数

0-P1/2:第一层,P1,640x640输入的RGB图像-》320x320输出
1-P2/4:第二层,P2,640x640输入的RGB图像-》160x160输出
流程图(FPN、PAN)

Model

cfg:配置文件
ch:channels,RGB三通道
nc:类别数
self.yaml.get('ch', ch)优先使用yaml配置,否则使用默认值ch,体现配置优先级。m = self.model[-1]获取模型最后一层,预期为Detect层。YOLOv5 的检测头。if isinstance(m, Detect):确认最后一层是否为Detect类的实例,确保后续操作仅对检测头执行。s = 256 # 2x min stride设定基准输入尺寸 256x256(通常为最小下采样步长 stride 的 2 倍,用于计算特征图缩放比例)。m.stride通过前向传播一个 1xchx256x256 的零张量,获取各检测层的输出特征图尺寸。m.anchors /= m.stride.view(-1, 1, 1)将锚框尺寸归一化到特征图尺度(除以对应层的 stride)。

initialize_weights(self)初始化模型所有层的权重参数self.info()打印模型的结构摘要信息(如层数、参数数量、梯度占比等)。
输出内容:
各层的名称、类型、输入/输出维度。
总参数量(可训练/不可训练)。
浮点运算量(FLOPs)估算(如果实现)。logger.info('')输出一个空行到日志,用于分隔模型初始化日志与其他后续日志。
前向传播


x:输入图像张量
augment:是否启用数据增强(多尺度+翻转)
profile:是否启用性能分析
- forward_once:单次前向传播
y, dt = [], [] # outputs
y:存储每一层的输出结果。
dt: 在性能分析模式下(profile=True),记录每一层的计算耗时。for m in self.model:遍历模型的所有层- m.f:表示当前层 m 的输入来源(默认为 -1,即来自前一层的输出)。
如果 m.f 是整数(如 3),直接从 y[3] 获取输入(跳层连接)。
如果 m.f 是列表(如 [2, 4, -1]),拼接多个层的输出作为输入(多分支结构)。
fuse

融合卷积层(Conv2d)和批归一化层(BatchNorm2d),目的是优化模型的计算效率
遍历模型的所有模块:for m in self.model.modules() 会遍历模型中的每一层。
检查模块类型:if type(m) is Conv and hasattr(m, 'bn') 判断当前模块是否是 Conv 类型(自定义的卷积层类),并且是否包含 bn(批归一化层)属性。
融合卷积和批归一化:调用 fuse_conv_and_bn(m.conv, m.bn) 将卷积层和批归一化层的参数合并为一个新的卷积层,并更新 m.conv。
移除批归一化层:delattr(m, 'bn') 删除原来的批归一化层。
更新前向传播方法:m.forward = m.fuseforward 将前向传播方法替换为融合后的版本(
fuseforward是专门为融合后的层设计的方法)。
打印模型信息:self.info() 输出融合后的模型结构信息。
NMS(Non-Maximum Suppression,非极大值抑制)

- mode 参数:
mode=True:表示需要添加 NMS 模块。
mode=False:表示需要移除 NMS 模块。 - present 变量:
检查模型的最后一层是否是 NMS 类型(type(self.model[-1]) is NMS)。
如果最后一层已经是 NMS,present 为 True;否则为 False。 - 添加 NMS 模块(if mode and not present):
如果 mode=True 且当前模型没有 NMS 模块(not present),则执行以下操作:
创建一个新的 NMS() 模块实例 m。
设置 m.f = -1(通常表示该模块的来源层,-1 可能表示“无”或“自动”)。
设置 m.i 为当前最后一层的索引 +1(确保新模块的索引正确)。
使用 add_module 方法将 NMS 模块添加到模型的末尾。
调用 self.eval() 将模型切换到推理模式(因为 NMS 通常在推理时使用)。 - 移除 NMS 模块(elif not mode and present):
如果 mode=False 且当前模型包含 NMS 模块(present),则执行以下操作:
直接通过切片 self.model[:-1] 移除最后一层(即 NMS 模块)。 - 训练时:通常不需要 NMS,可以调用 model.nms(False) 移除 NMS 模块。
- 推理时:需要 NMS 过滤冗余检测框,可以调用 model.nms(True) 添加 NMS 模块。
info打印
def info(self, verbose=False, img_size=640): model_info(self, verbose, img_size)
self: 表示该方法属于某个类(通常是YOLOv5的模型类)。
verbose=False: 一个布尔参数,控制是否打印详细信息。默认为 False,即只打印基本信息。
img_size=640: 输入图像的尺寸,默认为 640(YOLOv5的默认输入分辨率)。
调用 model_info(self, verbose, img_size) 函数,将当前模型实例、verbose 标志和 img_size 传递给它。
model_info 函数的作用是分析模型的结构和参数,并打印相关信息,例如:
模型的层数、参数数量、计算量(FLOPs)。
各层的详细信息(如果 verbose=True)。
输入尺寸对模型的影响。