论文阅读:ViT Vision Transformer An Image is worth 16X16 words
今天介绍的是 Transformer 在视觉领域的一篇非常重要的论文,Vision Transformer,这篇文章发表在 2021 ICLR 的会议上。长久以来 CNN 一直是 CV 领域最主流的模型,随着 Transformer 的提出,以及其在 NLP 领域的的统治地位,CV 界的人也开始思考把 Transformer 引入 CV 任务的可行性。果然,就有了这篇 Vision Transformer。这篇文章的作者同样来自谷歌。
好了,现在开始进入正题
Abstract
首先看摘要部分,文章作者一开始就提到说虽然 transformer 已经成为了 NLP 领域的主流模型,但是在 CV 领域,这个模型的使用还是非常的受限。因为 transformer 模型里面的核心模块是 attention 机制,所以作者接下来说到,在视觉领域,attention 要不与卷积神经网络一起使用,要不是用 attention 去替换卷积神经网络里的一些模块,但是整体的 CNN 架构还是保持的。然后文章作者证明说,其实视觉领域里面的任务,CNN 也不是非要不可的,文章作者就说如果有足够多的数据来做预训练,那么一个基于纯 attention 机制的 transformer 模型也能将图像分类任务处理地很好。所以文章的摘要,主要就是说 CV 任务也可以不依赖 CNN 模型,只要数据量足够,那么 transformer 预训练模型也能在 CV 领域取得很好的表现。
Introduction
导言的第一段,作者说在 NLP 领域,基于自注意力机制的架构,尤其是 transformer 模型,已经成为了 NLP 领域的标配。主流的方法一般是在一个很大的数据集上做预训练,然后再在一个小规模的特定数据集上做 finetune。多亏了 transformer 模型的计算高效性以及可扩展性,目前的模型规模也越来越大,基本都到了 1000 亿规模的参数量了。而且作者还提到说,随着你模型参数量以及数据量的增长,目前还没有看到性能饱和的现象。这似乎为一年之后的 ChatGPT 的出现埋下了伏笔。
然后第二段,文章作者介绍了 CV 领域的现状,CV 领域的很多任务还是以 CNN 模型为主流架构。然后,受到 NLP 领域的一些启发,也开始有相关的工作尝试在 CV 领域引入注意力机制,文章作者也列举了几篇相关工作,不过作者也提到,这些工作中的 attention 机制都是一些特定设计的 attention 机制,不像标准的 attention 机制,有很好的硬件支持,所以这类特殊的 attention 机制的工作还不能高效地进行大规模的训练,所以目前主流的 CV 任务中,还是基于 ResNet 的模型的效果是最好的。
第三段,文章作者就引出了 vision transformer 的工作,文章作者说受 transformer 在 NLP 领域成功的启发,文章作者们设计了一种可以在图像上进行注意力计算的 transformer。因为是在视觉领域应用 transformer,所以作者就直接称其为 vision transformer。文章作者提到说,为了实现在图像上进行标准的注意力操作,他们先把图像拆分成很多个图像 patch,然后每个图像 patch 通过一个 linear embedding 进行维度的变换,变换后的每个 patch 就类似 NLP transformer 里的词向量,patch 的数量就类似序列的长度,这样就可以进行标准的 attention 的计算了。然后在图像分类任务上进行有监督的训练。
接下来是导言的第四段,文章作者说如果 vision transformer (ViT) 在中等规模的数据集上训练,那么比起同样参数量的 ResNet 来说, ViT 的性能其实会弱一些,作者也做出了一些解释,文章中说是因为 Transformer 与 CNN 模型相比,它缺少一些 inductive biases,这个词翻译过来叫归纳偏置,我看相关的精度论文视频里面把归纳偏置解释为类似先验假设的一些知识。CNN 的先验假设就是 locality 和 translation equivariance 。听起来还是有些道理的,总结来说就是 transformer 比起 CNN 少了一些先验假设,所以为了达到同样的效果,需要更多的训练数据。因为导言的第五段,也就是最后一段,作者就介绍说,随着训练数据规模的增加,ViT 预训练模型的表现也变得越来越好,迁移到其它一些中等规模数据集上的表现已经持平甚至超越 ResNet 了。
Related Work
接下来是相关工作的介绍。
第一段主要还是讲了一下 transformer 在 NLP 的发展。自从 2017 年 transformer 在 NLP 领域出圈之后,NLP 领域基于 transformer 的模型也做得越来越大,这类模型一般都是在一个很大的语料库上做预训练,然后在特定的任务上做微调。然后又大概介绍了一下两个比较出名的工作,一个是 Google 的 BERT,一个是 OpnenAI 的 GPT。BERT 是用一种 denoising 的方式做预训练,也就是完形填空;而 GPT 是用语言模型做预训练。
第二段就是介绍 self-attention 在 CV 领域的应用。因为视觉要处理的对象一般都是一张图片,所以最直观的方法就是把图片看成是很多个像素的集合,但是如果直接这样处理,那么计算的复杂度肯定是显而易见地太大了。所以直接把像素当做序列肯定是不现实的。接下来作者介绍了一些相关工作,主要是怎么去近似整个图像。一类工作是不再对全局图像做 self-attention,而是对局部邻域做 self-attention。还有一类工作是用 sparse transformer,也就是对图像特定的像素点提取出来,做 self-attention。还有一类工作就是在不同尺度的 block 上做 self-attention。这些工作其实在 CV 任务上的效果也不错。但是都需要复杂的工程技巧去做硬件加速。
接下来第三段,文章作者提到了和他们想法最接近的一篇工作,这篇工作的核心思想和 ViT 基本一模一样,也是把图像拆成很多个 patch,然后 patch 之间计算 self-attention。文章作者也解释了两者的差异。之前的工作,图像的 patch size 是 2 × 2 2 \times 2 2×2,所以之前的那篇工作只能处理很小分辨率的图像,而本文的图像 patch 是 16 × 16 16 \times 16 16×16,可以处理更高分辨率的图像。而且本文也凸出了大规模预训练的 vision transformer 可以取得超越 CNN 的效果。这都是之前的相关工作所没有做到的。
第四段的相关工作,文章作者主要是介绍一些 CV 领域的工作如何把 self-attention 和 CNN 相结合。
第五段,文章作者提到了另外一篇和本文比较相关的工作,叫做 image GPT (iGPT),这是一个生成模型,而且其中的 self-attention 是直接作用在低分辨率的图像像素上的,这个生成模型是用无监督的方式训练的,用这个模型提取的特征表达去做分类,在 ImageNet 上可以取得 72% 的识别率。
最后一段,就是大概讲了一下数据规模对模型表达能力的提升是有帮助的。有些工作研究了使用额外的数据能够帮助模型提升识别率。另外有些工作研究了随着数据规模的增加,模型的识别率也能得到一定的提升。
Method
接下来,我们来看文章的核心部分,也就是 Vision transformer 的模型架构到底长啥样,如果对 transformer 比较了解的话,可以看到 vision transformer 基本和 transformer 一样,然后文章作者也给出一个整体的框架图,如下图所示:
从这个框架图,我们就能了解整个的算法流程,首先是输入一张 RGB 三通道的彩色图,将这张图拆成若干个 16 × 16 16 \times 16 16×16 的 patch,这里是拆成了 9 宫格的形式,也就是假设有 9 个 patch,实际的 patch 数量是由输入的尺寸与 patch 尺寸共同决定的,如果输入是 224 × 224 224 \times 224 224×224 的话,那么实际就会有 ( 224 × 224 ) / ( 16 × 16 ) = 196 (224 \times 224) / (16 \times 16) = 196 (224×224)/(16×16)=196 个 patch。这些 patch 都会经过一个线性映射层,映射到另外一个维度,因为每个 patch 是 16 × 16 16 \times 16 16×16 的大小,然后每个 patch 是 3 个通道,所以每个patch 拉伸成 1-D 向量的话,就变成了 $16 \times 16 \times 3 = 768 $ 维的向量,768 维的向量通过线性映射层,映射成一个维度为 D 的向量。然后这个维度为 D 的向量,可以认为是 patch embedding 得到的输出,后面的处理都是处理维度为 D 的向量。
然后作者也提到说,他们参考了 BERT 这篇文章的处理方式,在整个 patch embedding 的最前面,还插入了一个 class token,专门用于分类的特征表达,这个 class token 的特征维度也是 D,所以最终进入 transformer 的序列长度可以认为是 196 + 1 = 197 196+1=197 196+1=197,因为 attention 机制是一个全局的相关运算,所以文章作者认为这个 class token 的特征表达最后是会融合所有图像 patch 的信息的。这个 class token 通过 transformer 编码器之后,会得到一个输出,这个输出作为整个图像 patch 序列的特征表达,送入一个 MLP 进行最后的分类运算。文章作者这里也提到说,在预训练的时候,这个分类的 MLP 是带一个隐含层的,在进行任务微调的时候,是不带隐含层的。
接下来,作者介绍了一下位置编码,这里作者也是借鉴了 BERT 的处理方式,将位置编码表示成可以学习的 1-D 的位置编码,作者也说虽然可以用 2D 的位置编码,但是两者的最终效果没有什么差异,所以本文还是用 1-D 的位置编码。
然后作者将整个 transformer block 的运算流程介绍了一下,其实从框架示意图的右边部分也能清晰地了解整个运算过程。从 patch embedding 得到的向量,先做一个 layer-norm,然后送入多头自注意力模块进行计算,这个模块的输出会进行残差的连接,然后再经过一个 layer norm,然后再经过一个 MLP,这样的过程重复 L 个 block,最后把 class token 对应的输出送入分类 MLP 做最后的分类。
-
Inductive bias, 接下来作者也介绍了一下 vision transformer 的归纳偏置,相比 CNN,vision transformer 的归纳编制是很少的。CNN 的归纳偏置包括局部性以及平移不变性。而在 ViT 里,只有 MLP 有这样的归纳编制,attention 本身是一个全局的运算机制。而 2D 的图像结构或者相对位置信息,只有在拆分图像 patch 的时候会用到。
-
Hybrid Architecture,作者也提到了 CNN 结构与 transformer 的混合,因为输入的图像 patch,其实也可以换成 feature map,所以一种方式就是在前端用 CNN 结构,提取 feature map,然后将提取的 feature map 看做图像 patch,将这些 feature map 最后输入后端的编码器。
最后作者大概介绍了一下 finetune 与高分辨率图的处理。因为 ViT 的最佳使用方式是先在一个大规模的数据集上做预训练,然后再在特定的任务上做微调,微调的时候,需要把 MLP 的分类头替换成对应的类别数量。然后作者也提到说,一般微调的时候,如果处理更高分辨率的图像,效果会更好。然后作者接下来大概解释了一下说,处理高分辨率的图像的时候,图像的 patch size 还是可以与预训练的时候一样,这样就会让图像的 patch 数变多,也就是图像的 patch 序列会变长,但是这个不会影响 self-attention 的计算,不过会影响之前预训练时候的位置编码特征,因为预训练是好的位置编码是基于一定的长度进行学习的,现在如果需要改变序列长度,可能让之前学习到的位置编码特征失效。文章作者这里提出了一种插值的方式来解决这个长度不一致的问题。根据预训练时候学习到的位置编码信息以及图像 patch 在序列中的位置,插值出新增的序列位置。
- 参考
https://www.bilibili.com/video/BV15P4y137jb/?spm_id_from=333.788&vd_source=bb80399e033aacf33a21a9f9864c6086