Vision Transformer模型架构详解

🎀个人主页: https://zhangxiaoshu.blog.csdn.net
📢欢迎大家:关注🔍+点赞👍+评论📝+收藏⭐️,如有错误敬请指正!
💕未来很长,值得我们全力奔赴更美好的生活!

前言

2019年开始,自然语言处理(NLP)领域抛弃了循环神经网络(RNN)序列依赖的问题,开始采用Attention is All you need的Transformer结构[1],其中的Attention是一种可以让模型专注于重要的信息并能够充分学习和吸收的技术。在NLP领域中,伴随着各种语言Transformer模型的提出使得多项语言处理任务的精度和模型深度开始飞速提升。由于基于Transformer的预训练语言模型非常成功,研究者开始探索其在视觉领域的应用。2020年10月,Google创新性的设计了用于分类的Vision Transformer模型[2]—ViT。此后视觉Transformer模型的研究进入了快车道,本文主要对Vision Transformer模型架构进行详细介绍以及在pytorch中的使用方法进行介绍。


文章目录

  • 前言
  • 一、Vision Transformer模型架构
    • 1. Embedding层结构
    • 2. Transformer Encoder结构
      • (1)层归一化(Layer Norm)
      • (2)多头注意力机制(Multi-Head Attention)
      • (3)Dropout/DropPath
      • (4)MLP Block
    • 3. MLP Head结构
  • 二、PyTorch实现
    • 1. 首先安装vit-pytorch库:
    • 2.导入进行调用:
  • 总结


一、Vision Transformer模型架构

下图是原论文中作者给出的关于Vision Transformer的模型总体框架图:

在这里插入图片描述
从图中可以看出,Vision Transformer模型主要由三部分组成:第一部分为Linear Projection of Flattened Patches,也被称为Embedding层,主要用于将输入的图片数据转化为适合Transformer结构处理的形式。第二部分为Transformer Encoder部分,它是整个ViT模型的核心板块,在图右侧给出了更加详细的结构,它主要由层归一化(Layer Norm)、多头注意力机制(Multi-Head Attention)、Dropout/DropPath、MLP Block四部分组成用于学习输入图像数据的特征。第三部分为MLP Head,它是最终用于分类的层结构。下面本设计将对每一个组成部分进行一个详细介绍。

1. Embedding层结构

在视觉Transform模型中,其Transformer Encoder模块的输入形式是一个向量(token)序列,即一个二维矩阵[num_token, token_dim]的形式,如上图所示,输入的粉色小块token0-9对应的都是向量序列。

但是,图像处理和语言处理不一样,它的数据格式和Transformer Encoder输入格式是不一样,而是一个三维矩阵[H, W, C]的形式。所以在视觉Transform模型中首先加入了一个Embedding层结构用于将数据变化为向量序列。其主要过程为:首先将输入的图片形式数据按照模型定义的切割大小切割成多个小块(Patches),然后将切割的小块通过维度变化映射成向量形式。以常见的ViT-B/16为例,它首先将输入图片( 224 × 224 224\times224 224×224)按照 16 × 16 16\times16 16×16的大小进行切分得到196个Patches,接着通过线性映射将每一个Patches(16, 16, 3)映射成一个长度为768的向量。

在具体实现代码时,可以通过一个卷积层和Flatten层来直接实现。以ViT-B/16为例,如图所示其卷积层的参数为:卷积核大小是16x16、步距是16、卷积核的个数是768。数据通过卷积层后维度从(224, 224, 3)变化为(14, 14, 768),接着,将H和W两个维度展平即Flatten操作即可变化为(196, 768)这样的二维矩阵形式,这正是Transformer Encoder的输入格式。
在这里插入图片描述
除了将输入数据的形式变化为Transformer Encoder的输入格式,模型还在输入Transformer Encoder之前加入了[class]token以及Position Embedding,如下图所示。[class]token是参考了BERT所设计的,它是一个可以学习的参数,用于拼接到tokens中专门用于图像数据的分类。以ViT-B/16为例,就是让一个768长度的向量,与从Flatten层输出的数据拼接在一起,即,Cat((1, 768),(196, 768))—>(197, 768)。Position Embedding也是一个可以学习的参数。它是直接叠加在tokens上的(Add),因为对于图像数据而言,每一块和每一块在都有一定的位置依赖关系,所以Position Embedding主要用于表达Patches之间的位置关系。以ViT-B/16为例,就是让一个(197, 768)的向量与之前得到的(197, 768)向量相加。
在这里插入图片描述

