SPP/SPPF/Focal Module

news2024/9/21 16:44:23

一、在图像的分类任务重,卷积神经网络(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 = dim
        self.focal_window = focal_window
        self.focal_level = focal_level
        self.focal_factor = focal_factor
        self.use_postln_in_modulation = use_postln_in_modulation
        self.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 projection
        x = 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_all
            ctx_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_all
        ctx_all = ctx_all + ctx_global * gates[:, self.focal_level:]

        # normalize context    上下文归一化
        if self.normalize_modulator:
            ctx_all = ctx_all / (self.focal_level + 1)

        # focal modulation
        x_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

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

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

相关文章

华为云征文|华为云Flexus云服务器X实例部署Note Mark笔记工具

华为云征文|华为云Flexus云服务器X实例部署Note Mark笔记工具 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、Note Mark 介绍2.1 Note Mark 简介2.2 Note Mark 特点2.3 Note Mark 使…

iOS分渠道统计不再难,Xinstall帮你轻松搞定

在App推广和运营的过程中,iOS分渠道统计一直是一个令人头疼的问题。如何准确追踪各个渠道的推广效果?如何优化投放策略以提高转化率?这些问题困扰着无数推广者。今天,我们就来聊聊Xinstall这款强大的分渠道统计工具,看…

【自由能系列(中级)】自由能与变分自由能——从状态到配置的效益最大化【代码模拟】

自由能与变分自由能——从状态到配置的效益最大化 关键词提炼 #自由能 #变分自由能 #状态函数 #配置函数 #效益最大化 #物理系统 #优化问题 第一节:自由能与变分自由能的类比与核心概念 1.1 自由能与变分自由能的类比 自由能和变分自由能可以被视为物理系统的“…

Mysql高阶语句(1)

一、常用查询 1. 按关键字排序 使用 ORDER BY 语句对查询结果进行排序,可以按照一个或多个字段进行升序(ASC)或降序(DESC)排列 语法 SELECT column1, column2, ... FROM table_name ORDER BY column1 [ASC|DESC], c…

sqli-lab靶场学习(一)——Less1

前言 最近一段时间想切入安全领域,因为本身有做数据库运维工作,就打算从sql注入方向切入。而sql注入除了学习日常书本上的概念外,需要有个实践的环境,刚好看到sqli-lab这个靶场,就打算先用这个来学习。 安装部署 网上…

智能提醒助理系列-协作工具,一站式软件研发管理平台

本系列文章记录“智能提醒助理”wx公众号 建设历程。 一、需求分析 当前智能提醒产品体系为微信公众号小程序的模式。 以小程序为操作主体,公众号作为用户接收提醒的方式之一,还有短信和电话。 开发方式为自研,需要前端小程序服务端三方对…

天津自学考试转考流程及免冠照片处理方法说明

自学考试省际转考是指考生因为工作、生活或其他原因,需要将自学考试的考籍从一个省份转移到另一个省份继续参加自学考试的情况。在中国,自学考试是一种国家承认的学历教育形式,由各省、自治区、直辖市的教育考试机构负责组织实施。下面详细介…

必看|助攻|2024“高教社杯“全国大学生数学建模竞赛冲刺建议

数模国赛冲刺阶段小Tips tips0:赛中小天为大家带来助攻,请关注主页 赛前准备 01 加强赛前训练 写作队员:阅读往年获奖论文,关注思路、表达和排版。建模队员:了解各类模型特点和应用场景。编程队员:多做算法编程和数…

Datawhale X 李宏毅苹果书 AI夏令营(深度学习 之 实践方法论)

1、模型偏差 模型偏差是指的是模型预测结果与真实值之间的差异,这种差异不是由随机因素引起的,而是由模型本身的局限性或训练数据的特性所导致的。 简单来讲,就是由于初期设定模型,给定的模型计算能力过弱,导致在通过…

vector的实现

目录 1.vector的底层 2.vector构造函数的实现 ①构造函数 ②拷贝构造 3.访问函数实现 3.1迭代器iterator 3.2下标[]访问 4.析构函数和计算size、capacity、swap简单函数的实现 ①析构函数: ②计算size: ③计算capacity: ④swap函…

嵌入式软件--51单片机 DAY 3

一、独立按键 按键的作用相当于一个开关,按下时接通(或断开),松开后断开(或接通)。 (1)需求 通过SW1、SW2、SW3、SW4四个独立按键分别控制LED1、LED2、LED3、LED4的亮灭&#xff0…

爬虫数据解析

## 数据解析 聚焦爬虫 爬取页面中指定的页面内容 编码流程 指定url发起请求获取响应数据数据解析持久化存储 数据解析分类 正则bs4xpath(***) 数据解析原理概述 解析的局部的文本内容都会在标签之间或者标签对应的属性中进行存储进行指定标签的定…

最小生成树的两种算法模板

第一种模板&#xff1a; 思路&#xff1a;对于prime算法来说其实与朴素的dij算法差不多&#xff0c;都是找到最近的点然后更新其他的点 模板&#xff1a; #include<bits/stdc.h>using namespace std;const int N 100010;int n; int g[110][110]; int dis[110]; int st…

VMware Workstation 17.6 Pro 发布下载,新增功能概览

VMware Workstation 17.6 Pro 发布下载&#xff0c;新增功能概览 VMware Workstation 17.6 Pro for Windows & Linux - 领先的免费桌面虚拟化软件 基于 x86 的 Windows、Linux 桌面虚拟化软件 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-workstation-17/…

Linux日志-wtmp日志

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux 系统中的日志是记录系统活动和事件的重要工具&#xff0c;它们可以帮助管理员监视系统状态、调查问题以及了解系统运行…

B端系统门门清之:QMS-质量管理,泰山之重。

质量重于泰山&#xff0c;QMS&#xff08;质量管理系统&#xff09;在生产企业的经营中非常重要&#xff0c;质量的积累可以成就一个企业&#xff0c;想要毁掉一个企业&#xff0c;也是瞬间的事情&#xff0c;本文就和大家重点分享一下QMS系统。 一、什么是QMS系统&#xff0c…

SpringCloud开发实战(二):通过RestTemplate实现远程调用

目录 SpringCloud开发实战&#xff08;一&#xff09;&#xff1a;搭建SpringCloud框架 RestTemplate介绍 RestTemplate 是 Spring 框架中的一个类&#xff0c;它用于促进 HTTP 请求的发送和接收&#xff0c;并且简化了与 RESTful 服务的交互。RestTemplate 提供了许多便利的方…

C++ 学习 2024.9.3

封装栈与队列 栈: #include <iostream>using namespace std;class Stack { private:int *a; //动态数组存储元素int size; //栈容量int top; //栈顶元素索引 public://有参构造Stack(int size):size(size),top(-1){anew int[size];}//析构~Stack(){delete[]a…

八月二十九日(day 39)docker6

1.前端&#xff08;nginx&#xff09; [rootlocalhost ~]# docker pull nginx //拉取nginx镜像 [rootlocalhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 5ef79149e0ec 2 we…

【Godot4.3】基于纯绘图函数自定义的线框图控件

概述 同样是来自2023年7月份的一项实验性工作&#xff0c;基于纯绘图函数扩展的一套线框图控件。初期只实现了三个组件&#xff0c;矩形、占位框和垂直滚动条。 本文中的三个控件类已经经过了继承化的修改&#xff0c;使得代码更少。它们的继承关系如下&#xff1a; 源代码 W…