关于transformer与图像分类的文章参考:
https://blog.csdn.net/qq_40688292/article/details/112540486
关于transformer更具体的学习:(bilibili霹雳吧啦Wz):
Transformer
Transformer原论文:Attention is all you need
Transformer:最开始是针对NLP自然语言处理领域。
RNN记忆长度有限,所以后面有人提出LSTM,但它无法并行化(必须计算t0才能计算t0+1时刻的数据)。
而Transformer如果不受硬件限制,它的记忆长度可以无限长。同时,它可以做并行化。
Transformer中的Self-Attention以及Multi-Head Attention讲解:
Self-Attention
attention公式:
-
假设输入时序数据是x1、x2;
-
将x通过Embedding层,映射到更高的维度上,得到对应的a;(Embedding是将高维度数据变成低维度数据)
-
将a分别通过Wq、Wk、Wv这三个生成矩阵,生成对应的q、k、v;(Wq、Wk、Wv是共享的,通过全连接层实现的,可训练的参数)
忽略偏置,方便理解:
q:匹配每一个k,而k也是通过每一个a与每一个Wk相乘得到对应k1、k2;
是一个向量值乘一个矩阵得到一个键值
之后,k与q进行match
v:从a当中提取得到的(它认为有用的)信息(也是上面那么算); -
整个过程可以并行化,用矩阵乘法的方式书写。
最终得到Q、K、V。 -
将所求得的Q与每一个K来进行match操作;得到针对每个V的权重。
q1与每一个k的match:
q2与每一个k的match:
使用矩阵乘法:
k1k2放一起,要把它们转置(因为q1要分别乘以k1与k2得出结果,不转置的话没法乘)
向量点乘值越大表示向量间夹角越小,也就表示向量越相近。 -
用↑求得的α^(针对每一个V的权重大小)乘上V。权重越大,则会越关注某个V。
-
利用求得的α^做进一步操作:
即为Attention公式 -
将Self-Attention抽象成一个模块,输入a1、a2得到b1、b2。
Multi-Head Self-Attention
在Transformer里面使用最多的还是Multi-Head Self-Attention模块。
9. 还是和上面的一样,用a和Wq、Wk、Wv相乘得到对应的q、k、v。(与Self-Attention一模一样)
根据head对数据进行拆分。通过线性映射,把q均分给每个head(如q1)。
同理,将所有的k和v都进行拆分。
拆分后将第二个数值为1的参数全部归为head1:
把k和v也写成矩阵乘法的形式进行拆分:
head2:
(多头注意力其实就是类似卷积增加通道的操作,为了提取更多维度更多方式的特征)
- 对每一个head得到的结果进行拼接:
Concat:对每个head进行拼接。
把第一个数值相同的部分进行拼接。
- 使用Wo对拼接后的数据进行进一步融合。
- 关于位置编码:
把a3和a2的位置调换,发现对b1没有影响,可知这样是有问题的。
(弹幕:比如你需要翻译一个句子,输入“我是妈妈”和“我妈妈是”翻译结果肯定不一样,但是这里如果不加以处理就会处理成一样的结果)
所以提出了一个位置位置编码的思想: - 对每个ai,都加上一个pei(对应位置编码positional encoding),能相加就说明它们的shape是一样的。
pei的求得有两种方法:
论文原文中两种方法的结果没有太大差异。
Vision Transformer(vit)网络详解
ViT模型结构:
架构:
- 首先输入一张图片,把它分成好多patches
- 将每个patches输入Embedding层(Linear Projection of Flattened Patches),分别得到一个个向量(token)。
- 在这一系列token的最前边加上一个新的token,专门用于分类的class token。这个class token的维度跟之前的token一样,都是向量且向量长度一样。
加上位置信息,对应这里的0,1,…,9。 - 把(原token+class token+位置参数)输入Transformer Encoder(将Encoder block重复堆叠L次)中;
- 将class token所对应的输出通过MLP Head,得到最终的分类结果。
对每个模块细讲:
Embedding层
每个token对应一个向量。
图中的16:对应patches大小
(
弹幕:9个patches 每个patch相当于是1616的小图片
)
768:token维度(弹幕:每一个通道分成1616个小patch 3个通道共可以分成768个)
[14,14,768]后将高度和宽度这两个维度展平(14x14=196),得到196个token,每个token的维度是768。
加上类别token:初始化一个可训练的参数,大小是[1,768](维度要与之前的token相同)
将图片的patches通过embedding层和flatten之后,得到的tensor的shape是[196,768]。
拼接之后得到[197,768].
叠加位置编码(可训练的编码),此处直接通过相加的方式,要与[197,768]的形状保持一致。相加之后shape保持不变:[197,768]。
Position Embedding层
(
1-d是一维的位置编码,就是把位置定义为 0 1 2 3…
)
使用与不适用的差别较大,而位置编码的差异并不是很重要。所以源码中默认使用1D的Position,更简单,且参数更少。
关于训练得到的位置编码,它的每个位置上与其他位置上的余弦相似度:
在每个token上叠加位置编码,对每一个patches的位置编码,其实就是一个向量,可以针对每一个位置上的位置编码对其他位置上的编码去求得一个余弦相似度,得到了这幅图。
(弹幕:使用余弦相似度来表明任意两个patches之间在位置上的关联度)
颜色变化:-1~1,呈越来越亮的趋势。
就是每个小小格子和其它小小格子计算相似度,所有的小格子其实都是同一张图。
每个小小格子(这个patches所对应的位置编码)与它所在行与所在列的相似度都比较高。
(
为什么用cosine dist做encoding,因为三角函数有叠加性,所以留下了可以学习远处图片的可能性,其实这里应该才是为什么vit可能优于cnn
)
与最后一行和最后一列的相似度比较高,这就是最终学习到的位置编码。
Transformer Encoder层
将encoder block重复堆叠L次。
(类似于VGG的重复堆叠)
在transformer endoder前还有个dropout
MLP Head层
可以简单地理解为一个全连接层,如果要得到每个类的概率,就接上一个softmax函数
ViT-B/16
up主手绘的图:(太强了)
1、假设输入的图片是一张RGB彩色图片。
2、通过embedding层(卷积+flatten)
3、contact一个class token(可训练参数)
4、加上position embedding
5、通过dropout层
6、经过transformer encoder (就是将encoder block重复L次)
7、通过layer normal
8、直接对输出进行切片,提取class token 所对应的输出(1x768)
(弹幕:
可以理解为class是所有样本信息的特征提取,类似于cnn的卷积层,提取到我们想要的特征,最后丢到全连接去分类
)
9、通过MLP Head得到对应输出。可以根据训练方式来决定是否需要Pre-Logits。
3个ViT模型的参数
具体解释看原视频,我不记了。
Hybrid混合模型
用传统的网络去提取特征,再通过ViT模型进一步得到最终的结果。
此处的特征提取部分采用的是resnet50。但是与之前讲过的resnet50不一样:
以R50为backbone的混合架构模型:
1、先通过R50 backbone进行特征提取,而不是通过卷积核大小为16x16(举例)的卷积进行下采样。
在原r50网络中stage3重复6次
下采样了16倍。
2、将数据通过embedding层
3、后面的跟ViT一样
纯transformer与混合transformer
随着迭代训练次数epoch增多,ViT模型的精度会慢慢超过混合模型。