2. Transformer Encoder结构

Transformer Encoder其实就是将Encoder Block 重复堆叠L次, Encoder Block结构图如下图2.4所示,主要由层归一化(Layer Norm)多头注意力机制(Multi-Head Attention)Dropout/DropPathMLP Block四部分组成。

(1)层归一化(Layer Norm)

层归一化(Layer Norm):这是一种主要针对NLP领域提出的归一化方法,这里是对每个token进行归一化处理。目前的归一化层主要有BN、LN、IN、GN和SN五种方法,它解决了深度神经网络内部协方差偏移问题,是一种将深度神经网络之间的数据进行归一化的算法,使得深度学习的训练过程中梯度变化趋于稳定,从而使网络在训练时达到快速收敛的目的。将输入的图像shape记为[N, C, H, W],这些方法的主要不同之处是,BatchNorm是在Batch上进行的,对NHW做归一化,对于较小的Batch Size没有太大的作用;LayerNorm是在通道方向上进行的,对CHW归一化,对RNN有很大的作用;InstanceNorm是在图像的像素上进行的,对HW做归一化,主要用在风格化迁移等方面;GroupNorm首先将Channel进行分组,然后再做归一化;SwitchableNorm是将BN、LN、IN结合并给予权重,让网络自己去学习归一化层应当使用的方法。

*有关BN、LN、IN、GN归一化方法的详细介绍可以看我这篇文章:神经网络常用归一化和正则化方法解析(一);

在这里插入图片描述
Layer Norm即层归一化针对神经网络的某一层的所有输入按照以下公式进行归一化操作:

H H H是某一层中隐藏结点的数量, l l l表示层数,可以计算得到Layer Norm的归一化统计量 μ l \mu^l μl σ l \sigma^l σl,如下式:

μ l = 1 H ∑ i = 1 H a i l \mu^l=\frac{1}{H}\sum_{i=1}^{H}a_i^l μl=H1i=1Hail

σ l = 1 H ∑ i = 1 H ( a l − μ l ) 2 \sigma^l=\sqrt{\frac{1}{H}\sum_{i=1}^{H}\left(a^l-\mu^l\right)^2} σl=H1i=1H(alμl)2

其中 a l a^l al表示一个中间输出结果的总和。上面的统计量和样本数没有关系,而是和隐藏层的结点数有关,我们甚至可以使 Batch Size = 1。于是,我们可以根据约定的统计量进行归一化处理,

a ^ l = a l − μ l ( σ l ) 2 + ε {\hat{a}}^l=\frac{a^l-\mu^l}{\sqrt{\left(\sigma^l\right)^2+\varepsilon}} a^l=(σl)2+ε alμl

同样,在Layer Norm中常使用参数增益(gain)和偏置(bias)这两个参数来保障归一化操作不会破坏之前的信息,同BatchNorm中的 γ \gamma γ β \beta β

y i = γ a ^ l + β y_i=\gamma{\hat{a}}^l+\beta yi=γa^l+β

从以上公式可以看到, LN中同层神经元输入拥有相同的均值和方差,不同的输入样本有不同的均值和方差。所以,LN与Batch的大小无关,也不取决于输入Sequence的深度,所以可以在batchsize为1和RNN中对边长的输入Sequence进行Normalize操作。

(2)多头注意力机制(Multi-Head Attention)

