VIT 简单理解

关键思想:
ViT将输入图片分为多个patch(16x16),
再将每个patch投影为固定长度的向量送入Transformer,后续encoder的操作和原始Transformer中完全相同。

在这里插入图片描述

但是因为对图片分类,因此在输入序列中加入一个特殊的token,该token对应的输出即为最后的类别预测;

1. 将图片分割成多个patches;

例如输入图片大小为224x224,

  1. 将图片分为固定大小的patch,patch大小为16x16,
    则一张图像会生成(224/16)x (224/16) = 14x14 =196个patch,

  2. 即输入序列长度为196,每个patch维度16x16x3=768,( 即输入196 个列向量,每个列向量的维度为768)

  3. 线性投射层的维度为768xN (N=196),因此输入通过线性投射层之后的维度依然为196x768,即一共有196个token,每个token的维度是768。

  4. 这里还需要加上一个特殊字符cls,因此最终的维度是197x768。

到目前为止,已经通过patch embedding将一个视觉问题转化为了一个seq2seq问题;

1.1 使用 einops 库

其中, 每一对括号代表的是一个维度,

并且image patches 总是 表示成 括号的形式;

pip install einops

from einops import rearrange

p = patch_size # P in maths

x_p = rearrange(img, 'b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = p, p2 = p)

2. 加入位置编码

ViT同样需要加入位置编码,位置编码可以理解为一张表,表一共有N行,N的大小和输入序列长度相同,每一行代表一个向量,向量的维度和输入序列embedding的维度相同(768)。

注意位置编码的操作是sum,而不是concat。加入位置编码信息之后,维度依然是197x768;

2.1 不同位置编码

1-D 位置编码:例如3x3共9个patch,patch编码为1到9

2-D 位置编码:patch编码为11,12,13,21,22,23,31,32,33,即同时考虑X和Y轴的信息,每个轴的编码维度是D/2

实际实验结果表明,不管使用哪种位置编码方式,模型的精度都很接近,甚至不适用位置编码,模型的性能损失也没有特别大。原因可能是ViT是作用在image patch上的,而不是image pixel,对网络来说这些patch之间的相对位置信息很容易理解,所以使用什么方式的位置编码影像都不大
在这里插入图片描述

3. multi-head

LN输出维度依然是197x768。多头自注意力时,先将输入映射到q,k,v,如果只有一个头,qkv的维度都是197x768,

如果有12个头(768/12=64),则qkv的维度是197x64,一共有12组qkv,最后再将12组qkv的输出拼接起来,输出维度是197x768,然后在过一层LN,维度依然是197x768;

在这里插入图片描述

4.MLP.

将维度放大再缩小回去,197x768放大为197x3072,再缩小变为197x768

一个block之后维度依然和输入相同,都是197x768,因此可以堆叠多个block。最后会将特殊字符cls对应的输出 [公式] 作为encoder的最终输出 ,代表最终的image presentation(另一种做法是不加cls字符,对所有的tokens的输出做一个平均),如下图公式(在这里插入图片描述
),后面接一个MLP进行图片分类;

假设输入的图片是: x ∈ R H ∗ W ∗ C x \in R^{H*W*C} xRHWC,

目标是生成 N 个patch,

则生成的每个patch 大小为 x p ∈ R p ∗ p ∗ c x_{p} \in R^{ p * p * c} xpRppc,

N 的个数为 N = H ∗ W p ∗ p N = \frac{H*W}{p*p } N=ppHW;

从而此时的 N 个patch 便可以, 看做构成一个序列

6. image presentation

是否可以直接使用average pooling得到最终的image presentation,而不加特殊字符cls,通过实验表明,同样可以使用average pooling,原文ViT是为了尽可能是模型结构接近原始的Transformer,所以采用了类似于BERT的做法,加入特殊字符

学习率的影响较大,注意调参
在这里插入图片描述

7. 在下游任务上, 使用任务数据集去训练网络;

通常在一个很大的数据集上预训练ViT,然后在下游任务相对小的数据集上微调,已有研究表明在分辨率更高的图片上微调比在在分辨率更高的图片上预训练效果更好(It is often beneficial to fine-tune at higher resolution than pre-training)(参考2019-NIPS-Fixing the train test resolution discrepancy)

当输入图片分辨率发生变化,输入序列的长度也发生变化,虽然ViT可以处理任意长度的序列,但是预训练好的位置编码无法再使用(例如原来是3x3,一种9个patch,每个patch的位置编码都是有明确意义的,如果patch数量变多,位置信息就会发生变化),一种做法是使用插值算法,扩大位置编码表。但是如果序列长度变化过大,插值操作会损失模型性能,这是ViT在微调时的一种局限性

code :

https://github.com/The-AI-Summer/self-attention-cv

关于CNN+Transformer

既然CNN具有归纳偏置的特性,Transformer又具有很强全局归纳建模能力,使用CNN+Transformer的混合模型是不是可以得到更好的效果呢?将224x224图片送入CNN得到16x16的特征图,拉成一个向量,长度为196,后续操作和ViT相同

8. 小结

ViT原论文中最核心的结论是,当拥有足够多的数据进行预训练的时候,ViT的表现就会超过CNN,突破transformer缺少归纳偏置的限制,可以在下游任务中获得较好的迁移效果

但是当训练数据集不够大的时候,ViT的表现通常比同等大小的ResNets要差一些,因为Transformer和CNN相比缺少归纳偏置(inductive bias),即一种先验知识,提前做好的假设。CNN具有两种归纳偏置,一种是局部性(locality/two-dimensional neighborhood structure),即图片上相邻的区域具有相似的特征;一种是平移不变形(translation equivariance)其中g代表卷积操作,f代表平移操作。当CNN具有以上两种归纳偏置,就有了很多先验信息,需要相对少的数据就可以学习一个比较好的模型;

cls 的 token , 是指创建一个 token, 该toke n 代表的是该图片所对应的类别, token 的维度 以 序列中其他的 token 维度保持一致;

每个位置 与 其他位置的 余弦相似度,

  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值