论文信息
摘要
-
Vision Transformer的两个问题:
-
两个领域涉及的scale不同,NLP的scale是标准固定的,而CV的scale变化范围非常大。
-
CV比起NLP需要更大的分辨率,而且CV中使用Transformer的计算复杂度是图像尺度的平方,这会导致计算量过于庞大
-
-
作者的解决方案:
-
引入CNN中常用的层次化构建方式构建层次化Transformer
-
引入locality思想,对无重合的window区域内进行self-attention计算
-
介绍
Windows
首先看看Windows到底是怎么做的?
右侧:ViT的做法:
- 先来看看经典的做法,ViT把图片分成一个一个16*16的像素小块,我们常叫做patch。然后对每个patch拉成“向量”后,经过一个线性层变成Transformer网络需要的维度(还需要加入位置编码)。之后就是传统的Transformer计算了
- 这样就使得,每个patch代表一部分图片的信息,并且每层小encoder都有全局的感受野。但是这样带来的问题是图片尺寸大了的话,还用小的patch块就会导致patch的数量很多,计算量平方倍的增长。
左侧:Swin T的做法:
- 简单来说,重要的就两点:
- 每一层的patches分割是不一样的,浅层分割的patch更小,随着网络加深,慢慢合并(类似cnn的思想)
- 每一层都只计算局部自注意力(在红色框框即Windows内进行自注意力计算),这样计算量随输入图片尺寸线性增长,可以接收了,所以可以做一些场景分割等对高分辨率有较高要求的工作
Shifted Windows
等等,以上好像只说了Windows,那Shifted又是什么呢?
可以看出,Shift的意思就是在下一层,窗口的分区会进行偏移,有些窗口会被生成在前一个窗口的边界上,以连接这些窗口。注意这和Sliding Windows的
作者提出的Swin-Transformer在分类、检测、语义分割任务上都获得了SOTA。作者希望基于Transformer,并且能在多个图像相关的任务都达到SOTA的swin-transformer模型,能对未来人们发现更统一的模型做出贡献,真正打通我们对图像信息和文本信息的建模的认知。
相关工作
- CNN:
- 基于自注意力SA的框架
- 给CNN增加自注意力、Transformer
- 基于Transformer的视觉backbone
- ViT:无重叠、中等尺度的patch、实现了速度-精度的完美平衡;需要大数据集预训练
- DeiT:利用几种训练方法使得ViT能在ImageNet-1K数据集上训练,但是还是不适合需要高分辨率的图像任务
- 还有一些直接利用ViT,对其进行下采样或者反卷积后进行目标检测的方法,但是都没有获得特别好的结果
- 在基于ViT结构的分类方法中,Swin-Transformer也是实现了最佳的“速度-精度平衡”,即使它是用来作为一个一般化的backbone,没有对该任务进行优化
- 也有一些人尝试利用Transformer获得高分辨率的特征图,但是依然受限于随图片尺寸二次增长的计算复杂度,而我们的方法计算复杂度线性增长
- 我们的方法是有效并且高效的,同时在COCO目标检测和ADE20K语义分割两个任务达到了SOTA。
方法
总体结构
概览
-
首先,将图片分割为patches,patches的大小这里设置的是4×4,所以每个patch(token)的维度就是4×4×3=48,每个patch的特征的值就是原始的RGB数值。
-
阶段1:对进行一个线性层,可以把每个token的维度降低到C,然后在阶段1后面的Swin Transformer Block中,使用Modified Self Attentio进行计算,保持tokens的数量不变。
-
阶段2:为了进行分层表示,如之前所介绍的,开始合并patches。在这一层以2×2为一组对patches进行合并。所以每个patch的维度变为4C,总共的patches的数量缩小4倍(相当于原来patch的大小是4×4,现在是8×8)。然后再进行一次线性变换,使得输出的维度变为2C.
-
阶段3、阶段4:类似于阶段2,
Swin Transformer Block
将原来的Transformer Block的MSA替换为shifted windows multi-heads self attention,SW-MSA。其他结构保持不变
基于偏移窗口的自注意力机制
基于无重叠窗口的自注意力机制
不同于传统的全局的自注意力,我们的自注意力在不重叠窗口内部进行,假设总共有h×w个patches,每个窗口包括M×M个patches,那么两种机制的计算复杂度为
可见,MSA和patch数量hw成平方关系,而W-MSA在M固定的情况下,和hw只是线性关系。
在连续的block间进行偏移窗口分区
仅仅基于窗口的自注意力没有窗口之间的信息交流,限制了其能力。所以增加偏移窗口。那么怎么偏移呢?
其实它的做法也不复杂,通速地说,从当前的windows的中心点作为分割点,这里我画了一个草图:
对于偏移参数的高效batch设置
偏移窗口的一个问题就是增加了窗口的数量,并且会产生一些小于M×M尺寸的窗口,一种比较原始的方法就是把这些小的窗口填充(pad)到M×M。
这样做带来的计算量提升是很大的,比方说上面的例子中,相当于我们从2×2个窗口变成了3×3,计算量增大了2.25倍
为了解决这个问题,作者提出了cycle-shift方法,如下图所示:
这里还是比较巧妙的,具体步骤看附录,借用了陀飞轮画的图和解释,感谢!
相对位置偏差
在计算注意力时,我们参考其他人的工作,增加了一个相对位置偏差项B:
我们也尝试了绝对位置编码,效果较差一点点,我们没有采用
模型参数设置
-
四种模型
-
B:Base,计算复杂度和ViT/DeiT相当
-
T/S/L: Tiny/Small/Large,基础模型0.25,0.5,2倍的模型大小和计算复杂度
-
T、S模型的复杂度分别和ResNet-50 (DeiT-S) and ResNet-101相当
-
-
windows size:M=7
-
query dimension of each head:d=32
-
每层MLP的膨胀度:α=4
实验
分类
目标检测
语义分割
shift window和位置编码的影响
总结
主要的两个思想:
- Windows尺度变化:随着网络变深,将原来细分的patches不断合并,借鉴了CNN的尺度变化。把前面层的patches分割的十分小,从而支持高分辨率的任务;而后面不断合并,汇总patch的信息。
- 偏移窗口自注意力:采用窗口机制来进行局部自注意力,并且利用shifted机制来进行窗口之间的信息交流。成功把自注意力的计算量需求降低到线性增加。