多头注意力机制(Multi-Head Attention):通过多个注意力机制的并行组合,将独立的注意力输出串联起来,预期维度得到线性地转化。直观看来,多个注意头允许对序列的不同部分进行注意力运算

对于Self-Attention来说,假设输入的token长度为 L L L,则输入为 [ x 1 , x 2 . . . x L , ] [x_1,x_2...x_L,] [x1,x2...xL,],然后分别将 x 1 x 2 . . . x L x_1x_2...x_L x1x2...xL分别通过三个变化矩阵 W q , W k , W v W_q,W_k,W_v Wq,Wk,Wv(这三个参数是可训练的、共享的)得到对应的 q i , k i , v i , q^i,k^i,v^i, qi,ki,vi, 并将 q , k , v q,k,v q,k,v向量序列记为 Q , K , V Q,K,V Q,K,V。计算过程如下式所示,具体实现时使用全连接层实现。

( Q , K , V ) = ( q i , k i , v i ) = x i ∙ ( W q , W k , W v ) (Q,K,V)=\left(q^i,k^i,v^i\right)=x_i\bullet\left(W_q,W_k,W_v\right) (Q,K,V)=(qi,ki,vi)=xi(Wq,Wk,Wv)

其中 i = 1 , 2... L i=1,2...L i=1,2...L q q q表示query,后续会去和每一个k进行匹配, k k k代表key,后续会被每个 q q q匹配, v v v代表从 x x x中提取得到的信息value,后续 q q q k k k匹配的过程可以理解成计算两者的相关性,相关性越大对应 v v v的权重也就越大。

接着将 Q Q Q中的每一个 q i q^i qi去和 K K K中的每一个 k j k^j kj进行匹配,即点积操作。然后再除以 L \sqrt L L 得到对应的 α i , j \alpha_{i,j} αi,j,这样做的目的是进行点乘后的数值很大,导致通过Softmax后梯度变的很小,所以通过除以 L \sqrt L L 来进行缩放。具体计算过程如下式所示。

α i , j = q i ( k j ) T L \alpha_{i,j}=\frac{q^i\left(k^j\right)^T}{\sqrt L} αi,j=L qi(kj)T

α i , j \alpha_{i,j} αi,j表示 x i x_i xi x j x_j xj注意程度,然后对每一行分别进行Softmax处理得到 a ^ \hat{a} a^,相当于 x j x_j xj x i x_i xi权重,即对于 v v v的权重。具体计算过程如下式所示。

a ^ i , j = S o f t m a x ( α i , j ) {\hat{a}}_{i,j}=Softmax(α_{i,j}) a^i,j=Softmax(αij)

上面已经计算得到 a ^ i , j {\hat{a}}_{i,j} a^i,j,即针对每个 v v v的权重,接着进行加权得到最终结果,如下式所示。

b i = ∑ j = 1 L a ^ i , j × v j b^i=\sum_{j=1}^{L}{{\hat{a}}_{i,j}\times v^j} bi=j=1La^i,j×vj

其中 b i b^i bi表示 x i x_i xi经过Self-Attention后的结果。以上四式的过程习惯上用以下式来统一表示。

A t t e n t i o n ( Q , K , V ) = S o f t m a x ( Q ( K ) T L ) V Attention(Q,K,V)=Softmax\left(\frac{Q\left(K\right)^T}{\sqrt L}\right)V Attention(Q,K,V)=Softmax(L Q(K)T)V

对于Multi-Head Attention来说, 使用多头注意力机制能够联合来自不同head部分学习到的信息。首先根据使用的head的数目 h h h W q , W k , W v W_q,W_k,W_v Wq,Wk,Wv权值矩阵均分成 h h h份,即 W i Q , W i K , W i V W_i^Q,W_i^K,W_i^V WiQ,WiK,WiV, 其中 i = 1 , 2... h i=1,2...h i=1,2...h,然后还是和Self-Attention模块一样将 x i x_i xi分别通过变化矩阵 W i Q , W i K , W i V W_i^Q,W_i^K,W_i^V WiQ,WiK,WiV得到对应head的 q i , k i , v i q^i,k^i,v^i qi,ki,vi, 接下来针对每个head使用和Self-Attention中相同的方法即可得到对应的结果。如下式所示。

