YOLOv8-ultralytics-8.2.103部分代码阅读笔记-utils.py

devtools/2024/11/24 6:56:42/

utils.py

ultralytics\nn\modules\utils.py

目录

utils.py

1.所需的库和模块

2.def _get_clones(module, n): 

3.def bias_init_with_prob(prior_prob=0.01): 

4.def linear_init(module): 

5.def inverse_sigmoid(x, eps=1e-5): 

6.def multi_scale_deformable_attn_pytorch(value: torch.Tensor, value_spatial_shapes: torch.Tensor, sampling_locations: torch.Tensor, attention_weights: torch.Tensor,) -> torch.Tensor: 


1.所需的库和模块

# Ultralytics YOLO 🚀, AGPL-3.0 license
"""Module utils."""import copy
import mathimport numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.init import uniform___all__ = "multi_scale_deformable_attn_pytorch", "inverse_sigmoid"

2.def _get_clones(module, n): 

# 这段代码定义了一个名为 _get_clones 的函数,其作用是从一个给定的模块( module )创建多个克隆(副本),并返回这些克隆组成的列表。这个函数通常用于深度学习模型中,特别是在实现具有多个相同层的网络时,例如 Transformer 架构中的编码器和解码器层。
# 函数定义。
# 1.module : 要克隆的原始模块,它是一个 nn.Module 的实例。
# 2.n : 需要创建的克隆模块的数量。
def _get_clones(module, n):# 从给定的模块创建克隆模块的列表。"""Create a list of cloned modules from the given module."""# copy.deepcopy(module) : 使用 Python 标准库中的 copy 模块的 deepcopy 函数来创建 module 的深拷贝。深拷贝意味着创建一个新的模块实例,并复制所有相关的参数和缓冲区,使得原始模块和克隆模块之间没有任何共享的参数。# for _ in range(n) : 生成一个从 0 到 n-1 的序列,并对于序列中的每个元素,执行 copy.deepcopy(module) 来创建一个克隆模块。# [... for _ in range(n)] : 将所有克隆模块收集到一个列表中。# nn.ModuleList(...) : 将克隆模块的列表包装成一个 nn.ModuleList 。 nn.ModuleList 是 PyTorch 中的一个容器类,用于存储多个模块,并且可以像普通列表一样进行索引和迭代。它还确保其中的每个模块都被正确地注册到网络中,以便在训练时它们的参数会被优化。# 返回值 : 返回一个 nn.ModuleList 实例,其中包含了 n 个克隆的模块。return nn.ModuleList([copy.deepcopy(module) for _ in range(n)])

3.def bias_init_with_prob(prior_prob=0.01): 

# 这段代码定义了一个名为 bias_init_with_prob 的函数,它用于根据给定的概率值初始化卷积层或全连接层的偏置(bias)。这个函数的目的是为二分类问题的损失函数(如交叉熵损失)提供一个先验概率,从而帮助平衡正负样本的数量。
# 函数定义。
# 1.prior_prob : 一个浮点数,表示先验概率,默认值为 0.01。
def bias_init_with_prob(prior_prob=0.01):# 根据给定的概率值初始化 conv/fc 偏差值。"""Initialize conv/fc bias value according to a given probability value."""# 使用自然对数函数 np.log 计算 prior_prob 的对数几率(log-odds)。# 1 - prior_prob 表示负样本的概率。# (1 - prior_prob) / prior_prob 计算正负样本概率的比值。# -np.log((1 - prior_prob) / prior_prob) 计算这个比值的负对数,得到偏置值。# 返回值 :返回计算得到的偏置值。return float(-np.log((1 - prior_prob) / prior_prob))  # return bias_init
# 这个偏置值可以被用于初始化模型中的卷积层或全连接层的偏置,以帮助模型在训练开始时就考虑到类别不平衡的问题。
# 这种方法特别适用于目标检测和图像分割等任务中,其中正样本(例如,包含目标的边界框)的数量远少于负样本(例如,不包含目标的边界框)。通过这种方式,模型可以更好地学习到如何区分正负样本。

4.def linear_init(module): 

# 这段代码定义了一个名为 linear_init 的函数,它用于初始化线性模块(例如 nn.Linear )的权重和偏置。这个函数使用了均匀分布来初始化权重和偏置,这是一种常见的初始化方法,可以帮助模型在训练开始时避免过大或过小的梯度。
# 函数定义。
# 1.module : 要初始化的线性模块,通常是一个 nn.Linear 实例。
def linear_init(module):# 初始化线性模块的权重和偏差。"""Initialize the weights and biases of a linear module."""# 权重初始化。# 计算权重的初始化范围 bound 。这里使用的是 Xavier 初始化的一种变体,其中 bound 被设置为模块权重矩阵的第一个维度(即输入特征数)的平方根的倒数。bound = 1 / math.sqrt(module.weight.shape[0])# torch.nn.init.uniform_(tensor, a=0.0, b=1.0)# torch.nn.init.uniform_() 是 PyTorch 中的一个函数,用于将输入张量的值初始化为均匀分布的随机数。这个函数通常用于神经网络的权重初始化,以帮助模型在训练开始时避免过大或过小的梯度。# 参数说明 :# tensor : 要初始化的张量,通常是神经网络中的权重。# a : 均匀分布的下界,默认为 0.0。# b : 均匀分布的上界,默认为 1.0。# 功能描述 :# uniform_() 函数会将输入张量的每个元素随机初始化为在 [a, b) 区间内的均匀分布的值。这个函数是一个就地操作(in-place operation),意味着它会直接修改输入张量,而不会返回一个新的张量。# 返回值 :# 返回输入张量本身,已被修改为均匀分布的随机值。# 注意事项 :# 使用均匀分布初始化时,确保选择合适的上下界 a 和 b ,以避免在训练过程中出现梯度消失或梯度爆炸的问题。# 在某些情况下,使用其他初始化方法(如 Xavier 初始化或 He 初始化)可能会更有效,具体取决于网络的架构和激活函数的选择。# 使用 uniform_ 函数将权重初始化为均匀分布的值,范围在 [-bound, bound] 之间。uniform_(module.weight, -bound, bound)# 偏置初始化。检查模块是否有 bias 属性,并且 bias 不为 None 。if hasattr(module, "bias") and module.bias is not None:# 如果有偏置,则使用 uniform_ 函数将偏置初始化为均匀分布的值,范围在 [-bound, bound] 之间。uniform_(module.bias, -bound, bound)
# 这种初始化方法有助于模型在训练开始时就有一个合理的起点,从而有助于模型的收敛。

5.def inverse_sigmoid(x, eps=1e-5): 

# 这段代码定义了一个名为 inverse_sigmoid 的函数,它用于计算输入张量 x 的逆 Sigmoid 函数值。逆 Sigmoid 函数通常用于将 Sigmoid 函数的输出范围(0 到 1)映射回原始的实数范围。
# 函数定义。
# 1.x : 输入张量,其值应在 Sigmoid 函数的输出范围内,即 0 到 1。
# 2.eps : 用于数值稳定性的小常数,防止除以零。
def inverse_sigmoid(x, eps=1e-5):# 计算张量的逆 S 型函数。"""Calculate the inverse sigmoid function for a tensor."""# 使用 clamp 方法将 x 的值限制在 0 到 1 的范围内,以确保它们在 Sigmoid 函数的输出范围内。x = x.clamp(min=0, max=1)# x1 和 x2 分别是 x 和 1 - x 的值,它们被限制在 eps 以上,以避免除以零的错误。x1 = x.clamp(min=eps)x2 = (1 - x).clamp(min=eps)# 返回值 :返回输入张量 x 的逆 Sigmoid 函数值。return torch.log(x1 / x2)
# 这个函数在目标检测和图像分割等任务中非常有用,因为这些任务中的锚点(anchor)或预测框(prediction)通常会通过 Sigmoid 函数进行缩放,而逆 Sigmoid 函数可以用来恢复它们的原始尺度。

6.def multi_scale_deformable_attn_pytorch(value: torch.Tensor, value_spatial_shapes: torch.Tensor, sampling_locations: torch.Tensor, attention_weights: torch.Tensor,) -> torch.Tensor: 

