【深度学习】【目标检测】【Ultralytics-YOLO系列】YOLOV3核心文件common.py解读

news2025/4/24 6:27:36

【深度学习】【目标检测】【Ultralytics-YOLO系列】YOLOV3核心文件common.py解读

文章目录

  • 【深度学习】【目标检测】【Ultralytics-YOLO系列】YOLOV3核心文件common.py解读
  • 前言
  • autopad函数
  • Conv类
    • __init__成员函数
    • forward成员函数
    • forward_fuse成员函数
  • Bottleneck类
    • __init__成员函数
    • forward成员函数
  • Concat类
    • __init__成员函数
    • forward成员函数
  • 总结


前言

在详细解析YOLOV3网络之前,首要任务是搭建Ultralytics–YOLOV3【Windows11下YOLOV3人脸检测】所需的运行环境,并完成模型的训练和测试,展开后续工作才有意义。
本博文对models/common.py代码进行解析,common.py文件存放着YOLOV3网络搭建常见的通用模块。其他代码后续的博文将会陆续讲解。这里只做YOLOV3相关模块的代码解析,其他的通用模块是YOLO后续系列中创新和提出的。


autopad函数

用于自动计算卷积层的填充值(padding),以确保当步幅为1时卷积操作后的输出特征图尺寸保持不变。

def autopad(k, p=None):  # kernel, padding
    """
    用于自动计算卷积层的填充值
    :param k:卷积核大小
    :param p:填充值
    :return:计算得到的填充值
    """
    if p is None:   # 检查是否需要自动计算填充值,否则用户指定填充值
        # 正方形卷积核:isinstance(k, int)表示k是一个整数,卷积核是正方形,填充值p被为k//2,即卷积核大小的一半向下取整
        # 非正方形卷积核: 是一个列表或元组,则对每个维度分别计算填充值,同理计算填充值p
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p

理论基础: 在二维卷积中,输出特征图的尺寸可以通过以下公式计算:
O u t p u t S i z e = I n p u t S i z e + 2 p − k s + 1 OutputSize = \frac{{InputSize + 2p - k}}{{\rm{s}}} + 1 OutputSize=sInputSize+2pk+1
其中: I n p u t S i z e InputSize InputSize是输入特征图的尺寸; p p p是填充大小; k k k是卷积核大小; s s s是步长。
根据上述方程,当 s = 1 s=1 s=1且输出尺寸等于输入尺寸时,解出 p p p的值:
p = ⌈ k − 1 2 ⌉ = ⌊ k 2 ⌋ p = \left\lceil {\frac{{k - 1}}{2}} \right\rceil = \left\lfloor {\frac{k}{2}} \right\rfloor p=2k1=2k
由于填充大小 p p p必须是整数,因此使用向下取整除法(//),即 p = k / / 2 p=k//2 p=k//2 来自动计算填充值,确保了无论卷积核大小 k k k是奇数还是偶数,都可以正确计算出合适的填充大小,使得在步长为1的情况下,输出尺寸尽可能接近输入尺寸。对于非对称的卷积核,分别对每个维度应用此规则以保证各自的输出尺寸匹配相应的输入尺寸。


Conv类

__init__成员函数

构造函数,初始化自定义的卷积模块,通常包含卷积层、批量归一化层和激活函数。调用了【models/common.py】的autopad函数

def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
    """
    构造函数,初始化自定义的卷积模块
    :param c1:输入通道数
    :param c2:输出通道数
    :param k:卷积核大小,默认为 1
    :param s:步幅,默认为 1
    :param p:填充,默认为None(不指定为None会自动计算填充值)
    :param g:分组卷积的分组数,默认为 1(标准卷积)
    :param act:是否使用激活函数,默认为True(使用nn.SiLU()),False则使用nn.Identity()(相当于没使用任何函数),提供了指定激活函数对象则使用指定的激活函数
    """
    super().__init__()
    # 创建一个二维卷积层
    self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
    # 创建一个批量归一化层
    self.bn = nn.BatchNorm2d(c2)
    # 设置激活函数
    self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

本博文讲解的代码原论文的源码,是YOLOV5团队复现改进后的YOLOV3代码,因此自定义的卷积模块的结构与原论文的结构在激活函数的选择上有所不同。

在YOLOV5中,SiLU替换了早期版本中的Leaky ReLU,显著提升了模型的性能。在EfficientNet系列中,SiLU成为了默认激活函数。

forward成员函数

前向传播,执行自定义的卷积模块。

def forward(self, x):
    """
    前向传播,执行模块
    :param x:输入数据张量
    :return:卷积块的输出
    """
    return self.act(self.bn(self.conv(x)))

forward_fuse成员函数

融合前向传播,跳过了批量归一化层,推理阶段使用可以提高计算效率。

def forward_fuse(self, x):
    """
    融合前向传播,跳过了批量归一化层,推理阶段使用可以提高计算效率
    :param x:输入数据张量
    :return:卷积块的输出
    """
    return self.act(self.conv(x))

Bottleneck类

__init__成员函数

自定义的瓶颈模块,通常用于构建类似残差网络的残差块。

def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, shortcut, groups, expansion
    """
    构造函数,构建类似残差网络的残差块
    :param c1:输入通道数
    :param c2:输出通道数
    :param shortcut:是否使用残差连接,默认为 True
    :param g: 分组卷积的分组数,默认为1(标准卷积)
    :param e:扩展比例,用于计算中间隐藏层的通道数默认为 0.5
    """
    super().__init__()
    c_ = int(c2 * e)  # 计算中间隐藏层的通道数
    self.cv1 = Conv(c1, c_, 1, 1)       # 第一层1×1卷积层
    self.cv2 = Conv(c_, c2, 3, 1, g=g)  # 第二层3×3卷积层
    self.add = shortcut and c1 == c2    # 判断是否添加残差连接:使用残差连接且输入通道数等于输出通道数

原论文中YOLOV3的瓶颈模块都是带有残差连接的,同时YOLOV3的结构中有很多1×1卷积+3×3卷积这种顺次排列的情况,与残差连接的瓶颈模块相似(但不是瓶颈模块)。因此,Ultralytics-YOLOV3代码为了yaml配置文件的简洁明了,将二则结合起来成了新的瓶颈模块,即可以选择是否激活残差连接。

如下图标记的配置文件部分,假设不结合在一起,每个Bottleneck就要单独写俩个Conv,分别是1×1 Conv和3×3 Conv。

forward成员函数

前向传播,执行自定义的瓶颈模块。

def forward(self, x):
    """
    前向传播,执行模块
    :param x:输入数据张量
    :return:瓶颈模块的输出
    """
    # 如果进行残差连接,则将输入x和瓶颈模块的输出结果相加
    return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))

