VIT探索笔记
切入点
如何把一张图变成一句话? 对输入图做切割,分块,每一块就是一个token(单词);
假设一张224x224x3的图,分块,也就是论文中的patch, 每块大小为16x16x3,那就得到196块,这样就把一个CV问题变成了NLP问题。
有了patch的想法,再加上原汁原味的Transformer, 开始大力出奇迹,特别强调,作者是保持原汁原味的Transformer,然后在其他方向上做消融实验(大力出奇迹),比如位置编码,分块大小等
没办法从感性上去思考他是怎么working的? patch之间做Self-Attention,怎么就Nice了呢!!!!!
值得一提的相关研究,2020年Cordonnier提出一种方式,从输入图片取出2 x 2大小的patch并采用full self-attention,这与本篇采用的方式最为接近,但本篇进一步证明了使用大量训练数据训练的Transformer就比CNN SOTA具有更高的性能。论文地址:On the Relationship between Self-Attention and Convolutional Layers
内容点
- 和Transformer一样,没有任何卷积操作
- (ViT-H/14),(ViT-L/16), 数字14和16是patch size
网络结构
第一,九宫格-输入层
- 输入图片X: 224x224x3,
- patch大小设置为16x16x3,看结构图,九宫格的每一个格子是的大小16x16,维度是3,一个格子就是一个patch。
- 一张224x224的图有多少个patch呢?,也就是对应的NLP里面的token = (224x224) / (16x16) = 196个,相当于一张图转变一个196个token的句子,看上图,把九宫格拉直,就是个句子。
需要注意的是,假设输入图片X的size改变了,但是patch的size是保持不变的(16x16);从上面的分析,可以知道,输入图片X的size变大后(224x224==》256x256),那我们将得到256个patch。 由此,就带来一个问题,positional embedding(位置编码)信息对不上了,论文中给出的方法是插值法或者重新训练。
第二,Patch Embedding | Linear Projection of Flattened Patches | 线性全连接层
- 这一层的任务也叫做:Patch Embedding
- 线性的全连接层,输入是768xD,D为设置为768(也可以根据数据大小调参,大数据集可以调整为1024),
XE = 196 x (1616*3) x 768 x 768 = 196x768 - X经过全连接层后,得到196x768的向量,即X*E的输出为196x768
第三,Position Embedding(位置编码) 和 [class] embedding
- 位置编码有1D,2D等方式,作者在论文中做了消融实验,1D就足够好了,1D类似于对九宫格做1,2,3,4,5,6,7,8,9的位置编码;
- 打乱patch的位置,并不会改变结果,self-attention的特性
- 位置编码大小为196x768,
- X*E的输出(196x768),和 位置编码相加,得到 196x768,向量维度大小不变
- 最后,在加上一个维度,就是class标签的维度,class enbeding的大小为 1x768, cat(class enbeding, 位置编码+X*E)==》197x768, 197x768 也是Transformer Encoder的输入。
# 这里多1是class token,embed_dim即patch embed_dim
self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim))
# patch emded + pos_embed
x = x + self.pos_embed
第四,Transformer Encoder
- 作者保留了原汁原味的Transformer Encoder,
- 输入197x768,输出197x768
- 叠加L个
完整网络结构图