# 这段代码定义了一个名为 multi_scale_deformable_attn_pytorch 的函数,它实现了多尺度可变形注意力(Multiscale Deformable Attention)的计算。这个函数是多尺度可变形注意力机制的核心,它允许模型在不同尺度上动态地关注输入特征图的不同区域。
# 函数签名。
# 1.value : 值张量,即注意力机制中的值(V)。
# 2.value_spatial_shapes : 一个包含不同尺度值张量空间形状的列表。
# 3.sampling_locations : 采样位置张量,包含每个采样点的坐标。
# 4.attention_weights : 注意力权重张量,包含每个采样点的权重。
def multi_scale_deformable_attn_pytorch(value: torch.Tensor,value_spatial_shapes: torch.Tensor,sampling_locations: torch.Tensor,attention_weights: torch.Tensor,
) -> torch.Tensor:"""Multiscale deformable attention.https://github.com/IDEA-Research/detrex/blob/main/detrex/layers/multi_scale_deform_attn.py"""# 从输入张量中提取 批次大小 bs 、 头数 num_heads 、 嵌入维度 embed_dims 、 查询数 num_queries 、 尺度数 num_levels   和采样点数 num_points 。bs, _, num_heads, embed_dims = value.shape_, num_queries, num_heads, num_levels, num_points, _ = sampling_locations.shape# 将值张量 value 按照空间形状分割成多个尺度的值张量列表。value_list = value.split([H_ * W_ for H_, W_ in value_spatial_shapes], dim=1)# 将采样位置张量 sampling_locations 转换为适合 grid_sample 函数的网格坐标。sampling_grids = 2 * sampling_locations - 1# 对每个尺度的值张量,使用 grid_sample 函数进行双线性插值采样,并将采样结果存储在 sampling_value_list 中。# 初始化采样值列表。创建一个空列表 sampling_value_list 用于存储每个尺度的采样值。sampling_value_list = []# 遍历每个尺度。遍历 value_spatial_shapes ,它包含了每个尺度的特征图的高度和宽度。for level, (H_, W_) in enumerate(value_spatial_shapes):# bs, H_*W_, num_heads, embed_dims -># bs, H_*W_, num_heads*embed_dims -># bs, num_heads*embed_dims, H_*W_ -># bs*num_heads, embed_dims, H_, W_# 重塑和转置值张量。对每个尺度的值张量 value_list[level] 进行重塑和转置,以匹配 grid_sample 函数的输入要求。value_l_ = value_list[level].flatten(2).transpose(1, 2).reshape(bs * num_heads, embed_dims, H_, W_)# bs, num_queries, num_heads, num_points, 2 -># bs, num_heads, num_queries, num_points, 2 -># bs*num_heads, num_queries, num_points, 2# 准备采样网格。对采样位置 sampling_grids 进行转置和展平,以匹配 value_l_ 的形状。sampling_grid_l_ = sampling_grids[:, :, :, level].transpose(1, 2).flatten(0, 1)# torch.nn.functional.grid_sample(input, grid, mode='bilinear', padding_mode='zeros', align_corners=None)# torch.nn.functional.grid_sample 是 PyTorch 中的一个函数,它用于根据给定的坐标网格对输入张量进行采样。这个函数常用于图像变形、数据增强等任务。# 参数说明 :# input : 输入张量,可以是 4D 张量(N, C, H, W)或 5D 张量(N, C, D, H, W),分别代表批量图像或体积数据。# grid : 坐标网格张量,用于指定采样位置。对于 4D 输入, grid 的形状为(N, H_out, W_out, 2),对于 5D 输入, grid 的形状为(N, D_out, H_out, W_out, 3)。# mode : 采样模式,可以是 'bilinear'(双线性插值)或 'nearest'(最近邻插值)。# padding_mode : 填充模式,可以是 'zeros'(用 0 填充)或 'border'(用边界值填充)。# align_corners : 布尔值,指示是否将网格坐标与输入张量的角点对齐。如果设置为 True,则网格坐标被视为指向像素的角点;如果设置为 False,则网格坐标被视为指向像素之间的中心点。默认值为 None,此时与 align_corners=False 相同。# 功能描述 :# F.grid_sample 函数根据 grid 中的坐标网格对 input 张量进行采样。坐标网格的值通常在 [-1, 1] 之间,(-1, -1) 表示输入张量左上角的元素,(1, 1) 表示右下角的元素。该函数可以使用双线性插值或最近邻插值来计算采样点的值。# 返回值 :# 返回采样后的输出张量,其形状为(N, C, H_out, W_out)或(N, C, D_out, H_out, W_out),取决于输入张量和网格的形状。# bs*num_heads, embed_dims, num_queries, num_points# 执行采样。使用双线性插值( bilinear )模式和零填充( zeros )模式的 grid_sample 函数,根据采样网格 sampling_grid_l_ 对 value_l_ 进行采样。sampling_value_l_ = F.grid_sample(value_l_, sampling_grid_l_, mode="bilinear", padding_mode="zeros", align_corners=False)# 存储采样结果。将采样结果 sampling_value_l_ 添加到 sampling_value_list 中。sampling_value_list.append(sampling_value_l_)# (bs, num_queries, num_heads, num_levels, num_points) -># (bs, num_heads, num_queries, num_levels, num_points) -># (bs, num_heads, 1, num_queries, num_levels*num_points)# 重塑注意力权重。调整注意力权重张量的形状,以便于与采样值进行加权求和。attention_weights = attention_weights.transpose(1, 2).reshape(bs * num_heads, 1, num_queries, num_levels * num_points)# 计算加权和。将所有尺度的采样值堆叠起来,与注意力权重相乘,然后沿着最后一个维度求和,得到最终的输出张量。output = ((torch.stack(sampling_value_list, dim=-2).flatten(-2) * attention_weights).sum(-1).view(bs, num_heads * embed_dims, num_queries))# 调整输出形状并返回。调整输出张量的形状,使其维度顺序为 [bs, num_queries, num_heads * embed_dims] ,并确保张量在内存中是连续的。return output.transpose(1, 2).contiguous()
# 这个函数实现了多尺度可变形注意力机制的核心计算,它允许模型在不同尺度上动态地关注输入特征图的不同区域,这在处理具有不同尺度特征的目标时特别有用。


