目标检测tricks

embedded/2025/3/1 23:28:32/
A. Stochastic Weight Averaging (SWA)
1. 基本思想

SWA 的核心思想是通过对训练过程中不同时间点的模型参数进行加权平均,从而获得一个更好的模型。具体来说,SWA 在训练过程的后期阶段对多个不同的模型快照(snapshots)进行平均,而不是只使用最终的模型参数。

2. 为什么有效?

在深度学习训练中,尤其是在使用随机梯度下降(SGD)及其变体时,模型参数会在局部最优解附近波动。这些波动通常反映了损失函数的不同局部极小值或鞍点。通过平均这些波动中的参数,可以平滑这些波动,并找到一个更稳定的解决方案,从而提高模型的泛化能力。

SWA 的优点

提高泛化能力:通过平均多个模型的参数,可以减少单个模型可能存在的过拟合问题,从而提高模型的泛化能力。
增加稳定性:由于 SWA 平滑了参数的波动,使得最终模型更加稳定,减少了对初始条件和随机性的敏感性。
简单易用:相比于其他复杂的正则化方法(如 Dropout、DropConnect 等),SWA 实现起来非常简单,只需要在训练的后期阶段进行简单的参数平均即可。

SWA 的局限性

内存需求:如果需要存储多个模型快照,则可能会增加内存需求。
计算成本:在 SWA 阶段,虽然学习率较低,但仍然需要进行额外的前向和后向传播计算。
适用范围:SWA 主要适用于那些在训练后期参数波动较大的模型。对于一些已经非常稳定的模型,SWA 可能不会带来显著的改进。

SWA 的工作流程

1. 标准训练阶段
首先,模型按照标准的优化算法(如 SGD 或 Adam)进行训练。在这个阶段,模型参数会逐渐收敛到某个局部最优解。

for epoch in range(total_epochs):for batch_i, (inputs, targets) in enumerate(train_loader):optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, targets)loss.backward()optimizer.step()

2. SWA 启动阶段
当训练进入某一特定阶段(通常是训练的最后 25%),开始应用 SWA。此时,模型参数会被周期性地保存下来,并用于计算平均值。

swa_model = AveragedModel(model)
swa_start = int(0.75 * total_epochs)for epoch in range(total_epochs):if epoch >= swa_start:swa_model.update_parameters(model)

3. SWA 调度器
为了更好地控制学习率,在 SWA 阶段通常使用一个固定的学习率调度器(如 SWALR)。这个调度器确保在 SWA 阶段学习率保持在一个较低且固定的值。

swa_scheduler = SWALR(optimizer, swa_lr=0.05)

4. BN 层更新
在 SWA 结束后,批归一化(Batch Normalization, BN)层的统计量需要更新。这是因为 BN 层依赖于训练数据的均值和方差统计量,而在 SWA 过程中这些统计量没有被更新。因此,需要通过重新遍历训练数据集来更新这些统计量。

torch.optim.swa_utils.update_bn(train_loader, swa_model, device='cuda')

运用在YoloV8中的代码

import torch
from torch.optim.swa_utils import AveragedModel, SWALR
from ultralytics import YOLO
from torch.utils.data import DataLoader
from torchvision import transforms
from yolov8_dataset import YOLOv8Dataset  # 假设你有一个自定义的数据集类# 数据集和数据加载器
transform = transforms.Compose([transforms.ToTensor()])
train_dataset = YOLOv8Dataset(root='path/to/dataset', transform=transform)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)# 加载预训练的 YOLOv8 模型
model = YOLO('yolov8n.yaml')  # 根据需要选择合适的模型配置# 初始化优化器和学习率调度器
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)# 初始化 SWA 模型和调度器
swa_model = AveragedModel(model.model)
swa_start = int(0.75 * 100)  # 在训练的最后 25% 开始 SWA
swa_scheduler = SWALR(optimizer, swa_lr=0.05)total_epochs = 100for epoch in range(total_epochs):model.train()for batch_i, (imgs, targets) in enumerate(train_loader):optimizer.zero_grad()loss, outputs = model(imgs, targets)loss.backward()optimizer.step()if epoch >= swa_start:swa_model.update_parameters(model.model)swa_scheduler.step()else:lr_scheduler.step()# 在训练结束后,应用 SWA 最终步骤
torch.optim.swa_utils.update_bn(train_loader, swa_model, device='cuda')# 保存 SWA 模型
torch.save(swa_model.state_dict(), 'yolov8_swa.pth')

