Vision Transformer(ViT):打通CV与NLP领域的经典之作

打通的壁垒

回顾一下,在Transformer中,计算自注意力权重的时候,需要序列中的元素两两计算相似度(或者叫相容性函数),其计算复杂度是 O(n2)O( n^{2} )。所以,如果序列长度太长的话,计算复杂度很可能承受不了。

所以说想要直接将Transformer应用到CV领域,直接将一张图片拉直后将每个像素都看做一个序列中的点,就算一个224X224像素的图片,那么序列长度就会有5w+,这个时候再平方,也太大了,更不要提高清图片了。

怎么办呢?有几种思路:

1、限制注意力计算的范围:

只对元素前后附近的像素计算相似度。

只对小窗口内的像素计算相似度。

只按轴计算相似度,图片中的同一行、同一列元素。

计算注意力的时候用稀疏的方式,采样一定的元素进行计算,可以做k次,复杂度从O(n2)O( n^{2} ) 降到 k∗(n/k)2k*(n/k)^{2}

2、想办法将维度降下来:

比如先用CNN提取feature map,再在上面使用自注意力机制。这种方案是CNN和transformer的混用。

3、直接将图片划分成小格子,再进行embedding后将其视为nlp中的word。

这样直接可以只用transformer,不用CNN。同时,格子划分的粗细大小能够让我们控制序列的长度。

这几种方式当然都有人想到过并有一些文章出来。不过要说革掉CNN的命,显然第4种方案更加的彻底。同时,仅用transformer还带来一个长远的好处,就是将cv和nlp领域的基本模型骨架统一了,这样也激发了很多对于多模态混合任务的创新。

ViT的做法

ViT就是其中比较知名的作品,它是一个图像分类的模型,自然仍然是有监督学习的方式。

ViT可以说是充分利用了前人的工作(这么说并不有损其工作的重要性),其基础的思路已经有人提出过。包括在实现上,在ViT提出的时间点,模型底层也有很多很高效的实现,也免去了很多魔改模型、需要自己实现高效算子的麻烦。

ViT实现中尽量保持了原始的transformer编码器结构,只在少数地方(比如位置编码的部分)进行了改动。所以熟悉transformer的看到下面的模型结构图,可能就理解大体在做什么了。

论文:An Image is Worth 16×16 Words: Transformers for Image Recognition at Scale

原文代码:https://github.com/google-research/vision_transformer

推荐观看:ViT论文逐段精读【论文精读】

模型结构大体流程如下:

1、先将图片切成一个个的小块(patch)

2、将每个patch拉平后经过投影层获得embedding

3、在embedding的基础上添加位置编码信息,从1开始编号

4、添加一个初始的空patch,位置编号为0,用于对接预测输出

5、进过标准的transformer encoder

6、将0号位置的patch输出接上一个mlp进行分类:

由于transformer中的元素是两两交互的,所以0这个元素能够“看到”后面图片所有元素,所以能提取到整张图的信息。

7、输出分类结果,计算损失

作者为了尽量采用原始的transformer结构,更多只是在transformer block的前后多了一些适配工作。作者们最想证明的就是,即便不用针对cv领域做魔改,transformer本身就能够很好的应用在cv领域。

在其中多了不少对比实验,比

    THE END
    喜欢就支持一下吧
    点赞5 分享
    评论 抢沙发
    头像
    欢迎您留下宝贵的见解!
    提交
    头像

    昵称

    取消
    昵称表情代码图片

      暂无评论内容