来源:投稿 作者:橡皮
编辑:学姐
小声逼逼
在过去的两年里,Vision Transformer(ViT)
是计算机视觉(cv)领域最有影响力的工作之一。「它推翻了2012年在Alex net中提出的CNN在CV领域的统治地位: 当能够获得足够多的预训练数据时,将ViT应用到CV的效果非常好。」 最重要的是,ViT的提出正式打破了CV和NLP之间的壁垒,同时还给CV和多模态的研究工作挖了一个大坑。
再叨叨两句
其实很早之前在群里就听小伙伴们聊过vision transformer
,但是因为当时自己所做的工作用到ViT的属实是很少,所以对于主动去了解这个东西就有些嗤之以鼻。
真正开始学,或者说认真开始看原paper
结合code
去理解vision transformer
是由于我在AIR的暑研项目中,mentor
提出了个有意思的想法是「基于DETR (detection transformer)
思路构造多类别异常检测模型。」
这就使我不得不加班加点的去从头了解vision transformer
的结构以及其中的self-attention以及cross-attention
机制。借此机会也想跟大家分享一下关于我的学习心得。
心路历程 QVQ
对我个人而言,学习一个新技术或者去follow一项新的工作,我的学习路线通常是:
读原paper👉知乎一下大家有关这篇工作的讨论👉重读技术路线👉对照代码去再次理解技术路线以及着重关注损失函数。(以下参考了沐神讲vit视频下的笔记进行回忆)
首先是阅读原paper
通过标题和摘要可以获得一些信息:an image is worth 16*16 words
,即每一张输入transformer的图片都会被打散为若干个16*16的小方格(patches),这样就可以利用nlp里面典型的transformer结构去做大规模的图像识别。
值得一提的是在ViT之前,我们都知道transformer在nlp领域是基本操作,但是这么好的idea却在cv领域应用十分有限。
原文作者谷歌团队着手解决了这个问题:「attention+CNN或attention替换CNN components,但是保持CNN的整体结构」。 对于保持结构,是指的ResNet50
有4个stage(R2/R3/R4/R5)
,每个stage
不变,直接使用attention
取代每一个stage
里面的每一个block
。作者实验证明attention
并不需要非得和CNN
一起使用,跟transformer
一起用时,在大规模数据集上预训练并在中小数据集做fine-tuning
后照样能够取得sota
效果。
接下来我跳过related work
直接来看到了模型结构,不得不说看了主图基本上就明白很多了。 ViT这篇文章尽可能使用原始transformer,「旨在于享受架构的高效实现。」
输入一张图,将它打成33的patches
,然后再将其分别flattened
从33变为1*9,经过一个Linear Projection
后,将每个patches
转变成了patch embedding
。由于encoder
中需要做self-attention
,即所有元素两两之间计算自注意力,这与顺序无关。
但是由于每个patch
是来自于图片是有序的,所以作者在patch embedding
前面加了position embedding
,这样patch embedding + position embedding[CLS]=token
(包含了图片的patch信息和每个patch在原图的位置信息)。可以看到,其实真正输入进transformer
的就是tokens
,这与nlp
中的工作是异曲同工的。
另外,文章主图做的分类任务,虽然每个token
都会有输出,但是最终还是只拿[CLS]
来做分类!这是因为transformer encoder
中的self-attention
机制使得所有tokens
都在做两两的信息交互,那么[CLS]
同样也会跟着所有的patches
一起做交互,所以[CLS]
也是可以学到有用信息的拿来做最终的分类的。继续看上面,「最终分类任务就是把[CLS]
单拎出来到通用的MLP head
中得到类别判断,这样就可以使用cross-entropy
来进行训练了~」
根据代码重新过一遍前向过程
虽然ViT的整体思路在主图上的展示不能够再清晰,但是毕竟最终要拿来改代码做自己的任务嘛,根据代码重新过一遍前向过程是有必要的:图片RGB->Npatchespatches->经过linear projection(E)后:768(patch维度)D(embedding_dim)768->图片$ xE=196798 $至此2D图片转换为1D序列tokens! 另外别忘了position embedding
的存在,所以输入encoder
的序列长度是197768~
到这里其实阅读原文和代码就结束了,方法思路和代码的具体实现已经get到了。 我并没有看Related work以及实验部分的效果是因为现在ViT已经是经过各种大佬魔改之后被公认为还不错了。
VIT的坑
诚然ViT这篇文章中也提及到了一些transformer固有的缺陷,比如data-hungry,相比CNN缺少归纳偏置,序列长维度高以及计算复杂度高等。 但正因为有这一系列待解决的问题,留给后面研究的可能性也就越大。所以我认为ViT原文的可读性依然非常的大,它讲解了最基本的原理和insight,但是真正希望把vit应用到自己的工作(其他领域)当中去,还是要看一些经典的ViT拓展工作来获取独到的思路,如DETR等等~
VIT论文&代码详解🚀🚀🚀
关注下方《学姐带你玩AI》回复“VIT”领取
码字不易,欢迎大家点赞评论收藏!