SPP/SPPF/Focal Module

2024-09-04 00:20
文章标签 module spp focal sppf

本文主要是介绍SPP/SPPF/Focal Module,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、在图像的分类任务重,卷积神经网络(CNN)一般含有5层:

  1. 输入层
  2. 卷积层
  3. 激活层
  4. 池化层
  5. 全连接层

·  全连接层通常要求输入为一维向量。在CNN中,卷积层和池化层的输出特征图会被展平(flatten)为一维向量,然后作为全连接层的输入。因此,全连接层对输入的尺寸有严格要求。

·  第一个全连接层的输入维度必须与前一层展平后的特征向量的长度一致,这就要求前面的卷积和池化层的输出特征图尺寸必须经过计算或预定义,以确保能够正确展平。

全连接层要求每个输入神经元与每个输出神经元完全连接。因此,全连接层的输入必须是一个固定长度的一维向量。这意味着输入的特征图的尺寸必须是固定的,以确保展平后的向量长度是确定的。如果输入特征图的尺寸发生变化,那么展平后的向量长度也会改变,这将导致全连接层无法正确处理这些输入数据。

二、在yolov3中引入了SPP,在yolov5及以后使用SPPF

1.什么是SPP?为什么引入SPP?

卷积神经网络(CNN)由卷积层和全连接层组成,其中卷积层对于输入数据的大小并没有要求,唯一对数据大小有要求的则是第一个全连接层

SPP的提出就是为了解决CNN输入图像大小必须固定的问题。

SPP的作用:

  1. 处理不同输入尺寸

 SPP 模块通过在不同尺度上进行池化操作,将特征图转换为固定长度的输出特征。具体来说,SPP 模块在特征图上应用多个不同大小的池化窗口(例如 1×1、2×2、4×4),将这些池化操作的结果拼接在一起,从而获得一个固定长度的特征向量。

  1. 保留空间信息

SPP 模块在不同尺度上进行池化操作时,可以保留输入图像的空间信息。不同尺度的池化操作捕捉了特征图中的不同层次的空间信息,从而保留了图像的局部和全局特征。

SPPF比SPP更快:

SPP 是使用了3个kernel size不一样大的pooling 并行运算。SPPF是将kernel size为5的 pooling串行运算,这样的运算的效果和SPP相同,但是运算速度加快。因为SPPF减少了重复的运算,每一次的pooling 运算都是在上一次运算的基础上进行的。

SPP结构图:

SPPF结构图:

使用FocalNet替代SPPF

一、SPP、SPPF

1.SPP模块:SPP的提出就是为了解决CNN输入图像大小必须固定的问题

       主要目的是通过多个不同尺度的池化操作,提取输入特征图中的多尺度特征。这种操作有助于模型更好地理解不同尺度的目标,并增强其对目标的检测能力。

FocalNet的亮点在于其专为关注重要信息而设计的Focal Module。它利用空间金字塔池化(Spatial Pyramid Pooling)和动态卷积(Dynamic Convolution)来捕捉不同尺度的目标,并有效地抑制背景干扰。这种设计在保持模型小规模的同时,提高了模型对复杂场景的理解能力。

FocalModulation模型通过以下步骤实现:

1. 焦点上下文化: 用深度卷积层堆叠来编码不同范围的视觉上下文。

焦点上下文化是指在不同的焦点级别(spatial scales)(也就是使用不同大小的卷积核)上聚合上下文信息。它通过一系列的卷积层对输入特征进行不同大小的卷积操作,从而捕捉不同范围的上下文信息。


2. 门控聚合: 通过门控机制,选择性地将上下文信息聚合到每个查询令牌的调制器中。

通过门控机制对不同焦点级别的上下文信息进行加权和合并的过程。其核心作用是根据每个焦点级别的信息重要性来调整其贡献,以实现更有效的上下文信息融合。


3. 逐元素仿射变换: 将聚合后的调制器通过仿射变换注入到每个查询令牌中。

意思就是将聚合后的上下文特征(ctx_all)注入到每个查询令牌(q)中,具体表现为与查询特征逐元素相乘。这一步骤将上下文信息直接作用于查询特征中,实现特征调制。