Concat类

__init__成员函数

用于在深度学习模型中实现张量的拼接操作。

def __init__(self, dimension=1):
    """
    构造函数,用于实现张量在指定维度上的拼接操作
    :param dimension: 指定拼接的维度,默认为 1
    """
    super().__init__()
    self.d = dimension

forward成员函数

前向传播,执行拼接。

def forward(self, x):
    """
    前向传播,执行拼接
    :param x:输入数据张量列表
    :return:拼接后的张量
    """
    # 将输入张量列表沿着指定维度拼接成新的单一张量
    return torch.cat(x, self.d)

总结

尽可能简单、详细的介绍了核心文件common.py文件的作用:存放着YOLOV3网络搭建常见的通用模块。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2341252.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

16.Chromium指纹浏览器开发教程之WebGPU指纹定制

WebGPU指纹概述 WebGPU是下一代的Web图形和计算API,旨在提供高性能的图形渲染和计算能力。它是WebGL的后继者,旨在利用现代GPU的强大功能,使得Web应用能够实现接近原生应用的图形和计算性能。而且它是一个低级别的API,可以直接与…

SQL预编译——预编译真的能完美防御SQL注入吗

SQL注入原理 sql注入是指攻击者拼接恶意SQL语句到接受外部参数的动态SQL查询中,程序本身 未对插入的SQL语句进行过滤,导致SQL语句直接被服务端执行。 拼接的SQL查询例如,通过在id变量后插入or 11这样的条件,来绕过身份验证&#…

运行neo4j.bat console 报错无法识别为脚本,PowerShell 教程:查看语言模式并通过注册表修改受限模式

无法将“D:\neo4j-community-4.4.38-windows\bin\Neo4j-Management\Get-Args.ps1”项识别为cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 前提配置好环境变量之后依然报上面的错…

【EDA软件】【设计约束和分析操作方法】

1. 设计约束 设计约束主要分为物理约束和时序约束。 物理约束主要包括I/O接口约束(如引脚分配、电平标准设定等物理属性的约束)、布局约束、布线约束以及配置约束。 时序约束是FPGA内部的各种逻辑或走线的延时,反应系统的频率和速度的约束…

【Lua】Lua 入门知识点总结

Lua 入门学习笔记 本教程旨在帮助有编程基础的学习者快速入门Lua编程语言。包括Lua中变量的声明与使用,包括全局变量和局部变量的区别,以及nil类型的概念、数值型、字符串和函数的基本操作,包括16进制表示、科学计数法、字符串连接、函数声明…

光谱相机在肤质检测中的应用

光谱相机在肤质检测中具有独特优势,能够通过多波段光谱分析皮肤深层成分及生理状态,实现‌非侵入式、高精度、多维度的皮肤健康评估‌。以下是其核心应用与技术细节: ‌一、工作原理‌ ‌光谱反射与吸收特性‌: ‌血红蛋白‌&a…

机器学习第一篇 线性回归