AveragedModel 类简化实现

import copyclass AveragedModel:def __init__(self, model):self.n_averaged = 0  # 记录已经累加的模型快照数量self.module = copy.deepcopy(model)  # 复制原始模型结构和参数def update_parameters(self, model):self.n_averaged += 1for p_swa, p_model in zip(self.module.parameters(), model.parameters()):device = p_swa.devicep_model_ = p_model.detach().to(device)if self.n_averaged == 1:p_swa.detach().copy_(p_model_)else:p_swa.detach().mul_(1.0 - 1.0 / self.n_averaged).add_(p_model_, alpha=1.0 / self.n_averaged)
Stochastic Weight Averaging (SWA) 参数更新公式

在 Stochastic Weight Averaging (SWA) 中,参数更新的过程涉及到将当前模型的参数逐步累加到一个平均模型中。以下是具体的公式和解释。

第一次调用 update_parameters

当第一次调用 update_parameters 方法时,直接将 p_model 赋值给 p_swa

p swa = p model p_{\text{swa}} = p_{\text{model}} pswa=pmodel

这意味着 p_swa 直接被设置为当前模型的参数。

后续调用 update_parameters

从第二次调用开始,使用以下公式更新 p_swa

p swa = ( 1 − 1 n ) ⋅ p swa + 1 n ⋅ p model p_{\text{swa}} = \left(1 - \frac{1}{n}\right) \cdot p_{\text{swa}} + \frac{1}{n} \cdot p_{\text{model}} pswa=(1n1)pswa+n1pmodel

其中 $ n $ 是已经累加的模型快照数量。

第二次调用 update_parameters 的例子

n = 2 n = 2 n=2 时,公式变为:

p swa = 1 2 ⋅ p swa + 1 2 ⋅ p model p_{\text{swa}} = \frac{1}{2} \cdot p_{\text{swa}} + \frac{1}{2} \cdot p_{\text{model}} pswa=21pswa+21pmodel

这表示 p_swa 被更新为其当前值的一半加上 p_model 的一半。

更多调用的例子

随着训练的继续,每次调用 update_parameters 都会更新 p_swa,逐渐平滑模型参数的的波动。例如:

  • n = 5 n = 5 n=5 时:
    p swa = 4 5 ⋅ p swa + 1 5 ⋅ p model p_{\text{swa}} = \frac{4}{5} \cdot p_{\text{swa}} + \frac{1}{5} \cdot p_{\text{model}} pswa=54pswa+51pmodel

  • n = 6 n = 6 n=6 时:
    p swa = 5 6 ⋅ p swa + 1 6 ⋅ p model p_{\text{swa}} = \frac{5}{6} \cdot p_{\text{swa}} + \frac{1}{6} \cdot p_{\text{model}} pswa=65pswa+61pmodel

B. SAHI (Slice and Hyper Inference)
SAHI 的核心思想

图像切片:将大图像切分成多个小块(slices),以便更好地捕捉小目标。
超推理(Hyper Inference):对每个切片进行独立的推理,并合并结果以获得最终的检测结果。
自动切片选择:根据目标的大小和分布,自适应地选择合适的切片策略。

工作流程

以下是 SAHI 的典型工作流程:

加载图像:读取待检测的大图像。
图像切片:将图像切分成多个小块(slices),每个切片的大小和重叠度可以根据需求调整。
模型推理:对每个切片分别进行目标检测模型的推理。
结果合并:将所有切片的检测结果合并成一个完整的检测结果,并去除重复检测框。
后处理:对合并后的检测结果进行进一步处理,如非极大值抑制(NMS)等。

以Yolov5为例的插入sahi代码

