VIT就是Vision Transformer。
目录
1.Transformer在视觉领域上使用的难点
在nlp中,输入transformer中的是一个序列,而在视觉领域,需要考虑如何将一个2d图片转化为一个1d的序列,最直观的想法就是将图片中的像素点输入到transformer中,但是这样会有一个问题,因为模型训练中图片的大小是224*224=50176,而正常的bert的序列长度是512,是bert的100倍,这个的复杂度太高了。
2.输入序列长度的改进
如果直接输入像素点复杂度太高的话,就想着如何降低这部分的复杂度
1)使用网络中间的特征图
比如用res50最后一个stage res4 的feature map size只有14*14=196,序列长度是满足预期的
2)孤立自注意力
使用local window而不是整张图,输入的序列长度可以由windows size来控制
3)轴自注意力
将在2d图片上的自注意力操作改为分别在图片的高和宽两个维度上做self-attention,可以大大降低复杂度,但是由于目前硬件没有对这种操作做加速,很难支持大规模的数据量级。
3.VIT对输入的改进
先将图片切分成一个个patch,然后每一个patch作为一个token输入到transformer中,但是由于整个transformer每个token之间都会做attention,所以输入本身并不存在一个顺序问题。但是对于图片而言,每个patch之间是有顺序的,所以类比bert,给每个patch embedding加上一个position embedding(是sum)。同时最终的输出也借鉴了bert, 用0和cls来替代整体,这部分对应的embedding就是最终的输出。
4.前向过程:
首先VIT中将224*224的图片切分成了一个个16*16的patch,最终切分出了196个patch,每个patch的大小是16*16*3=768(3是RGB通道个数),同时每个输入都要加上cls,所以整个embedding的输入是197*768。经过layer norm之后,得到的维度不变。经过多头注意力时,如果使用的是base版本的12头自注意力,那么每个头的k,q,v对应的维度将变为768/12=64,最后将12个头的embedding再拼接到一起,就是64*12=768,然后再经过一个layer norm,最后通过一个MLP,这里一般会将维度放大四倍,197*3012,然后再投射回去,变成197*768。
这里显示的是一个transformer block,可以往上不断的叠加,L层这样的block叠加到一起就是最终的transformer encoder。
5.消融实验
1.cls和GAP(global average pooling,其他视觉任务中的基本操作)结果差不多
2.位置编码:1d,2d,相对位置编码的结果也差不多
2d编码:分别用D/2的向量去描述横纵坐标
相对位置编码:两者之间差了几个单位距离
3.归纳偏置:较少的使用到了2d位置信息
4.混合模型:不使用投影而是直接使用CNN得到16*16的patch
5.微调:当图像块大小变大时,效果理论上会变好,但是位置信息变得不可用起来,因为大图片和小图片被切分成了不同的块数,位置信息变得无效。这里做了个简单的2d差值。