数据集:公开的World Happiness Report | Kaggle中的happiness dataset2017. 目标:基于GDP值预测幸福指数。(单特征预测) 代码: 文件一:prepare_for_traning.py """用于科学计算的一个库…

CS144 Lab1实战记录:实现TCP重组器

文章目录 1 实验背景与要求1.1 TCP的数据分片与重组问题1.2 实验具体任务 2 重组器的设计架构2.1 整体架构2.2 数据结构设计 3 重组器处理的关键场景分析3.1 按序到达的子串(直接写入)3.2 乱序到达的子串(需要存储)3.3 与已处理区…

Linux安装mysql_exporter

mysqld_exporter 是一个用于监控 MySQL 数据库的 Prometheus exporter。可以从 MySQL 数据库的 metrics_schema 收集指标,相关指标主要包括: MySQL 服务器指标:例如 uptime、version 等数据库指标:例如 schema_name、table_rows 等表指标:例如 table_name、engine、…

BeautifulSoup 库的使用——python爬虫

文章目录 写在前面python 爬虫BeautifulSoup库是什么BeautifulSoup的安装解析器对比BeautifulSoup的使用BeautifulSoup 库中的4种类获取标签获取指定标签获取标签的的子标签获取标签的的父标签(上行遍历)获取标签的兄弟标签(平行遍历)获取注释根据条件查找标签根据CSS选择器查找…

HTTP的Header

一、HTTP Header 是什么? HTTP Header 是 HTTP 协议中的头部信息部分,位于请求或响应的起始行之后,用来在客户端(浏览器等)与服务器之间传递元信息(meta-data)(简单理解为传递信息的…

linux虚拟机网络问题处理

yum install -y yum-utils \ > device-mapper-persistent-data \ > lvm2 --skip-broken 已加载插件:fastestmirror, langpacks Loading mirror speeds from cached hostfile Could not retrieve mirrorlist http://mirrorlist.centos.org/?release7&arch…

AI-Sphere-Butler之如何使用Llama factory LoRA微调Qwen2-1.5B/3B专属管家大模型

环境: AI-Sphere-Butler WSL2 英伟达4070ti 12G Win10 Ubuntu22.04 Qwen2.-1.5B/3B Llama factory llama.cpp 问题描述: AI-Sphere-Butler之如何使用Llama factory LoRA微调Qwen2-1.5B/3B管家大模型 解决方案: 一、准备数据集我这…

协同推荐算法实现的智能商品推荐系统 - [基于springboot +vue]

🛍️ 智能商品推荐系统 - 基于springboot vue 🚀 项目亮点 欢迎来到未来的购物体验!我们的智能商品推荐系统就像您的私人购物顾问,它能读懂您的心思,了解您的喜好,为您精心挑选最适合的商品。想象一下&am…

Jenkins的地位和作用

所处位置 Jenkins 是一款开源的自动化服务器,广泛应用于软件开发和测试流程中,主要用于实现持续集成(CI)和持续部署(CD)。它在开发和测试中的位置和作用可以从以下几个方面来理解: 1. 在开发和测…

【集合】底层原理实现及各集合之间的区别

文章目录 集合2.1 介绍一下集合2.2 集合遍历的方法2.3 线程安全的集合2.4 数组和集合的区别2.5 ArrayList和LinkedList的区别2.6 ArrayList底层原理2.7 LinkedList底层原理2.8 CopyOnWriteArrayList底层原理2.9 HashSet底层原理2.10 HashMap底层原理2.11 HashTable底层原理2.12…

srp batch

参考网址: Unity MaterialPropertyBlock 正确用法(解决无法合批等问题)_unity_define_instanced_prop的变量无法srp合批-CSDN博客 URP | 基础CG和HLSL区别 - 哔哩哔哩 (bilibili.com) 【直播回放】Unity 批处理/GPU Instancing/SRP Batche…

【Linux运维涉及的基础命令与排查方法大全】

文章目录 前言1、计算机网络常用端口2、Kali Linux中常用的命令3、Kali Linux工具的介绍4、Ubuntu没有网络连接解决方法5、获取路由6、数据库端口 前言 以下介绍计算机常见的端口已经对应的网络协议,Linux中常用命令,以及平时运维中使用的排查网络故障的…

Webview+Python:用HTML打造跨平台桌面应用的创新方案

目录 一、技术原理与优势分析 1.1 架构原理 1.2 核心优势 二、开发环境搭建 2.1 安装依赖 2.2 验证安装 三、核心功能开发 3.1 基础窗口管理 3.2 HTML↔Python通信 JavaScript调用Python Python调用JavaScript 四、高级功能实现 4.1 系统级集成 4.2 多窗口管理 五…

克服储能领域的数据处理瓶颈及AI拓展

对于储能研究人员来说,日常工作中经常围绕着一项核心但有时令人沮丧的任务:处理实验数据。从电池循环仪的嗡嗡声到包含电压和电流读数的大量电子表格,研究人员的大量时间都花在了提取有意义的见解上。长期以来,该领域一直受到对专…