ViT

ViT:如果在足够多的数据上做预训练,直接用NLP中搬来的Transformer也能把视觉问题解决的很好,这打破了视觉和NLP之间模型上的壁垒,所以就开启了多模态领域的快速发展。

在开始读原文之前,这里展示了一个ViT有趣的特性,即在以下四种情况下CNN甚至人眼都难以分辨图片中是一只鸟,而ViT效果拔群

第一个是遮挡,第二是数据分布偏移(纹理去除),第三是加一个patch,第四是打乱随机排列组合

 

摘要:在视觉里第一次抛弃CNN架构使用纯注意力,尤其是在大规模数据集下做预训练,然后迁移到中小型数据集上,效果媲美最好的CNN。这里提到的中小型数据集和更少的硬件资源是对比视觉领域动辄2500天TPUv3的计算量,transformer的训练对于普通人来说依然是非常恐怖的,类似于“小目标”。

 

引言:现在transformer在NLP领域主流方式是先在超大规模数据集上预训练,然后在特定领域数据上微调(fine-tune),随着模型和数据集的增长,还没有看到饱和的现象。

自注意力操作需要将输入的元素之间两两相互计算attention,也就是说复杂度是O(n2),BERT的输入是512,但是二维的图像即便是224*224也是五万多,直接翻了一百倍,计算量爆炸。224也仅能满足分类任务的需求,检测、分割等更为复杂的任务图片要更大。这里提了几个前人工作的解决办法,一个就是输入CNN处理后的特征图,这个是比较小的。另外一个方向是孤立自注意力机制(stand alone attention),它一次只输入图片一小块,类似于卷积。轴注意力机制(axial attention)是在二维图像上做H和W两个方向的自注意力,压缩为两个一维向量来表示。但上述方法因为比较特殊难以硬件加速,所以没有成为大模型的主流方法。

ViT的方案是将图片分解为许多patch(16*16),每一个patch作为一个元素,相当于NLP里的单词,这里呼应了题目,一个图片等价于许多16*16的单词。这种方案在之前其实有人提过,从技术角度讲一模一样。只是google更有钱,他们工作的创新点在于他们证明了在大规模数据集下预训练,就可以使一个标准transformer(在Nlp领域中提出的模型,不需要做更改)在视觉任务上取得很好的结果。所以再次证明做深度学习,有钱很重要,同样一个工作你用钱重新砸一遍就变成了这个工作的创始人。这是之前李沐在GAN这篇文章里讲过的,就是说GAN这个东西其实LSTM的作者在几十年前就提出过,只是受限于当时的背景,人工智能没有火起来。一个好的东西,人们总是能记住教会他们怎么用的那个人,而不是最初发明他的那个人。也就是说,一个好的工作,你发扬光大也很重要。

引言的最后也可以把最想表达的结果放出来,使大家提前知道结果:在如ImageNet这样的中型数据集上,不加强约束的transformer表现要弱于ResNet,因为卷积有归纳偏置。这个事我们在transformer那篇笔记里提过,transformer是一个更一般的假设,约束比较弱,所以要用更大的数据。而一旦给transformer用上足够大的数据,就能够比归纳偏置效果更好。ViT只要能在足够规模的数据上预训练,就能够在下游任务上有很好的迁移学习效果。

 

结论:与之前使用子注意力机制的工作相比,本工作除了在刚开始抽取图像块以及位置编码时使用了一些图像特有的归纳偏置,此外都是用transformer的通用结构。好处是降低门槛,不需要了解视觉领域的领域知识。这个简单且扩展性较强的策略和大规模预训练结合起来时,效果就会出奇的好。

 

相关工作:transformer预训练是使用自监督的方式,即在大型语料库中人为的创造一些任务,比如说让模型预测句子的顺序,词语挖空完形填空等等。

视觉方向主要是解决上述图像太大不适合作为直接输入的问题,各种各样的解决办法,这些办法效果都不错,但是需要很复杂的工程在计算上加速,所以没法让训练大模型成为可能。

CNN和自注意力结合的工作是非常多的,但是这里作者没有给出评价。

还有一个image GPT,但是这个iGPT预训练完微调后效果远远不如这一篇ViT

此外老师还提到MAE(何凯明)这类工作之前,生成式网络在视觉领域很多任务上是没法跟判别式网络相比的,MAE是第一次做到生成式比判别式分类任务结果更好。

 

方法:模型在设计上是尽可能按照原始transformer来做的,可以尽可能借鉴NLP许多成功经验和方法

大体流程是拿到一张图先打成许多patch,变成一个序列,然后线性投射为一个特征(patch embedding)。这里和nlp一样,patch序列是有顺序的,否则意思就变了,所以还要有位置编码。那么这个整体的token就同时包含了图片信息和位置信息。接下来就跟NLP那边完全一样了