from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction
from sahi.utils.yolov5 import Yolov5TestConstants# 加载预训练的 YOLOv5 模型
detection_model = AutoDetectionModel.from_pretrained(model_type='yolov5',model_path=Yolov5TestConstants.YOLOV5N_MODEL_LOCAL_PATH,  # 替换为你的模型路径confidence_threshold=0.3,device="cuda"  # 或 "cpu"
)# 图像路径
image_path = "path/to/your/image.jpg"# 使用 SAHI 进行小目标检测
result = get_sliced_prediction(image=image_path,detection_model=detection_model,# slice_height 和 slice_width:每个切片的高度和宽度。可以根据图像大小和目标的尺度进行调整slice_height=512,slice_width=512, # 切片之间的重叠比例。增加重叠可以减少目标被切分的风险,但会增加计算量。overlap_height_ratio=0.2,overlap_width_ratio=0.2
)# 打印检测结果
print(result)
C. SeNet (Squeeze-and-Excitation Networks) 通道注意力
SeNet 工作流程图解:

输入特征图

输入是一个三维张量,包含高度 H H H、宽度 W W W 和通道数 C C C

Input:  U ∈ R H × W × C \text{Input: } U \in \mathbb{R}^{H \times W \times C} Input: URH×W×C

Squeeze(挤压):全局平均池化 (Global Average Pooling, GAP)

对每个通道进行全局平均池化操作,将空间维度压缩为一个标量。输出是一个向量 z ∈ R C z \in \mathbb{R}^C zRC,表示每个通道的全局信息。

z c = 1 H × W ∑ i = 1 H ∑ j = 1 W U ( i , j , c ) z_c = \frac{1}{H \times W} \sum_{i=1}^{H} \sum_{j=1}^{W} U(i,j,c) zc=H×W1i=1Hj=1WU(i,j,c)

其中, z c z_c zc 是第 c c c 个通道的全局平均值。

Excitation(激励):两个全连接层

使用两个全连接层来生成每个通道的权重。第一个全连接层将特征维度从 C C C 降到 C r \frac{C}{r} rC,其中 r r r 是降维比率。第二个全连接层将特征维度从 C r \frac{C}{r} rC 升回到 C C C。中间使用 ReLU 激活函数和 Sigmoid 激活函数分别处理两个全连接层的输出。

z ^ = ReLU ( W 1 ⋅ z ) s = σ ( W 2 ⋅ z ^ ) \begin{aligned} \hat{z} &= \text{ReLU}(W_1 \cdot z) \\ s &= \sigma(W_2 \cdot \hat{z}) \end{aligned} z^s=ReLU(W1z)=σ(W2z^)

其中, W 1 ∈ R C r × C W_1 \in \mathbb{R}^{\frac{C}{r} \times C} W1RrC×C W 2 ∈ R C × C r W_2 \in \mathbb{R}^{C \times \frac{C}{r}} W2RC×rC 分别是第一和第二全连接层的权重矩阵, σ \sigma σ 表示Sigmoid激活函数。

Reweight(重加权):逐元素相乘

将生成的通道权重 s ∈ R C s \in \mathbb{R}^C sRC 应用到原始特征图 U U U 上,通过逐元素相乘的方式重新加权特征图。输出是一个与输入特征图形状相同的张量 U ′ ∈ R H × W × C U' \in \mathbb{R}^{H \times W \times C} URH×W×C

U ′ ( i , j , c ) = s c × U ( i , j , c ) U'(i,j,c) = s_c \times U(i,j,c) U(i,j,c)=sc×U(i,j,c)

以上就是SENet的工作流程描述,包括了公式和步骤。

Spatial Attention Mechanism 空间注意力机制

SAM工作流程

1. 输入特征图

输入是一个三维张量,包含高度 H H H、宽度 W W W 和通道数 C C C

Input:  F ∈ R H × W × C \text{Input: } F \in \mathbb{R}^{H \times W \times C} Input: FRH×W×C

2. 生成注意力图

通过卷积层和其他操作生成注意力图 A A A

(1). 第一卷积层
Z 1 = C o n v 1 × 1 ( F ) Z_1 = Conv_{1 \times 1}(F) Z1=Conv1×1(F)

(2). 第二卷积层及激活函数
A = σ ( C o n v 1 × 1 ( Z 1 ) ) A = \sigma(Conv_{1 \times 1}(Z_1)) A=σ(Conv1×1(Z1))
其中 σ \sigma σ 是 Sigmoid 函数:

σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1 + e^{-x}} σ(x)=1+ex1

3. 归一化处理

对生成的注意力图进行归一化处理,使其值在合理范围内。

  • Sigmoid 归一化

    A = σ ( Z 1 ) = 1 1 + e − Z 1 A = \sigma(Z_1) = \frac{1}{1 + e^{-Z_1}} A=σ(Z1)=1+eZ11

  • Softmax 归一化(可选):

    A = Softmax ( Z 1 ) = e Z 1 ∑ e Z 1 A = \text{Softmax}(Z_1) = \frac{e^{Z_1}}{\sum e^{Z_1}} A=Softmax(Z1)=eZ1eZ1

4. 加权融合

将生成的注意力图与原始输入特征图逐元素相乘,从而实现对重要区域的强调和不重要区域的抑制。

F ′ = A ⊙ F F' = A \odot F F=AF

其中 ⊙ \odot 表示逐元素相乘操作。


http://www.ppmy.cn/embedded/169176.html

相关文章

一文掌握Charles抓包工具的详细使用

Charles是一款强大的HTTP代理/HTTP监视器/反向代理工具,广泛用于开发和测试网络应用程序。在爬虫开发中,Charles可以帮助开发者拦截、查看和修改HTTP/HTTPS请求和响应,从而更好地理解网络通信过程,分析和调试爬虫程序。本文将详细介绍Charles的安装、配置、基本使用方法以及…

探索微软 Bing 的智能搜索功能:开启智能搜索新时代

在信息爆炸的当下,搜索引擎已成为我们获取知识的得力助手。微软 Bing 凭借智能搜索功能,为用户带来了全新体验。接下来,让我们一同深入了解其智能搜索的独特之处。 一、Bing 智能搜索的核心技术支撑 1.1 自然语言处理(NLP) Bing 运用先进的自然语言处理技术,能深入理解…

代理IP服务器实现游戏多账号管理

去年帮朋友调试海外仓系统时见识了魔幻场景:德国仓显示库存充足,美国仓却持续超卖。查了三天才发现是动态IP导致ERP系统间歇性断联。今天就揭秘跨境企业最头疼的组网问题——怎么用静态IP搭建稳定传输通道。 一、海外仓组网最怕的3个"掉链子"…

osgEarth安装总结

第一步:安装OSG 直接通过git下载源码,使用cmake进行编译, git clone --depth 1 https://github.com/openscenegraph/OpenSceneGraph.git mkdir build cd build cmake .. make sudo make isntall编译过程中缺什么库,就安装什么库 …

Vue-Flow绘制流程图(Vue3+ElementPlus+TS)简单案例

本文是vue3Elementplusts框架编写的简单可拖拽绘制案例。 1.效果图&#xff1a; 2.Index.vue主代码&#xff1a; <script lang"ts" setup> import { ref, markRaw } from "vue"; import {VueFlow,useVueFlow,MarkerType,type Node,type Edge } fro…

Python 爬虫与网络安全有什么关系

Python爬虫和网络安全之间存在密切的关系。爬虫是一种用于自动化从网络上获取信息的程序&#xff0c;而网络安全是保护计算机网络和系统免受未经授权的访问、攻击和数据泄露的实践。本文将探讨Python爬虫与网络安全之间的关系以及如何在爬虫开发中注意网络安全。 爬虫的作用和…

网络安全与认知安全的区别 网络和安全的关系

前言 说说信息安全 与网络安全 的关系 一、包含和被包含的关系 信息安全包括网络安全&#xff0c;信息安全还包括操作系统安全&#xff0c;数据库安全 &#xff0c;硬件设备和设施安全&#xff0c;物理安全&#xff0c;人员安全&#xff0c;软件开发&#xff0c;应用安全等。…

3、HTTP请求报文和响应报文是怎样的,有哪些常见的字段?【中高频】

HTTP请求报文主要是由 请求行、请求头部、空行和请求体 四部分组成&#xff08;第一行必须是一个请求行&#xff08;request line&#xff09;&#xff0c;用来说明请求类型、要访问的 资源 以及使用的HTTP版本。紧接着是一个首部&#xff08;header&#xff09;小节&#xff0…