http://www.ppmy.cn/devtools/136485.html

相关文章

vscode下面python调试报错ImportError: cannot import name ‘Literal‘ from ‘typing‘

1 问题描述 我在vscode下面编写python程序,这个程序是在一个英伟达anoconda环境下的项目。之前能运行能调试,最近发现只能运行ctlf5,但是使用f5进行调试时,报错“File “c:\Users\86137.vscode\extensions\ms-python.debugpy-202…

详解八大排序(五)------(计数排序,时间复杂度)

文章目录 1. 计数排序(CountSort)1.1 核心思路1.2 实现代码 2. 时间复杂度比较 1. 计数排序(CountSort) 1.1 核心思路 计数排序的核心思路是另外创建一个数组,记录原数组中出现的成员个数,再依次打印新数组…

SpringSecurity基于内存的多个登录用户支持

Spring Security 支持各种来源的用户数据,包括内存、数据库、LDAP 等,它们被抽象为一个 UserDetailsService 接口,任何实现了 UserDetailsService 接口的对象都可以作为认证数据源。在这种设计模式下,Spring Security 显得尤为灵活…

Android Activity 基础接口知识和常见问题

Activity 知识点及问题点 接口onMultiWindowModeChangedonConfigurationChanged 常见问题Android解决点击桌面图标,就重新启动应用程序问题 接口 onMultiWindowModeChanged 定义 onMultiWindowModeChanged是Android中Activity类的一个回调方法。它会在活动&#xf…

挂壁式空气净化器什么牌子净化好?测评高热度品牌排行

近年来,挂壁式空气净化器日益成为消费者关注的焦点。随着市场需求的激增,其品牌和型号亦愈发丰富。作为家电测评领域的专业人士,我已评测了众多挂壁式空气净化器,发现部分产品存在质量问题,净化效果不佳,尤…

第二十九章 TCP 客户端 服务器通信 - 记录的拼接

文章目录 第二十九章 TCP 客户端 服务器通信 - 记录的拼接记录的拼接多路复用 TCP设备正在关闭连接使用CLOSE命令断开连接 第二十九章 TCP 客户端 服务器通信 - 记录的拼接 记录的拼接 在某些情况下,TCP会将不同的记录连接在一起形成单个记录。如果客户端或服务器…

HTML5实现剪刀石头布小游戏(附源码)

文章目录 1.设计来源1.1 主界面1.2 皮肤风格1.2 游戏中界面 2.效果和源码源码下载万套模板,程序开发,在线开发,在线沟通 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/143798520 HTM…

Linux安装RabbitMQ

安装步骤 rabbitmq使用erlang开发,依赖于erlang,所以需要先下载erlang,且版本要兼容: 可在官网查看erlang与rabbitmq的版本对应关系 https://www.rabbitmq.com/docs/which-erlangCentOs7安装运行 下载 下载地址 https://www.rab…