但是在encoder的输出端会输出很多结果,究竟应该用哪个输出来做分类呢,所以这里再次借鉴了BERT加入了extra learnable embedding,他是一个特殊字符cls(分类字符),在输入端作为一个向量输入,它的位置编码是0。我们认为这个cls能够从所有的embedding中学到信息,从而我们只需要根据这个cls在输出端的输出进行分类。也就是说cls学到了全局信息,集成了最后最抽象最高层的特征结果。这里弹幕有人指出,如果只是做简单的分类任务,这个encoder就够用了,不需要解码

 

以上是只看图片大概走一遍流程,下面补充一些细节

输入是一张图片X 224*224*3,如果将一个pach边长设为16,那么一共有14*14=196个token,也就是说每一个patch的维度为16*16*3=768。线性映射层(E)就是全连接层,其维度为768*768,第二个768在文中称为D,是人为定义的维度,第一个768是16*16*3。

那么X×E = 196*768 × 768*768(参数矩阵?) = 196*768。即196个token,每个token人为定义其长度为768。至此一个CV的问题已经完全成为一个NLP问题,输入模型的是一维序列而非二维的图片。因为我们刚说还加了一个cls,所以最终输出维度为197*768。

此外,位置编码也是768长的一维向量,所以一共有196个位置,位置编码也是196*768的矩阵,直接sum到embedding里面去,这个位置编码是可以学的。

 也就是说,上图右侧流程图中,embedded patches就是197*768,结果一个LN后维度不变,多头的时候复制三份,根据头数的选择将token的维度缩小,例如base版本的ViT选择12个头,那每个头的维度就是768/12=64。那么K/Q/V的维度其实是197*64,做完自注意力再把十二个头拼接起来,就又变成197*768。再一层LN不变。MLP中会把维度放大四倍到3072,再投影回去。整个encoder输入和输出的维度一模一样,也就是说这个encoder可以随意叠加L个。

针对位置编码,我们刚讲过,用的是一个标准可学习的1D position embedding,也就是BERT里用的位置编码。因为做图片,空间位置可能会更为敏感,这也是我个人在学这个方法时最大的疑惑。这里原文作者说也尝试了各种编码方法,但效果都差不多。

文章中对于cls token和位置编码作者做了详细的消融实验,例如还有一个我疑惑的问题就是为什么一定要加一个class token来表示全局信息,为什么不像卷积架构一样在模型的最后面将所有东西整合起来(global average pooling, GAP),作为全局信息。原文作者说了,实验证明两者都可以,效果差不多,他选择用class token是为了尽量和NLP保持一致。其目的在于,通过所有实验告诉我们一个标准的transformer可以做视觉,而并不是针对视觉问题做的许多改动带来的结果。作者在这里还加了一张图片,如果将GAP中使用的学习率拿到CLS里直接用,会造成非常差的结果,但是重新调整学习率以后,效果差不多。所以说做这种实验需要重新调参,不要参数不变,一看效果不好就下结论。

在预训练结束后进行微调的时候,通常来说如果能用一个更大的图片是能够获得更好的结果,例如256*256或者更大。但是图片大了,patch大小不变的话,序列长度就变长了。当然如果你的硬件条件允许,序列长度是可以随意增加的。但是你之前训练好的位置编码矩阵就不能用了,作者在这里说他们发现直接对位置编码矩阵进行二位插值就能继续用,他们用的就是torch官方自带的interpolate插值方法实现的。当然插值这个事肯定是会影响结果的,所以这是ViT在微调时候的一个局限性。

 

实验:主要对比ResNet(残差网络),ViT,以及混合模型

效果差得不太多,ViT略好,不过训练成本要低得多

最后对比了在不同体量数据集进行预训练后各个网络的效果,这是最重要的结果。当预训练数据较小时,ViT远不如残差网络,只有当数据体量逐渐增大,ViT才能逐渐赶上,最后超过CNN。

后面还画了每一个头学到的是什么特征,位置编码学到的东西,以及不同深度的注意力学到的遥相关的平均距离,内容非常全,建议看原文

 

自监督:很重要

 

朱老师这里提到一个点,ViT有许许多多的点可以继续探索和研究,从改模型的角度讲,有人已经将自注意力模块换成mlp发现效果也很好,甚至有一篇论文叫mataformer把自注意力模块换成了池化(池化操作里甚至没有可以学习的东西),也能取得很好的结果,他认为transformer效果很好的原因并不是自注意力这个特殊的算子,而是这个架构非常好。

在朱老师看来卷积 子注意力 MLP究竟鹿死谁手还犹未可知。

 

posted @   诸葛村夫CC  阅读(597)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示