1. 图解什么是 Transformer
Transformer 是 Google 团队在 17 年 6 月提出的 NLP 经典之作,
由 Ashish Vaswani 等人在 2017 年发表的论文 Attention Is All You Need 中提出。
Transformer 在机器翻译任务上的表现超过了 RNN,CNN,只用 encoder-decoder 和 attention 机制就能达到很好的效果,最大的优点是可以高效地并行化。
Transformer 是一种基于 encoder-decoder 结构的模型,
在 Encoder 中,
在 Decoder 中,
下面我们具体看一下其中这几个概念,这里主要参考 Jay Alammar,他在 The Illustrated Transformer 中给出了很形象的讲解。
例如我们要进行机器翻译任务,输入一种语言,经过 Transformer,会输出另一种语言。
Transformer 的 encoder 由 6 个编码器叠加组成,
decoder 也由 6 个解码器组成,
在结构上都是相同的,但它们不共享权重。
每一个 encoder 都分为两个子层:
每一个 decoder 也具有这两个层,但还有一个注意力或差层,用来帮助解码器关注输入句子的相关部分
首先使用嵌入算法将输入的 word 转换为 vector,
最下面的 encoder ,它的输入就是 embedding 向量,
在每个 encoder 内部,
输入向量经过 self-attention,再经过 feed-forward 层,
每个 encoder 的输出向量是它正上方 encoder 的输入,
向量的大小是一个超参数,通常设置为训练集中最长句子的长度。
在这里,我们开始看到 Transformer 的一个关键性质,
即每个位置的单词在 encoder 中都有自己的路径,
self-attention 层中的这些路径之间存在依赖关系,
然而在 feed-forward 层不具有那些依赖关系,
这样各种路径在流过 feed-forward 层时可以并行执行。
Positional Encoding 是一种考虑输入序列中单词顺序的方法。
encoder 为每个输入 embedding 添加了一个向量,这些向量符合一种特定模式,可以确定每个单词的位置,或者序列中不同单词之间的距离。
例如,input embedding 的维度为4,那么实际的positional encodings如下所示:
在下图中,是20个单词的 positional encoding,每行代表一个单词的位置编码,即第一行是加在输入序列中第一个词嵌入的,每行包含 512 个值, 每个值介于 -1 和 1 之间,用颜色表示出来。
可以看到在中心位置分成了两半,因为左半部分的值由一个正弦函数生成,右半部分由余弦函数生成,然后将它们连接起来形成了每个位置的编码向量局团扒。
当然这并不是位置编码的唯一方法,只是这个方法能够扩展到看不见的序列长度处,例如当我们要翻译一个句子,这个句子的长度比我们训练集中的任何一个句子都长时。
例如我们要翻译:”The animal didn't cross the street because it was too tired” 这句话
这句话中的“it”是指什么?它指的是 street 还是 animal?
这对人类来说是一个简单的问题,但对算桐昌法来说并不简单。
而 Self-Attention 让算法知道这里的 it 指的是 animal
当模型在处理每个单词时,self-attention 可以帮助模型查看 input 序列中的其他位置,寻找相关的线索,来达到更好的编码效果。它的作用就是将对其他相关单词的“understanding”融入我们当前正在处理的单词中。
例如上图中,在第5层时,我们就知道 it 大概指的是 animal 了。
第一步,为编码器的每个输入单词创建三个向量,
即 Query vector, Key vector, Value vector
这些向量通过 embedding 和三个矩阵相乘得到,
请注意,这些新向量的尺寸小于嵌入向量。它们的维数为64,而嵌入和编码器输入/输出向量的维数为512.它们不一定要小,这是一种架构选择,可以使多头注意力计算(大多数)不变。
将x1乘以WQ得到Query向量 q1,同理得到Key 向量 和, Value 向量
这三个向量对 attention 的计算有很重要的作用
第二步,是计算一个得分
假设我们要计算一个例子中第一个单词 “Thinking” 的 self-attention,就需要根据这个单词,对输入句子的每个单词进行评分,这个分数决定了对其他单词放置多少关注度。
分数的计算方法是,
例如我们正在考虑 Thinking 这个词,就用它的 q1 去乘以每个位置的 ki
第三步和第四步,是将得分加以处理再传递给 softmax
将得分除以 8(因为论文中使用的 key 向量的维数是 64,8 是它的平方根)
这样可以有更稳定的梯度,
然后传递给 softmax,Softmax 就将分数标准化,这样加起来保证为 1。
这个 softmax 分数决定了每个单词在该位置bbei表达的程度。
很明显,这个位置上的单词将具有最高的softmax分数,但有时候注意与当前单词相关的另一个单词是有用的。
第五步,用这个得分乘以每个 value 向量
目的让我们想要关注单词的值保持不变,并通过乘以 0.001 这样小的数字,来淹没不相关的单词
第六步,加权求和这些 value 向量
这就是第一个单词的 self-attention 的输出
得到的向量接下来要输入到前馈神经网络,在实际实现中用矩阵乘法的形式完成
论文中还增加一种称为 multi-headed 注意力机制,可以提升注意力层的性能
它使得模型可以关注不同位置
虽然在上面的例子中,z1 包含了一点其他位置的编码,但当前位置的单词还是占主要作用, 当我们想知道“The animal didn’t cross the street because it was too tired” 中 it 的含义时,这时就需要关注到其他位置
这个机制为注意层提供了多个“表示子空间”。下面我们将具体介绍,
1. 经过 multi-headed , 我们会得到和 heads 数目一样多的 Query / Key / Value 权重矩阵组
论文中用了8个,那么每个encoder/decoder我们都会得到 8 个集合。
这些集合都是随机初始化的,经过训练之后,每个集合会将input embeddings 投影到不同的表示子空间中。
2. 简单来说,就是定义 8 组权重矩阵,每个单词会做 8 次上面的 self-attention 的计算
这样每个单词会得到 8 个不同的加权求和 z
3. 但在 feed-forward 处只能接收一个矩阵,所以需要将这八个压缩成一个矩阵
方法就是先将8个z矩阵连接起来,然后乘一个额外的权重矩阵WO
下图显示了在例句中,it 的不同的注意力 heads 所关注的位置,一个注意力的焦点主要集中在“animal”上,而另一个注意力集中在“tired”,换句话说,it 是 “animal”和“tired”的一种表现形式。
当然如果选了8个层,将所有注意力 heads 都添加到图片中,就有点难以解释了。
这里有一个细节,
即在每个 encoders 和 decoders 里面的 self-attention, ffnn,encoders-decoders attention 层,都有 resial 连接,还有一步 layer-normalization
下面我们看一下 Decoder 部分
1. 输入序列经过编码器部分,然后将最上面的 encoder 的输出变换成一组 attention 向量 K和V
这些向量会用于每个 decoder 的 encoder-decoder attention 层,有助于解码器聚焦在输入序列中的合适位置
重复上面的过程,直到 decoder 完成了输出,每个时间步的输出都在下一个时间步时喂入给最底部的 decoder,同样,在这些 decoder 的输入中也加入了位置编码,来表示每个字的位置。
2. 解码器中的 self attention 层与编码器中的略有不同
在解码器中,在 self attention 的 softmax 步骤之前,将未来的位置设置为 -inf 来屏蔽这些位置,这样做是为了 self attention 层只能关注输出序列中靠前的一些位置。
Encoder-Decoder Attention 层的工作方式与 multiheaded self-attention 类似,只是它用下面的层创建其 Queries 矩阵,从编码器栈的输出中获取 Keys 和 Values 矩阵。
3. 解码器最后输出的是一个向量,如何把它变成一个单词,这就要靠它后面的线性层和 softmax 层
线性层就是一个很简单的全连接神经网络,将解码器输出的向量映射成一个更长的向量。
例如我们有 10,000 个无重复的单词,那么最后输出的向量就有一万维。
每个位置上的值代表了相应单词的分数。
softmax 层将这个分数转换为了概率。
我们选择概率最大的所对应的单词,就是当前时间步的输出。
学习资源:
https://arxiv.org/pdf/1706.03762.pdf
https://jalammar.github.io/illustrated-transformer/
https://ai.googleblog.com/2017/08/transformer-novel-neural-network.html
2. Transformer详解,输入部分(词嵌入、位置编码)
由图可知:
inputs和带标签的输入分别进encoder和decoder
Positional Encoding
线性层
softmax层
由N个念渣编码器堆叠而成
每个编码器有两个子层相连接
第一个子层橘好->多头 自注意力机制 和规范化层以及一个残差连接
第二个子层->全连接层和规范化层以及一个残差连接
由N个解码器堆叠而成
每个编码器有三个子层相连接
第一个子层->一个多头 自注意力机制 层和规范化层以及一个残差连接
第二个子层->多头 注意力机制 和规范化层以及仔伍悄一个残差连接
第三个子层->全连接层和规范化层以及一个残差连接
目的是为了将目标文本的 数字表示 ->向量表示,为了在高维空间捕捉词汇间的关系
效果如下
在Transformer编码器中没有针对词汇位置信息的处理,故需要在embedding层后加入位置编码器,将 词汇位置不同可能会产生不同语义的信息 加入到嵌入张量中(embedding),用来弥补位置信息的缺失。
3. 为何Transformer论文作者声称“Attention is all you need”
详解Transformer (论文Attention Is All You Need). 正如论文的题目所说的,Transformer中抛弃了传统的CNN和RNN,睁返整个网络悉基饥结构完全是由Attention机制组成。. 更准确地讲,Transformer由且锋悔
4. Swin Transformer
目前transformer从语言到视觉任务的挑战主要是由于这两个领域间的差异:
为了解决以上两点,我们提出了层级Transformer,通过滑动窗口提取特征的方式将使得 self.attention 的计算量降低为和图像尺寸的线性相关。
我们观察到将语言领域迁移到视觉领域的主要问模缺指题可以被总结为两种:
在源扮耐码实现中两个模块合二为一,称为 PatchEmbedding 。输入图片尺寸为 的RGB图片,将 4x4x3 视为一个patch,用一个linear embedding 层将patch转换为任意dimension(通道)的feature。源码中使用4x4的stride=4的conv实现。->
这是这篇论文的核心模块。
window partition 分为 regular window partition 和 shift window partition ,对应于 W-MSA 和 SW-MSA 。通过窗口划分,将输入的 feature map 转换为 num_windows*B, window_size, window_size, C ,其中 num_windows = H*W / window_size / window_size 。然后resize 到 num_windows*B, window_size*window_size, C 进行attention。源码如下:
由 regular window partition 模块 和 mutil-head self attention 模块组成。
W-MSA相比于直接使用MSA主要是为了降低计算量。传统的transformer都是基于全局来计算注意力,因此计算复杂度非常高。但是swin transformer通过对每个窗口施加注意力,从而减少了计算量。attention的主要计算过程如下:
假设每一个 window 的区块大旦配小为 ,输入的尺寸为 ,以下为原始的 和 的计算复杂度:
虽然 降低了计算量,但是由于将attention限制在 window 内,因此不重合的 window 缺乏联系,限制了模型的性能。因此提出了 模块。在 MSA 前面加上一个 cycle shift window partition
swin transformer中没有使用 pooling 进行下采样,而是使用了和yolov5中的 focus 层进行 feature map 的下采样。 -> ,在使用一个全连接层-> ,在一个stage中将feature map的高宽减半,通道数翻倍。
基准模型结构命名为 Swin-B ,模型大小和计算复杂度和 ViT-B / DeiT-B 相近。同时我们也提出了 Swin-T , Swin-S 和 Swin-L ,分别对应 0.25× , 0.5× 和 2× 倍的模型尺寸和计算复杂度。 Swin-T 和 Swin-S 的计算复杂度分别和 ResNet-50 、 ResNet-101 相近。 默认设置为7。 代表第一层隐藏层的数量。
5. Transformer为什么适合自动驾驶毫末智行CEO顾维灏亲自揭秘
作为在自然语言处理(NLP)领域应用广泛的深度学习模型,Transformer 近两年强势来袭,不仅横扫 NLP 领域,而且在 CV 上也锋芒毕露。江湖传言,Transformer 架构就像是绝世高手的武林秘籍,得秘籍者得天下!
毫末智行作为国内首先大规模使用 Vision Transformer 技术的公司,CEO顾维灏第一时间在内部推动了此项技术的落地,力求在智能驾驶的赛道上能抢占先机。
Transformer 的杀手锏
据顾维灏介绍,最初的 Transformer 来自于 NLP,它的出现将 NLP 领域向前推动了一大步。其中的关键要素就是Transformer 具备:超强的序列建模能力、全局信息感知能力。
得益于这两点优势,Transformer 几乎取代了基于 RNN 的算法在 NLP 中的地位,也被引入到 CV 领域。但值得深入思考的是,Transformer 如何利用优势在视觉领域发挥作用呢?
要知道 NLP 中处理的是语句,句子是天然的序列数据,所以很容易理解 Transformer 是如何处理它们的。可在视觉领域,“序列”的概念并不是显式的,因此可以从空间和时间两个维度去理解。
首先是空间维度,静态图像从空间上可以被划分成多个区域(block),一种典型的划分方式就是按照高和宽进行划分,例如,一幅图像的高和宽分别是 H 和 W,如果要求 block 的长宽均为 M,那么最终会得到 (H/M W/M) 个 block。
其实可以把 block 看成是 NLP 句子中的词,这里的只不过是“视觉词”(visual words)。这样一来,就可以将一幅图像转化成一个按照空间顺序排列的 block 集合,一方面这样的视角转换保证了不丢失视觉信息,另一方面让应用 Transformer 变得非常容易。
另一种则是通过时间维度去理解视觉中的序列,即视频。视频是由静态的图像帧组成,把每一帧看成是一个基本单元(同样可以类别成句子中的词),那么就可以很自然地按照时间序列把一个片段组织起来,从而应用 Transformer 进行后续的特征提取。
图引自论文《An Image is Worth 16x16 Words Transformer for Image Recognition at scale”》
除了强大的序列建模能力,Transformer 的主要模块 Multi-Head Self-Attention 可以同时感知到输入序列的全局信息,这是 Transformer 相比于 CNN 的巨大优势。在 CNN 中,信息只能从局部开始,随着层数的增加,能够被感知到的区域逐步增大。然而 Transformer 从输入开始,每一层结构都可以看到所有的信息,并且建立基本单元之间的关联,也意味着Transformer 能够处理更加复杂的问题。
Transformer 的优化升级
目前处于 Transformer 在视觉中应用的早期,大家使用 Transformer 的方式主要参考了其在 NLP 中的应用经验。但是,如果直接将 Transformer 应用到视觉上,也会存在一些难题。
其一,核心模块多头注意力机制(Multi-Head Self-Attention )的计算量与 block 的个数成正比,因此在视觉中 block 数量要远多于 NLP 中句子的词数,这就造成了计算量的陡增。
其二,Transformer 擅长全局关系的学习,对于局部细节信息关注有限,然而视觉中很多任务需要足够丰富的细节信息做判断,比如语义分割。
针对上述的问题, 毫末智行人工智能研发团队对核心模块多头注意力机制(Multi-Head Self-Attention)进行了优化,同时采用了金字塔的结构增强 Transformer 对于细节信息的感知。
图引自论文《LeViT a Vision Transformer in ConvNet Clothing for Faster Inference》
Transformer 的未来演化
尽管我们在上面提到了 Transformer 的一些不尽如意之处,但随着研究的深入,大家逐步发现在同一结构中结合 CNN 和 Transformer 各自的优势,即可做到相互的扬长避短。在未来,把CNN 和 Transformer 进行整合将成为 Transformer 的演化路径之一。
具体来说,主干网使用 CNN,Head 使用 Transformer 结构,可以有效提升网络的速度(相比纯使用 Transformer);相反,主干网使用 Transformer 结构,Head 使用 CNN 的结构,可以有效提升结果精度(相比于纯使用 CNN)。
其次,核心模块 Multi-Head Self-Attention 内部也可以通过降低子空间的维度、对输入 block 进行分组等手段降低其计算量且不至于损失过多精度。
最后,通过控制 block 的粒度,使 Transformer 能够感知到不同尺度的信息,从而达到局部和全局的信息融合。
毫末智行团队已经将上述的改进逐步添加到了毫末智行自己的模型中。未来,我们将不断在提升速度的同时保证出色的精度,让 Transformer 在实际的业务中生根发芽。
图引自论文《End to End Object Detection with Transformers》
基于 Transformer 的感知算法表现出了极强的泛化性和鲁棒性,也因此顾维灏坚定认为,Transformer 的优秀特性极有可能在智能驾驶的场景中发挥出传统 CNN 算法所不能企及的感知能力。
目前, 毫末智行的人工智能团队正在逐步将基于 Transformer 的感知算法应用到实际的道路感知问题,例如车道线检测、障碍物检测、可行驶区域分割、红绿灯检测&识别、道路交通标志检测、点云检测&分割等。 未来,相关 Transformer 感知算法更加和稳定成熟后,逐步替换基于 CNN 的感知算法。
Transformer 技术的进一步应用,不仅为毫末智行在各条智能驾驶产品线上的视觉算法落地带来成倍的效率提升,还能够让各项视觉性能指标快速达到业内领先水平。
6. Transformer模型解析记录
整个Transformer模型由Encoder和Decoder两部分组成。Encoder负责对输入数据的编码,而Decoder负责对编码后的数据进行解码。
Encoder由N个结构相同,参数不共享的模块组成,每个模块又由多头自注意力层和全连接层组成,其中多头自注意力层和全连接层都加上了残差连接和layer normalization。
Decoder与Encoder结构类似,相比于Encoder,Decoder部分多了一个 Multi-Head Attention ,第一个 Multi-Head Attention 采用Masked操作,第二个 Multi-Head Attention 的 K 和 V 使用Encoder的手轮备输出,而Q使用上一个Decoder block的输出。
Decoder的输出通过一个线性层和softmax输出下一个翻译单词的概率。
Encoder由N个结构相同,参数不共享的的Layer组成(论文中N=6),也即图1左侧的单元,最左边有个“Nx”。
每个Layer由 Multi-Head Attention 和 Feed-Forward 两个sub_layer组成。其中每个sub_layer都加了残差连接(Resial Connect)和归一化(Normalization)操作。则每个sub_layer的输出可表示为:
Muti-Head Attention从结构上来看就是通过h个不同的线性变换将输入 投影到h个不同的 组合,最后将h个不同的Attention结果拼接起来,最后经过一个Liner层得到Muti-Head Attention的输出。
其中, 、
Muti-Head Attention输出的维度是
关于Attention的详细介绍,可以参考之前文档:
Feed Forward也称Position-wise feed-forward networks,该层主要提供非线性变换。之所以是position-wise是因为过线性层时每个位置i的变换参数是一样的。
该层比较简单,是一个两层的全连接层,第一层的激活函数为 Relu,第二层不使用激活函数,对应公式为:
问 :Attention输出之后的结果会和 相乘来进行维度变换,那这里为什么又要增加一个2层的FFN网络呢?
答 :FFN网络的加入给模型增加了非线性(Relu激活函数),增加了模型的表现能力。当然去掉FFN层也是可以的,只不过效果上会差些。
Decoder是图1的右半部分,与左半部分的Encoder类似,但又存在一些区别。
Decoder比Encoder多了一个Multi-Head Attention,第一个Multi-Head Attention采用Masked操作,因为在生成任务中,前面的词语是看不到后面词语的信息的,因此需要加入Masked来避免信息泄露。第二个Multi-Head Attention输入的 是根据Encoder的输出编码矩阵映射而来,而 是根据上一个Decoder的输出映射而来。
最后有一个 Softmax 层计算下一个翻译单词的概率。
模型在解码的过程中需要毕毁注意的是训练和预测不一样。
在训练时,解码桐罩是一次全部decode出来,用上一步的ground truth来预测(mask矩阵也会改动,让解码时看不到未来的token);
而预测时,因为没有ground truth了,需要一个个预测。
上面简单介绍了 Encoder 和 Decoder 模块,下面简单介绍一下Transformer的Position Embedding。
引入Position Embedding主要是为了弥补Transformer模型对位置信息的不足,将Position Embedding与token Embedding相加后,即可保留各个token的位置信息。
论文作者提出了两种添加位置信息的的方法:
一种方法是直接用不同频率的正余弦函数直接计算各个token的位置id,公式如下:
另一种方法是直接学习出一个Position Embedding。
通过实验发现,两种方法结果差不多,最后作者选择了第一种方法。
Transformer 与 RNN 不同,可以比较好地并行训练。
Transformer 本身是不能利用单词的顺序信息的,因此需要在输入中添加位置 Embedding,否则 Transformer 就是一个词袋模型了。
Transformer 的重点是 Self-Attention 结构,其中用到的 Q, K, V矩阵通过输出进行线性变换得到。
Transformer 中 Multi-Head Attention 中有多个 Self-Attention,可以捕获单词之间多种维度上的相关系数 attention score。
Transformer 模型详解 (推荐)
【NLP】Transformer模型原理详解
【经典精读】Transformer模型深度解读
7. Transformer解读(附pytorch代码)
Transformer早在2017年就出现了,直到BERT问世,Transformer开始在NLP大放光彩,目前比较好的推进就是Transformer-XL(后期附上)。这里主要针对论文和程序进行解读,如有不详实之处,欢迎指出交流,如需了解更多细节之处,推荐知乎上 川陀学者 写的。本文程序的git地址在 这里 。程序如果有不详实之处,欢迎指出交流~
2017年6月,Google发布了一篇论文《Attention is All You Need》,在这篇论文中,提出了 Transformer 的模型尺搭,其旨在全部利用Attention方式来替代掉RNN的循环机制,从而通过实现并行化计算提速。在Transformer出现之前,RNN系列网络以及seq2seq+attention架构基本上铸就了所有NLP任务的铁桶江山。由于Attention模型本身就可以看到全局的信息, Transformer实现了完全不依赖于RNN结构仅利用Attention机制,在其并行性和对全局信息的有效处理上获得了比之前更好的效果。
纵观图1整个Transformer的结构,其核心模块其实就是三个:Multi-Head attention、Feed Forward 以及 Add&Norm。这里关于Multi-Head attention部分只讲程序的实现,关于更多细节原理,请移至开头推荐的知乎链接。
Transformer中的attention采用的是多头的self-attention结构,并且在编码器中,由于不同的输入mask的部分不一样,因此在softmax之前采用了mask操作,并且解码时由于不能看到t时刻之后的数据,同样在解码器的第一个Multi-Head attention中采用了mask操作,但是二者是不同的。因为编码器被mask的部分是需要在输入到Transformer之前事先确定好,而解码器第一个Multi-Head attention被mask的部分其实就是从t=1时刻开始一直到t=seq_len结束,对应于图2。在图2中,横坐标表示解码器一个batch上的输入序列长度(也就是t),紫色部分为被mask的部分,黄色部分为未被mask的部分,可以看出,随着t的增加,被mask的部分逐一减少。而解码器第二个Multi-Head attention的mask操作和编码器中是一样的。
mask+softmax程序如下:
mask操作其实就是对于无效橡困返的输入,用一个负无穷的值代替这个输入,这样在softmax的时候其值就是0。而在attention中(attention操作见下式),softmax的操作出来的结果其实就是attention weights,当attention weights为0时,表示不需要attention该位置的信息。
对于Multi-Head attention的实现,其实梁饥并没有像论文原文写的那样,逐一实现多个attention,再将最后的结果concat,并且通过一个输出权重输出。下面通过程序和公式讲解一下实际的实现过程,这里假设 , , 的来源是一样的,都是 ,其维度为[batch_size, seq_len, input_size]。(需要注意的是在解码器中第二个Multi-Head的输入中 与 的来源不一样)
首先,对于输入 ,通过三个权重变量得到 , , ,此时三者维度相同,都是[batch, seq_len, d_model],然后对其进行维度变换:[batch, seq_len, h, d_model//h]==>[batch, h, seq_len, d]==>[batch×h, seq_len, d],其中d=d_model//h,因此直接将变换后的 , , 直接做DotProctAttention就可以实现Multi-Head attention,最后只需要将DotProctAttention输出的维度依次变换回去,然后乘以输出权重就可以了。关于程序中的参数valid_length已在程序中做了详细的解读,这里不再赘述,注意的是输入的valid_length是针对batch这个维度的,而实际操作中由于X的batch维度发生了改变(由batch变成了batch×h),因此需要对valid_length进行复制。
FFN的实现是很容易的,其实就是对输入进行第一个线性变换,其输出加上ReLU激活函数,然后在进行第二个线性变换就可以了。
Add&norm的实现就是利用残差网络进行连接,最后将连接的结果接上LN,值得注意的是,程序在Y的输出中加入了dropout正则化。同样的正则化技术还出现在masked softmax之后和positional encoding之后。
positional encoding的实现很简单,其实就是对输入序列给定一个唯一的位置,采用sin和cos的方式给了一个位置编码,其中sin处理的是偶数位置,cos处理的是奇数位置。但是,这一块的工作确实非常重要的,因为对于序列而言最主要的就是位置信息,显然BERT是没有去采用positional encoding(尽管在BERT的论文里有一个Position Embeddings的输入,但是显然描述的不是Transformer中要描述的位置信息),后续BERT在这一方面的改进工作体现在了XLNet中(其采用了Transformer-XL的结构),后续的中再介绍该部分的内容。
无论是编码器还是解码器,其实都是用上面说的三个基本模块堆叠而成,具体的实现细节大家可以看开头的git地址,这里需要强调的是以下几点:
中出现的程序都在开头的git中了,直接执行main.ipynb就可以运行程序,如有不详实之处,还请指出~~~
8. swin transformer理解要点
这是跑通的分类以及分割源码介绍,大家有需要可以参考一下:
1、 Swin-Transformer分类源码(已跑通)
2、侍辩滚 Swin-Transformer分割源码(已跑通)
3、 Swin-Unet(分割改编)
我们假设图片的大小是224×224的,窗口大小是固定的,7×7。这里每个方框都是一个窗口,每个窗口是固定有7×7个patch,但是patch的大小是不固定的,它会随着patch merging的操作而发生变化。比如我们看这儿,patch大小是4×4的,那怎么变成8×8呢?我们把周边4个窗口的patch拼在一起,相当于patch扩大了2×2倍,从而得到8×8大小的patch。
我们发现经过这一系列的操作之后,patch的数目在变少,最后整张图只有一个窗口,7个patch。所以我们可以认为降采样是指让patch的数量减少,但是patch的大小在变大。
这便是对ViT的一个改进,ViT从头至尾都是对全局做self-attention,而swin-transformer是一个窗口在放大的过程,然后self-attention的计算是以窗口为单位去计算的,这样相当于引入了局部聚合的信息,和CNN的卷积过灶瞎程很相似,就像是CNN的步长和卷积核大小一样,这样就做到了窗口的不重合,区别在于CNN在每个窗口做的是卷积的计算,每个窗口最后得到一个值,这个值代表着这个窗口的特征。而swin transformer在每个窗口做的是self-attention的计算,得到的是一个更新过的窗口,然后通过patch merging的操作,把窗口做了个合并,再继续对这个合并后的窗口做self-attention的计算。
其实这边困扰了我一小下,因为我们印象中降采样都是像CNN一样,会变小,但是swin transformer没有给我们变小的感觉。其实这就是感受野没理解到位的问题,CNN到最后,设计适当,最后一个特征图的感受野是可以放大到整张图的,swin transformer最后一个stage也是一个窗口涵盖了整张图。
Swin-transformer是怎么把复杂度降低的呢? Swin Transformer Block这个模块和普通的transformer的区别就在于W-MSA,而它就是降低复杂度计算的大功臣。
关于复杂度的计算,我简单的给大家介绍一下,首先是transformer本身基于全局的复杂度计算,这一块儿讲起来有点复杂,感兴趣的同学我们可以会后一起探讨推导过程。在这里,我们假设已知MSA的复杂度是图像大小的平方,根据MSA的复杂度,我们可以得出A的复杂度是(3×3)²,最后复杂度是81。Swin transformer是在每个local windows(红色部分)计算self-attention,根据MSA的复杂度我们可以得出每个红色窗口的复杂度是1×1的平方,也就是1的四次方。然后9个窗口,这些窗口的复杂度加和,最后B的复杂度为9。
W-MSA虽然降低了计算复杂度,但是不重合的window之间缺乏信息交流,所以想要窗口之间的信息有所交流,那么就可以把左图演化成右图这样,但是这就产生了一个问题,如此操作,会产生更多的windows,并且其中一部分window小于普通的window,比如4个window -> 9个window,windows数量增加了一倍多。这计算量又上来了。因此我们有两个目的,Windows数量不能多老余,window之间信息得有交流。
我们看到,原来的图被划分了9个窗口,中间的区域A就是信息交流的证明。我们先把左上部分(蓝色以外的窗口)移动到右下,然后再用切分四块的方法去切这个图片,这时候区域A就被隔出来了,达到了我们想要的效果。
transformer的出现并不是为了替代CNN。因为transformer有着CNN没有的功能性,它不仅可以提取特征,还可以做很多CNN做不到的事情,比如多模态融合。而swin transformer就是一个趋势,将CNN与transformer各自的优势有效的结合了起来。这是暂时对它的一些细节补充。最近听说MLP出来了,还没有细看,时代进展未免也太快了,手里针对ViT改进的文章还没投出去,就已经开始要立不住脚了。
希望可以帮助到大家,如果你觉得这篇文章对你有一定的帮助,那就点个赞支持一下吧!如果有什么问题的话也可以在文章下面评论,我们一起交流解决问题!
以下是我所有文章的目录,大家如果感兴趣,也可以前往查看
👉戳右边: 打开它,也许会看到很多对你有帮助的文章
9. 为什么说Transformer的注意力机制是相对廉价的注意力机制相对更对于RNN系列及CNN系列算法有何优势
QA形式对自然语言处理中注意力机制(Attention)进行总结,并对Transformer进行深入解析。
二、Transformer(Attention Is All You Need)详解
1、Transformer的整体架构是怎样的?由哪些部分组成?
2、Transformer Encoder 与 Transformer Decoder 有哪些不同?
3、Encoder-Decoder attention 与self-attention mechanism有哪些不同?
4、multi-head self-attention mechanism具体的计算过程是怎样的?
5、Transformer在GPT和Bert等词向量预训练模型中具体是怎么应用的?有什么变化?
一、Attention机制剖析
1、为什么要引入Attention机制?
根据通用近似定理,前馈网络和循环网络都有很强的能力。但为什么还要引入注意力机制呢?
计算能力的限制:当要记住很多“信息“,模型就要变得更复杂,然而目前计算能力依然是限制神经网络发展的瓶颈。
优化算法的限制:虽然局部连接、权重共享以及pooling等优化操作可以让神经网络变得简单一些,有效缓解模型复杂度和表达能力之间的矛盾;但是,如循环神经网络中的长距离以来问题,信息“记忆”能力并不高。
可以借助人脑处理信息过载的方式,例如Attention机制可以提高神经网络处理信息的能力。
2、Attention机制有哪些?(怎么分类?)
当用神经网络来处理大量的输入信息时,也可以借鉴人脑的注意力机制,只 选择一些关键的信息输入进行处理,来提高神经网络的效率。按照认知神经学中的注意力,可以总体上分为两类:
聚焦式(focus)注意力:自上而下的有意识的注意力,主动注意——是指有预定目的、依赖任务的、主动有意识地聚焦于某一对象的注意力;
显着性(saliency-based)注意力:自下而上的有意识的注意力,被动注意——基于显着性的注意力是由外界刺激驱动的注意,不需要主动干预,也和任务无关;可以将max-pooling和门控(gating)机制来近似地看作是自下而上的基于显着性的注意力机制。
在人工神经网络中,注意力机制一般就特指聚焦式注意力。
3、Attention机制的计算流程是怎样的?
Attention机制的实质其实就是一个寻址(addressing)的过程,如上图所示:给定一个和任务相关的查询Query向量q,通过计算与Key的注意力分布并附加在Value上,从而计算Attention Value,这个过程实际上是Attention机制缓解神经网络模型复杂度的体现:不需要将所有的N个输入信息都输入到神经网络进行计算,只需要从X中选择一些和任务相关的信息输入给神经网络。
step1-信息输入:用X= [x1, · · · , xN ]表示N 个输入信息;
step2-注意力分布计算:令Key=Value=X,则可以给出注意力分布
我们将称之为注意力分布(概率分布),为注意力打分机制,有几种打分机制:
step3-信息加权平均:注意力分布可以解释为在上下文查询q时,第i个信息受关注的程度,采用一种“软性”的信息选择机制对输入信息X进行编码为:
这种编码方式为软性注意力机制(soft Attention),软性注意力机制有两种:普通模式(Key=Value=X)和键值对模式(Key!=Value)。
4、Attention机制的变种有哪些?
与普通的Attention机制(上图左)相比,Attention机制有哪些变种呢?
变种1-硬性注意力:之前提到的注意力是软性注意力,其选择的信息是所有输入信息在注意力 分布下的期望。还有一种注意力是只关注到某一个位置上的信息,叫做硬性注意力(hard attention)。硬性注意力有两种实现方式:(1)一种是选取最高概率的输入信息;(2)另一种硬性注意力可以通过在注意力分布式上随机采样的方式实现。硬性注意力模型的缺点:
变种2-键值对注意力:即上图右边的键值对模式,此时Key!=Value,注意力函数变为:
变种3-多头注意力:多头注意力(multi-head attention)是利用多个查询Q = [q1, · · · , qM],来平行地计算从输入信息中选取多个信息。每个注意力关注输入信息的不同部分,然后再进行拼接:
5、一种强大的Attention机制:为什么自注意力模型(self-Attention model)在长距离序列中如此强大?
(1)卷积或循环神经网络难道不能处理长距离序列吗?
当使用神经网络来处理一个变长的向量序列时,我们通常可以使用卷积网络或循环网络进行编码来得到一个相同长度的输出向量序列,如图所示:
从上图可以看出,无论卷积还是循环神经网络其实都是对变长序列的一种“局部编码”:卷积神经网络显然是基于N-gram的局部编码;而对于循环神经网络,由于梯度消失等问题也只能建立短距离依赖。
(2)要解决这种短距离依赖的“局部编码”问题,从而对输入序列建立长距离依赖关系,有哪些办法呢?
由上图可以看出,全连接网络虽然是一种非常直接的建模远距离依赖的模型, 但是无法处理变长的输入序列。不同的输入长度,其连接权重的大小也是不同的。
这时我们就可以利用注意力机制来“动态”地生成不同连接的权重,这就是自注意力模型(self-attention model)。由于自注意力模型的权重是动态生成的,因此可以处理变长的信息序列。
总体来说,为什么自注意力模型(self-Attention model)如此强大:利用注意力机制来“动态”地生成不同连接的权重,从而处理变长的信息序列。
(3)自注意力模型(self-Attention model)具体的计算流程是怎样的呢?
同样,给出信息输入:用X = [x1, · · · , xN ]表示N 个输入信息;通过线性变换得到为查询向量序列,键向量序列和值向量序列:
上面的公式可以看出,self-Attention中的Q是对自身(self)输入的变换,而在传统的Attention中,Q来自于外部。
注意力计算公式为:
自注意力模型(self-Attention model)中,通常使用缩放点积来作为注意力打分函数,输出向量序列可以写为:
二、Transformer(Attention Is All You Need)详解
从Transformer这篇论文的题目可以看出,Transformer的核心就是Attention,这也就是为什么本文会在剖析玩Attention机制之后会引出Transformer,如果对上面的Attention机制特别是自注意力模型(self-Attention model)理解后,Transformer就很容易理解了。
1、Transformer的整体架构是怎样的?由哪些部分组成?
Transformer其实这就是一个Seq2Seq模型,左边一个encoder把输入读进去,右边一个decoder得到输出:
Transformer=Transformer Encoder+Transformer Decoder
(1)Transformer Encoder(N=6层,每层包括2个sub-layers):
sub-layer-1:multi-head self-attention mechanism,用来进行self-attention。
sub-layer-2:Position-wise Feed-forward Networks,简单的全连接网络,对每个position的向量分别进行相同的操作,包括两个线性变换和一个ReLU激活输出(输入输出层的维度都为512,中间层为2048):
每个sub-layer都使用了残差网络:
(2)Transformer Decoder(N=6层,每层包括3个sub-layers):
sub-layer-1:Masked multi-head self-attention mechanism,用来进行self-attention,与Encoder不同:由于是序列生成过程,所以在时刻 i 的时候,大于 i 的时刻都没有结果,只有小于 i 的时刻有结果,因此需要做Mask。
sub-layer-2:Position-wise Feed-forward Networks,同Encoder。
sub-layer-3:Encoder-Decoder attention计算。
2、Transformer Encoder 与 Transformer Decoder 有哪些不同?
(1)multi-head self-attention mechanism不同,Encoder中不需要使用Masked,而Decoder中需要使用Masked;
(2)Decoder中多了一层Encoder-Decoder attention,这与 self-attention mechanism不同。
3、Encoder-Decoder attention 与self-attention mechanism有哪些不同?
它们都是用了 multi-head计算,不过Encoder-Decoder attention采用传统的attention机制,其中的Query是self-attention mechanism已经计算出的上一时间i处的编码值,Key和Value都是Encoder的输出,这与self-attention mechanism不同。代码中具体体现:
4、multi-head self-attention mechanism具体的计算过程是怎样的?
Transformer中的Attention机制由Scaled Dot-Proct Attention和Multi-Head Attention组成,上图给出了整体流程。下面具体介绍各个环节:
Expand:实际上是经过线性变换,生成Q、K、V三个向量;
Split heads: 进行分头操作,在原文中将原来每个位置512维度分成8个head,每个head维度变为64;
Self Attention:对每个head进行Self Attention,具体过程和第一部分介绍的一致;
Concat heads:对进行完Self Attention每个head进行拼接;
上述过程公式为:
5、Transformer在GPT和Bert等词向量预训练模型中具体是怎么应用的?有什么变化?
GPT中训练的是单向语言模型,其实就是直接应用Transformer Decoder;
Bert中训练的是双向语言模型,应用了Transformer Encoder部分,不过在Encoder基础上还做了Masked操作;
BERT Transformer 使用双向self-attention,而GPT Transformer 使用受限制的self-attention,其中每个token只能处理其左侧的上下文。双向 Transformer 通常被称为“Transformer encoder”,而左侧上下文被称为“Transformer decoder”,decoder是不能获要预测的信息的。