| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> Swin Transformer理解 -> 正文阅读 |
|
[人工智能]Swin Transformer理解 |
最近在阅读transformer,也作个笔记,供学习使用。希望阅读者有CNN的基础,如YOLO,MobileNets,ResNet等,并且一定要先阅读ViT。不然读起来可能比较吃力。当然笔记也尽可能解释清楚 1 核心参考
2 研究背景:ViT的缺点1、显存占用–Token数量。Token是指模型运行中的最小处理单元。ViT中的Token指的是一个Patch,Token的数量就是Patch的数量。那Patch又是什么呢?就是一张图片被切分成9小片,那么每一小片就是一个Patch。所以这里 3 研究意义
4 摘要1、本文提出一种可以适用于多种任务的backbone(特征提取网络)->swin transformer(swin: shifted windows结合:移动窗口) 5 引言Swin Transformer的研究动机是让Transformer作为一个通用的骨干网络(backbone)。在ViT中把图片打成Patch,其中Patch Size为16×16。所以图中(b)的16×也就是16倍下采样率,也就意味着每一个Patch(token),它至始自终代表的尺寸是差不多的,每一层的Transformer block看到token的尺寸都是16倍下采样率。虽然它可以通过全局的自注意力的操作来达到全局建模能力,但是它对多尺寸的特征把握就会弱一点。但是我们知道,多尺寸的特征对于下游任务是非常重要的,比如目标检测中的FPN,通过不同尺寸的特征融合,从而能够很好的处理物体不同尺寸的问题。而在ViT中,它处理的特征都是单一尺寸,而且是low resolution。也就是说自始至终都是处理16倍下采样过后的特征,也就意味着ViT不适合处理密集预测型的任务,同时对于ViT而言,它的自注意力始终在最大窗口(整图,图中红框)上进行的,即它是一个全局建模,也就是说它的复杂度是跟图像的尺寸进行平方倍的增长。之前虽然Patch Size为16×16能处理224×224的图片,但是图像尺寸为800×800,即使用Patch Size为16×16,序列的长度依旧很长,这个计算复杂度还是很难承受的。 那么另外一个挑战,就是如何去生成多尺寸的特征呢?CNN主要采用pooling池化操作,池化操作能够增大卷积层能看到的感受野,从而使每次池化后的特征去抓住物体的不同尺寸。Swin Transformer也提出一个类似池化的操作,叫做Patch merging,就是把相邻的小patch合成一个大patch,那这样合并成的一个大patch就能看到之前小patch看到的内容,这感受野就增大了,同时也能抓住多尺寸的特征。所以Swin Transformer刚开始是4倍下采样,然后变成8倍、16倍。之所以刚开始是4倍,是因为它最开始的这个patch是4×4大小的。那当有了多尺寸的信息,即4×,8×,16×的特征图,那么就可以把这些多尺寸的特征图输给一个FPN,从而就可以做检测了。 Swin Transformer的一个关键设计因素,移动窗口。如图所示,如果在Transformer第l层,把输入或者特征图分成红色小窗口的话,那就会有效的降低序列程度,从而减少计算复杂度。图中灰色的小patch,是最基本的元素单位,也就是那个4×4的Patch。每个红色的框是一个中型的计算单元,也就是一个窗口。在论文中,每一个窗口默认有7×7=49个小Patch。图中主要是画了一个示意图,主要是讲解shift操作是怎么完成的。那么,如果我们用蓝色的框表示整体特征图,shift操作就是往右下角的方向整体移动了两个patch,也就变成了像右图那个的格式,然后我们在新的特征图里再次分成四个方格,那最后shift我们就有很多窗口。这样的好处就是窗口与窗口之间现在可以有信息交流了,而之前没有shift,这些窗口之间没有重叠,每次自注意力的操作都在小窗口里进行了,这样这个窗口里的patch就无法注意到别的窗口里的那些patch的信息,这就达不到使用Transformer的初衷了。因为Transformer的初衷就是更好的理解上下文。再配合上之后提出的 patch merging,合并到 Transformer 最后几层的时候,每一个 patch 本身的感受野就已经很大了,就已经能看到大部分图片了,然后再加上移动窗口的操作,它所谓的窗口内的局部注意力其实也就变相的等于是一个全局的自注意力操作了。这样既省内存,效果也好。 6 算法模型总览假设我们现在有一张输入图片224×224×3,首先第一步像ViT那样,把图片拆分重排成patch。由于论文中patch_size大小为4×4( 首先,我们可以看到现在的序列长度为3136,而在ViT中,由于patch_size大小为16×16,他的序列长度只有196,而这里3136就太长了,是目前Transformer不能接受的序列长度,那应该怎么做呢?Swin Transfomer文中引入了基于窗口的自注意力计算,每个窗口只有49(7×7)个patch,所以序列长度只有49,这样就很小了,这样就解决了计算复杂度的问题。也就是说Swin Transformer Block是基于窗口去算自注意力的,至于每个一个Block里做了什么,我们之后讲,先把它当成是一个黑盒,现在只关心输入输出的维度。大家也知道,如果不对Transformer去做更多的约束的话,那Tranformer输入的序列长度是多少,那么它输出的序列长度也是多少。注:这里读了ViT论文的应该知道。 所以说经过两层Swin Transformer Block之后,输出还是56×56×96。那到这,其实Swin Transformer的第一个阶段(stage 1)已经走完了。注:作者写的是两个 Swin Transformer Block,实际上这里永远是偶数个,我们可以看到这里面,LN其实就是layer norm,MLP,这里和Transfomer Block是一样的,唯一的区别就是把原来的MSA换成W-MSA,作者接连使用了两个Transformer Block,是因为作者要使用一个W-MSA和一个SW-MSA,这两个东西都得用,才能取得比较好的结果。所以我们可以注意看,作者使用的Swin Transformer Block都为偶数个。也就是说该模型最重要的就是W-MSA和SW-MSA,当然可能还有一个Patch Merging不知道是怎么操作的。 6.1 Patch Merging那么,接下来如果想要有多尺寸的特征信息,那就要构建一个层级式的Transformer,就像CNN里有一个池化的操作。论文中Patch Merging也就是这个功能。
6.2 W-MSA和SW-MSA现在我们来看基于窗口或者移动窗口的自注意力,也就是论文核心W-MSA和SW-MSA 举个例子,来看窗口是怎么划分的?原来的图片平均分成一些没有重叠的窗口,就拿第一层的输入来说,它的尺寸是56×56×96,即有一张维度为56×56的张量,然后把它切成图中黄色不重复的方格,这每个方格就是一个窗口,但是注意这个窗口并不是最小的计算单元,最小的计算单元还是之前的那个Patch,也就意味着,每一个小窗口其实还有M×M个Patch,论文中M默认为7,也就是说几个橘黄色的小方格里有7×7=49个小Patch。现在所有的自注意力的计算都是在这些小窗口里计算的,也就意味着序列长度永远都是49。那么原来大的整体特征图有多少个窗口呢?(56/7)×(56/7)=64个窗口。也就说我们会在这64个窗口里分别去算自注意力。 那公式是怎么推算的呢?我们先拿标准的多头自注意力来举例。那么现在有一个输入,首先把它变成QKV三个向量,这个过程就是原来的向量分别乘了三个系数矩阵(这里可以回顾ViT),然后一旦得到Q和K之后就会做一个相乘,得到自注意力矩阵attention。有了这个自注意力矩阵再和V做一次乘法,也就是相当于做了一次加权。最后因为是一个多头自注意力,还会有一个projection layer,这个投射层就会把向量的维度投射到我们想要的维度(和FC差不多) 那现在如果我们给这些向量都加上他们该有的维度,也就是说刚开始时输入是hwC,第一步(图中红框)QKV相当于是用hwC的向量去乘一个C×C的系数矩阵,最后得到了hwC,所以每一个计算复杂度是hwC^2 ,因为有3次操作,所以是3hwC^2。 第二步(图中绿框)计算自注意力hwC×Cwh得到hw×hw。这个计算复杂度就变成了(hw)^2×C。 第三步(图中紫框)自注意力矩阵和value的乘积计算复杂度还是(hw)^2×C, 所以现在变成了2(hw)^2×C。 第四步(图中黑框),投射层hwC乘以C×C变成hwC,它的计算复杂度为hwC^2。所以综上得到公式1 那基于窗口的自注意力计算复杂度优势如何得到的呢?因为在每个窗口里算的还是多头自注意力,所以可以直接套用公式一,只不过高度和宽度变化了,那现在高度和宽度不再是 hw,而是变成窗口的大小 M×M,即 h 变成了 M,w 也是 M,它的序列长度只有 M × M 这么大 。所以当把 M 值带入到公式(1)之后,我们就得到计算复杂度是4M^2 × C^2 + 2 M^4 ×C,这个就是在一个窗口里算多头自注意力所需要的计算复杂度。那一共有多少个窗口呢?其实我们现在是有h/M×w/M个窗口。那我们用这么多个窗口乘以每个窗口所需要的计算复杂度,就会得到公式二。 我们可以看到虽然公式前面是一样的,只有后面从2(hw)^2×C 变成了2M^2 ×hwC,看起来好像差别不大,但其实如果仔细带入数字进去算呢,你会发现计算复杂的差距是相当巨大的。因为如果hw是56×56的,但M^2只有49,所以是相当了几十甚至是上百倍的。 另外,作者还提到这种基于窗口计算自注意力的方式虽然很好地解决了内存和计算量的问题,但是现在窗口和窗口之间没有通信了,这样我们就达不到全局建模了,也就文章里说的会限制模型的能力,所以我们最好还是要有一种方式能让窗口和窗口之间互相通信起来,这样效果应该会更好,因为具有上下文的信息,所以这里作者就提出移动窗口的方式。 作者刚开始提出移动窗口,其实我们刚开始就简单的提到过了,就是把原来的窗口往右下角移一半,就变成了右边窗口的形式,如果Transformer是上下两层连着做这种操作,先是 window再是 shifted window 的话,就能起到窗口和窗口之间互相通信的目的了。 7 其他技巧其实作者后面还讲了两个点。一个是怎样提高移动窗口的计算效率,他们采取了一种非常巧妙的 masking,也就是掩码的方式;另外一个点就是这篇论文里没有用绝对的位置编码,而是用相对的位置编码 但这两个点其实都是为了提高性能的一些技术细节,跟文章整体的故事已经没有多大关系了。 那目前的这个移动窗口的方式,到底还有哪些问题呢?为什么作者还要提高它的计算性能呢?我们直接来看下图。下图是一个基础版本的移动窗口,就是把第一个的窗口模式变成了第二个的窗口的方式 。虽然这种方式已经能够达到窗口和窗口之间的相互通信了,但是我们会发现一个问题,就是原来我们计算的时候,特征图上只有四个窗口,但是当你做完移动窗口操作之后,现在得到了9个窗口,窗口的数量增加了,而且每个窗口里的元素大小不一,比如说中间的窗口还是4×4=16个 Patch,但是别的窗口有的有4个 patch,有的有8个 patch,这都不一样了,如果想做快速运算,就是把这些窗口全都压成一个 patch直接去算自注意力,现在就做不到了,因为窗口的大小不一样 。 所以说整体而言,上图介绍了一种高效的、批次的计算方式。比如我们本来移动窗口之后得到了9个窗口,而且窗口之间的patch数量每个都不一样,我们为了达到高效性,为了能够进行批次处理。我们先进行一次循环位移,把9个窗口变成4个窗口,然后用巧妙的掩码方式让每个窗口之间能够合理地计算自注意力,最后再把算好的自注意力还原,就完成了基于移动窗口的自注意力计算。 那现在,我们就通过一个例子来看掩码操作是怎么做的。首先蓝色框图是已经经过循环位移的,也就是说0134其实是原来的那个图。8相当于是从原来的A移到现在的A,25相当于是从原来的B移到现在的B,67相当于是从原来的C移到现在的C。总之这个就是已经经过了循环位移之后得到的,然后我们在中间画两条线,就把它打成了四个窗口,也就是窗口0123。整个特征图大小我们暂且是14×14的,也就是高和宽这两边分别有14个Patch。之所以划分成4个窗口,也是因为每个窗口里有7×7个Patch。然后012~8,并不是里面的内容,而是一种序号,主要就是来区分不同的区域的。因为比如对于区域0来说,也就是这个窗口0,它里面的元素都是相邻的,所以它可以互相去做自注意力的,所以这一大块里,所有的Patch我们都用序号0来代替。但是作为窗口1而言呢(这里是划分为4个大窗口里的1),它左边的区域是原图,它右边的区域2呢,是移动过来的,所以这两个区域是不相同的,它们之间不应该做自注意力计算。所以我们就用两个序号来代替这个区域里的Patch。那类似对于窗口而言,区域2用3和6两个序号代替,区域3用4、5、7、8四个序号代替。 在最后3.3节,作者提出了Swin Transformer的几个变体。 Swin Tiny的计算复杂度跟 ResNet-50 差不多。然后Swin Small 的复杂度跟 ResNet-101 是差不多的,这样主要是想去做一个比较公平的对比。那这些变体之间有哪些不一样呢?,其实主要不一样的就是两个超参数:向量维度的大小 c和每个 stage 里到底有多少个 transform block。这里其实就跟残差网络就非常像了,残差网络也是分成了四个 stage,每个 stage 有不同数量的残差块
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/8 3:47:59- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |