写在前面
什么是Transformer呢?就是把符号向量化为Token, 再和位置编码求和或者做阿达玛积,最后送入一定层数的Attention Block构成的Encoder和Decoder,就完成了Transformer的基础功能。
那么,把上述过程,用在图片上面,这就是Vision Transformer,简称ViT
ViT的特点
CNN | Transformer | |
---|---|---|
作用范围 | 局部 | 全局 |
作用频域 | 低频 | 高频 |
平移不变性 | 强(有) | 弱(无) |
正是因为CNN具有以上归纳偏置(这个词不好理解,比如说,一个孩子,第一次见到蛇被吓了一跳,日后遇到类似蛇的绳子,也会被吓一大跳,孩子对这个蛇状东西的认知,就是孩子的归纳偏置,这是一种方法论,而非具体的操作或者认知)的特点,所以在图像方面也就更适合,相对于Transformer,需要的数据相对就会少很多。
以上似乎说的是Transformer用于图像上会有很多缺点,那么就没有优点么?有的,
- 对图像尺寸的处理更为灵活,不太需要类似CNN哪种dedicated design的卷积核、步长和padding设计,以满足output的尺寸要求;
- 较强的并行计算能力,不需要类似CNN那样,以Kernel为一个窗口在图上滑动,一个个计算窗口中的卷积值(但这似乎也是个缺点,显然,CNN这样做一定是省计算资源的);
- Transformer可以处理多模态任务,尤其是插入prompt之后,可以在一个网络模型中完成特征提取;
- Transformer对全局特征的把握强于CNN(但是这好像也不算一个优点,对于尺度小的目标,就不行了,例如BEV视角中的目标普遍都很小,用ViT效果还是不如CNN);
- Transformer对空间信息的利用会更高一点;
ViT的结构
ViT和Transformer的步骤是相同的,只不过对Token的处理上会有些许差异,具体如下:
- 利用nn.Conv2d(kernel_size=patch_size, stride=patch_size),把图像按照patch_size切割成小块,然后用卷积进行DownSample
- 这里有一个 [ 256 , 256 , 3 ] [256, 256, 3] [256,256,3]的图片
- 图片被切分成了 16 × 16 16 \times 16 16×16个小patch,每个patch内拥有 p a t c h _ s i z e = 16 × 16 patch\_size = 16\times 16 patch_size=16×16个像素
- 送入nn.Conv2d(kernel_size=16, stride=16),把 p a t c h _ s i z e = 16 × 16 patch\_size = 16\times 16 patch_size=16×16卷成 p a t c h _ s i z e = 1 × 1 patch\_size = 1\times 1 patch_size=1×1
- 经过Patch_embedding后,生成一个经过Conv下采样的 16 × 16 16\times 16 16×16个patch的Tokens
- 生成位置编码Position-Embedding(PE)(详情参考Transformer之位置编码的通俗理解)
- 上述两个步骤的结果相加,生成一个 [ B , H × W , C ] [B, H\times W, C] [B,H×W,C]的向量,作为后面Attention的输入
- 将上述结果送入多层Transformer的Attention(详情参考Transformer之Attention的通俗理解),具体结构如下
如图所示,如果有12层这样的结构,那么这就是
V
i
T
_
B
a
s
e
ViT\_Base
ViT_Base,如果有24层,那么就是
V
i
T
_
L
a
r
g
e
ViT\_Large
ViT_Large,一定要注意看别人代码中用的是哪一个ViT,因为对应的Pth预训练文件是不同的。
ViT的Pipeline
按照上面步骤,将ViT组装起来,就是ViT的pipeline