深度可分离卷积

=深度卷积+点对点卷积

演示分组,深度,深度可分离卷积|3D卷积神经网络_哔哩哔哩_bilibili

import torch
import torch.nn as nn__all__ = ['FocalModulation']class FocalModulation(nn.Module):def __init__(self, dim, focal_window=3, focal_level=2, focal_factor=2, bias=True, proj_drop=0.,use_postln_in_modulation=False, normalize_modulator=False):super().__init__()self.dim = dimself.focal_window = focal_windowself.focal_level = focal_levelself.focal_factor = focal_factorself.use_postln_in_modulation = use_postln_in_modulationself.normalize_modulator = normalize_modulator#f_linear 是1x1卷积核,用于线性投影,将输入特征映射到更高的维度上 来生成查询、上下文、门控self.f_linear = nn.Conv2d(dim, 2 * dim + (self.focal_level + 1), kernel_size=1, bias=bias)#self.h  是1x1卷积核   用于后续的焦点调制self.h = nn.Conv2d(dim, dim, kernel_size=1, stride=1, bias=bias)  #stride步长  bias布尔值 表示是否使用偏置项# self.act 定义了GELU激活函数self.act = nn.GELU()# self.proj 是1x1卷积,用于投影调制后的特征。self.proj = nn.Conv2d(dim, dim, kernel_size=1)# self.proj_drop 是一个dropout层,用于正则化self.proj_drop = nn.Dropout(proj_drop)# self.focal_layers 是一个模块列表,存储了不同焦点级别的卷积层self.focal_layers = nn.ModuleList()self.kernel_sizes = []for k in range(self.focal_level):kernel_size = self.focal_factor * k + self.focal_window     #focal_factor 是放大因子 用来控制卷积核大小的增伤速率# self.focal_window 是基准卷积核的大小#随着k的增大,卷积核不断地增大self.focal_layers.append(  #用于存储所有的焦点卷积层nn.Sequential(   #nn.Sequential用于将多个神经网络层组合在一起  包含卷积层和激活函数nn.Conv2d(dim, dim, kernel_size=kernel_size, stride=1, #stride=1表示卷积步长为1。# groups=dim启用了深度可分离卷积,即每个输入通道都有自己的卷积核,这大大减少了计算量groups=dim, padding=kernel_size // 2, bias=False),nn.GELU(), #一个GELU激活函数,常用于增加非线性,使网络能更好地学习复杂的模式))self.kernel_sizes.append(kernel_size) #用于存储每个焦点级别的卷积核大小。if self.use_postln_in_modulation:self.ln = nn.LayerNorm(dim)def forward(self, x):"""Args:x: input features with shape of (B, H, W, C)"""C = x.shape[1]# pre linear projectionx = self.f_linear(x).contiguous() #1x1的卷积操作,作用是将输入特征x进行通道上的线性投影q, ctx, gates = torch.split(x, (C, C, self.focal_level + 1), 1)  #将投影后的张量x沿通道维度(维度1)分成三部分:# q:查询(Query),大小为(B, C, H, W)# ctx:上下文(Context),大小为(B, C, H, W)# gates:门控(Gates),大小为(B, self.focal_level + 1, H, W),用于对不同焦点级别的上下文进行加权# context aggreation#上下文聚合ctx_all = 0.0#ctx_all = 0.0初始化一个变量,用于累积不同焦点级别的上下文。for l in range(self.focal_level):#逐级聚合上下文ctx = self.focal_layers[l](ctx)# 使用门控值gates对当前焦点级别的上下文ctx进行加权,然后累加到ctx_allctx_all = ctx_all + ctx * gates[:, l:l + 1]#ctx.mean(2, keepdim=True).mean(3, keepdim=True):对上下文ctx进行全局平均池化,得到一个全局上下文特征。ctx_global = self.act(ctx.mean(2, keepdim=True).mean(3, keepdim=True)) #self.act()  对全局上下文特征应用GELU激活函数# 对全局上下文特征ctx_global应用最后一个门控值的加权,然后加到ctx_allctx_all = ctx_all + ctx_global * gates[:, self.focal_level:]# normalize context    上下文归一化if self.normalize_modulator:ctx_all = ctx_all / (self.focal_level + 1)# focal modulationx_out = q * self.h(ctx_all)  # 卷积后的上下文特征与查询q逐元素相乘(对应于焦点调制机制),得到输出特征x_out。x_out = x_out.contiguous()  # 确保x_out在内存中的连续性# post linear porjection  后线性投影:对调制后的特征进行投影和Dropout,得到最终输出x_out = self.proj(x_out)x_out = self.proj_drop(x_out)return x_out

