ViT论文逐段精读【论文精读】
By 跟李沐学AI
Summary
Topics Covered
- ViT终结CNN统治地位
- 图片拆成16x16图像单词
- ViT缺少归纳偏置需大数据
- 自注意力学到全局距离概念
Full Transcript
{沐神AI字幕组} 如果说在过去的一年中在计算机视觉领域 {制作:Reza/Keii 校验:Keii/Reza} 哪个工作的影响力最大 那应该非Vision Transformer莫属了 因为他挑战了 自从2012年 Alexnet 提出以来 卷积神经网络 在计算机视觉领域里绝对统治的地位 他的结论就是说呢 如果在足够多的数据上去做预训练 那我们也可以不需要卷积神经网络 直接用一个从自然语言处理那边 搬过来的标准的Transformer
也能把视觉问题解决得很好 而且Vision Transformer 不光是在视觉领域挖了一个大坑 因为他打破了 cv 和 nlp 在模型上的这个壁垒 所以在多模态领域也挖了一个大坑 于是在短短的一年之内 各种基于Vision Transformer的工作层出不穷 公开的论文应该已经有上百篇了 有把它扩展到别的任务的 有对模型本身进行改进的 有对它进行分析的 还有对目标
函数或者训练方式进行改进的 基本上是可以说 开启了 cv 的一个新时代 那么Vision Transformer到底效果有多好呢 我们可以先来 看一下 paperwithcode的这个网站 这个网站就是说 如果你想知道 现在某个领域 或者某个数据集 表现最好的一些方法有哪些 你就可以来查一下 我们先来看 图像分类在ImageNet的这个数据集上 排名靠前的呢 全都是基于Vision Transformer
那如果我们换到目标检测这个任务 在 coco 这个数据集上呢 我们可以看到 排名前几的 都是基于 Swin Transformer 的 Swin Transformer 呢是 今年 ICCV 21的最佳论文 你可以 把它想象成是一个多尺度的 Vit(Vision Transformer) 当然还有很多领域了 语义分割 实例分割 视频 医疗 遥感 基本上可以说Vision Transformer把整个 视觉领域里所有的任务都刷了个遍
那我们今天要读Vision Transformer这篇论文 也不光是因为他效果这么炸裂啊 还是因为他有很多 跟 cnn 很不一样的特性 我们可以先来看一下这篇论文啊 这篇论文的题目叫做Vision Transformer 一些有趣的特性 我们可以来看他的图1 他的图1里举了一些例子 就是说在卷积神经网络 cnn 上工作的不太好 但是用Vision Transformer 都能处理很好的例子 比如说第一个就是遮挡
那在这么严重的遮挡情况下呢 不光是卷积神经网络 其实就是 我也很难看得出其中有一只鸟 第二个例子呢 就是数据分布上有所偏移 在这里就是对图片做了一次 纹理去除的操作 所以说导致图片看起来非常魔幻 我也很难看出来其中到底是什么物体 第三个就是在鸟头的位置 加了一个对抗性的 patch 第四个呢就是说把图片 打散了以后做排列组合
所以说卷积神经网络也是很难去 判断这到底是一个什么物体的 但所有这些例子呢 Vision Transformer都能处理得很好 所以说鉴于Vision Transformer效果这么好 而且他还有这么多有趣的特性 跟卷积神经网络如此不一样 那所以我们今天就来精读一下 这篇Vision Transformer 的论文 那我们先来看一下题目啊 题目是说一张图片等价于很多16x16大小的单词
那为什么是16x16 而且为什么是单词呢 其实他是说 把这个图片看作是很多很多的 patch 就假如说我们把这个图片 然后打成这种方格的形式 每一个方格的大小都是16x16 那这个图片 其实就相当于是很多 16x16大小的这个 patch 组成的一个整体 接下来第二句是 transformer 去做大规模的图像识别 作者团队呢来自 google research google brain team
好 接下来我们看一下摘要 摘要是说 虽然说现在Vision Transformer 已经是 nlp 领域啊 自然语言处理领域里的一个标准啊 我们也知道就 BERT model 啊 GPT 3 然后或者是T5模型 但是呢用 transformer 来做 cv 还是很有限的 在视觉里呢 这个自注意力 要么是跟卷积神经网络一起用 要么就是说去把某一些
卷积神经网络里的卷积 替换成自注意力 但是呢还是保持整体的这个结构不变 他说的这一整体结构呢是指 比如说我们有一个残差网络 res50 (ResNet50) 还有四个 stage res 2 res 3 res 4 res 5 那他就说这其实这个 stage 是不变 他只是去取代每一个 stage 每一个 block 的这个操作 而这篇文章呢 就证明了 这种对于卷积神经网络的依赖呢 是完全不必要的
一个纯的Vision Transformer 直接作用于一系列图像块的时候呢 他也是可以在图像分类这个任务上 表现得非常好的 尤其是当 在你在大规模的数据及去做预训练 然后又迁移到 中小型数据及使用呢 这个Vision Transformer 能获得跟最好的卷积神经网络 相媲美的结果 那这里呢 把ImageNet CIFAR-100, VATB 当做中小型数据集 其实ImageNet 对于很多人来说
都已经是很大的数据集了 然后摘要的最后一句话呢 还指出了另外一个好处 他说 Transformer需要更少的这个训练资源 你乍一听 觉得这真的很好啊 正愁手上两块卡或者四块卡训练不动 大模型呢 就能训练的模型 而且表现还这么好 但其实你想多了 作者这里指着少的训练资源呢 是指2,500天 TPUv3的天数 他说的少了
只是跟更耗卡的那些模型去做对比 这个怎么说呢 还是比较讽刺的啊 就跟某人说我先定一个小目标 先挣它一个亿 那接下来我们来看一下引言啊 引用说 自注意力机制的这个网络 尤其是Transformer 已经是自然语言处理里的必选模型了 现在比较主流的方式呢 就是先去一个大规模的数据集上 去做预训练 然后再在一些特定领域的小数据集上
去做微调 那其实这个就是要BERT 这篇paper里提出来的 接下来说呢 多亏了Transformer的计算高效性 和这个可扩展性 现在已经可以训练超过1,000亿 参数的模型了 啊比如说像GPT3 然后最后一句话呢 他是说 随着你的这个模型和数据级的增长呢 我们还没有看到任何性能饱和的现象 这个就很有意思了因为我们知道 很多时候不是 你一味的扩大数据集
或者说扩大你的模型 就能获得更好的效果的 尤其是当扩大模型的时候 很容易碰到就是过拟合的问题 那对于Transformer来说 好像目前还没有观测到这个瓶颈啊 比如说最近微软和 英伟达又联合推出了一个 超级大的语言生成模型 叫Megatron-Turing 他已经有5,300亿的参数了 然后还能在各个任务上 继续大幅度提升性能 没有任何性能饱和的现象
那在继续往下读引言之前呢 我想先说一下把 transformer 用到 视觉问题上的一些难处 我们先来回顾一下 transformer 啊 假如说 我们有一个 transformer 的encoder 我们输入呢是有一些元素 在这里 假如说是在自然语言处理呢 这些就是一个句子里的一个一个的单词 输出了也是一些元素 Transformer里 最主要的操作呢就是自注意力操作 自注意力操作呢 就是说
每个元素都要跟每个元素去做互动 是两两互相的 然后算得一个Attention 就是算得一个自注意力的图 然后用这个自注意力的图去做加权平均 然后最后得到这个输出 因为在做自注意力的时候呢 我们是两两相互的 就是说这个计算复杂度呢 是跟这个序列的长度乘乘三倍的 目前一般在自然语言处理呢 就是说 现在硬件能支持的这个序列长度呢
一般也就是几百或者上千 比如说在BERT里 也就是512的这个序列长度 那我们现在换到视觉领域 我们就是想用 Transformer的话 首先第一个要解决的问题就是 如何把一个2d的图片 变成一个1d的序列 或者说变成一个集合 那最直观的方式就是说 我们把每个像素点 当成这边的这种元素 然后直接把2d的图片拉直 然后把这扔到Transformer里 然后自己跟自己学去就好了
但是想法很美好 实现起来复杂度太高 一般来说呢 在视觉里面 我们训练分类任务的时候呢 这个图片的输入大小 大概是224x224 这么大 那如果把图片里的每一个像素点 都直接当成这里的元素来看待呢 那其实他的序列长度呢 就不是512了 那他的序列长度就是 224x224=50176
因为我们一共就有这么多像素点吧 一共有50,000个像素点 所以这就是序列的长度 那这个序列长度50,000呢 其实也就意味着相当是 BRET 序列长度 512x100倍 所以这个复杂度是相当可怕的 然后呢这还只是分类任务啊 他的图片大小就24x24 这么大 那对于检测或者分割这些任务呢 现在很多模型的输入呢 都已经是变成600x600
或者800x800或者更大了 那这个计算复杂度就更是高不可攀了 所以说我们现在回到引言第二段 第二段就说呢 所以说在视觉邻域 卷积神经网络还是占主导地位的 像Alexnet 或者 ResNet 但是呢 transformer 在 nlp 领域又这么火 自注意力又这么香 那我计算机视觉 那就是想用一下自注意力怎么办 所以说呢很多工作就是想
怎么能把自注意力用到视觉里来呢 一些工作呢就是说 去把这个 卷积神经网络和自注意力混到一起用 另外一些工作呢就是说 整个把卷积神经都换掉了 然后就全用自注意力 这些方法呢其实都在干一个事 就说你不是说序列长度太长 所以导致没办法把 transformer 用到视觉里来吗 那我就想办法就降低这个序列长度 那比如说像这篇论文
就是 CVPR 18 Local Network 他就说既然用这个像素点当输入 导致序列长度太长的话 我们就不用图片当这transformer的 直接输入 我们把网络中间的这个特征图 当做transformer的输入 那大家都知道 假如说我们有残差网络 res50 那其实在他最后一个 stage 到res4的时候呢 他的feature map size 呢 其实就只有14*14 那么大
那14*14的话 你把他拉平 其实也就只有196个元素 意思就是说这个序列长度呢 就只有196 这个呢就是可以接受的范围之内了 所以他就用过这种方式 用特征图 当做 transformer 输入的方式 去降低这个序列长度 那像他说的第二个方向呢 他其实举了两个例子 一个叫做 Stand-Alone Attention 另外一个是 Axial Attention 就是一个是孤立自注意力
一个是轴注意力 那对于这个孤立自注意力 他做的什么事呢 他意思是说 你这个复杂度高是来源于你用整张图 那如果我现在不用整张图了 我就用一个 local 的一个 window 就我就用一个局部的小窗口呢 那这个复杂度就是你可以控制 你可以通过控制这个窗口的大小 来让这个计算 复杂度在你可接受的范围之内 那这个就有点相当于回到卷积 那一套操作
因为卷积也是在一个局部的 窗口里做的 对于这个轴自注意力工作 他的意思是说图片的复杂度高 是因为他的序列长度是 N = H x W 他是由2d的矩阵 那我们能不能把图片这个2d矩阵 拆分成两个1d的 向量呢 所以他们就是先在高度这个dimension身上 去做一次 self-attention 就做一个自注意力 然后他们 再去在这个
宽度这个dimension上再去做一次自注意力 相当于他把一个 在2d矩阵上进行的自注意力操作呢 变成了两个1d的 顺序的操作 这样这个计算复杂度就大幅降低了 然后Vision Transformer的 作者又说这些后一种方式呢 就是说这个 完全 用自注意力把卷积操作的这一类工作呢 他们虽然理论上是非常高效的 但事实上呢
因为他们的这个自注意力操作 都是一些比较特殊的自注意力操作 所以说呢 没有在现在的这个硬件上呢去加速 所以就会导致你很难去把它 训练一个大模型 所以说截止到目前为止呢 像这种Stand-Alone Attenion或者这个 Axial Attention他的模型都还没有太大 就是跟这种百亿千亿级别的大Transformer模型比呢 还是差的很远啊 因此啊最后一句话就说 在大规模的图像识别上呢
这个传统的残差网络呢 还是效果最好的 那介绍完之前的工作呢 接下来就该讲Vision Transformer 这篇 paper 到底做了什么事了 所以我们可以看到 自注意力 早已经在计算机视觉里有所应用 而且甚至已经有完全用自制力去 取代卷积操作的工作了 所以这篇论文呢 他就换了个角度去讲故事 他说他们呢 是被Transformer在NLP领域里这个 可扩展性
所启发他们想做的呢就是 直接应用于一个标准的Transformer 直接作用于图片 尽量做少的修改 就是不做任何针对视觉任务的 特定的改变 看看这样的Transformer呢 能不能在视觉领域里 扩展得很大很好 如果直接用Transformer呢 那老问题又回来了 这个这么长的序列长度该怎么办 所以Vision Transformer是怎么处理的呢 Vision Transformer是像我们刚才讲的一样
他把一个图片呢打成了很多 patch 每一个patch呢就是16乘16 我们来看 假如说这个图片的大小是224x224 那刚开始我们算呢 这个 sequence length呢 是224乘224 等于50176 那现在如果我们换成 patch 就是这一个 patch 相当于是一个元素呢 那有效的长宽又会是多少呢 那比如说现在这个宽度
现在这个宽度就变成了24 除以16 其实就相当是14了 同样的高度呢也就是14 所以说这样的话呢 最后的这个序列长度呢 就变成了14x14x196 意思就是说现在这张图片呢 就只有196个元素 那196 对于Transformer来说呢 还是可以 接受的这个序列程度 然后呢我们把这里的每一个 patch 呢
当做一个元素 然后通过一个这个 fc layer 就会得到一个 linear embedding 然后这些呢就会当做输入传给Transformer 这个时候呢 你其实可以很容易的看出来 一个图片呢 就已经变成一个一个 的这样的图片块了 然后你可以把这些的图片块呢 当成是像NLP里的那些单词 这一个句子有多少词 那就相当是一个图片 现在有多少个 patch 这就是他题目的意义
一个图片等价于 很多16乘16的单词 然后最后一句话呢 他说他说我们训练这个Vision Transformer呢 是用的有监督的训练啊 为什么要突出啊有监督呢 因为对于 nlp 那边来说的话 Transformer 基本上 都是用无监督的方式去训练的 要么是用language modeling 要么是用mask language modeling 总之都是无监督的训练方式 但是对于视觉来说呢 大部分的基线(baseline)网络 还都是用这个
有监督的训练方式去训练 走到这呢我们可以看出来 这个Vision Transformer这篇 paper 呢 真的是把 视觉当成自然语言处理的任务去做 尤其是中间的这个模型呢 他就是用了一个Transformer encoder 跟BERT是完全一样 那如果你已经听过沐神 讲解BERT这篇论文的 那其实Vision Transformer这篇论文对你而言 没有任何技术难点 这篇论文其实就是想告诉你 用这么简洁的一套框架啊
Transformer也能在视觉里起到很好的效果 那其实大家就会很好奇啊 这么简单的做法 之前难道就没有人想过这么做吗 那其实肯定是有人这么做了 那其实Vision Transformer这篇论文在 相关工作里已经介绍过 他说跟他们这篇工作最像的呢 其实是一篇 ICLR 2020的paper 那篇论文呢 是从这个 输入图片里去抽这个2x2的图片patch
为什么是2x2呢 因为那篇论文的作者呢只在CIFAR-10 这个数据集上去做了实验 那CIFAR-10的那些图片呢 都是32x32的 所以说 你只需要抽2x2的patch就够了 如果你抽16x16那就太大 一旦抽好这个patch以后呢 然后他们就在上面做 self-attention 所以说你你一听 那其实这个不就是Vision Transformer吗 那确实是 从技术上而言 他就是Vision Transformer
但是呢 Vision Transformer的作者告诉你说 我们的区别在哪呢 我们的工作就是证明了 如果你在大规模的数据集上 去做这个预训练的话 就跟NLP那边一样 在大规模的语料库上去做预训练 那么我们就能让一个标准的Transformer 就是不用在视觉上做任何的更改 或者特殊的改动 就能取得 比现在最好的卷积神经网络还好 或者差不多的结果啊 同时他们还指出
说之前的这个ICLR的这篇论文呢 他们用的是很小的patch 是2x2的 所以让他们的模型呢只能处理那些 小的图片 而Vision Transformer呢 是可以handle medium-resolution 也就是224这种的图片 所以这篇文章的主要目的呢 就是来告诉你 Transformer在Vision 这边 能够扩展的有多好 这是在超级大数据集 和超级大模型的两方 加持下 Transformer 到底能不能取代卷积神经网络的地位
那我们回到引言啊 一般引言的最后呢 就是把你最想说的结论 或者最想表示的结果放出来 这样大家不用 看完整篇论文 就能知道你这篇论文的贡献 到底有多大 他说呢当在中型大小的数据集上 比如说ImageNet去训练的时候呢 如果不加比较强的约束 ViT的模型 其实跟同等大小的残差网络相比呢 其实是要弱的就是要弱几个点
那作者就得解释啊那他为什么弱啊 所以论文紧接着说 这个看起来不太好的结果呢 其实是可以预期的 为什么呢 因为 transformer 跟卷积神经网络相比 他缺少一些卷积神经网络 有的归纳偏置 这个归纳偏置 这个概念很有意思 他其实说的呢就是指一种先验知识 或者一种我们提前做好的假设 比如说呢对于卷积神经网络来说
我们常说的就有两个inductive bias 两个归纳偏置 一个呢叫做 locality 因为卷积神经网络 是以滑动窗口这种形式 是一点一点在图片上进行卷积的 所以他假设 图片上相邻的区域会有相邻的特征 那这个假设当然是非常合理的 比如说桌子和椅子呢 就大概率他经常就会在一起 靠的越近的东西呢 他的相关性就会越强 另外一个归纳偏置呢叫做平移等变性
也就是我们常说的 translation equivariance(平移同变性) 他的意思呢就是 如果你把它写成公式的话呢 其实是这样的 f(g(x)) = g(f(x)) 就是不论你先做 g 这个函数 还是先做 f 这个函数 最后的结果呢是不变的 这里你可以把 f 理解成是卷积 然后 g 呢可以理解成是平移这个操作 那意思就是说 无论你先做平移还是先做卷积
最后的结果是一样的 因为卷积神经网络里 这个卷积核就相当于是一个模板一样 像一个 template 一样 不论你这个图片同样的物体移到哪里 那只要是同样的输入进来 然后遇到了同样的卷积核 那他的输出永远是一样的 一旦卷积神经网络有了这两个 归纳偏置以后呢 他其实就有了很多先验信息 所以他就需要相对少的数据 去学一个比较好的模型 但是对于Transformer来说呢
他没有这些先验信息 所以说他所有的这些能力 对视觉世界的 感知呢全都需要从这些数据里自己学 为了验证这个假设呢 作者就在 更大的数据集上去做了预训练 这里的这个14M 1,400万的图片呢 就是ImageNet 22k数据集 这里的300M数据集呢 就是google他们自己的 JFT 300M数据 上了大数据以后呢果然这效果拔群 他们立马就发现
这个大规模的预训练呢 就比这个归纳偏置要好 Vision Transformer 只要在有这个足够的 数据去预训练的情况下呢 就能在 下游任务上获得很好的迁移学习效果 具体来说呢就是当 在ImageNet 21 k 上去训练 或者说在 这个 JFT 300M上 去训练的时候呢 vit 就能获得 跟现在最好的残差网络相近 或者说更好的结果啊
最后他还罗列了一些结果啊 比如说ImageNet 88.5 确实相当高 ImageNet-ReaL CIFAR-100 还有 VTAB 这些数据集 VTAB其实 也是这个作者团队 他们提出来的一个数据集 是融合了19个数据集 主要是用来检测一个模型 这个稳健性好不好的 所以从侧面也可以反映出呢 Vision Transformer的稳健性也是相当不错的 所以读到这样呢引言算是读完了 那引言还是写的非常简洁明了的
第一段先上来说 因为Transformer在 NLP 那边扩展的很好 越大的数据或者越大的模型 最后的performance就会一直上升 没有饱和的现象 那自然而然就会有一个问题 那如果把Transformer 用到视觉里来 是不是视觉的问题 也能获得大幅度的提升呢 第二段就开始讲前人的工作 因为这么好的方向不可能没人做过 所以一定要讲清楚 自己的工作 和前人的工作的区别在哪里
他说啊之前的工作呢 要么就是把卷积神经网络和自注意力合起来 要么就是用自注意力 去取代卷积神经网络 但是呢从来都没有工作 直接把Transformer用到视觉领域里来 而且也都没有获得很好的扩展效果 所以第三段他就讲Vision Transformer 就是用了一个标准的Transformer模型啊 只需要对图片做一下预处理 就是把图片打成块 然后送到Transforner里就可以了 别的什么改动都不需要
这样彻底可以把一个视觉问题 理解成是一个NLP问题 这样就CV和 NLP这两个领域 就大一统了 最后两段当然是卖一下结果了 只要在有足够多 数据区域训练的情况下 Vision Transformer 在很多数据集上取得很好的效果 那接下来我们按照沐神读论文的方式 先来看一下结论 结论里呢他上来没有任何花里胡哨 直接一句话就点明了 这篇 paper 在到底在干什么
直接拿NLP领域里 标准Transformer来做计算机视觉问题 然后他说 跟之前的那些工作就是用 自注意力的那些工作不一样的呢 除了在刚开始的抽图像块的时候 还有这个位置编码 用了一些图像特有的这个归纳偏置 如此之外呢 就再也没有引入任何图像特有的 归纳偏置了 这样的好处呢就是 我们不需要对Vision领域有什么了解
或者有什么domain knowledge(领域知识) 我们可以直接把这个图片呢 理解成为是一个序列的图像块 就跟一个句子里有很多单词一样 然后就可以直接呢 NLP里面一个标准的Transformer 来做图像分类 这个简单 然后呢扩展性很好的这个策略呢 当你跟大规模预训练结合起来的时候 工作得出奇的好 怎么个好法呢 就是说Vision Transformer 在很多这个图像 分类的这个benchmark 上呢
超过了之前最好的方法 而且还相对便宜 就训练起来还相对便宜 然后接下来第二段呢 他又写了一些目前还没有解决的问题 或者是对未来的一个展望吧 为什么要写这一段呢 其实是因为Vision Transformer这篇论文呢 属于是一个挖坑的论文 这挖坑呢你可以是挖一个新问题的坑 或者是挖一个新数据集的坑 那这篇论文呢 其实是挖了一个新模型的坑
又说如何能Transformer来做 cv 那所以很自然的第一个问题就是说 那Vision Transformer不能只做分类啊 那这个Vision Transformer 肯定还得去做这个分割和检测 对吧另外两个最主流的视觉任务啊 就是之前另外一篇很popular的工作 就是这个DETR DETR是去年啊 目标检测了一个力作 他现在是改变了整个目标检测 之前的框架 就是出框的这种方式啊
鉴于ViT和DETR而良好的表现呢 所以说他是拿Vision Transformer做视觉的 其他问题呢应该是没有问题的 而事实上呢也 正是如此 就 在 ViT 出来短短的一个半月之后呢 就在2020年12月 检测这块呢 就出来了一个工作叫做ViT-FRCNN 就已经把ViT用到detection上了 seqmentation 呢 也一样 同年12月
只有一篇SETR SETR的论文 把Vision Transformer用到分割里了 但这里我想说的是 大家的手速真的是太快了 因为虽然表面看起来 SERT这篇论文 是12月份才传到arXiv上的 但是他是CVPR2020的中稿论文 也就意味着他在11月15号的时候 就已经完成了论文的写作 并且投稿了 所以说啊 cv 圈这个卷的程度啊
已经不能用月来计算了 一定要用天来计算 而且紧接着三个月之后 Swin Transformer 横空出世 他把多尺度的这个设计呢 融合到了Transformer里面 所以说更加适合做视觉的问题了 真正证明了Transformer是能够当成一个 视觉领域一个通用的骨干网络的 另外一个未来工作方向呢 他就是说 要去探索一下这个自监督的预训练方案 那是因为在NLP领域
所有的这些大的Transformer 全都是用自监督的方式训练 一会我们在看实验的时候呢 也可以一起讨论一下之前NLP 包括Vision 里边是怎么做自监督预训练的 所以说呢Vision Transformer这篇论文呢 他也做了一些初始实验 他们证明了 就是说用这种自监督的训练方式呢 也是 ok 的 但是呢跟这个 有监督的训练比起来呢 还是有不小的差距的 最后呢作者还说 就说
继续把这个Vision Transformer变得更大 有可能会带来更好的结果 这个坑呢作者团队没有等别人去填 他想着 反正别人可能也没有这种计算资源 那我就来把这个坑填一填吧 所以说过了半年 同样的作者团队又出了一篇论文 叫 Scaling Vision Transformer 就是把Transformer变得很大 提出了一个ViT-G 然后就把ImageNet 分类的准确率刷到90以上了 所以说
这篇论文真的是一个很好的挖坑之作 他不光是给视觉挖了一个坑 就是从此以后 你可以用传送门来做所有 视觉的任务了 他同时还挖了一个更大的坑 就是在CV和NLP能够大一统之后 那是不是多模态的任务 就可以用一个Transformer去解决了呢 而事实上多模态那边的工作呢 最近一年也是井喷式的增长 由此可以看来 Vision Transformer这篇论文的影响力 还是非常巨大的
那我们现在回到相关工作 大家说了一下 Transformer在NLP领域的应用 他说啊 自从2017年这个Transformer提出来 去做这个机器翻译以后呢 基本上Transformer就是很多 NLP任务里表现最好的方法 现在大规模的这个 Transformer模型呢 一般都是先在一个大规模语料库上 去做预训练 然后再在这个目标任务上呢 去做一些细小的微调 这里面有两系列比较出名的工作 一个就是BERT
一个就是GPT BERT呢 是用了一个 denoising 自监督的方式其实就是完形填空 就是你有一个句子 然后你把其中某些词划掉 然后你先要把这些词 再 predict 出来 这个GPT呢 用的是 language modeling 去做自监督 language modeling 呢 是你已经有一个句子 然后我要去预测下一个词是什么 也就是 next word prediction 预测下一个词 因为这两个任务呢 其实都是我们人为定的
就说语料都在哪 句子就在哪是完整的 我们只是人为的去划掉其中某些部分 或者把最后的词拿掉 然后去做这种完形填空 或者预测下一个词 所以这叫自监督的训练方式 这下就开始讲自注意力在视觉里的应用 视觉里呢就是说如果你想 简单的使用一个自注意力 还用到这个图片上 最简单的方式就是说 你把每一个像素点当成是一个元素啊 你就去让他们两两去
做自注意力就好了 但是呢我们在引言里也说过 这个是平方复杂度 所以说是很难应用到真实的这个图片 输入尺寸上的 那像现在分类任务的224x224 一个Transformer都很难处理 那更别提 就我们人眼看的比较清晰的图 一般都是1 k 或者4 k 这种画质了 那序列长度都是上百万 直接在像素层面使用Transformer 肯定是不现实的
所以说呢如果你想用Transformer 那就一定得做一些这个近似 这里他就罗列一些例子啊 比如说这些工作呢 他们是说你的复杂度高 是因为你用了整张图 所以你的序列长度长 那我现在不用整张图 我就用这个 local neighborhood 啊 我就用一个 小窗口 制作这个自注意力 那序列长度不就大大降低了吗 那最后的这个计算复杂度 不也就降低了吗 那另外一条路呢就是用 Sparse
Transformer 这个顾名思义啊 就是说 我去只对一些稀疏的点去做自注意力 所以只是全局注意力的一个近似 还有一系列方法呢 就是说把这个自注意力 用到不同大小的这种 block 上 或者说在极端的情况下呢 就是直接走轴了 也就是我们刚才讲的轴注意力 就先在横轴上去做自注意力 然后再在纵轴上做自注意力 那这个序列长度也是大大减小的
然后他说啊 这些特制的自注意力结构 其实在计算机视觉上的结果都不错 就是表现是没问题 但是他需要很复杂的工程呢 去加速这个算子 虽然在 cpu 或者 gpu 上跑的很快 或者说让训练一个大模型成为可能 接下来这段 我们其实已经在引言里读过了 就是说跟他们工作最相似的呢 是一篇ICLR2020论文 Vision Transformer呢 就是在用了更大的 patch
和更多的数据集 去训练一个更好的 transformer 然后他说啊 在计算机视觉领域 肯定还有很多工作呢 是把这个卷积 神经网络和这个自注意力结合起来的 而这类工作呢是相当多的 而且基本涵盖了视觉里的很多任务 比如说这个检测啊 分类啊 然后这个视频 还有多模态啊 然后呢作者又说 还有一个工作跟他们的工作很相近 就叫image GPT 我们都知道啊
GPT呢是用在NLP里呢 是一个生成性的模型 那image GPT呢 同样也是一个生成性模型 也是用无监督的方式去训练的 他跟Vision Transformer 有什么相近的地方呢 是因为他也用了Transformer 最后这个 iGPT 能达到一个什么效果 如果我们拿训练好的模型去做一个微调 或者说就把他当成一个特征提取器呢 我们会发现他ImageNet的上 最高这个分类准确率 也只能到72
那像这篇 Vision Transformer 最后的结果已经有88.5了 所以说是远高于这个72的结果 但这个结果也是最近一篇论文 MAE(何凯明) Masked Autoencoders Are Scalable Vision Learners 爆火的原因 因为在BEiT BERT Pre-Training of Image Transformer 或者MAE这类工作之前 生成是网络在视觉领域很多任务上 是没法跟判别式网络比的 判别式网络 往往要比生成式网络的结果要高很多 但是 MAE 就做到了 就在ImageNet-1k 这个数据集上去做训练啊
就用一个生成式的模型 比之前判别式模型的效果要好 而且不光是在分类任务上 最近他们还研究了一下 迁移学习的效果 就是在目标检测上效果也非常好 最后呢作者又说Vision Transformer 其实还跟另外一系列工作是有关系的 就是用 比ImagNet还大的数据集 去做这个预训练 这种使用额外数据的方式呢 一般能够帮助你达到特别好的效果啊 比如说之前2017的这篇论文
其实也就是介绍 JFT300M的 这个数据集的论文呢 研究了就是卷积神经网络的效果 是怎么随着数据集的增大 而提高的 还有一些论文呢 是研究了当你在更大的数据集上 比如说ImageNet-21 k 和 JFT300M 去做预训练的时候 这个迁移学习的效果会怎么样 就是当你迁移到ImageNet 或者CIFAR-100上的效果会如何 在这篇论文里呢 Vision Transformer上说我们也是
聚焦于最后两个数据集 就是这个ImageNet-21k 和 JFT300M 但是呢 我们并不是训一个残差网络 我们是去训Transformer 那其实这个相关工作写的非常彻底的 而且他列举了很多 跟他们工作最相近的啊 比如说这篇ICLR2020的论文 还有这个 iGPT 还有之前研究大数据集的 比如说BIT 其实写相关工作这个章节呢
就是要让读者知道在你的工作之前 别人做了哪些工作 你跟他们的区别在哪里 这个只要写清楚了 其实是对你非常有利的 并不会因此降低论文的这个创新性 反而会让整个文章变得更加简单易懂 接下来 我们就一起来读一下这个文章的第三节 这个主体部分 那么说啊在模型的设计上 是尽可能的按照 这个最原始的这个Transformer里 来做的 这样一个好处 就是说呢
我们可以直接把 NLP那边已经 成功的 Transformer的架构 直接拿过来用 我们就不用自己再去魔改模型了 而且因为Transformer 已经在NLP领域火了这么多年了 他有一些写得非常高效的一些实现 同样Vision Transformer 可以直接把他拿过来用 那接下来看3.1 他说模型的 一个总览图呢 画在图一里了 模型的总览图啊 其实对很多论文来说是非常重要的 画得好的模型总览图呢
能够让读者在不读论文的情况下 光看这张图 就能大概知道 你整篇论文在讲什么内容 Vision Transformer这张图呢 其实画得就很好 因为我们也可以看到啊 当别人在讲解Vision Transformer这篇论文 或者跟他对比的时候 就是直接把这个图1 直接就复制粘贴过去了 而不是说自己为了讲解的需要 还要再费尽心思再从头再画一个图 接下来 我们先大概过一下这个整体的流程 然后我们再具体的过一遍
整个网络的这个前向操作 这样对Vision Transformer的理解就更深刻了 首先呢给定一张图 他是先把这张图呢打成了这种 patch 比如说这里是把这个图打成了九宫格 然后他把这些 patch 呢 变成了一个序列 每个 patch 会通过一个叫线性的投射层的操作 得到一个特征 也就是这篇论文里说的 patch embedding 但我们大家都知道啊这个自注意力 是所有的元素之间两两去做这个交互
所以说他本身并不存在一个顺序问题 但是对于图片来说呢他是一个整体 这个九宫格是有自己的顺序的 比如说这图片就是 1 2 3 一直到第九张图片 还是有顺序的 如果这个顺序颠倒了呢 其实就不是原来这张图片了 那同样类似NLP那边呢 我们给这个 patch embedding加上了一个position embedding 就加上一个位置编码 一旦加上这个位置编码信息以后呢 这个整体的 token
就既包含了这个图片块 原本有的图像信息 又包含了这个图像块的所在位置信息 那一旦我们得到 这些一个一个的 token 那其实接下来就可能 NLP那边是完全一样了 我们直接把它 给这么一个Transformer encoder 然后Transformer encoder呢 就会同样的反馈给我们很多输出 那这里问题又来了 那这么多输出 我们该拿哪个输出去做最后的分类呢 所以说再次借鉴BERT BERT那边呢
有这个叫 extra learnable embedding 也就是一个特殊字符叫 cls 叫分类字符 同样的我们在这里 也加了这么一个特殊的字符 这里用新号代替 而且他也是 position embedding 他有位置信息的他永远是0 因为所有的token都在跟所有的token 做交互信息 所以他们相信呢 这个class embedding 能够从别的这些embedding里头 去学到有用的信息
从而我们只需要根据他的输出 做一个最后的判断就可以 那最后这个 MLP Head 其实就是一个通用的分类头了 最后用交叉熵函数去进行模型的训练 至于这个Transformer encoder 也是一个标准transformer 这篇论文也把具体的结构列在右边了 比如说当你有这些patch的时候呢 你先进来做一次 layer norm 然后再做 multi-head self-attention 然后再 layer norm 然后再做一个 MLP
这就是一个Transformer block 然后你可以把它叠加 L 次 啊就得到了你的Transformer Encoder 所以说整体上来看 Vision Transformer的架构还是相当简洁 它的特殊之处就在于如何把一个图片 变成这里的一系列的 token 我们接下来呢 可以具体按照论文中的文字 再把整个模型的前向过程走一遍 假如说啊我们有个图片 X 然后他的dimension呢 是224x224x3
如果我们这里使用16x16的这个 patch size 大小呢 那我们就会得到多少 token 呢 等于24平方除以16的平方 也就是196 就是14的平方 就我们一共会得到196个图像块 那每一个图像块的维度如何呢 其实就是16x16x3 也就是768 3就是RGB channel 所以呢我们就把原来这个图片
224x224x3 变成了一个有196个patch 每个patch的维度是768 那接下来这个线性投射层是什么呢 其实这个线性投射层呢 就是一个全连接层 文章后面呢是用大E这个符号呢 就代表这个全连接层的 这个全连接层的维度是多少呢 其实这个全连接层的维度呢 是768x768 这个768呢 也就是文章中一直说的那个D
当然这个D是可以变的 就如果你的Transformer变得更大了 那这个D也可以变得相应的更大 但是前面这个768 是从图像patch算来的 是16x16x3算来的 所以这个是不变的 那经过了这个线性投射 我们就得到我们的这个 patching embedding 那具体来说呢就是如果 XE =1 那在维度上呢 其实就可以理解成是196x768 然后又乘了个768x768的矩阵 然后这两个维度抵消掉
所以最后你得到的还是196x768 意思就是 我现在有196个 token 每个 token 向量的维度呢是768 那到现在呢 就其实已经 成功的把一个 Vision 的问题 变成了一个NLP 的问题 我的输入呢就是一系列 1d 的 token 而不再是一张2d的图了 那除了图像本身 带来的这些 token 以外呢 我们之前也说过 这里面要加一个额外的 cls token 就是一个特殊的字符
那这个特殊字符他只有一个token 他的维度也是768 这样方便 你可以和后面图像的信息呢直接 拼接起来 所以最后序列的长度就是整体 进入Transformer中的这个序列 长度呢其实是196 +1 就是197 乘以768了 这197呢 就是有196个图片 对应的 token 和一个那个特殊字符 cls token
最后呢我们还要加上这些位置编码信息 那位置编码呢刚才我们说 1 2 3 一直到9 其实这只是一个序号 而并不是我们真正使用的位置编码 因为我们不可能把这个1 2 3 4 5 6 这些数字 然后传给一个Transformer去学 具体的做法呢是我们有一个表啊 这个表的每一行呢 其实就代表了这里面的1 2 3 4这个序号 然后每一行呢就是一个向量
这个向量的维度是多少呢 跟这边是一样的 跟这边的D是一样的 是768 这个向量也是可以学的 然后我们把这个位置信息呢 加到这所有的这些的token里面 而注意这里面是加 而不是拼接 就不是 concatenation 是直接sum了 所以加完位置编码信息以后呢 这个序列还是197x768 那到此呢 我们就做完了整个 对图片的这个预处理
包括加上特殊的字符 c l s 和加上这个位置编码信息啊 也就是说我们对于Transformer 输入这块的 embedded patches 呢 就是197x768的一个tensor 这个tensor呢 先过一个 layer norm 出来 还是197x768 然后我们就要做这个多头注意力了 那多头注意力呢 这里就变成了三份 k q v
每一个都是197x768 197x768 这样的 那这里呢因为我们做的是多头自注意力 所以其实最后的这个维度呢 并不是768 假设说我们现在用的是Vision Transformer 的base版本 也就是说他用多头呢是用了12个头 那这个维度呢就变成了768 除以12也就等于64的维度 也就是说这里的 k q v呢 变成了197x64
197x64这样 但是有12个头 12个对应的 k q v 去做这个自注意力操作 最后呢再把这些 12个头的输出直接拼接起来 这样64拼接出来以后呢 又变成了768 所以多头注意力出来的结果 经过拼接呢 到这块还是197x768 然后再过一层 layer norm 还是197x768 然后再过一层 MLP
MLP 这里呢会把维度相对应的放大 一般呢是放大四倍 所以说就是197乘以3072 然后再把它缩小投射回去 然后再变成197乘768 就输出了 这个呢 就是一个Transformer block的前向传播的过程 所以说进去呢是197x768 出来呢还是197x768 这个序列的长度 和每个token对应的维度大小 都是一样的
所以说 你就可以在一个Transformer block上呢 不停的往上叠Transformer block 想加多少加多少 那最后呢 有 L 层这个Transformer block的模型呢 就是这个Transformer Encoder 也就是这里面这个Transformer Encoder的 其实到这里呢就已经把Vision Transformer 这整个的模型讲完了 我们再回到正文 再快速的把3.1过一遍看 有没有什么遗漏的 他说啊 标准的Transformer 是需要一系列这个1D的token呢 当做输入
那但是对于2 d 的图片怎么办呢 那我们就把这个图片呢 打成这么多的小 patch 具体有多少个 patch 呢 就是 N 等于这个 HW/P^2 那其实也就是我们之前算过的 24的平方 除以16的平方 也就是196 当然这个是对于patch size =16 而言了 如果你patch size变了就变成8啊 或者变成14 那对应在这里的这个序列长度呢 也会相应改变 他说啊这个Transformer从头到尾
都是用了这个 D 当做向量的长度的 也就是我们刚才说的那个768啊 所以就是从头到尾他的向量长度都是 768 这个维度是不变的 那为了和Transformer这个维度匹配上呢 所以说 我们的这个图像的 patch 的维度呢 也得是这个 D dimension也就是768 那具体怎么做呢 就是用一个 可以训练的 linear projection 也就是一个全连接层 从全连接层出来的这个东西呢
叫做 patch embedding 然后接着说为了最后的分类呢 我们借鉴了 BERT 里的这个 class token 一个特殊的 cls token 这个 token 是什么呢 是一个可以学习的特征 他呢跟图像的特征有同样的维度 就都是768 但他只有一个token 就是经过很多层的这个Transformer block 以后呢 我们把他这个输出 当成是整个Transformer的模型的输出 也就是当做整个图片的这个特征
那一旦有了这个图像特征了 后面就好做了 因为你卷积神经网络到这块也是有一个 图像的整体的特征 我们就在后面加一个这个 MLP的这个 分类图就可以了 然后对于位置编码信息呢 这篇文章就用的是标准的这个可以学习的 1D position embedding 也就是BERT里用的位置编码 那当然作者也尝试了别的编码形式了 就比如说因为你是做图片嘛 所以你对空间上的位置可能更敏感
你可能需要一个2D aware 就是能处理2D信息的一个 这个位置编码 那最后发现了这个结果其实都差不多 没什么区别 其实针对这个特殊的 class token 还有这个位置编码呢 作者们还做了详细的消融实验 因为对于 Vision Transformer 来说 怎么对图片进行预处理 还有怎么对图片最后的输出进行 后处理是很关键的 因为毕竟中间的这个模型 就是一个标准的transformer
没什么好讲的 所以我们现在就来看一下这些 消融实验 首先我们说一下这个 class token 他说 因为在这篇论文中呢 我们想跟原始的这个transformer保持尽可能的一致 所以说呢我们也用了这个class token 因为这个class token呢 在NLP那边的分类任务里也是用的 在那边呢 也是当做一个全局的 对句子理解的一个 特征那在这里呢 我们就是把它当做一个图像的整体特征
那拿到这个token的输出以后呢 我们就在后面接一个这个 mlp mlp 里面呢 是用 tanh 当做一个非线性的激活函数 去做这个分类的预测 但是这个 class token 的设计呢 是完全从 nlp 里边借鉴过来的 之前在视觉领域呢 我们其实不是这么做的 那比如说我们现在有一个残差网络 一个 Res50 我们现在有这个前面的几个 block res 2 res 3 res 4 res 5对吧 假如说是2345
那在最后这个 stage 出来的呢 是一个 feature map 这个 feature map 呢 是14乘14这么大 然后在这个 feature map 之上呢 我们其实是做了一步这个 gap 的操作 也就他这里说的 global average pulling 就是一个全局的平均池化 池化以后的特征呢 其实就已经拉直了 就是一个向量了 那这个时候 我们就可以把这个向量 理解成是一个全局的 对于这个图片的一个特征 然后我们就拿这个特征去做分类
那现在对于transformer来说 如果你有一个transformer的model 然后你进去呢有这么多 n 个元素 而你出来呢也是有这么多 n 个元素 我们为什么不能 直接在这 n 个输出上 去做一个这个 globel average pulling 然后得到一个最后的特征呢 我们为什么非得在这个前面呢 加一个 class token 然后最后用 class token 去做输出 然后去做分类呢 那其实通过实验呢 作者最后的结论是说
其实这两种方式都可以 就 你也可以去做这个 global average pulling 那得到一个全局的特征然后去做分类 或者你用什么一个 class token 去做vision transformer这篇论文 所有的实验 都是用 class token 去做的 他主要的目的呢 就是跟 原始的这个transformer而保持尽可能的一致 就像他这里说的 stay as close as possible 我不想让你觉得他这个效果好 有可能是因为某些 trick 带来的 或者是某些针对 cv 的改动而带来的
那就是想告诉你一个标准的transformer 照样能做视觉 那我们往下拉看这张图 这张图里呢 其实这个绿线呢 就代表这个全局平均池化 就是原来vision 领域里怎么做的 然后这个 class token 呢 就代表是 nlp 那边怎么做 就这条蓝线 那我们可以看到呢 其实最后呢 这个绿线和蓝线的效果是一样的 但是作者指出呢 这个绿线和蓝线用的这个学习率是不一样的
就是你得好好调参 如果你不好好调餐呢 比如说直接 把这个 class token 用的这个 learning rate 直接 拿过来去做这个全局平均池化呢 那他效果是非常差的 只有这么多可能大概低了 五六个点吧 所以说呢有的时候也不是你的 idea 不work 可能主要还是参没调好 炼丹技术还是要过硬 我们再来看一下位置编码 他这里也做了很多这个消融实验 主要的呢其实就三种 1D的 2D的
或者是这个 relative positional embedding 1D的呢 其实也就是 nlp 那边常用的一个 位置编码 也就是这篇文章 从头到尾都在使用的位置编码 2D的这个位置编码呢 他是这个意思就是原来你1D那边呢 比如说你把一个图片打成九宫格 我们之前有的是123 直到9那我们现在 与其用这种方式去表示那些图像块呢 我们用这种方式 就是11 12 13
21 22 23 31 32 33 去表示这么一个九宫格的图片 那这样是不是跟视觉问题就更贴近呢 因为他有了这个整体的这个 structure 信息 那具体是怎么做呢 就是说假如说原来的这种1D的这种 位置编码他的这个 维度是d 那现因为横坐标 纵坐标你都得需要去表示 那对于横坐标来说呢 你有一个d/2的维度 那对于纵坐标来说一样
你也有一个d/2的维度 就是你分别有这么一个 d/2的这个向量 去表述这个横坐标 然后还有一个d/2的向量呢去描述这个纵坐标 最后你把这两个d/2的向量 拼接在一起 concat在一起就又得到了一个 长度为 d 的这个向量 我们把这个向量呢叫做2d 的位置编码 那第三种 这个相对位置编码是什么意思呢 就是说假如我们讲还是1 d 的情况
那这个patch和这个patch的距离 既可以用绝对距离来表示 又可以用 他俩之间的这个相对距离来表示 那比如说他们现在之间 差了7个单位距离 也就是他这里说的这个 offset 这样呢也可以认为是一种方式 就表示各个这个图像块 之间的这个位置信息 但是呢这个消融实验最后的结果也是 无所谓 那我们现在来看他这个表8 表8里说 如果你不加任何的这个位置编码呢
那效果肯定是很差的 这个61其实也不算很差 transformer根本没有感知 这个图片位置的能力 在没有位置编码的情况下 他还能达到这个61的效果 其实已经相当不错了 然后如果你来对比这个1D 2D和这个 relative 三种位置编码的形式呢 你会发现 所有的这个 performance 呢 都是64 64 64 没有任何区别 这个现象其实还比较奇怪 这作者在后面呢
也给出了一个他们认为比较 合理的解释 就是说呢他们这个vision transformer呢 是直接在这个图形块上去做的 而不是在原来的这个像素块上去做 因为这个图像块很小 比如说14x14 而不是全局的那种224x224 所以你去排列组合这种小块 或者你想知道这些小 块之间相对的位置信息呢 还是比较容易的 所以你用什么位置编码都无所谓 那么现在从附录回到正文
刚才看了那些消融实验以后呢 我们也可以看出来 其实这个 class token 呢 也可以用这个 global average pooling 去替换 包括最后的这个 1 d 的 positional embedding 呢 也可以用2 d 的 或者相对的这种位置编码去替换 但是为了尽 可能的对这个标准的transformer 不做太多改动 所以说本文中vision transformer 还是用了这个 class token 而且还是用了这个 1d 的位置编码 然后接下来就开始说 这个transformer encoder了
那其实transformer在现在来看呢 已经是一个非常标准的操作了 那他这里对transformer 或者说这个多头自注意力的解释呢 都没有放在正文里 直接就放在这个附录里了 就跟你看现在卷积神经网络的论文 也不会有人把卷积写在正文里 然后作者呢 用公式把整体的这个过程呢 总结了一下 就说 刚开始你这个 x 1 p x 2 p x n p 呢 其实就是这些图像块的 patch 然后一共有 n 个 patch
所以说123一直到 n 那每个 patch 呢 先去跟这个 linear projection 也就是那个全连接层去做转换 从而得到这个 patching embedding 得到这些 patching embedding之后呢 我们在它前面 拼接一个这个 class embedding 因为我们需要用它去做最后的输出 而一旦得到 所有的这个 tokens 呢 我们需要对这些 token 进行位置编码 所以说我们把这个位置编码信息 加进去 这个呢就是对于transformer的输入了
z 0就是这个输入 接下来呢这块就是一个循环 对于每一个transformer block 来说呢 那里面都有两个操作 一个是多头自注意力 一个是 mlp 然后在做这两个操作之前呢 我们都要先过layer norm 然后每一层出来的结果呢 都要再去有一个残差连接 所以说这个 zl'呢就是每一个 多头自注意力出来的结果 这个 zl 呢 就是每一个transformer block 整体做完以后出来的结果
然后我们这个 l 层循环完了之后呢 我们把 zl 就是最后一层的那个输出的 zl 0也就是这个 class token 所对应的输出呢 当做整体图像的一个特征 从而去做最后的这个分类任务 那所以到这呢 对vision transformer的文字描述也结束了 所以他就补了一些分析 比如说这个归纳偏置 然而又提出了一个模型的变体 叫做这个混合模型 最后在3.2里又讲了讲
当你遇到更大尺寸图片的时候 你该怎么去做微调 那么先来看归纳偏置 他说vision transformer 比 cnn 而言呢 要少很多这种图像特有的归纳偏置 那比如说在 cnn 里呢这个 locality 还有这个 translation equivariance 就是这个局部性 这个平移等变性 是在模型的每一层都有所体现的 这个先验知识呢 相当于贯穿整个模型始终 但是对于 vit 来说呢
这个 mlp 这个类型呢 是局部而且平移等变性的 但是自注意力层呢 绝对是全局的 这种图片2 d 的信息呢 基本 vit没怎么用 其实也就是刚开始把图片 切成 patch 的时候 还有就是加这个位置编码的时候用了 而除此之外 就再也没有用任何针对视觉问题 就针对图像的这个归纳偏置了 而且这个位置编码呢 说白了其实也是刚开始随机初始化的
并没有携带任何2D的信息 所有的关于这个图像块 之间的这个距离信息呢 这个场景信息呢 都得重头学 所以他这里呢 也就是先给后面的结果做了个铺垫 就是说我vision transformer 没有用太多的这个归纳偏置 所以说在中 小数据集上进行一训练的时候呢 效果不如卷积神经网络是可以理解 那讲完这个呢很自然呢大家就会想 今天transformer 这个全局建模的能力比较强 然后卷积神经网络呢
又比较 data efficient 就不用那么多的训练数据 那我们是不是可以搞一个这个 混合的网络呢 就是说前面是卷积神经网络 后面是transformer了 在他这里呢也做了对应的实验 具体来说呢就是原来你有一个图片 你把它打成 patch 比如说打成16乘16的patch 然后你得到了196个元素 然后这196个元素呢 去和这个全连接层去做一次操作 最后得到这个patch embedding
那现在呢我们不把图片打成块了 我们去按照卷积神经网络那样去处理 图片就是一整张图进来 然后我们把它给一个 cnn 比如说一个残差网络 res 50 那他最后的那个特征图出来呢 是一个14*14的特征图 那这个特征图呢 刚好你把它拉直了以后呢 他也是196个元素 然后你用这 新得到的这196个元素呢 去跟这个 全连接层去做操作
得到新的这种 patch embedding 那其实呢 这里就是两种不同的 对图片进行预处理的方式 那一种呢就是直接把它打成 patch 很简单直接过全连接层 另外一种呢就是还要再过一个 cnn 得到这么196个序列长度 但是呢这得到的这个序列长度 都是196 所以说后续的操作全都是一样的了 都是直接扔给一个transformer 然后最后做分类 然后我们再来看3.2
为什么要把这个微调 放在这个3乘3呢 因为之前有工作说呢 如果你在微调的时候呢 能用比较大的这个图像尺寸 不是用224乘224了 而是用256乘256 甚至更大320乘320 那你就会得到更好的结果 那vision transformer肯定也不会放弃这个刷脸的机会 然后他也想在 更大的这个尺寸上去做微调 但是呢 用一个预训练好的vision transformer
其实是不太好去调整这个输入尺寸的 他这里说 当你用更大尺寸的图片的时候呢 如果我们把 patch size 保持一样 就还用16*16 但是你图片扩大了 那很显然 你这个序列长度就增长了对吧 你原来的这个序列长度呢是n是 224的平方除以十六的平方 假如说你现在换成了320的图片 那就是320的平方除以16的平方
那对 序列长度肯定是增加了 所以说transformer呢从理论上来说呢 他是可以处理任意长度的 要只要硬件允许 任意长度都可以 但是呢 你提前预训练好的这些位置编码呢 有可能就没用了 因为你原来的位置编码 比如说九宫格的话你是1-9 他是有明确的这个位置信息的意义在里面的 你现在图片变大了 如果保持 patch size 不变的话 你有可能得到十六宫格 二十五宫格
你的patch增多了 那你现在的位置信息呢 就从1到25 而不是从1到9了 那这个时候位置编码该如何使用呢 那他这里发现呢 其实简单的做一个2 d 的插值 就可以了 那在这里呢他们这个操作 其实就是用torch官方自带的这个 interpolate的函数 就能够完成 但是呢这里的插值 也不是说可以想插多长就插多长 当你从一个很短的序列 想要变到一个很长的序列的时候 比如说你从256到512
甚至变到768更长的时候呢 直接这样一个简单的插值操作呢 是会让最后的效果掉点的 所以说这里的插值呢 其实只能说是一种临时的解决方案 他算是vision transformer 在微调的时候的一个局限性 最后他说 因为你用了这个图片的位置信息 去做这个插值 所以说这块的这个尺寸改变 还有这个抽图像块 是vision transformer里唯一的地方 用了2 d 信息的 这个归纳偏置
接下来我们一起来读实验部分 他说 在这个章节主要是对比的残差网络 vit 他们这个混合模型的 这个表征学习能力 为了了解到底训练好每个模型 需要多少数据呢 他们在不同大小的数据集上 去做预训练 然后在很多的数据集上去做测试 当考虑到预训练的这个计算代价的时候 就是预训练的时间长短的时候呢 vision transformer表现的非常好
能在大多数数据之上取得最好的结果 同时需要更少的时间去训练 最后作者呢还做了一个小小的实验 就做了一个自监督的实验 他说 自监督说的实验的结果呢 还可以 虽然没有最好 但他说这个呢还是比较有潜力的 而事实上确实如此 时隔一年之后 最近大火的 mae 就证明了自监督的方式去训练 vit 确实效果很好 数据集的使用方面呢 主要就是说
用了这个image net的数据集 他把这个有1,000个类 就是大家最普遍使用的这个1,000类的 image net数据集呢 叫做image net 或者在很多别的论文里呢 叫image net-1 k 然后更大的那个集合 imagenet-21 k 就是有21,000个类别 而且有1400万图片的那个数据集呢 叫做imagenet-21 k jft 数据集呢 就是 google 自己的数据集 就是有那个三个亿的图片的数据集
他的任务呢全都做的是分类 也用的都是比较popular的数据集 比如说 cifar oxford pet oxford flower 这些数据集 接下来我们看一下模型的变体 它呢一共是三种模型 其实就是跟transformer 那边 对应了就是有 base large 和 huge 就是说对应的这些参数 全都逐渐的变大 比如说用了更多的 transformer block 或者用了更长的这个向量维度 或者 mlp 的 size 变大
或者说多头自注意力的时候 用了更多的头 然后他接着正文里又补充了一些内容 因为他的模型呢 不光跟这个 transformer 本身有关系 他还跟你这个输入有关系 当然这个patch size大小变化的时候 比如说从16乘16变大 变成32乘32 或者变小变成8乘8的时候呢 那这个模型的位置编码就不一样 所以patch size呢 也要考虑到这个模型命名里面 于是他们模型命名的方式就是
比如 vit-l 16 意思就是说呢 他用的是一个 vit large 的模型 然后他的输入 patch size 呢是16*16 接着他又说 说这个transformer的这个序列长度呢 其实是跟你这个patch size成反比的 因为你patch size越小 那你切成的块就越多 你patch size越大切成的块就越小 所以当 模型用了更小的patch size的时候呢 计算起来就会更贵 也就意味着比如说你这个 vit-l 16
你要换成 vit-l 8的话呢 那那个 vit-l 8的模型就要比这个16要贵很多 因为他的序列程度增加了 好讲了这么多 终于到可以看结果的时候了 这个表2呢 是说当他 已经在大规模的数据及上进行预训练了 然后在这么多数据集上 去做fine-tune的时候得到的表现 他这里呢先对比了几个 vit 的变体 比如说 vit 的 hugemodel就是他最大的那个模型
放在这里是用来秀肌肉的 因为全都取得了最好的结果 然后跟卷积神经网络那边呢 他就跟这个 bit 和这个 noisy student 做对比了 跟 bit 做对比的原因呢 是因为 bit 确实是之前 卷积神经网络里做的比较大的 而且也是因为 是这个作者团队自己本身的工作 所以正好拿来可以比 所有之前做过的这些数据集呢 bit 也都做过 那至于这个noisy student 呢
是因为他是 image net 之前 表现最好的方法 他用的方式呢 是用 pseudo-label(伪标签)去进行 self training 也就是我们常说的用这个伪标签 也取得了很好的效果 首先我们可以从这个表里看出来呢 vit huge 这个模型 而且用比较小的patch 在14 就是相对更贵一点的模型 他呢能取得所有数据集上最好的结果 虽然说 这里这个99.74被黑体了
大概99.68也没差多少 但是呢因为这些数值 比如说这里 这里这些数值 都太接近了 都是差零点几个点或者一点几个点 没有特别大的差距 作者就觉得没有展示出vision transformer的威力 作者就得从另外一个角度来凸显 vit 的优点 那他找了一个什么角度呢 他说因为我们训练起来更便宜 所以我们先来看 他说的训练更便宜呢 是说他们最大的这个 vit huge 的模型呢
也只需要训练2,500天 tpuv 3天数 正好呢 这个 bit 和 noisy student 呢 也都是 google 的工作 也都是用 tpu v3训练的 所以刚好可以拿来比 那 bit 呢是用了9,900天 然而 noises student 就更不得了了 那用了一万多天 所以他说从这个角度上来说呢 vit 不仅比 你之前的这个 bit 和 nosy student 要训练的快 而且效果还比你好
那这一下双重卖点大家就会觉得 vision transformer 真的是比卷积神经网络要好 那在众多数据集上秀完肌肉之后呢 接下来就该做一些分析 那首先第一个分析也就是最重要的 vision transformer到底需要多少数据 才能训练的比较好 那我们来看图三 这个图3应该是整个 vision transformer论文 最重要的 take home message 就是他最想让你知道的 其实这一张图
基本就把所有的实验都快概括了 这张图的意思呢 就是说 当你使用不同大小的数据集的时候 比如说 image net 呢是1.2million 而这个21 k 呢是14million 一直到最后 jft 呢是300million 就是当你的数据集不断增大的时候 那 resnet 和 vit 到底在 image net 的 fine-tune 的时候 效果如何 他这个图上点有点多 所以不太好看 但他的主要意思是说这个灰色 代表 bit
也就是各种大小的这个 resnet 比如说这个下面呢 应该就是个 res 50 上面呢应该就是152 就是从最小的然后到最大的 这有这么一个范围 那同样呢中间这样应该也是 这是个五十 这是个152 他这里想展示呢 就是说在中间的这个灰色的区域 就是 resnet 能达到的这个效果范围 那剩下的这些圆圈点了 就是各种大小不一的 vision transformer
我们首先来看 在最小的image net上做预训练 resnet 和vision transformer 的比较如何 vision transformer呢是全面不如 resnet 因为 resnet 这个效果范围在这 可是 vision transformer 基本所有的点都在这个范围之下 就是 vision transformer 在中小型数据集上 去做预训练的时候呢 的效果是远不如残差网络的原因呢 就是因为 vision transformer 没有用那些先验知识 没有用那些归纳偏置 所以他需要更多的数据
去让这网络学的更好 那接下来我们换到这个 image net的21 k 用中间这一档的数据集去预训练 效果如何呢 我们会发现呢 resnet 和 vision transformer就差不多了 他们的效果呢都是在这个范围里面 只有当用特别大的数据集 用三个亿的图片数据集 去做预训练的时候呢 我们可以发现 Vision Transformer 基本是全面 超过 resnet 了 因为你看 vision transformer范围在这
但是 resnet 的范围在这 首先呢 就是即使是最小的这个 vit-b 32 就这个蓝点 也比这个 res 50高 其次呢就是当你用最大的模型 就是 vit h 14的时候呢 它是比 bit 对应的 res 152 还要高的 那总之呢这个图其实只有两个信息 一个信息呢 就是说如果你想用 vision transformer 那你 至少得准备差不多这么大的数据集 如果你只有很小的数据集呢
那还是用卷积神经网络比较好 第二个点呢 就是当你有规模 比这个数据集更大的时候呢 用 vision transformer 应该能给你更好的结果 他的扩展性更好一些 其实整篇论文讲的呢 就是这个 scaling 接下来呢作者又做了图四 原因呢是因为在图三的时候 他要用 vision transformer 去跟这个 resnet 的比 所以他还在训练的时候呢 用了一些强约束 比如说用了dropout 还用了 weight decay 用了 label smoothing
所以就不太好分析 vision transformer 这个模型本身的一些特性 所以说在图四里呢 他做的是这个 linear fewshot evaluation 这个 linear evaluation 呢 就是我一旦拿到这个预训练的模型呢 我是直接把它当一个特征提取器 我不去fine tune 而是拿这些特征直接来做一个了 just take a regression 就行了 同时呢他选了 few shot 然后在图里有没有看到了是 five shot 就是在image net上 你去做这个 linear evaluation 的时候呢
每一类呢就随机选了5个 sample 所以这个evaluation做起来是很快的 作者呢也就是用这种方式 去做大量的消融实验 那在图四里呢 这个横轴还是表示的这个预训练 数据集的大小 这里呢他没有用别的数据集 他就用的是 jft 但是呢他取了一些 jft 的子集 比如说这个10million30million100million 300million 这样呢因为 所有的数据都是从一个数据集里来的 他就没有那么大的 distribution
gap 那这样比较起来模型的效果呢 就更加能体现出模型本身的特质 至于结果呢其实跟图三也是差不多的 说这条浅灰色的线呢是 res 50 然后这条深灰色的线呢 是 res 152 当用很小的预训练数据集的时候呢 vision transformer呢是完全比不过 resnet 的 文章里给出的解释呢 因为缺少归纳偏置和那些约束的方法 比如说之前说的 weight decay label smoothing 这些
所以就导致这里的 vision transformer呢 容易过拟合 导致最后学到的特征呢 不适合做其他任务 但是随着预训练数据集的增大 vision transformer的稳健性就上来了 但是因为这里的提升 也不是很明显 所以说 作者其实在这一段的最后也写了 如何用 vision transformer 去做这种 小样本的学习 是一个非常有前途的方向 那么接下来看图五 由于 vision transformer 这篇论文 之前说了 他的预训练呢
比用卷积神经网络要便宜 他这里呢就得做更多的实验 去支持他的这个论断 因为毕竟大家对transformer的印象都是说 又大又贵 很难训练 那在图五里呢 画了两个表 一个表这个 average-5 意思呢 就是他是在五个数据集上 去做了evaluation 然后把这个数字呢平均了 那这五个数据集呢分别是 image net real pets flowers cifar 10和 cifar 100 然后因为 imagenet 太重要了
所以说他把 imagenet 单独摘出来 然后又画了一张表 但其实这两张表的结果呢都差不多 首先我们看图例 图例说一下这蓝色的这些圈呢 都是 vit 然后这个灰色呢就是 resnet 然后这个橙色的加号呢 就指的是混合模型 就是前面是卷积神经网络 后面是 transformer 但是图里各种大大小小的点呢 其实就是各种配置下大小不一样的 这种 vision transformer 的变体
或者说是 reset 的变体 这两张图里 所有的模型都是在 jft 300million这个数据集上去训练的 他的意思就是说呢 他不想让模型的能力 受限于数据集的大小 所以说呢 所有的这些模型都在最大的数据集上 去做预训练好了 我们可以看到有几个比较有意思的现象 首先第一个现象就是说 如果你拿蓝色这些圈 叫 vit 去跟灰色这些 resnet 的比呢 你会发现 在同等的计算复杂度的情况下
一般transformer都是比 resnet 要好的 这个呢就证明了他们所说的 就是训练一个 vision transformer 是要比训练一个卷积神经网络要便宜的 第二个比较有意思的点呢 我们可以发现在比较小的模型上呢 这个混合模型的精度是非常高的 他比 vision transformer 和对应的 resnet 都要高 这个呢倒也没什么惊讶了 按道来说这个混合模型呢 就应该吸收了双方的优点 就是说既不需要很多的数据去预训练 同时呢
又能达到跟 vision transformer一样的效果 但是比较好玩的就是说 当随着这个模型越来越大的时候呢 这个混合模型慢慢的就跟 vision transformer 差不多了 而且甚至还不如 在同等计算条件下的一个 vision transformer 这个还是比较有意思的 就为什么卷积神经网络抽出来的特征 没有帮助 vision transformer去更好的学习呢 当然这里作者也没有做过多的解释 其实怎么预处理一个图像 怎么做这个 tokenization
是个非常重要的点 之后有很多论文都去研究了这个问题 最后呢 如果我们看这个整体趋势的话呢 就是随着这个模型不断的增加呢 这个 vision transformer的效果也在不停增加 并没有一个饱和的现象 饱和的话就是一般就增加到一个平台 就不增加了 但是现在的这个趋势呢 还是在不停的往上走的 当然如果只从这个图里来看呢 其实 除了这个混合模型有点饱和之外呢
其实卷积神经网络的这个效果呢 好像也没有饱和 那分析完这个训练成本以后呢 作者就继续做了一些可视化 他希望通过这个可视化呢 能够分析一下 vit 内部的表征 那如果要类似卷积神经网络那边呢 那第一个要看了呢 那就是第一层 到底学到了什么样的特征 那 vision transformer的第一层呢 就是那个 linear projection layer 也就是那个我们说的E 那么现在来看图7 图七呢就是展示一下那个E
是如何embed rgb value 他这里呢只是展示了头28个 主成分其实这个 vision transformer 而学到的跟卷积神经网络也很像 都是这种 看起来像 gabor filter 的这种 有一些颜色 然后还有一些纹理 所以说呢作者说 这些成分 是可以当做这个基函数的 也就是说 可以去描述 每一个图像块的这种底层的结构 那看完了 patch embedding呢 那接下来就要看一下
这个positional embedding 这个位置编码是怎样工作的 那么再回来看图7中间的这个图 这个图呢就画的是这个位置编码的 这个相似性 相似性越高呢就是1 相似性越低呢就是-1 因为他做的是个 cosine 的 similarity 他的横纵坐标呢 就分别是对应的 patch 首先我们来看 如果是同一个 patch 自己跟自己比 那这个相似性肯定是最高的嘛 所以说对于11这个 position 来说呢
那这个肯定黄色点是在这呢 那接下来呢我们能观察到 这个学到的位置编码 真的是可以表示一些这个距离的信息的 比如说假如说我们看这个 那就说离中心点越近的地方呢 他就会越黄 然后离中心点越远的地方呢 他就会越蓝 也就意味着他的相似度越低 所以他已经学到了这个距离的概念 同时呢我们还可以看到 他还学到一些行和列之间的这个规则 比如说你看这个
每一个都是同行同列的 这个相似度更高 同行同列 同行同列 也就意味着虽然他是一个1D的 位置编码 但他呢已经学到了2D 图像的这种距离的概念 所以作者在文中也说了 就这也可以解释 为什么 他们换成2 d 的位置编码以后呢 并没有得到效果上的提升 是因为1D已经够用了 最后呢作者就想看一下这个自注意力呢 到底有没有
起作用因为之所以大家想用 transformer吗 就是因为自注意力这个操作呢 能够模拟长距离的关系 那在 nlp 那边呢 就是说一个很长的句子里 抬头的一个词和结尾的一个词 也能互相有关联 那在图像里呢 就是很远的两个像素点 之间也能做自注意力 这作者呢 在这里就想看一下 自注意力到底是不是像期待的一样 去工作的 那我们回到图7 看最右边的这张图
这张图呢画的是这个 vit large 16的这个模型 viti large 只有24层 所以说这个横坐标呢这个网络深度 这就是从0到24 那这些五颜六色的点呢 就是每一层的transformer block 里面的那个多头 自注意力的头 那对于 vit large来说呢 我们一共有16个头 所以其实就是说每一列呢 我们其实是有16个点的 他这里纵轴画的是一个叫 mean attention distance 的东西
就是平均注意力的距离 这个他是怎么定义的呢 假如说你图像上有两个点 那 a b 那这个 mean tension distance 呢 假如说我们用的 d 来表示 d a b 呢 就相当于是 l a b l a b就是这两个点之间 真正的 pixel 之间差的距离 乘以他们之间的 attention weights 因为自注意力是全局在做 所以说每个像素点跟每个像素点 都会有一个这个 自注意力权重
那这个 d ab 的大小呢 就能反映这个模型到底能不能 注意到很远的两个 pixel 那这个图里的规律呢还是比较明显的这假如说我们先看头几层 那头几层呢就说有的自注意力头 注意的距离还是挺近的 这可能20个 pixel 但是有的头呢能到120个 pixel 所以这也就证明了 自注意力真的能在网络最底层 就最刚开始的时候 就已经能注意到全局上的信息了
而不是像卷积神经网络一样 刚开始第一层的是 receptive field (感受野) 非常小 就只能看到附近的这些 pixel 那随着网络越来越深呢 网络学到的这个特征呢 也会变得越来越 high level 就是越来越具有语义信息 所以说我们别人看到了 大概就是网络的后半部分呢 他的这个自注意力与距离呢都非常远了 也就意味着 他已经学到这个带有语义性的概念 而不是靠临近的这个像素点 去进行判断 那为了验证这一点呢
作者又画另外一个图 就是图6 他这里面呢 是用网络最后一层那个output token 去做的这些图 他发现如果用输出的 token 这个自注意力 折射回原来的这个输入图片呢 我们其实可以看到 他真的学到了这些概念 比如说第一个里面这个狗 他其实已经注意点这个狗了 这个飞机 飞机 那作者最后一句话写 对于全局来说 因为你这个输出token 是融合了所有的信息
这个全局的特征 他们就发现 模型已经可以关注到那些图像区域 哪些区域呢 就是跟最后分类有关的区域 在文章到最后 作者还做了一个尝试 就是如何用自监督的方式 去训练一个 vision transformer 这篇论文 其实如果算上附录的话呢 一共有22页 那在这么多结果中呢 作者把别的结果都放到了附录里 而把这个自监督放到了正文里 可见他的重要性
他之所以重要是因为在 nlp 领域呢 transformer这个模型 确实起到了很大的推动作用 但另外一个真正让 transformer能火起来 另外一个成功的因素呢 其实是大规模的自监督训练 这两个是缺一不可的 那之前我们说过 nlp 那边的这个自监督呢 无非就是完形填空或者预测下一个词 因为这篇论文整体都仿照的是 bert 所以他就想说 我能不能也借鉴 bert 是这个目标函数
去创建一个专属于 vision 的目标函数 那 bert 呢用的其实就是完形填空了 也就叫 mask language modeling 就是一个句子给你 然后你把一些词 mask 掉 然后你通过一个模型 最后再去把它预测出来 那同样的道理呢 这篇论文就搞了个 masked patch prediction 意思就是说我有一张图片 然后已经画成 patch 了 而这时候我把某些 patch 随机抹掉 通过这个模型以后呢 你再把这个patch给我重建出来
这其实真的是很激动人心的 因为他不论是从模型上 还是从目标函数上 cv 和 nlp 真的就做到大一统 但是呢他们这个模型 他说最后 比如说 vit base 一个patch size16的模型呢 在imagenet上 只能达到大概80的准确率 虽然呢 相对于从头来训练这个 vision transformer呢 他已经提高了两个点 但是跟最好的这种就是 有监督的训练方式比呢 差了四个点
然后作者说 他把跟对比学习的结合呢 当做是future work 了 因为对比学习 其实去年 cv 圈最火的一个 topic 是所有自监督学习方法里 表现最好的 所以紧接着 vit 呢 MoCo v3就出来了 还有DINO 也出来 这两篇论文都是用 Contrastive 去训练了一个 vision transformer 最后 我们来回顾 总结一下这篇 vision transformer的论文 这篇论文写的还是相当简洁明了的
他在有这么多内容和结果的情况下呢 做到了有轻有重 把最重要的结果都放在了正文里 图和表做的也都一目了然 那从内容上来说呢 vision transformer真的是挖了一个很大的坑 你可以从各个角度去分析他 或者提高他 推广他 比如说如果从任务角度来说呢 vision transformer只做了分类 那其实还很自然 那你就可以拿他去做检测 分割和甚至别的领域的任务
那如果从改变结构的角度来说呢 那你可以去改刚开始的tokenization 你也可以改中间的这个 transformer block 因为后来就 已经有人把这个 self attention 呢 换成 mlp 而且还是可以工作的很好 然后就在几天前呢 甚至有一篇论文叫 mataformer 他觉得 transformer真正 work 的原因呢 是因为 transformer这个架构 而不是某些特殊的算子 所以他就把这个self attention上呢 直接换成了一个池化操作 然后他发现呢
用一个甚至不能学习的池化操作 也就是他提出这个poll former 的这个模型呢 也能在视觉领域取得很好的效果 所以说在模型的改进上呢也大有可为 而如果从目标函数来讲呢那就更是了 你可以继续走有监督 然后也可以尝试很多不同的这个 自监督训练的方式 最后更重要的呢 是他打通了 cv 和 nlp 之间的鸿沟 挖了一个更大的多模态的坑 那接下来大家还可以用它去做视频
去做音频 甚至还可以去做一些 基于touch的这种信号 就各种modality的信号都可以拿来用 在我看来呢卷积 自注意力或者 mlp 究竟鹿死谁手还犹未可知 我是很期待下一个即将出现的 一个改进版的 vision transformer 还有可能真的就是一个简洁高效 通用的视觉骨干网络 而且可以完全不用任何标注信息
Loading video analysis...