• 问答
  • 技术
  • 实践
  • 资源
A Survey on Visual Transformer 及引文理解
技术讨论

作者丨yearn
来源丨Smarter
编辑丨极市平台

A Survey on Visual Transformer阅读,以及自己对相关引文的理解。

Transformer 作为NLP领域的大杀器,目前已经在CV领域逐渐展露锋芒,大有替代CNN的趋势,在图像分类,视频处理,low/high level的视觉任务都有相应的transformer刷榜。这篇文章在介绍这些工作的同时,讨论了他们的challenges和今后可能的研究方向。

上图基本上就是本文的主要内容了,作者首先对attention,transformer做一个简单介绍,然后介绍transformer在NLP中的应用,最后将其在CV中的应用分为四类加以介绍。这四类分别为classification, high-level vision, low-level vision 和 video processing.Classification顾名思义就是分类任务,High-level vision作者定义为:“对图像中所见内容的解释和使用”,包括目标检测、分割等。Low-level vision定义为“为图像提取描述信息”,典型应用包括超分,图像去噪,风格迁移等。

2. Formulation of Transformer

Transformer 由一个encoder,一个decoder模块组成。每个encoder是一个self-attention层加一个全连接层,每个decoder由两种attention层加一个全连接层组成,在对句子进行处理前,首先要将每个单词转化为 $512$ 维的embedding。

2.1 Self-Attention Layer

自注意力机制先将一个embedding转化为三个向量,query,key和value($q,k,v$),三者的维度都与原始embedding一致。所有的embedding放在一起组成三个大矩阵 $Q,K,V$,然后注意力机制计算过程如下

  • 计算不同输入向量的得分 $S=Q\cdot K^T$
  • 为了梯度的稳定性进行归一化 $S_n=S/\sqrt{d_k}$
  • 将得分转化为概率 $P=softmax(S_n)$
  • 最后得到加权的矩阵 $Z=V\cdot P$

这整个过程可以被统一为一个简单的函数 $Attention(Q,K,V)=softmax(\frac{Q\cdot K^T}{\sqrt{d_k}}\cdot V)\$ 直观来看,第1步计算两个不同向量之间的分数,这个分数用来确定我们在当前位置编码单词时对其他单词的注意程度。步骤2标准化得分,使其具有更稳定的梯度,以便更好地训练;步骤3将得分转换为概率。最后,将每个值向量乘以概率的总和,概率越大的向量将被下面几层更多地关注

encoder-decoder attention layer其实和自注意力机制非常类似,不同之处在于,key,value矩阵 $K,V$ 是从encoder那里继承来的,$Q$ 是从上一层继承来的。

到目前为止,我们所描述的模型中缺少的一件事是解释输入序列中单词顺序的方法。因此一般都会显式的将位置信息进行编码然后加入原始的词向量中,如下图所示

数学定义为

$PE(pos,2i)=\sin(\frac{pos}{10000^{\frac{2i}{d{model}}}}) \$$PE(pos,2i+1)=\cos(\frac{pos}{10000^{\frac{2i}{d{model}}}}) \$

开始看到这两个式子,会觉得很莫名其妙,这个sin,cos,10000都是从哪冒出来的?这里的pos表示token在sequence中的位置,例如第一个token就是0。$i$ ,或者准确意义上是 $2i$ 和 $2i+1$ 表示了Positional Encoding的维度,$i\in[0,d_{model}/2]$ 。所以当pos为1时,对应的Positional Encoding可以写成:

$$
PE\left( 1 \right)=\left[ \sin \left( {1}/{{{10000}^{{0}/{512}\;}}}\; \right),\cos \left( {1}/{{{10000}^{{0}/{512}\;}}}\; \right),\sin \left( {1}/{{{10000}^{{2}/{512}\;}}}\; \right),\cos \left( {1}/{{{10000}^{{2}/{512}\;}}}\; \right),\ldots \right] \
$$

2.2. Multi-Head Attention

在single-head的模型中,我们最终得到的embedding融合了其他各个位置,但是他很有可能被单词本身dominate(自身对自身的attention一般很大),而且我们不能确保随机初始化后不断学习得到$Q,K,V$这些矩阵带来的attention一定对。因此multi-head可以看作是一种ensemble,我们现在有多组矩阵${Qi}{i=1}^h,{Ki}{i=1}^h,{Vi}{i=1}^h$,他们将同一个输入embedding映射到不同的表达空间以此来提高模型的表达能力。不过此时query,key,value的维度不再与原始embedding一致,而是变为$d{model}/h$,因此每个head经过self-attention将word映射为$d{model}/h$维的embedding,将这些embedding连接在一起就变为原始维度,数学定义如下

