神经网络学习笔记3——Transformer、VIT与BoTNet网络 系列文章目录神经网络学习笔记1——ResNet残差网络、Batch Normalization理解与代码神经网络学习笔记2——VGGNet神经网络结构与感受野理解与代码文章目录系列文章目录A、Transformer模型一、细节补充1.并行计算2、BatchNorm和LayerNorm二、编码器-解码器encode-decode三、注意力机制Attention四、自注意力机制Self-Attention五、多头注意力机制Multi-Head AttentionB、VITVision Transformer模型一、transformer与图像二、模型分析1、Embedding层2、Transformer Encoder模块3、MLP Head模块C、Bottleneck Transformer(BoTNet)网络混合模型一、Multi-Head Self-Attention模块二、Bottleneck TransformerD、总结A、Transformer模型最近Transformer在CV领域很火Transformer是2017年Google在Computation and Language上发表的当时主要是针对NLP自然语言处理领域提出的主要针对的是NLP领域里的机器翻译任务。在此之前大家处理这类的任务使用的模型都是RNN、LSTM之类的时序网络但是这类模型不可避免的存在着记忆长度有限或者说所能利用到的语句信息是有限的这种问题以及随着序列长度增加带来的梯度爆炸梯度消失等问题虽然LSTM在RNN的基础上一定程度地缓解了这类问题但这类基于RNN的网络模型另外一个比较严重的问题是不能并行化。想要计算tn时刻的数据必须要先计算tn-1时刻的数据无法并行化带来的问题就是计算效率特别低。针对这些问题谷歌团队提出了Transformer中文名变形金刚现在的Transformer被认为成为类似NLP、CNN、RNN之后的第四大类基础模型或许这就是Attention Is All You Need的含金量吧。transformer的一大核心就是提出一个依赖于注意力机制Attention的模型。一、细节补充1.并行计算数据并行的模型训练中训练任务被切分到多个进程(设备)上,每个进程维护相同的模型参数和相同的计算任务但是处理不同的数据(batch data)。数据并行可通过增加并行训练设备来提高训练吞吐量。输入数据切分整个训练数据集:根据并行进程数划分,每个进程只读取自身切分的数据读取仅由具体某个进程负责, 根据并行进程数划分,再将不同数据块发送到对应进程上RNN系列的模型就必须按照顺序从 X1 计算到 Xn 这个问题导致面对即使是在GPU上RNN的计算性能依然比较差且过长的序列会导致早期的隐藏历史信息ht会被丢掉迭代掉。而RNN之所以不能并行化是因为虽然X0,X1,X2你都知道了但是由于你计算的时候不止要输入Xi还要输入上一时刻Xi-1计算的依赖ht-1那么你就不得不一个个的按顺序去计算X0得出的h0又用h0和X1得出的h1。而你无法和transformer一样直接把这批数据[X0,X1,X2,…,Xn]当作一个完整矩阵同时处理而需要一条一条的处理。Transformer的并行化是指在训练阶段的数据并行化测试阶段只有encoder可以并行化decoder不能并行化在decoder阶段可能Transformer在代码层面上可能会有点小不同。Transformer的并行化被认为主要体现在self-attention模块在Encoder端Transformer可以并行处理整个序列并得到整个输入序列经过Encoder端的输出在self-attention模块对于某个序列从 X1,X2,…,Xn self-attention模块可以直接计算 ​Xi,Xj 的点乘结果。在不考虑batch的问题时假设输入一个时间序列Xi表示i时刻X的值或者可以理解为输入一段视频Xi表示第i帧图片。训练的时候进入模型的是所有的训练集Xi同时进入而不是X0X1X2一个个依次序进入。所以transformer可以同时对这批数据进行处理各种矩阵运算也就可以并行化。2、BatchNorm和LayerNormBatchNorm一般用于CV领域而LayerNorm一般用于NLP领域这是由两个任务的本质差异决定的视觉的特征是客观存在的特征而语义特征更多是由上下文语义决定的一种统计特征因此他们的标准化方法也会有所不同。BatchNorm批量归一化批量归一化是对一个中间层的单个神经元进行归一化操作batch方向做归一化。计算第l层网络中每个神经元在Batch大小为N的样本上输出的N个结果计算每个神经元输出的N个结果的均值和方差然后使用均值和方差来对这N个输出结果做归一化所以归一化的维度是在Batch上进行的LayerNorm层归一化层归一化是对一个中间层的所有神经元进行归一化channel方向做归一化。计算第l层网络中的每个神经元在Batch中每个输入样本的输出对于每个输入样本计算所有神经元输出结果的均值和方差使用均值和方差来归一化对于这个输入样本的输出结果所以归一化的维度以在整个层上进行的都是为了更好的获取均值和方差二、编码器-解码器encode-decode编码器负责把自然语言序列映射为隐藏层含有自然语言序列的数学表达然后解码器把隐藏层在映射为自然语言序列。自回归步骤1.输入自然语言序列到编码器2.编码器输出的隐藏层在输入到解码器3.启动解码器4.得到第一个字5.将第一个字落下来再输入到解码器得到第二个字6.重复此过程直到解码器输出终止符序列生成完成。原论文的模型图这其实就是一个编码器-解码器架构可简单划分为左边的区域为编码器Inputs编码器输入Positional Enocding位置编码Nxn个这样的层堆叠Multi-Head Attention多头注意力机制层Add Norm类似残差设置归一化Feed Forward前馈神经网络第一个子层连接结构包括一个多头自注意力子层qkv来自编码器输入qkv和归一化层以及一个残差连接。第二个子层连接结构包括一个前馈全连接子层和归一化层以及一个残差连接。编码器Encoder: 由N6个相同的layers组成, 每一层包含两个sub-layers. 第一个sub-layer 就是多头注意力层multi-head attention layer然后是一个简单的全连接层。 其中每个sub-layer都加了residual connection残差连接和normalisation归一化。右边的区域为解码器Outputs解码器输入Positional Enocding位置编码Nxn个这样的层堆叠Masked Multi-Head Attention带掩码的多头注意力机制层掩盖后面的值使其权重为0Multi-Head Attention多头注意力机制层Add Norm类似残差设置归一化Feed Forward前馈神经网络第一个子层连接结构包括一个多头掩码自注意力子层qkv来自解码器输入qkv做Masked掩码和归一化层以及一个残差连接。第二个子层连接结构包括一个多头注意力子层kv来自编码器输出q来自解码器第一子层的输出和归一化层以及一个残差连接。第三个子层连接结构包括一个前馈全连接子层和归一化层以及一个残差连接。解码器Decoder: 由N6个相同的Layer组成但这里的layer和encoder不一样 这里的layer包含了三个sub-layers, 其中有一个self-attention layer, encoder-decoder attention layer 最后是一个全连接层。前两个sub-layer 都是基于multi-head attention layer。这里有个特别点就是masking, masking 的作用就是防止在训练的时候 使用未来的输出的单词。比如训练时第一个单词是不能参考第二个单词的生成结果的。Masking就会把这个信息变成0用来保证预测位置 i 的信息只能基于比 i 小的输出。三、注意力机制Attention所谓Attention机制便是聚焦于局部信息的机制比如图像中的某一个图像区域。随着任务的变化注意力区域往往会发生变化。其本质是一种通过网络自主学习出的一组权重系数并以“动态加权”的方式来强调我们所感兴趣的区域同时抑制不相关背景区域的机制。在计算机视觉领域中注意力机制可以大致分为两大类强注意力和软注意力。由于强注意力是一种随机的预测其强调的是动态变化虽然效果不错但由于不可微的性质导致其应用很受限制。与之相反的是软注意力是处处可微的即能够通过基于梯度下降法的神经网络训练所获得因此其应用相对来说也比较广泛。软注意力按照不同维度如通道、空间、时间、类别等出发目前主流的注意力机制可以分为以下三种通道注意力、空间注意力以及自注意力Self-attention。针对于注意力机制的引起方式可以分为两类一种是非自主提示另一种是自主提示。其中非自主提示指的是由于物体本身的特征十分突出引起的注意力倾向自主提示指的是经过先验知识的介入下对具有先验权重的物体引起的注意力倾向。换句话说可以理解为非自主提示源自于物体本身而自主提示源自于一种主观倾向。关于注意力与自注意力机制区别具体理解可以看看这篇博客四、自注意力机制Self-Attentionq代表query后续会去和每一个k进行匹配k代表key后续会被每个q匹配v代表Value从a中提取得到的信息后续q和k匹配的过程可以理解成计算两者的相关性相关性越大对应v的权重也就越大qkv时称为自注意机制将输入来源中的构成元素想象成是由一系列的Key,Value数据对构成此时给定目标中的某个元素Query通过计算Query和各个Key的相似性或者相关性得到每个Key对应Value的权重系数然后对Value进行加权求和即得到了最终的Attention数值。所以本质上Attention机制是对输入中元素的Value值进行加权求和而Query和Key用来计算对应Value的权重系数。另外还有一种理解方式我们可以将查询键和值理解为一种软寻址Soft Addressing。Value可以看作存储器存储的内容Key看作是存储器的地址。当KeyQuery时则取出Key地址对应存储器中的Value值这被称为硬寻址。而软寻址则是通过计算Key和Query的相似度来进行寻址这种方法不只是获取一个Key地址中存储器的Value值而是获取所有的存储器中的Value值的加权和 。至于每个Value的权重重要程度是通过Key和Query相似度计算得到的最终的输出是所有Value值和其权重的加权和。Attention机制的具体计算过程如果对目前大多数方法进行抽象的话可以将其归纳为两个过程第一个过程是根据Query和Key计算权重系数第二个过程根据权重系数对Value进行加权求和。而第一个过程又可以细分为两个阶段第一个阶段根据Query和Key计算两者的相似性或者相关性第二个阶段对第一阶段的原始分值进行归一化处理五、多头注意力机制Multi-Head Attention根据模型图可以理解为将原始的V、K、Q单独输入线性层处理投影到比较低的维度然后做h次Scaled Dot-Product Attention并得到h个输出合并输出最后做一次线性投影。通过一个注意力机制的多次并行运行将独立的注意力输出串联起来线性地转化为预期维度。直观看来多个注意头允许对序列的不同部分进行注意力运算允许模型同时关注来自不同位置的不同表示子空间的信息。多头注意力通过利用同一查询的多个不同版本并行实现多个注意力模块来工作。其思想是使用不同的权重矩阵对查询进行线性变换得到多个查询。每个新形成的查询本质上都需要不同类型的相关信息从而允许注意模型在上下文向量计算中引入更多信息。每个头都创建了自己对查询和输入矩阵的表示从而允许模型学习更多的信息。例如在训练语言模型时一个注意力头可以学习关注某些动词例如行走、驾驶、购买与名词例如学生、汽车、苹果的关系而另一个注意力头部则学习关注代词例如他、她、it与名词的关系可以像卷积一样学到更多东西。每个头还将创建自己的注意力得分向量以及相应的注意力权重向量B、VITVision Transformer模型从深度学习暴发以来CNN一直是CV领域的主流模型而且取得了很好的效果相比之下基于self-attention结构的Transformer在NLP领域大放异彩。虽然Transformer结构已经成为NLP领域的标准但在计算机视觉领域的应用还非常有限。ViTvision transformer是Google在2020年提出的直接将Transformer应用在图像分类的模型通过这篇文章的实验给出的最佳模型在ImageNet1K上能够达到88.55%的准确率先在Google自家的JFT数据集上进行了预训练说明Transformer在CV领域确实是有效的而且效果还挺惊人。VIT推动了NLP与CV的统一促进了多模态领域的发展。一、transformer与图像硬件支持的序列长度一般为几百到上千而transformer需要把2维图片转为1维序列比如说一张图片输入大小为224x224以像素点为基础进行拉长为序列那么序列长度为224x22450176平方复杂度太大。如何降低序列长度1、提纯出特征图作为输入比如resnet后期的特征图就会比较小可以作为transformer输入。2、Stand-Alone Attention孤立自注意力切分为局部小窗口控制输入。3、Axial Attention轴注意力把高宽hw拆分成两个1维矩阵分别做自注意力。4、vit将图像切分为n个patch每个patch作为一个元素进行输入一个图片等价于一句话一个patch等价于一个单词。二、模型分析给定一张图像左下角并划分成n个patch把patch作为元素并排成一个序列每个patch都会通过Linear Projection of Flattened Patches线性投射层也就是一个全连接层进行处理给patch加上位置编码得到Patch Position 的Embedding层token通过Extra learnable embedding和位置编码额外加入class token0*通过token之间做交换信息时学习所需信息使用DropOut/DropPath正则化处理传入Transformer Encoder模块处理根据embedding0*和MLP Head通用分类头分类用MLP交叉熵函数进行模型训练1、Embedding层从图中看Transformer Encoder读入的是一小块一小块这样的图片。这样做的原因是将一个个小块图像视为tokentoken可以理解为NLP中的一个字或词在Transformer中计算每个token之间的相关性。这一点就和卷积神经网络有很大区别了。以往的CNN以卷积 池化的方式不断下采样这样理论上模型可以通过加深模型深度达到增大感受野的目的。不过这样会有两个缺点实际结果中显示CNN对边缘的响应很弱。这也非常好理解越靠边缘的像素因为被卷积次数少自然在梯度更新时贡献更少。CNN只能和临近像素计算相关性。由于其滑窗卷积的特性无法对非领域的像素共同计算例如左上角的像素无法和右下角的像素联合卷积。这就导致了某些空间信息是无法利用的。同时根据MAE论文中所说的自然图像具有冗余性即相邻像素点代表的信息是差不多的所以只计算领域像素无法最大化利用图像特征。回到ViT中仅仅把图像拆分成小块patch是不够的Transformer Encoder需要的是一个向量shape为[num_token, token_dim]。对于图片数据来说shape为[H,W,C]是不符合要求的所以就需要转换要将图片数据通过这个Embedding层转换成token。以ViT-B/16为例假设输入图像为224x224x3一个token原始图像shape为16x16x3那这样就可以将图像拆分成(224/16)^2 196个patch也就是196个图像块然后将每个图像块线性映射至一维向量中那么这个一维向量的长度即为16163768维。将196个token叠加在一起最后维度就是[196, 768]。同时需要注意的是token可以添加位置编码。由于self-attention的机制在没有字符位置的情况下图片切割出来的patch会被打乱所以当添加了位置编码分类准确率将会更高。其中位置编码也分1-D、2-D、Relative但是差别不会很大。另外输入tensor还需要有一个额外的class token0*class token0*不管是NLP还是图像都在使用主要是作为图像的整体特征它的数据格式是[1,768]方便与后面其他token的信息直接拼接这样做是因为分类信息是在后面需要取出来单独做预测的shape也就从[196, 768]变为[197, 768]。2、Transformer Encoder模块Transformer Encoder也就是堆叠encoder block几次和常规的CNN类似主要由几个部分组成Layer Normalization相比于Batch Normalization来说BN是针对所有的样本对某一个特征图计算均值和方差然后然后对这个特征图神经元做归一化。LN是对某一个样本计算该样本所有特征图的均值和方差然后对这个样本做归一化。BN适用于不同mini batch数据分布差异不大的情况而且BN需要开辟变量存每个节点的均值和方差空间消耗略大而且 BN适用于有mini_batch的场景。LN只需要一个样本就可以做归一化可以避免 BN 中受 mini-batch 数据分布影响的问题也不需要开辟空间存每个节点的均值和方差。K、Q、VKQV每个都是[197,768]也就是KQV维度是197x(768/Lx)后面的输出拼接后又会还原为768的。Multi-Head Attention这个结构是self-attention中的一种上面有做详细介绍。DropOut/DropPathViT-B/16模型是使用了DropOut但实际别人复现的代码中使用的是DropPath。两者对最后的结果影响不大这里也不展开详细说了。MLP Block由一个全连接层 GELU激活函数 DropOut组成采用的是倒瓶颈结构输入特征层经过一次全连接之后放大通道膨胀为原来的4倍后一个全连接层再恢复成原来的数目。所以经过MLP Block之后tensor的shape是不变的。Lx进行L个堆叠3、MLP Head模块经过Transformer Encoder后输出tensor的shape和输入tensor的shape是一样的以ViT-B/16为例输入是[197, 768]输出还是[197, 768]。下游任务如果是分类模型需要提取出对应的class token0*获取分类结果。Vision Transformer中说MLP是由一个全连层 Tanh激活 全连接层组成。但实际使用起来一层全连接层直接做分类即可后面如果需要得到每个类别的概率的话需要接上一个softmax激活函数。C、Bottleneck Transformer(BoTNet)网络混合模型一种简单却功能强大的backbone该架构将自注意力纳入了多种计算机视觉任务,是 CNN Attention的结合包括图像分类目标检测和实例分割。该方法在实例分割和目标检测方面显著改善了基线同时还减少了参数从而使延迟最小化。将卷积和自注意力进行结合其中一大原因就是因为纯 ViT 类型的结构对于输入尺寸特别敏感不能变动是 224 × 224 224 就是 224 × 224 224 。然而我们的目标检测实例分割等任务的输入可能是 1024 × 1024 1024 的大图。如果硬Train一发纯 Transformer计算量怕机器吃不消。BoTNet 则是将 Attention 模块融入到 CNN 原有的 backbone 中通过且仅在ResNet中用Multi-Head Self-Attention (MHSA)来替换3 × 3 convolution并且不进行其他任何更改。resnet模型可以看我之前的博客一、Multi-Head Self-Attention模块这个MHSA Block是核心创新点其中高度和宽度的相对位置编码分别为 Rh 和 Rw。其中 q、 k、 v 分别代表查询、键和权值。十 和 X 分别代表逐元素求和和矩阵乘法而 1x1 代表逐点卷积。蓝色的部分分别代表位置编码position encodings 和 价值映射value projection。具体步骤传入输入XX的格式应该是H × W × d 分别表示输入特征矩阵的高宽以及单个 token 的维度把X分别作为WQ、WK、WV初始化两个可学习的参数向量 Rh和Rw分别表示高度和宽度不同位置的位置编码然后将它们通过广播机制加起来那就是二维 ( i , j ) 位置的编码为 Rhi Rwj 的两个 d维向量相加这与VIT的一维位置编码不同。输出r代表位置编码。注意现在有四个参数分别为q、w、v、r他们的矩阵格式都是H × W × d。将qr进行矩阵乘法得到内容位置content-position输出qrT 将qk进行矩阵乘法得到内容-内容content-content输出qkT。将qrT与qkT进行矩阵加法并对得到的矩阵进行softmax归一化指数处理处理输出的值的矩阵格式为HW×HW。最后将输出值与权值V进行矩阵乘法得到输出Z。其与之前的Transformer中的MHSA有所不同由于处理对象不是一维的而是类似CNN模型所以有非常多特性与此相关。归一化这里并没有使用Layer Norm而是采用的Batch Norm与CNN一致。非线性激活BoTNet使用了三个非线性激活左侧content-position模块引入了二维的位置编码这是与Transformer中最大区别。BotNet即将ResNet中的第4个block中的bottleneck替换为MHSAMulti-Head Self-Attention模块形成新的模块取名叫做Bottleneck Transformer (BoT) 。仅仅对ResNet-50 C5结构的更换最终测试却在Mask R-CNN的实例分割在coco数据集上取得了44.4% Mask AP 49.7% Box AP。在分类任务中在 ImageNet上取得了84.7%的top-1准确性。并且比 EfficientNet快2.33倍。既然MHSA这么强大为什么不把C2到C5的所有3X3卷积层都更换为MHSA呢论文中提及如果全部更换为MHSA其计算量将会是几何甚至指数级提升但带来的效益却远远不成正比。所以最终只修改了C5的结构C5的Bottleneck也不一定3个全用MHSA。二、Bottleneck Transformer在 Multi-Head Self-Attention 结构前后加上 1 × 1 卷积就得到了 Bottleneck Transformer。Bottleneck Transformer 和 ViT 中的 Transformer block 其实是有亲属关系的他们不是差异很大的结构。作者在论文中首先提到说具有 MHSA 的 ResNet botteneck 块可以被视作具有 bottleneck 结构其他方面具有微小差异例如残差结构正则化层等的 Transformer 块。最右边的是单个C5层把上一层的输出进行收缩Contraction维度从2048缩小512(÷4作为输入经过MHSA模块得到H×W×512的输出再经过扩大Expansion从512放大2048(×4作为输出。D、总结Transformer、VIT与BoTNet的原理及模型结构基本的学习就到这了对于实际使用的话可能暂时不做因为还没有合适的机会与一定的硬件局限。原因是虽然在当时实验结果达到了SOTA但是相比于CNN它需要更多的数据集。在小数据集上训练出来的精度是不如CNN的但在大数据集上ViT精度更高需要更多的数据和更好的训练平台是我所欠缺的。存在这种差异的一个直观的解释是ViT因为self-attention独特的机制更多的利用token与token跨像素之间的信息而CNN只是对领域的像素进行计算所以相同参数的情况下ViT获得的信息更多在某种程度上可以看成是模型深度更深。所以小数据集上ViT是欠拟合的。所以实际开发中的做法是基于上千万级别的大数据集上训练得到一个预训练权重然后再在小数据集上做迁移虽然论文谈及vit相对不贵贵是指训练消耗之类的意思但这都是相对于大数据集而言的在中小数据集层面CNN还是相当好用的。