VIT代表着transformer向cv领域的正式进军,nlp在transformer中将字符转为token,如要将cv中每个像素点作为token,224*224=50176>>512,参数量巨大。VIT提供了一个成功的思路将图像转为一定长度的token又能保留二维空间信息。

VIT步骤为:

1、将图像切分为patch,如将224*224的图片切成16*16的patch,每个patch的大小为16*16*3

2、将patch信息拉平,线性层映射为指定位数如768或1024(embedding size),这一步也可以不使用线性层而用16x16尺度,步长为16,通道数为768的卷积实现

3、采用torch.rand随机初始化的方式分别生成cls符号的token embedding、所有序列的位置编码,位置编码与token embedding相加。VIT采用了自动学习的位置编码方式

4、多个Transforer编码器组成的模型主体

5、取出cls信息作loss计算

vit采用了transformer的编码部分,区别在于

1)Norm前置

2)输入大小是固定的,无需进行pad

FAQ:

Q:位置编码目的

A: rnn的输入有时序关系,但transformer的patch是一起输入的,需增加前后关系

Q:位置编码为什么是相加而不是拼接

A:拼接维度变大,未见到什么特别有说服力的说法

Q:为什么是1维位置编码

A:对比后加一维比不加好,改成2维、相对位置编码区别不大

Q: fast qkv

A: 有些模型只用到了transformer的编码结构,编码结构中qkv可以通过1个线性层统一计算后再chunk切块操作分头成3个q、k、v。解码结构中q来自解码端,k、v来自编码端就不能这么操作。

# fast qkv 方式
# 使用torch.chunk函数(torch.cat的逆函数),将qkv拆成3个部分,分别是q、k、v,每一个尺寸均为(n_batch, n_token, hidden_size)

self.qkv_linear = nn.Linear(config.hidden_size, 3 * self.all_head_size, bias=False)   # 768->3*768
qkv = self.qkv_linear(hidden_states)
q, k, v = torch.chunk(qkv, 3, dim=-1)


# 分别计算方式
self.query = nn.Linear(config.hidden_size, self.all_head_size)  # 768->768            self.key = nn.Linear(config.hidden_size, self.all_head_size)
self.value = nn.Linear(config.hidden_size, self.all_head_size)
q = self.query(hidden_states)
k = self.key(hidden_states)
v = self.value(hidden_states)

缺点:

        1)需要大数据集进行预训练,小规模数据集上效果会差一点,收敛速度也比resnet等慢。在中小型数据集上预训练,ViT是不如resent的,只有在大型数据集上预训练,ViT表现要比resent好。后面的Deit、Beit通过修改预训练任务的方式解决这个问题。

        2)不适合于高分辨率场景。swinT解决了这个问题。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