这篇关于SPP/SPPF/Focal Module的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134468

相关文章

Python中ModuleNotFoundError: No module named ‘timm’的错误解决

《Python中ModuleNotFoundError:Nomodulenamed‘timm’的错误解决》本文主要介绍了Python中ModuleNotFoundError:Nomodulen... 目录一、引言二、错误原因分析三、解决办法1.安装timm模块2. 检查python环境3. 解决安装路径问题

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.

nginx-rtmp-module构建流媒体直播服务器实战指南

《nginx-rtmp-module构建流媒体直播服务器实战指南》本文主要介绍了nginx-rtmp-module构建流媒体直播服务器实战指南,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. RTMP协议介绍与应用RTMP协议的原理RTMP协议的应用RTMP与现代流媒体技术的关系2

jupyter在加载pkl文件时报错ModuleNotFoundError: No module named 'pandas.core.internals.managers'; '的解决方法

笔者当看到这个错误的时候一脸懵逼,在pycharm上正常运行的code 放在jupyter就不成了,于是就研究一翻。 一开始以为自己的pkl文件有问题,研究重点放在这里,最后发现不是。 然后取搜索pycharm和jupyter下的python的\Lib\site-packages\pandas\core\internals有什么不同 发现jupyter下没有pandas\core\intern

【NodeJS】Error: Cannot find module 'ms'

转载自:http://blog.csdn.net/echo_ae/article/details/75097004 问题: Error: Cannot find module 'ms'at Function.Module._resolveFilename (module.js:469:15)at Function.Module._load (module.js:417:25)at Module

【虚拟机/服务器】配置ngx_http_empty_gif_module记录

下载Nginx源码 查看Nginx内置模块 1、在可视化界面中 可以看到 ngx_http_empty_gif_module.c 是Nginx的内置模块,不需要再进行安装 2、在bash命令行中 tar nginx 解压后进入nginx目录,./configure --help | grep empty_gif 即可查看我想要的 ngx_http_empty_gif_module

多个,多层嵌套module,打aar包

参考https://blog.51cto.com/4259297/1699714 1.在要打包的module中下添加fat-aar.gradle文件。(该文件只能在项目个gradle是2.3.3是才可食用) 2.把项目的gradle修改为2.3.3,但是不打包的gradle依然是以前的。 3.由于打包的的gradle和不打包的是不一样的,所以需要在修改gradle的文件中的添加判断标志

兔子--AndroidStudio中删除Module

常见问题:右键项目,没有delete,, 怎么删除项目呢? 步骤如下:   1  选择:Edit Configuration 2,选中要删除的q1,点击红色的减号 3.点击减号之后,效果如下 4.在settings.gradle中删除include中的q1项目 5.点击选中的这个图标 6.等待构建完成了,,,再次右键,,看看,,就出现了delete,哈

兔子-在as中删除项目以及删除后报错already disposed:Module:'haha'

1. 2.点左上角红色的减号,,Apply 3,删除setting.gradle中include中的要删除的项目 . 4.选择要删除的项目,,点击键盘的delete键 5.点击第二个图标。 删除成功!! 完全删除haha项目之后,仍然报这个错误。 解决办法:重启as

【PyTorch】使用容器(Containers)进行网络层管理(Module)

文章目录 前言一、Sequential二、ModuleList三、ModuleDict四、ParameterList & ParameterDict总结 前言 当深度学习模型逐渐变得复杂,在编写代码时便会遇到诸多麻烦,此时便需要Containers的帮助。Containers的作用是将一部分网络层模块化,从而更方便地管理和调用。本文介绍PyTorch库常用的nn.Sequen