h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) {head}_i=Attention\left(QW_i^Q,KW_i^K,VW_i^V\right) headi=Attention(QWiQ,KWiK,VWiV)

其中 Q W i Q QW_i^Q QWiQ同前式相比多了一个 W i Q W_i^Q WiQ,表示这里是根据划分的变化矩阵去计算每一个head的结果。即通过 W i Q , W i K , W i V W_i^Q,W_i^K,W_i^V WiQ,WiK,WiV映射得到每个head的 q i , k i , v i q^i,k^i,v^i qi,ki,vi,然后计算结果。
最后将每个head得到的结果进行concat拼接,接着将拼接后的结果通 过 W o 过W^o Wo(可学习的参数)进行融合,融合后得到最终的结果 b i b^i bi。如式(2-11)所示。

M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , h e a d 1 … h e a d h ) W o MultiHead\left(Q,K,V\right)=Concat\left({head}_1,{head}_1\ldots{head}_h\right)W^o MultiHead(Q,K,V)=Concat(head1,head1headh)Wo

(3)Dropout/DropPath

Dropout/DropPath:在学习深度学习模型时,由于模型的参数过多、样本数量过少,导致了模型的过度拟合。在神经网络的训练中,常常会碰到一些问题。该方法具有较低的训练数据损失,具有较高的训练准确率。但是,测试数据的损失函数比较大,导致预测的准确性不高。

Dropout能在一定程度上减轻过度拟合,并能在某种程度上实现正规化。其基本原理是:在前向传播前进的过程中,使一个神经元的激活值以 p的概率不能工作,这在下面的图中可以看到。停止工作的神经元用虚线表示,与该神经元相连的相应传播过程将不在存在。这使得模型更加一般化,因为它不会依赖于一些局部特征。

DropPath类似于Dropout,不同的是Dropout 是对神经元随机“失效”,而DropPath是随机“失效”模型中的多分支结构。例如如下图右图所示,若 x x x为输入的张量,其通道为[B,C,H,W],那么DropPath的含义为一个Batch_size中,在经过多分支结构时,随机有drop_prob的样本,不经过主干,而直接经过分支(图中虚线)进行恒等映射。这在一定程度上使模型泛化性更强。
在这里插入图片描述

(4)MLP Block

MLP Block:如前文中Transformer Encoder结构图右侧所示,MLP Block由全连接层、GELU激活函数、Dropout组成,以ViT-B/16为例,第一个全连接层会把输入节点个数翻4倍(197, 768)—> (197, 3072),第二个全连接层会还原回原节点个数(197, 3072)—> (197, 768)。

3. MLP Head结构

通过Transformer Encoder后输出的维度和输入的维度是保持不变的,以ViT-B/16为例,输入的是(197, 768)输出的还是(197, 768)。这里只需要从[class]token抽取生成的对应结果,即从(197, 768)中抽取出[class]token对应的(1, 768),即为需要的分类信息。然后就可以用 MLP Head进行最后的分类得到结果。原论文中提到,在训练ImageNet21K时MLP Head是由全连接层+tanh激活函数+全连接层组成。但是如果是在ImageNet1K或者自己的数据集上时,只需要使用一个全连接层(Linear)即可,其结构如下图所示。
在这里插入图片描述

二、PyTorch实现

ViT模型共有三个不同的规模,如下所示:
。

1. 首先安装vit-pytorch库:

$ pip install vit-pytorch

2.导入进行调用:

import torch
from vit_pytorch import ViTmodel = ViT(image_size = 224,patch_size = 32,num_classes = 1000,dim = 1024,depth = 6,heads = 16,mlp_dim = 2048,dropout = 0.1,emb_dropout = 0.1
)imgs = torch.randn(1, 3, 224, 224)preds = model(imgs) # (1, 1000)

