transformer的具体应用:图像分类

本文详细描述了ViT(VisionTransformer)的处理流程,包括图片预处理(如随机裁剪),图片切割成Patch,添加[class]token和位置编码,以及TransformerEncoder和MLPHead的结构和作用。重点介绍了如何通过卷积实现图片到Token的转换和位置编码对图像顺序的记录。
摘要由CSDN通过智能技术生成

模型结构/算法流程

ViT的处理流程大致可以分为以下几个步骤:

1.图片预处理
 

预处理这个步骤在论文里并没有详细说明,但是对于ViT这个结构而言,输入的图片尺寸并不是自定义的,ViT-B/16为例,输入的图片尺寸必须为224x224。

因此,首先需要对输入图片进行尺寸变化,具体方式可以是直接缩放(Resize),也可以进行随机裁剪(RandomResizedCrop),在后面复现的代码中,使用的是随机裁剪的方式。

2.图片切割

Transformer需要输入的是一维的Token,对于二维的图像,一种朴素的想法就是把一个个像素点拉平,这样就成了一个一维序列。但是这样造成的一个后果是计算量太庞大,比如一张224x224的图片,变成1维度之后就成了50176,相当于直接输入一篇五万字的文章,模型难以计算。

那么,一个改进的想法就是把一张图片分成nxn个Patch,每一个Patch作为一个Token,这样计算量就大大减小了。

以ViT-B/16为例,将输入图片(224x224)按照16x16大小的Patch进行划分,划分后可以得到共( 224 / 16 ) 2 = 196 (224/16)^2=196(224/16) 
2
 =196个Patch。每个Patch是三通道的小图片,shape为(16, 16, 3),将其展平就变成了一个长度为768的向量。

每一个向量作为一个单独的输入,那样我们总共有196个向量,在代码中,可以变成一个[196,768]的矩阵,进行并行输入。

这一步的操作在论文中是直接采用切割的处理办法,但是在后面的代码实现中,采用了一种更巧妙的解决思路,就是利用一个卷积核大小为16x16,步距为16,卷积核个数为768的卷积层来进行实现。

再来回顾我们的卷积层计算公式:


输入为[224,244,3],经过卷积层变成[14,14,768],再映射为[196,768]。

这样,就完成了从图片到Token之间的转换。

3.添加[class]token


在上面的结构图中可以看到,输入Encoder的最左侧部分添加了一个0*这个Token,这个就是额外添加的一个[class]token,单独用来处理类别信息,经过Encoder之后,需要单独将这个Token再提取出来,输入到MLP Head之中再输出分类结果。

这也是为什么结构图中MLP Head的位置是和这个[class]token对齐。

4.添加位置编码


在Transformer中,位置编码的作用是为了记忆输入的语序信息。ViT中,同样需要位置编码来记录各图像块之间的位置信息。

这里主要有两种位置编码思路,一种思路是在转换之前(14,14)的图像块矩阵添加二维(2-D)位置编码,另一种思路是在转换后(196+1)这个维度上添加一维(1-D)位置编码。

作者也对其做了实验,实验结果如下表所示:

可以看到,添加一维位置编码和二维位置编码并没有太大的差异。作者随后也对一维位置编码的结果进行了可视化,结果如下图所示:

上图中是每一个Patch中各位置的位置编码相似性度量,越接近黄色的位置代表越靠近位置编码的中心位置,可以看到,即使是一维位置编码,同样可以比较好地记录二维信息。

5.Transformer Encoder


ViT虽然采用的是Transformer Encoder的结构,但是和Transformer原始的Encoder还是有所区别,我将两者的结构进行对比,如下图所示,左侧为Transformer原始的Encoder结构。


可以看到,大致上两者结构是相同的,主要区别在于Norm层的顺序,原始Transformer的Norm层在多头注意力和前馈网络之后,而ViT将其放到前面,这里的原因,论文里没有做解释。

关于Norm层,ViT仍是采用Transformer中用到Layer Normalization,计算公式如下:


Norm层之后同样是多头注意力层(Multi-Head Attention),和Transformer中的一样。

后面的MLP是个单独的结构,论文里没有绘制其详细结构,看到博主太阳花的小绿豆[1]对其进行了绘制,这里转贴在此。MLP也并不复杂,就是两个线性层+GELU激活函数+Dropout的结构,具体细节可以看后面的代码。

6.MLP Head


在Transformer Encoder输出结果之后,需要再将第一个添加的Class Token提取出来,然后输入到MLP Head进行分类。在论文中,作者先是在ImageNet21K上进行预训练,MLP Head结构由Linear+tanh激活函数+Linear组成,但是迁移到其它数据集训练时,只需要用一个一个Linear即可。

输出结果之后,再和真实标签做交叉熵损失,这样就可以完成ViT的训练过程。

代码来源于https://github.com/WZMIAOMIAO/deep-learning-for-image-processing/tree/master/pytorch_classification/vision_transformer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值