This commit is contained in:
erenup 2021-08-28 19:40:02 +08:00
parent 4fe87ce13e
commit 083cd0c39d
2 changed files with 48 additions and 17 deletions

View File

@ -1,4 +1,11 @@
## 图解Attention ## 图解Attention
内容组织:
- 图解Attention
- seq2seq框架
- seq2seq细节
- Attention
- 致谢
篇章1中我们对Transformers在NLP中的兴起做了概述。本教程的学习路径是Attention->Transformer->BERT->NLP应用。因此本篇章将从attention开始逐步对Transformer结构所涉及的知识进行深入讲解希望能给读者以形象生动的描述。 篇章1中我们对Transformers在NLP中的兴起做了概述。本教程的学习路径是Attention->Transformer->BERT->NLP应用。因此本篇章将从attention开始逐步对Transformer结构所涉及的知识进行深入讲解希望能给读者以形象生动的描述。
问题Attention出现的原因是什么 问题Attention出现的原因是什么

View File

@ -1,4 +1,25 @@
# <h2 id='t0'> 图解transformer </h2>
# 图解transformer
内容组织:
- 图解transformer
- Transformer宏观结构
- Transformer结构细节
- 输入处理
- 词向量
- 位置向量
- 编码器encoder
- Self-Attention层
- 多头注意力机制
- Attention代码实例
- 残差连接
- 解码器
- 线性层和softmax
- 损失函数
- 附加资料
- 致谢
在学习完[图解attention](./2.1-图解attention.md)后我们知晓了attention为循环神经网络带来的优点。那么有没有一种神经网络结构直接基于attention构造并且不再依赖RNN、LSTM或者CNN网络结构了呢答案便是Transformer。因此我们将在本小节对Transformer所涉及的细节进行深入探讨。 在学习完[图解attention](./2.1-图解attention.md)后我们知晓了attention为循环神经网络带来的优点。那么有没有一种神经网络结构直接基于attention构造并且不再依赖RNN、LSTM或者CNN网络结构了呢答案便是Transformer。因此我们将在本小节对Transformer所涉及的细节进行深入探讨。
Transformer模型在2017年被google提出直接基于Self-Attention结构取代了之前NLP任务中常用的RNN神经网络结构并在WMT2014 Englishto-German和WMT2014 English-to-French两个机器翻译任务上都取得了当时的SOTA。 Transformer模型在2017年被google提出直接基于Self-Attention结构取代了之前NLP任务中常用的RNN神经网络结构并在WMT2014 Englishto-German和WMT2014 English-to-French两个机器翻译任务上都取得了当时的SOTA。
@ -12,7 +33,8 @@ Transformer模型在2017年被google提出直接基于Self-Attention结构
注释和引用说明:本文将通过总-分的方式对Transformer进行拆解和讲解希望有助于帮助初学者理解Transformer模型结构。本文主要参考[illustrated-transformer](http://jalammar.github.io/illustrated-transformer)。 注释和引用说明:本文将通过总-分的方式对Transformer进行拆解和讲解希望有助于帮助初学者理解Transformer模型结构。本文主要参考[illustrated-transformer](http://jalammar.github.io/illustrated-transformer)。
## <h2 id='t1'> Transformer宏观结构 </h2>
## Transformer宏观结构
注意:本小节为讲解方式为:总-分,先整体,再局部。 注意:本小节为讲解方式为:总-分,先整体,再局部。
@ -50,7 +72,7 @@ Transformer最开始提出来解决机器翻译任务因此可以看作是seq
以上便是Transformer的宏观结构啦下面我们开始看宏观结构中的模型细节。 以上便是Transformer的宏观结构啦下面我们开始看宏观结构中的模型细节。
## <h2 id='t2'> Transformer结构细节 </h2> ## Transformer结构细节
了解了Transformer的宏观结构之后。下面让我们来看看Transformer如何将输入文本序列转换为向量表示又如何逐层处理这些向量表示得到最终的输出。 了解了Transformer的宏观结构之后。下面让我们来看看Transformer如何将输入文本序列转换为向量表示又如何逐层处理这些向量表示得到最终的输出。
@ -60,9 +82,10 @@ Transformer最开始提出来解决机器翻译任务因此可以看作是seq
- 位置向量 - 位置向量
- 编码器 - 编码器
- 解码器 - 解码器
### <h2 id='transformer_input'> 输入处理 </h2>
#### <h2 id='word_emb'> 词向量 </h2> ### 输入处理
#### 词向量
和常见的NLP 任务一样我们首先会使用词嵌入算法embedding algorithm将输入文本序列的每个词转换为一个词向量。实际应用中的向量一般是 256 或者 512 维。但为了简化起见我们这里使用4维的词向量来进行讲解。 和常见的NLP 任务一样我们首先会使用词嵌入算法embedding algorithm将输入文本序列的每个词转换为一个词向量。实际应用中的向量一般是 256 或者 512 维。但为了简化起见我们这里使用4维的词向量来进行讲解。
如下图所示假设我们的输入文本是序列包含了3个词那么每个词可以通过词嵌入算法得到一个4维向量于是整个输入被转化成为一个向量序列。在实际应用中我们通常会同时给模型输入多个句子如果每个句子的长度不一样我们会选择一个合适的长度作为输入文本序列的最大长度如果一个句子达不到这个长度那么就填充先填充一个特殊的“padding”词如果句子超出这个长度则做截断。最大序列长度是一个超参数通常希望越大越好但是更长的序列往往会占用更大的训练显存/内存,因此需要在模型训练时候视情况进行决定。 如下图所示假设我们的输入文本是序列包含了3个词那么每个词可以通过词嵌入算法得到一个4维向量于是整个输入被转化成为一个向量序列。在实际应用中我们通常会同时给模型输入多个句子如果每个句子的长度不一样我们会选择一个合适的长度作为输入文本序列的最大长度如果一个句子达不到这个长度那么就填充先填充一个特殊的“padding”词如果句子超出这个长度则做截断。最大序列长度是一个超参数通常希望越大越好但是更长的序列往往会占用更大的训练显存/内存,因此需要在模型训练时候视情况进行决定。
@ -72,7 +95,7 @@ Transformer最开始提出来解决机器翻译任务因此可以看作是seq
输入序列每个单词被转换成词向量表示还将加上位置向量来得到该词的最终向量表示。 输入序列每个单词被转换成词向量表示还将加上位置向量来得到该词的最终向量表示。
#### <h2 id='pos_emb'> 位置向量 </h2> #### 位置向量
如下图所示Transformer模型对每个输入的词向量都加上了一个位置向量。这些向量有助于确定每个单词的位置特征或者句子中不同单词之间的距离特征。词向量加上位置向量背后的直觉是将这些表示位置的向量添加到词向量中得到的新向量可以为模型提供更多有意义的信息比如词的位置词之间的距离等。 如下图所示Transformer模型对每个输入的词向量都加上了一个位置向量。这些向量有助于确定每个单词的位置特征或者句子中不同单词之间的距离特征。词向量加上位置向量背后的直觉是将这些表示位置的向量添加到词向量中得到的新向量可以为模型提供更多有意义的信息比如词的位置词之间的距离等。
@ -94,7 +117,8 @@ $$
当然,上述公式不是唯一生成位置编码向量的方法。但这种方法的优点是:可以扩展到未知的序列长度。例如:当我们的模型需要翻译一个句子,而这个句子的长度大于训练集中所有句子的长度,这时,这种位置编码的方法也可以生成一样长的位置编码向量。 当然,上述公式不是唯一生成位置编码向量的方法。但这种方法的优点是:可以扩展到未知的序列长度。例如:当我们的模型需要翻译一个句子,而这个句子的长度大于训练集中所有句子的长度,这时,这种位置编码的方法也可以生成一样长的位置编码向量。
### <h2 id='encoder'> 编码器encoder </h2> ### 编码器encoder
编码部分的输入文本序列经过输入处理之后得到了一个向量序列这个向量序列将被送入第1层编码器第1层编码器输出的同样是一个向量序列再接着送入下一层编码器第1层编码器的输入是融合位置向量的词向量*更上层编码器的输入则是上一层编码器的输出*。 编码部分的输入文本序列经过输入处理之后得到了一个向量序列这个向量序列将被送入第1层编码器第1层编码器输出的同样是一个向量序列再接着送入下一层编码器第1层编码器的输入是融合位置向量的词向量*更上层编码器的输入则是上一层编码器的输出*。
下图展示了向量序列在单层encoder中的流动融合位置信息的词向量进入self-attention层self-attention的输出每个位置的向量再输入FFN神经网络得到每个位置的新向量。 下图展示了向量序列在单层encoder中的流动融合位置信息的词向量进入self-attention层self-attention的输出每个位置的向量再输入FFN神经网络得到每个位置的新向量。
@ -107,7 +131,7 @@ $$
![一层传一层](./pictures/2-multi-encoder.webp) ![一层传一层](./pictures/2-multi-encoder.webp)
2个单词的例子$x_1, x_2 \to z_1, z_2 \to r_1, r_2$ 2个单词的例子$x_1, x_2 \to z_1, z_2 \to r_1, r_2$
#### <h2 id='self-attention'> Self-Attention层 </h2> #### <h3 id='self-attention'> Self-Attention层 </h3>
下面来分析一下上图中Self-Attention层的具体机制。 下面来分析一下上图中Self-Attention层的具体机制。
@ -171,7 +195,7 @@ Attention score是根据"*Thinking*" 对应的 Query 向量和其他位置的每
![Think计算](./pictures/2-sum.png) ![Think计算](./pictures/2-sum.png)
Thinking经过attention之后的向量表示$z_1$ Thinking经过attention之后的向量表示$z_1$
##### <h3 id='self-attention-metric'> Self-Attention矩阵计算 </h3> ##### Self-Attention矩阵计算
将self-attention计算6个步骤中的向量放一起比如$X=[x_1;x_2]$便可以进行矩阵计算啦。下面依旧按步骤展示self-attention的矩阵计算方法。 将self-attention计算6个步骤中的向量放一起比如$X=[x_1;x_2]$便可以进行矩阵计算啦。下面依旧按步骤展示self-attention的矩阵计算方法。
$$X = [X_1;X_2] \\ $$X = [X_1;X_2] \\
@ -187,7 +211,7 @@ Z = softmax(\frac{QK^T}{\sqrt{d_k}}) V$$
![输出](./pictures/2-attention-output.webp) ![输出](./pictures/2-attention-output.webp)
图:得到输出$Z$ 图:得到输出$Z$
#### <h2 id='mha'> 多头注意力机制multi-head attention </h2> #### 多头注意力机制
Transformer 的论文通过增加多头注意力机制(一组注意力称为一个 attention head进一步完善了Self-Attention。这种机制从如下两个方面增强了attention层的能力 Transformer 的论文通过增加多头注意力机制(一组注意力称为一个 attention head进一步完善了Self-Attention。这种机制从如下两个方面增强了attention层的能力
@ -226,7 +250,7 @@ Transformer 的论文通过增加多头注意力机制(一组注意力称为
当我们编码单词"it"时,其中一个 attention head (橙色注意力头)最关注的是"the animal",另外一个绿色 attention head 关注的是"tired"。因此在某种意义上,"it"在模型中的表示,融合了"animal"和"tire"的部分表达。 当我们编码单词"it"时,其中一个 attention head (橙色注意力头)最关注的是"the animal",另外一个绿色 attention head 关注的是"tired"。因此在某种意义上,"it"在模型中的表示,融合了"animal"和"tire"的部分表达。
#### <h2 id='mha'> Attention代码实例</h2> #### Attention代码实例
下面的代码实现中张量的第1维是 batch size第 2 维是句子长度。代码中进行了详细注释和说明。 下面的代码实现中张量的第1维是 batch size第 2 维是句子长度。代码中进行了详细注释和说明。
``` ```
@ -317,7 +341,7 @@ print(output.shape)
``` ```
### <h2 id='resnet'> 残差连接</h2> #### 残差连接
到目前为止我们计算得到了self-attention的输出向量。而单层encoder里后续还有两个重要的操作残差链接、标准化。 到目前为止我们计算得到了self-attention的输出向量。而单层encoder里后续还有两个重要的操作残差链接、标准化。
@ -337,7 +361,7 @@ print(output.shape)
![2层示意图](./pictures/2-2layer.png) ![2层示意图](./pictures/2-2layer.png)
2层Transformer示意图 2层Transformer示意图
## <h2 id='decoder'> 解码器 </h2> ## 解码器
现在我们已经介绍了编码器中的大部分概念,我们也基本知道了编码器的原理。现在让我们来看下, 编码器和解码器是如何协同工作的。 现在我们已经介绍了编码器中的大部分概念,我们也基本知道了编码器的原理。现在让我们来看下, 编码器和解码器是如何协同工作的。
@ -354,7 +378,7 @@ print(output.shape)
1. 在解码器里Self Attention 层只允许关注到输出序列中早于当前位置之前的单词。具体做法是:在 Self Attention 分数经过 Softmax 层之前屏蔽当前位置之后的那些位置将attention score设置成-inf 1. 在解码器里Self Attention 层只允许关注到输出序列中早于当前位置之前的单词。具体做法是:在 Self Attention 分数经过 Softmax 层之前屏蔽当前位置之后的那些位置将attention score设置成-inf
2. 解码器 Attention层是使用前一层的输出来构造Query 矩阵而Key矩阵和 Value矩阵来自于编码器最终的输出。 2. 解码器 Attention层是使用前一层的输出来构造Query 矩阵而Key矩阵和 Value矩阵来自于编码器最终的输出。
## <h2 id='linear'> 线性层和softmax </h2> ## 线性层和softmax
Decoder 最终的输出是一个向量其中每个元素是浮点数。我们怎么把这个向量转换为单词呢这是线性成和softmax完成的。 Decoder 最终的输出是一个向量其中每个元素是浮点数。我们怎么把这个向量转换为单词呢这是线性成和softmax完成的。
@ -365,7 +389,7 @@ Decoder 最终的输出是一个向量,其中每个元素是浮点数。我们
![线性层](./pictures/2-linear.png) ![线性层](./pictures/2-linear.png)
图:线性层 图:线性层
## <h2 id='train'> 损失函数 </h2> ## 损失函数
Transformer训练的时候需要将解码器的输出和label一同送入损失函数以获得loss最终模型根据loss进行方向传播。这一小节我们用一个简单的例子来说明训练过程的loss计算把“merci”翻译为“thanks”。 Transformer训练的时候需要将解码器的输出和label一同送入损失函数以获得loss最终模型根据loss进行方向传播。这一小节我们用一个简单的例子来说明训练过程的loss计算把“merci”翻译为“thanks”。
@ -402,7 +426,7 @@ Transformer训练的时候需要将解码器的输出和label一同送入损
- Greedy decoding由于模型每个时间步只产生一个输出我们这样看待模型是从概率分布中选择概率最大的词并且丢弃其他词。这种方法叫做贪婪解码greedy decoding - Greedy decoding由于模型每个时间步只产生一个输出我们这样看待模型是从概率分布中选择概率最大的词并且丢弃其他词。这种方法叫做贪婪解码greedy decoding
- Beam search每个时间步保留k个最高概率的输出词然后在下一个时间步根据上一个时间步保留的k个词来确定当前应该保留哪k个词。假设k=2第一个位置概率最高的两个输出的词是”I“和”a“这两个词都保留然后根据第一个词计算第2个位置的词的概率分布再取出第2个位置上2个概率最高的词。对于第3个位置和第4个位置我们也重复这个过程。这种方法称为集束搜索(beam search)。 - Beam search每个时间步保留k个最高概率的输出词然后在下一个时间步根据上一个时间步保留的k个词来确定当前应该保留哪k个词。假设k=2第一个位置概率最高的两个输出的词是”I“和”a“这两个词都保留然后根据第一个词计算第2个位置的词的概率分布再取出第2个位置上2个概率最高的词。对于第3个位置和第4个位置我们也重复这个过程。这种方法称为集束搜索(beam search)。
## <h2 id='train'> 附加资料 </h2> ## 附加资料
我希望上面讲的内容,可以帮助你理解 Transformer 中的主要概念。如果你想更深一步地理解,我建议你可以参考下面这些: 我希望上面讲的内容,可以帮助你理解 Transformer 中的主要概念。如果你想更深一步地理解,我建议你可以参考下面这些:
@ -421,7 +445,7 @@ Transformer训练的时候需要将解码器的输出和label一同送入损
- 查看这个项目【Tensor2Tensor repo】 - 查看这个项目【Tensor2Tensor repo】
链接地址https://github.com/tensorflow/tensor2tensor 链接地址https://github.com/tensorflow/tensor2tensor
## <h2 id='train'> 致谢 </h2> ## 致谢
主要由哈尔滨工业大学张贤同学翻译撰写由多多同学、datawhale项目同学重新组织。最后期待您的阅读反馈和star哦谢谢。 主要由哈尔滨工业大学张贤同学翻译撰写由多多同学、datawhale项目同学重新组织。最后期待您的阅读反馈和star哦谢谢。