总结

以上就是对Vision Transformer模型架构的详细介绍及其适用,Vision Transformer模型作为第一个将Transformer结构应用到计算机视觉上的模型,对近年来计算机视觉的研究具有很大的意义,其常常与swin Transformer(可以理解为FPN结构的ViT)用作其他任务如检测、分割的backbone以及视觉特征提取器。

参考:
Attention is all you need
An image is worth 16x16 words: Transformers for image recognition at scale

文中图片大多来自论文和网络,如有侵权,联系删除,文中有不对的地方欢迎指正。

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

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

相关文章

Title FX Pack

TitleFXPack增强了游戏标题/标志与惊人的效果,使科幻,赛博朋克,幻想,和其他主题的生活。轻松提升游戏的视觉效果。 下载: ​​Unity资源商店链接 资源下载链接

cache教程 2.单机并发缓存

0.对原教程的一些见解 个人认为原教程中两点知识的引入不够友好。 首先是只读数据结构 ByteView 的引入使用是有点迷茫的,可能不能很好理解为什么需要ByteView。 第二是主体结构 Group的引入也疑惑。其实要是熟悉groupcache,那对结构Group的使用是清晰…

linux中堡垒机

堡垒机 堡垒机概念目的 安装Jumpserver使用资产管理应用管理附加设置问题 堡垒机 概念 堡垒机,就是在一个特定的网络环境下,为了保障网络和数据不受来自外部和内部用户的入侵和破坏,采用各种技术手段监控和记录运维人员对网络内的服务器、网…

12.11_黑马数据结构与算法笔记Java

目录 070 栈 链表实现 概念理清:什么时候是指针的指向,什么时候是元素本身? 071 栈 数组实现 072 栈 e01 有效的括号 072 栈 e02 后缀表达式求值 072 栈 e03 中缀表达式转后缀1 072 栈 e03 中缀表达式转后缀2 072 栈 e03 中缀表达式转…

来看!天津靠谱Java培训机构哪家更好一点?

Java培训对某些计算机爱好者和IT从业者来说,是一道必经之路。包括Java基础、JavaWeb、JavaEE、大数据开发、人工智能等多方面的技术领域。参加Java培训可以帮助我们掌握计算机编程语言的基础知识,掌握Java语言编程技巧,快速提高编程水平。 报…

JVM虚拟机系统性学习-运行时数据区(方法区、程序计数器、直接内存)

方法区 方法区本质上是 Java 编译后代码的存储区域,存储了每一个类的结构信息,如:运行时常量池、成员变量、方法、构造方法和普通方法的字节码指令等内容 方法区主要存储的数据如下: Class 类型信息,如该 Class 为 …

人工智能在安全领域的应用

ChatGPT 等 AI 应用在网络安全领域的应用效果明显,其自动编程能力、分析能力及自身集成的知识库能够帮助网络安全从业者提升工作效率,改进组织的网络安全计划。 (一)代码生成与检测能力 可用于开发漏洞挖掘工具。如目前可以利用…

欧拉函数与欧拉定理

文章目录 AcWing 873. 欧拉函数题目链接欧拉函数欧拉函数的证明思路CODE时间复杂度分析 AcWing 874. 筛法求欧拉函数题目链接问题分析与时间复杂度CODE思路 欧拉定理 AcWing 873. 欧拉函数 题目链接 https://www.acwing.com/activity/content/problem/content/942/ 欧拉函数 …

Keil新建STM32软件工程 - (详细步骤图文)

文章目录 1. 前言2. 下载芯片对应的Keil开发包3. 下载芯片对应的标准外设库 - STM32F10x_StdPeriph_Lib_Vx.x.x4. 新建工程文件夹 - Demo34.1 移植标准外设库4.2 启动文件介绍及如何选择 5. 新建软件工程 - Demo5.1 打开Keil → Project → New uVision Project5.2 选择芯片型号…

