Pyramid Vision Transformer, PVT(ICCV 2021)原理与代码解读

2024-06-07 21:12

本文主要是介绍Pyramid Vision Transformer, PVT(ICCV 2021)原理与代码解读,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

paper:Pyramid Vision Transformer: A Versatile Backbone for Dense Prediction without Convolutions

official implementation:GitHub - whai362/PVT: Official implementation of PVT series

存在的问题

现有的 Vision Transformer (ViT) 主要设计用于图像分类任务,难以直接用于像素级密集预测任务,如目标检测和分割。这是因为存在以下问题

  1. 低分辨率输出:传统的Vision Transformer(ViT)在处理密集预测任务(如目标检测和语义分割)时,输出分辨率较低,难以获得高质量的像素级别预测。
  2. 高计算和内存开销:ViT在处理大尺寸输入图像时,计算和内存开销较高,限制了其在实际应用中的效率。

本文的创新点

为了解决上述问题,作者提出了 Pyramid Vision Transformer (PVT), PVT结合了卷积神经网络的金字塔结构和Transformer的全局感受野,旨在克服传统Transformer在处理密集预测任务时遇到的分辨率低、计算和内存开销大的问题。它可以作为 CNN 骨干网络的替代品,用于多种下游任务,包括图像级预测和像素级密集预测。具体包括:

  1. 金字塔结构:PVT引入了金字塔结构,可以生成多尺度的特征图,这对于密集预测任务是有益的。
  2. 空间缩减注意力层(SRA):为了处理高分辨率特征图并减少计算/内存成本,作者设计了 SRA 层来替代传统的多头注意力 (MHA) 层。
  3. 纯Transformer骨干:PVT 是一个没有卷积的纯 Transformer 骨干网络,可以用于各种像素级密集预测任务,并与 DETR 结合构建了一个完全无需卷积的目标检测系统。

实际效果

  • PVT 在多个下游任务上进行了广泛的实验验证,包括图像分类、目标检测、实例和语义分割等,并与流行的 ResNets 和 ResNeXts 进行了比较。
  • 实验结果表明,在参数数量相当的情况下,PVT 在 COCO 数据集上使用 RetinaNet 作为检测器时,PVT-Small 模型达到了 40.4 的 AP(平均精度),超过了 ResNet50+RetinaNet(36.3 AP)4.1 个百分点。
  • PVT-Large 模型达到了 42.6 的 AP,比 ResNeXt101-64x4d 高出 1.6 个百分点,同时参数数量减少了 30%。
  • 这些结果表明 PVT 可以作为 CNN 骨干网络的一个有效的替代,用于像素级预测,并推动未来的研究。

方法介绍

Overall Architecture

PVT的整体结构如图3所示

和CNN backbone类似,PVT也有四个stage来生成不同尺度的特征图。所有stage都有一个相似的架构,包括一个patch embedding层和 \(L_i\) 个Transformer encoder层。

在第一个stage,给定大小为 \(H\times W\times 3\) 的输入图片,我们首先将其划分为 \(\frac{HW}{4^2}\) 个patch,每个大小为4x4x3。然后将展平的patch送入一个线性映射层得到大小为 \(\frac{HW}{4^2}\times C_1\) 的输出。然后将输出和位置编码一起进入有 \(L_1\) 层的Transformer encoder,得到的输出reshape成大小为 \(\frac{H}{4}\times \frac{W}{4}\times C_1\) 的特征图 \(F_1\)。同样的方式,以前一个stage的输出特征图作为输入,我们得到特征图 \(F_2,F_3,F_4\),相对于原始输入图片的步长分别为8,16,32。用了特征图金字塔 \(\{F_1,F_2,F_3,F_4\}\),我们的方法可以很容易地应用于大多数下游任务,包括图像分类、目标检测和语义分割。

Feature Pyramid for Transformer

和CNN backbone用不同stride的卷积来得到不同尺度特征图不同,PVT使用一个渐进式shrinking策略,通过patch embedding层来控制特征图的尺度。 

我们用 \(P_i\) 来表示第 \(i\) 个stage的patch size,在stage \(i\) 的开始,我们首先将输入特征图 \(F_{i-1}\in \mathbb{R}^{H_{i-1}\times W_{i-1}\times C_{i-1}}\) 均匀地划分成 \(\frac{H_{i-1}W_{i-1}}{P_i^2}\) 个patch,然后将每个patch展平并映射得到一个 \(C_i\) 维的embedding。在线性映射后,embedded patch的大小为 \(\frac{H_{i-1}}{P_i}\times \frac{W_{i-1}}{P_i}\times C_i\),其中宽高比输入小了 \(P_i\) 倍。

这样,我们就可以在每个stage灵活地调整特征图的尺度,从而将Transformer构建成金字塔结构。

Transforme Encoder

由于PVT需要处理高分辨率(stride-4)的特征图,我们提出了一种spatial-reduction attention(SRA)来替换encoder中传统的multi-head attention(MHA)。

和MHA类似,SRA的输入包括一个query \(Q\),一个key \(K\),一个value \(V\)。不同的是SRA在attention operation之前减小了 \(K\) 和 \(V\) 的大小,如图4所示,这大大减少了计算和内存的开销。

stage \(i\) 的SRA如下

其中 \(Concat(\cdot)\) 是拼接操作。\(W^{Q}_j\in \mathbb{R}^{C_i\times d_{head}},W^{K}_j\in \mathbb{R}^{C_i\times d_{head}},W^{V}_j\in \mathbb{R}^{C_i\times d_{head}},W^O\in \mathbb{R}^{C_i\times C_i}\) 是线性映射参数。\(N_i\) 是stage \(i\) 中attention层的head数量,所以每个head的维度(即\(d_{head}\))等于 \(\frac{C_i}{N_i}\)。\(SR(\cdot)\) 是降低输入序列(即 \(K\) 或 \(V\))空间维度的操作,如下:

其中 \(\mathbf{x}\in\mathbb{R}^{(H_iW_i)\times C_i}\) 表示一个输入序列,\(R_i\) 表示stage \(i\) 中attention层的reduction ratio。\(Reshape(\mathbf{x},R_i)\) 是将输入序列 \(\mathbf{x}\) reshape成大小为 \(\frac{H_iW_i}{R^2_i}\times (R^2_iC_i)\) 的序列的操作。\(W_S\in \mathbb{R}^{(R^2_iC_i)\times C_i}\) 是一个linear projection,它将输入序列的维度降低到 \(C_i\)。\(Norm(\cdot)\) 是layer normalization。和原始的Transformer一样,attention operation按下式计算

通过上述公式我们可以发现,MSA的计算/内存开销是MHA的 \(\frac{1}{R^2}\),因此MSA可以在有限的资源下处理更大的输入特征图或序列。

代码解析

见PVT v2的代码解析 PVT v2 原理与代码解析-CSDN博客

实验结果 

模型涉及到的一些超参总结如下:

  • \(P_i\):stage \(i\) 的patch size
  • \(C_i\):stage \(i\) 的输出通道数
  • \(L_i\):stage \(i\) 中的encoder层数
  • \(R_i\):stage \(i\) 中SRA的reduction ratio
  • \(N_i\):stage \(i\) 中SRA的head数量
  • \(E_i\):stage \(i\) 中FFN层的expansion ratio

作者设计了一系列的PVT模型,具体配置如表1

和其它SOTA模型在ImageNet的结果对比如表2所示

用RetinaNet上和其它backbone的结果对比如表3所示,可以看到PVT不同大小的模型与ResNet系列相比,参数更少精度更高。

在语义分割模型Semantic FPN上PVT也超越了对应的ResNet

这篇关于Pyramid Vision Transformer, PVT(ICCV 2021)原理与代码解读的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

SpringBoot中配置文件的加载顺序解读

《SpringBoot中配置文件的加载顺序解读》:本文主要介绍SpringBoot中配置文件的加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot配置文件的加载顺序1、命令⾏参数2、Java系统属性3、操作系统环境变量5、项目【外部】的ap

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

Mysql用户授权(GRANT)语法及示例解读

《Mysql用户授权(GRANT)语法及示例解读》:本文主要介绍Mysql用户授权(GRANT)语法及示例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql用户授权(GRANT)语法授予用户权限语法GRANT语句中的<权限类型>的使用WITH GRANT

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指