$$
MultiHead(Q',K',V')=Concat(head_1,...,head_h)W^0 \
$$

这里$head_i=Attention(Q_i,K_i,V_i)$, $Q'$表示${Qi}{i=1}^h$,$W^0\in\mathbb{R}^{d{model}\times d{model}}$。

这就是基本的Multihead Attention单元,对于encoder来说就是利用这些基本单元叠加,其中key, query, value均来自前一层encoder的输出,即encoder的每个位置都可以注意到之前一层encoder的所有位置。

对于decoder来讲,我们注意到有两个与encoder不同的地方,一个是第一级的Masked Multi-head,另一个是第二级的Multi-Head Attention不仅接受来自前一级的输出,还要接收encoder的输出,下面分别解释一下是什么原理。

第一级decoder的key, query, value均来自前一层decoder的输出,但加入了Mask操作,即我们只能attend到前面已经翻译过的输出的词语,因为翻译过程我们当前还并不知道下一个输出词语,这是我们之后才会推测到的。

而第二级decoder也被称作encoder-decoder attention layer,即它的query来自于之前一级的decoder层的输出,但其key和value来自于encoder的输出,这使得decoder的每一个位置都可以attend到输入序列的每一个位置。

总结一下,k和v的来源总是相同的,q在encoder及第一级decoder中与k,v来源相同,在encoder-decoder attention layer中与k,v来源不同。

2.3. Other Parts in Transformer

Residual in the encoder and decoder. 在上面的结构图中可以看到,每个encoder,decoder模块都是会有一个残差连接+layerNorm的,具体而言就是

$$
LayerNrom(X+Attention(X)) \
$$

Feed-forward neural network. 这个模块不是简单的FCN,而是两层FCN加一个非线性的激活函数,即$FFCN(X)=W_2\sigma(W_1 X)$

Final layer in decoder. 解码器的最后一层旨在将向量转为一个字。这是通过一个线性层和一个softmax层来实现的。线性层将向量投影到一个$d{word}$维的logit向量中,其中$d{word}$是词汇表中的单词数。然后,使用softmax层将logits向量转换为概率。

大多数用于计算机视觉任务的Transformer都使用原编码器模块。总之,它可以被视为一种不同于CNN和递归神经网络RNN的新型特征选择器。与只关注局部特征的CNN相比,transformer能够捕捉到长距离特征,这意味着transformer可以很容易地获得全局信息。与RNN的隐态计算顺序相比较,Transformer的自注意层和全连接层的输出可并行计算,且速度快。因此,进一步研究Transformer在自然语言处理和计算机视觉领域的应用具有重要意义。

3. Revisiting Transformers for NLP

Transformers出现后,克服了RNN训练速度慢的缺陷,使得大规模预训练模型成为可能。BETR及其变种(SpanBERT,RoBERTa)等都是基于transformer的模型。在BERT的预训练阶段,对BookCorpus和英语维基百科数据集进行了两个任务

  • Mask一部分token让模型来预测。
  • 输入两个句子让模型预测第二个句子是否是文档中的原始句子。 在预训练之后,BERT可以添加一个输出层在下游任务进行fine-tune。在执行序列级任务(如情感分析)时,BERT使用第一个token的表示进行分类;而对于token级别的任务(例如,名称实体识别),所有token都被送入softmax层进行分类。

Generative Pre-Trained Transformer (GPT2,GPT3)是另一种基于Transformer解码器架构的预训练模型,它使用了带掩码的自我注意机制。 GPT和Bert系列最重要的区别在于与训练的方式,GPT是单向Transformer模型,这种单向的性质使其在文本生成方面具有强大的能力,今年Google使用“钞”能力造出的GPT3更是在各种任务都有非常优越的表现,而且不再需要fine-tune。

当然还有其他的一些PTM模型,但这并不是改文章的主题,因此作者只是列出来以供参考。

还有一些多模态的transformer和这篇文章比较相关,可以简单了解一下。VideoBERT使用基于CNN的module将图像转化为token,然后使用transformer的encoder来为下游任务学习一个video-text representation。VisualBERT和VL-BERT提出了single-stream unified transformer,用于捕获视觉元素和图像-文本关系,用于像视觉问题回答(VQA)和视觉常识推理(VCR)的下游任务。此外,Speech bert探索了用transformer编码器编码音频和文本pair的可能性,以处理自动文本任务,如语音问题回答(SQA)。

4. Visual Transformer

这一部分是文章的中心

4.1. Image Classification

图像作为一种高维、噪声大、冗余度高的形态,被认为是生成建模的难点,这也是为什么过了好几年,transformer才应用到视觉领域。比较初始的应用是在Visual Transformer一文中,作者使用CNN提取low-level的特征,然后将这些特征输入Visual Transformer(VT)。在VT中,作者设计了一个tokenizer将各个pixel分成少量的visual tokens,每个token代表了图像中的某些语义信息。然后使用transformer来建模token之间的关系。最后输出的tokens直接被用来做分类或者处理一下恢复成特征图用于实例分割。

与这项工作不同的是,最近出现的iGPT , ViT 和 DeiT 都是只使用transformer的文章。

在CV中使用transformer,目前来看主要的两个问题,以及下列文章的核心区别在于

  • 得到Token的方式。
  • 训练的方式。
  • 评估representation的方式。

只要得到token,我们就能像NLP一样使用transformer;有训练目标我们就能train我们的model;有评估方式我们才知道自己的model好还是坏。接下来的几篇文章我也会从这几个方面进行讲解。

4.1.1 iGPT

Token:iGPT使用一种比较暴力的方式得到token:原始图像($3\times 224\times 224$)进行预处理,将其调整为低分辨率,并将其重塑为一维序列(从左到右,从上到小)。对于RGB数据,我们的字典大小为$\text{num_vocab}=256$(文中采取了比较有趣的手段减小字典),每个像素相当于一个word,即对每个pixel,我们采用nn.Embedding(num_vocab, embed_dim)提取每个像素embedding。至此图片数据已经完全转化为了transformer的输入形式$[\text{seq_len,embed_dim}]$。其中seq_len取决于down sample保留了多少pixel。

Pretrain: iGPT有两种预训练方式:(i) 像自编码器一样进行逐像素预测。(ii)像Bert一样mask一部分pixel然后预测。其实第一种方式的实现与bert也很类似,就是预测第$i$个pixel的时候,mask掉$i+1...$之后的所有pixel。

attn_mask = torch.full(
        (len(x), len(x)), -float("Inf"), device=x.device, dtype=x.dtype
)
attn_mask = torch.triu(attn_mask, diagonal=1)#[784, 784]
#attn_mask = [[0,-inf,-inf...,-inf],
#            [0,0,-inf,...,-inf],
#            [0,0,0,...,-inf],
#            [0,0,0,...,0]]

Evaluation:两种评估方式,(i) fine-tune:增加了一个小的分类头,用于优化分类目标并adapt所有权重。(ii)Linear-probe:将pretraining的模型视作特征提取器,增加一个分类头,只训练这个分类头。第二种方式的直觉在于“一个好的特征应该能够区分不同的类”,除此之外,fine-tune效果好有可能是因为架构很适合下游任务,但是linear-probe只取决于特征质量。

主要过程的代码如下,数字只是为了示例,下面假设字典长度为16(pixel一共16种)

# x:原始图像处理后得到的序列 [32*32, 64],64为batchsize,32是下采样后的长款
length, batch = x.shape
# 将每个pixel作为token求embedding,128为embedding的维度
h = self.token_embeddings(x) # [32*32, 64, 128]
# 添加位置编码
h = h + self.position_embeddings(positions).expand_as(h)
# transformer
for layer in self.layers:
    h = layer(h)
# 自回归编码需要输出logits,映射回字典长度
logits = self.head(h) # [32*32,64,16]
# 16类的cross_entropy,对每个pixel计算损失
loss = self.criterion(logits.view(-1, logits.size(-1)), x.view(-1))

4.1.2 ViT

上文我们提到过,BERT在执行序列级的任务时使用第一个token作为特征得到分类结果。比如下面这句,他会在第一个位置加上CLS token,([CLS]谷歌和[MASK][MASK]都是不存在的。[SEP]同时,[MASK]也是不存在的。[SEP])最后使用该CLS token得到的结果进行分类。那么我们是不是也可以参照这种方式直接进行分类呢?答案是肯定。

Token: 一个图像$x\in\mathbb{R}^{H\times W\times C}$将被处理为一个patch 序列$x_p\in\mathbb{R}^{N\times(P^2C)}$. (H,W)是原始分辨率,(P,P)是每个patch的分辨率,$N=HW/P^2$是序列长度。由于transformer在所有层中使用恒定宽度,一个可训练的线性投影将每个$x_i$映射到D维向量,其输出称为patch embeddings。

Pretrain: 传统情况下ViT也是要预训练的,不同于iGPT,这不是一个生成式的模型,只采用了transformer的encoder,因此直接在imagenet做分类任务进行pretrain。文章显示数据集小的时候效果一般,数据集大的时候因为data bias已经被消除了很多,此时效果非常好。

Evaluation:分类任务的评价不再多说。

总结一下就是如下公式

4.2. High-level Vision

4.2.1 Generic Object Detection

基于transformer的目标检测可以分为两类,也即下图的(a)(b)

Transformer-based set prediction for detection.

DETR 是这类工作的先驱,其将目标检测视为集合预测问题,去掉了目标检测种很多手工的组件像NMS,anchor generation等。

Token:CNN将图像downsample为$z_0\in\mathbb{R}^{d\times h\times w}$,然后将$z_0$的空间维度压缩为一维,造成一个序列$\mathbb{R}^{d\times (wh)}$。这个token的获取方式挺有意思,空间维度塌缩。当然也要加上位置编码

Train:如何将object detection转化为set prediction然后进行训练,这是一个非常有意思的问题。作者使用了object queries,这实际上是另一组可学习的positional embedding,其功能类似于anchor。之后每个query进过decoder后算一个bbox和class prob。

Evaluation:目标检测传统的评估方式。

DETR也大方地承认了他的缺点:训练周期长,对小物体检测效果差。

Transformer-based backbone for detection.与DETR不同,ViT-FRCNN将ViT与传统的检测框架融合,直接使用transformer的encoder作为backbone提取特征,与ViT处理图像的方式一致,但是输出的patch feature重新调整为一个图像的特征图送入传统检测模型。

总结一下,目前transformer已经在很多视觉应用中展现出了强大的实力。使用transformer最重要的两个问题是如何得到输入的embedding(妥善处理position embedding),模型的训练与评估。目前还有很多非常有价值的课题值得我们探索,例如,对于最终的性能,像CNN或PointNet这样的特征提取模块是必要的吗\?如何让visual transformer受益于像BERT或GPT-3在NLP社区做的大规模的预训练数据。是否有可能预先训练单个transformer模型,并通过几次微调来针对不同的下游任务进行微调(人民币玩家们加油)\?

4.3. Low-level Vision

这里所谓的low-level,其实就是输出并不是标签这种形式,而是超分,或者生成模型,直接输出图片。这一类应用的大体框架如下,transformer编码器将图像作为像素序列或小块,以该序列作为输入语句,transformer解码器就能成功地生成所需的图像。在未来的工作中,为不同的图像处理任务设计合适的体系结构将是一个有意义的方向。

Image transformer一文最先使用完整的transformer做图像生成的工作。他将每个值为$[0,255]$的像素编码成一个$d$维向量,作为编码器的输入。特殊之处在于decoder,每个输出像素$q'$是经过计算输入像素$q$以及已经生成像素$m_1,...$之间的attention得到的。$q'=Attention(q,m_1,m_2,...,)$。

对于图像条件生成,如超分和图像修复,使用编码器-解码器架构,其中编码器的输入是低分辨率的图像或损坏的图像。对于无条件和class-conditional生成(即噪声到图像),只使用解码器输入噪声向量。由于解码器的输入是原生成的像素,在生成高分辨率图像时会带来较大的计算成本,因此提出了一种局部自注意方案,只使用最接近的生成像素作为解码器的输入。结果表明,该图像转换器在图像生成和翻译任务上与基于cnn的模型具有竞争性能,表明了基于转换器的模型在低层次视觉任务上的有效性。

到这里用于图像的transformer基本算是搞完了,还有一些基于视频的,多模态的,self-attention在CV中的应用都不是我关注的重点。最后再看一看目前存在的问题以及未来可能的发展方向

5. Conclusions and Discussions

5.1. Challenges

目前来看,大多数应用都保留了transformer在NLP任务中的原始形态,这一形态不一定适合images,因此是否会有改进版本,更加适合视觉任务的transformer尚且未知。除此之外,transformer需要的数据量太大,缺少像CNN一样的inductive biases,我们也很难解释他为什么work,在本就是黑盒的DL领域又套了一层黑盒。最后也是大多数非人民币玩家关注的点在于,基本的ViT模型需要180亿次浮点运算来处理一个图像。相比之下,轻量级的CNN模型GhostNet只需约6亿次FLOPs就能达到类似的性能,这个运算消耗实在太过昂贵。

5.2. Future Prospects

  • 像NLP一样的大一统模型,一个transformer解决所有下游任务。
  • 高效的部署与运行。
  • 可解释性。
  • 0
  • 0
  • 2541
收藏
暂无评论
shijie

华南理工

  • 18

    关注
  • 52

    获赞
  • 2

    精选文章
近期动态
  • 目标检测
文章专栏
  • shijie的专栏