从头到尾的数据之旅

目录 引言 链表介绍 单向链表的接口实现 结构 创建节点 头插 尾插 头删 尾删 打印 节点查找 节点前插入 节点删除 内存释放 总结 引言 在前面的学习中,我们深入了解了顺序表,通过其增删查改的操作,我们发现了顺序表在某些情况…

如何批量给文件名加相同字段?

如何批量给文件名加相同字段?文件名批量修改是一项蕴藏了非常多知识的电脑操作技能,批量修改文件名称不仅仅是修改名称这么简单,有时候我们还可能需要批量王文件名称中添加一些相同的文字字段,批量操作注重的是高效率,…

《Vue.js设计与实现》—Vue3响应系统的原理

一、响应式数据与副作用函数 1. 副作用函数 1-1 指令材料 在JavaScript中,副作用函数是指在执行过程中对外部环境产生可观察的变化或影响的函数。这种函数通常会修改全局变量、修改传入的参数、执行I/O操作(如读写文件或发送网络请求)、修…

论文阅读《Learning Adaptive Dense Event Stereo from the Image Domain》

论文地址:https://openaccess.thecvf.com/content/CVPR2023/html/Cho_Learning_Adaptive_Dense_Event_Stereo_From_the_Image_Domain_CVPR_2023_paper.html 概述 事件相机在低光照条件下可以稳定工作,然而,基于事件相机的立体方法在域迁移时性…

【教程】开始使用ipaguard进行代码加固混淆

开始使用ipaguard 前言 iOS加固保护是直接针对ios ipa二进制文件的保护技术,可以对iOS APP中的可执行文件进行深度混淆、加密。使用任何工具都无法逆向、破解还原源文件。对APP进行完整性保护,防止应用程序中的代码及资源文件被恶意篡改。Ipa Guard通过…

springMVC 学习总结(三) 拦截器及统一异常处理

一.拦截器 1.拦截器与过滤器的区别 拦截器 Interceptor 和 过滤器 Filter类似,主要用于拦截用户请求并作出一定处理操作, 但两则也有不同之处,如过滤器只在Servlet前后起作用,是Servlet规范定义的,是Servlt容器才支…

NGINX高性能服务器与关键概念解析

目录 1 NGINX简介2 NGINX的特性3 正向代理4 反向代理5 负载均衡6 动静分离7 高可用8 结语 1 NGINX简介 NGINX(“engine x”)在网络服务器和代理服务器领域备受推崇。作为一款高性能的 HTTP 和反向代理服务器,它以轻量级、高并发处理能力以及…

2-1基础算法-枚举/模拟

文章目录 1.枚举2.模拟 1.枚举 [例1] 特别数的和 评测系统 #include <iostream> using namespace std; bool pa(int x) {while (x) {if (x % 10 2 || x % 10 1 || x % 10 0 || x % 10 9) {return true;}else {x x / 10;}}return false; } int main() {int sum0;i…

【pytest】单元测试文件的写法

前言 可怜的宾馆&#xff0c;可怜得像被12月的冷雨淋湿的一条三只腿的黑狗。——《舞舞舞》 \;\\\;\\\; 目录 前言test_1或s_test格式非测试文件pytest.fixture()装饰器pytestselenium test_1或s_test格式 要么 test_前缀 在前&#xff0c;要么 _test后缀 在后&#xff01; …

低压无功补偿在分布式光伏现场中的应用

摘要&#xff1a;分布式光伏电站由于建设时间短、技术成熟、收益明显而发展迅速&#xff0c;但光伏并网引起用户功率因数异常的问题也逐渐凸显。针对分布式光伏电站接入配电网后功率因数降低的问题&#xff0c;本文分析了低压无功补偿装置补偿失效的原因&#xff0c;并提出了一…

代码随想录算法训练营第46天| 139.单词拆分 多重背包

JAVA代码编写 139.单词拆分 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 **注意&#xff1a;**不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 示例 1&#xff1a; 输入: s &…