Vision Transformer细节理解
Transformer模型架构图
首先来看一下Transformer模型的架构图,因为Vision Transformer是Transformer模型在CV领域的应用,所以在学习ViT模型之前有必要了解一下Transformer的基础架构。关于Transformer架构的基础知识可去B站观看这个视频。
Transformer
由两个部分组成,一个是编码端(左半部分),一个是解码端(右半部分)。对于编码端来说,输入字符Inputs
转化为对应的数字,再由数字转化为Input Embedding
,然后和对应的Positional Encoding
相加,组成了最终的Inputs Embedding
。然后这个输入流经多头注意力层,再流经前馈神经网络,堆叠N个后最终输出。
Patch+Position Embedding
由于ViT模型中只使用了编码端,所以我们重点看一下编码端,主要做的是如何把编码器放入CV任务中。
在NLP中,将原始字符转换为数字,再对每个数字进行embeding
,在和Positional Embedding相加,解决了输入的问题。
那么现在的问题是,一张图片如果想输入到这个模型中,应该怎么融入进去呢?
要把左边的这张图片放进右边的模型架构中去,那么最核心的思想一定是把图片仿照着NLP中的方式转换成一个一个的
token
,那么怎么转化成一个一个的token
呢?
一个非常朴素的思想是这样的,将一个图片(假设是单通道)的每一个像素点当做一个token
,再把每个像素点对应的token
转化为各自的embedding
(可能不准确,但是差不多),和对应的位置编码进行相加不就解决了一个图片输入转换为token
的问题吗?
但这样的话,会遇到一个非常严重的问题,就是复杂度的问题。一张单通道224224大小的图片,如果每一个像素点都当做一个
token
的话,序列长度将变成224224=50176,即Transformer模型输入那里变成了50176的大小,相当于BERT的100倍。这个长度太大了,由长度就会导致参数量的问题,长度太大参数量也将会非常大,这是我们所不能承受的。
针对复杂度的问题,我们怎么处理呢?
这几种改进方式其实都可行,都有论文发表出来,但是实施起来比较复杂。我们其实想得到一个简单的方式去处理这个问题,那么一个非常简单的方式就是把整个图像化整为零,切分为
patch
。
相当于减少了输入的长度。
现在可以看一下ViT论文中的模型了。
模型中的数据流转如下图所示:
为什么要加入一个
CLS
符号呢?
简单的意思是说,减少对原始Transformer模型的更改,所以加上了
CLS
。潜在的意思是说,原始的Transformer在训练的时候是带有CLS
符号的。这句话的解释其实是不太正确的。
CLS
符号的出现不是在原始的Transformer模型中,而是在NLP中的一个预训练模型-BERT中。
其实。整个Transformer在整合输出信息的时候,有多种方式。
BERT
中为什么使用了CLS
符号呢?
所以在论文中有这样一个实验结果:
Transformer模型为什么需要一个位置编码?
为什么需要位置编码?
就是告诉模型哪个图像的patch
在前面,哪个图像的patch
在后面。
为什么位置编码可以和patch embedding相加?
位置编码究竟有没有作用呢?
Transformer Encoder
整体再串讲一遍:
参考文献
- https://www.bilibili.com/video/BV1Uu411o7oY?spm_id_from=333.999.0.0
- 代码实现可看我的这个博客。