Self-Attention 与 Transformer

来源: Microstrong
文章主要内容概览:

null

1. Seq2Seq 以及注意力机制

Seq2Seq 任务指的是输入和输出都是序列的任务。例如说英语翻译成中文。

1.1 Encoder-Decoder 模型与 Seq2Seq 的关系?

答:编码器-解码器(Encoder-Decoder)模型最初是由 Cho 等提出应用在机器翻译中。由于在机器翻译中是文本到文本的转换,比如将法语翻译成英语,Sutskever 等也称编码器-解码器模型为序列到序列学习(Seq2Seq)。

相关论文如下:

【1】Cho K, Van Merri ënboer B, Gulcehre C, et al. Learning phrase representations using RNN encoder-decoder for statistical machine translation[J]. arXiv preprint arXiv:1406.1078, 2014.

【2】Sutskever I, Vinyals O, Le Q V. Sequence to sequence learning with neural networks[C]//Advances in neural information processing systems. 2014: 3104-3112.

1.2 Encoder-Decoder 模型

通常来说,Seq2Seq 任务最常见的是使用 Encoder+Decoder 的模式,先将一个序列编码成一个上下文矩阵,在使用 Decoder 来解码。当然,我们仅仅把 context vector 作为编码器到解码器的输入。

null

编码器-解码器模型虽然非常经典,但是局限性也很大。最大的局限性是编码器和解码器之间唯一的联系是一个固定长度的语义向量 context vector。也就是说,编码器要将整个序列的信息压缩成一个固定长度的向量。它存在三个弊端:

(1)对于编码器来说,语义向量 context vector 可能无法完全表示整个序列的信息。
(2)对于编码器来说,先输入到网络的序列携带的信息可能会被后输入的序列覆盖掉,输入的序列越长,这种现象就越严重。
(3)对于解码器来说,在解码的时候,对于输入的每个单词的权重是不一致的。

以上三个弊端使得在解码的时候解码器一开始可能就没有获得输入序列足够多的信息,自然解码的准确率也就不高。所以,在 NMT(Neural Machine Translation,神经机器翻译)任务上,还添加了 attention 的机制。

1.3 注意力机制的本质思想

关于注意力机制入门文章请看我之前的一篇文章:深度学习中的注意力机制,Microstrong,地址:https://mp.weixin.qq.com/s/3911D_FkTWrtKwBo30vENg

熟悉了注意力机制的原理后,我们来探究一下注意力机制的本质思想。

null

我们可以这样来看待 Attention 机制(上图):将 source 中的构成元素想象成是由一系列的 <key,value> 数据对构成,此时给定 Target 中的某个元素 Query(解码器隐藏层状态 [公式] ),通过计算 Query 和各个 Key(输入句子中的每个单词)的相似性或者相关性,得到每个 Key 对应的 Value(输入句子中每个单词对应得语义编码,及各个编码器隐藏层状态 [公式] ~ [公式] )的权重系数,(也就是编码器每个隐藏层向量的权重 [公式] ),然后对 Value 进行加权求和,得到最后的 Attention 数值。所以本质上 Attention 机制是对 Source 中的元素的 Value 进行加权求和。而 Query 和 Key 用来计算对应的 Value 权重系数。
image.png
其中, [公式] 代表 source 的长度,在机器翻译的例子里,计算 Attention 的过程中,Source 中的 Key 和 Value 合二为一,为一个东西,也即输入句子中每个单词对应的语义编码,所以可能不容易看出这种能够体现本质思想的结构。
当然,从概念上理解,把 Attention 仍然理解为从大量信息中有选择地筛选出少量重要信息并聚焦到这些重要信息上,忽略大多不重要的信息,这种思路仍然成立。聚焦的过程体现在权重系数的计算上,权重越大越聚焦于其对应的 Value 值上,即权重代表了信息的重要性,而 Value 是其对应的信息。

对于 Attention 机制的具体计算过程,如果对目前大多数方法进行抽象的话,可以将其归纳为两个过程:第一个过程是根据 Query 和 Key 计算权重系数,第二个过程根据权重系数对 Value 进行加权求和。而第一个过程又可以细分为两个阶段:第一个阶段根据 Query 和 Key 计算两者的相似性或者相关性;第二个阶段对第一阶段的原始分数值进行归一化处理。这样,可以将 Attention 的计算过程抽象为下图展示的三个阶段。

null

在第一个阶段, 可以引入不同的函数和计算机制,根据 Query 和某个 ,计算两者的相似性或者相关性,最常见的方法包括:求两者的向量点积、求两者的向量 Cosine 相似性或者通过再引入额外的神经网络来求值,即如下方式:
image.png
第一阶段产生的分数值根据具体产生的方法不同其数值取值范围也不一样,第二阶段引入类似 SoftMax 的计算方式对第一阶段的得分进行数值转换,一方面可以进行归一化,将原始计算分数值整理成所有元素权重之和为 1 的概率分布;另一方面也可以通过 SoftMax 的内在机制更加突出重要元素的权重。即一般采用如下公式计算:
image.png
第二阶段 的计算结果 a_i 即为 Value_i 对应的权重系数,然后进行加权求和即可得到 Attention 数值:

image.png
通过如上三个阶段的计算,即可求出针对 Query 的 Attention 数值,目前绝大多数具体的注意力机制计算方法都符合上述的三阶段抽象计算过程。

2. 基于 LSTM 方法论存在的一些弊端

null

传统的 RNN 存在梯度消失和梯度爆炸的问题。LSTM 和 GRU 都缓解了梯度消失和梯度爆炸的问题,但是没有彻底解决该问题。因此,为了让模型的能力进一步提升,在论文《Attention is All You Need》中提出了 Transformer 模型,该模型利用 Attention 机制可以完全代替 RNN、CNN 等系列模型。目前大热的 Bert 就是基于 Transformer 构建的,这个模型广泛应用于 NLP 领域,例如:机器翻译、问答系统、文本摘要和语音识别等方向。

关于 RNN、LSTM 中梯度消失与爆炸问题的文章:

【1】循环神经网络(RNN),Microstrong,地址:https://mp.weixin.qq.com/s/IPyI2Ee6Kzyv3wFAUN7NOQ
【2】理解 LSTM 网络,Microstrong,地址:https://mp.weixin.qq.com/s/0Q0aK4xmyKkZ0fMUIhc3Sg

3. Transformer 的总体结构

Transformer 的结构和 Attention 机制一样,Transformer 模型中也采用了 Encoder-Decoder 架构。但其结构相比于 Attention 更加复杂,论文中 Encoder 层由 6 个 Encoder 堆叠在一起,Decoder 层也一样。

null

每一个 Encoder 和 Decoder 的内部结构如下图:

null

  • Encoder 包含两层,一个 Self-attention 层和一个前馈神经网络层,Self-attention 层能帮助当前节点不仅仅只关注当前的词,从而能获取到上下文的语义。
  • Decoder 也包含 Encoder 提到的两层网络,但是在这两层中间还有一层 Attention 层,帮助当前节点获取到当前需要关注的重点内容。

4. Transformer Encoder 的结构

首先,模型需要对输入的数据进行一个 embedding 操作,也可以理解为类似 word2vec 的操作,embedding 结束之后,输入到 Encoder 层,Self-attention 处理完数据后把数据送给前馈神经网络,前馈神经网络的计算可以并行,得到的输出会输入到下一个 Encoder。

null

4.1 Positional Encoding

Transformer 模型中缺少一种解释输入序列中单词顺序的方法,它跟序列模型还不一样。为了处理这个问题,Transformer 给 Encoder 层和 Decoder 层的输入添加了一个额外的向量 Positional Encoding,维度和 embedding 的维度一样,这个向量采用了一种很独特的方法来让模型学习到这个值,这个向量能决定当前词的位置,或者说在一个句子中不同的词之间的距离。这个位置向量的具体计算方法有很多种,论文中的计算方法如下:
image.png
其中 pos 是指当前词在句子中的位置, i 是指向量中每个值的 index,可以看出,在偶数位置,使用正弦编码,在奇数位置,使用余弦编码。

最后把这个 Positional Encoding 与 embedding 的值相加,作为输入送到下一层。

null

4.2 Self-Attention

让我们从宏观视角看自注意力机制,精炼一下它的工作原理。

例如,下列句子是我们想要翻译的输入句子:

The animal didn't cross the street because it was too tired

这个“it”在这个句子是指什么呢?它指的是 street 还是这个 animal 呢?这对于人类来说是一个简单的问题,但是对于算法则不是。

当模型处理这个单词“it”的时候,自注意力机制会允许“it”与“animal”建立联系。

随着模型处理输入序列的每个单词,自注意力会关注整个输入序列的所有单词,帮助模型对本单词更好地进行编码。如果你熟悉 RNN(循环神经网络),回忆一下它是如何维持隐藏层的。RNN 会将它已经处理过的前面的所有单词/向量的表示与它正在处理的当前单词/向量结合起来。而自注意力机制会将所有相关单词的理解融入到我们正在处理的单词中。

null

如上图所示,当我们在编码器#5(栈中最上层编码器)中编码“it”这个单词的时,注意力机制的部分会去关注“The Animal”,将它的表示的一部分编入“it”的编码中。接下来我们看一下 Self-Attention 详细的处理过程。

(1)首先, Self-Attention 会计算出三个新的向量,在论文中,向量的维度是 512 维,我们把这三个向量分别称为 Query、Key、Value,这三个向量是用 embedding 向量与一个矩阵( W^Q, W^K, W^V)相乘得到的结果,这个矩阵是随机初始化的,维度为(64,512),注意第二个维度需要和 embedding 的维度一样,其值在 BP 的过程中会一直进行更新,得到的这三个向量的维度是 64。

null

[公式][公式] 权重矩阵相乘得到 [公式] ,就是这个单词相关的 query 向量,最终使得输入序列的每个单词都创建一个 query 向量,一个 key 向量和一个 value 向量。
什么是"query"向量、"key"向量和"value"向量呢?
答:它们都是有助于计算和理解注意力机制的抽象概念。请继续阅读下文的内容,你就会知道每个向量在计算注意力机制中到底扮演什么样的角色。
(2)计算 Self-Attention 的分数值,该分数决定了我们在某个位置 encode 一个词时,对输入句子的其他部分的关注程度,这个计算方法是 query 与 key 做点积,假设我们在这个例子中的第一个词 Thinking 计算自注意力向量,我们需要拿输入句子中的每个单词对 Thinking 打分,这些分数决定了在编码单词 Thinking 过程中有多重视句子的其他部分。

这些分数是通过打分单词(所有输入句子的单词)的 key 向量与 Thinking 的 value 向量相点击来计算,所以如果我们是处理位置最靠前的词的注意力的话,第一个分数是 [公式][公式] 的点击积,第二个是 [公式][公式] 的点积。

null

(3)接下来, 把点成的结果除以一个常数,这里我们除以 8,这个值一般是采用上文提到的矩阵的第一个维度的开方即 64 的开方 8,这会让梯度更稳定。当然也可以选择其他的值,8 只是默认的值。然后把得到的结果做一个 softmax 的计算。softmax 的作用是使所有单词的分数归一化,得到的分数都是正值且和为 1。得到的结果即是每个词对于当前位置的词的相关性大小。

这个 softmax 分数决定了每个单词对编码当下位置(“Thinking”)的贡献。显然,已经在这个位置上的单词将获得最高的 softmax 分数,即当前位置的词相关性肯定会很大,但有时关注另一个与当前单词相关的单词也会有帮助。

null

(4)下一步 就是把每个 Value 向量和 softmax 得到的值进行相乘(这是为了准备之后将它们求和),这里的直觉是希望关注语义上相关的单词,并弱化不相关的单词(例如,让它们乘以 0.001 这样的小数)。然后对相乘的值进行相加,得到的结果即是 self-attetion 层在当前位置的输出(在我们的例子中是对于第一个单词)。

null

这样自自注意力的计算就完成了。得到的向量就可以传递给前馈神经网络。然而实际中,这些计算是以矩阵形式完成的,以便算得更快。那我们接下来就看看如何用矩阵实现的。
(1)第一步是计算 Query 矩阵,Key 矩阵和 Value 矩阵,为此我们将输入的句子的词嵌入装进矩阵 [公式] 中,将其乘以我们的训练的权重矩阵( [公式] , [公式] , [公式]


由上图可知,[公式] 矩阵中的每一行对应于输入句子中的一个单词

(2)最后我们处理的是矩阵,将步骤(2)~(4)利用下面的公式

在实际场景中,我们采用的都是矩阵的计算方法,直接计算出 Query, Key, Value 的矩阵,然后把 embedding 的值与三个矩阵直接相乘,把得到的新矩阵 Q 与 K 相乘,除以一个常数,做 softmax 操作,最后乘上 V 矩阵。这种通过 query 和 key 的相似性程度来确定 value 的权重分布的方法被称为 scaled dot-product attention。

4.3 Multi-Headed Attention

通过增加一种叫做“多头”注意力(“multi-headed”attention)的机制,论文进一步完善了自注意力层,并在两方面提高了注意力层的性能:

  • 它扩展了模型专注于不同位置的能力。在上面的例子中,虽然每个单词的编码都在 z_1 中有或多或少的体现,但是它可能被实际的单词本身所支配。如果我们翻译一个句子,比如“The animal didn’t cross the street because it was too tired”,我们会想知道“it”指的是哪个词,这时模型的“多头”注意力机制会起到作用。
  • 它给出了注意力层的多个“表示子空间”(representation subspaces)。接下来我们将看到,对于“多头”注意力机制,我们有多个 Query/Key/Value 权重矩阵集(Transformer 使用八个注意力头,因此我们对于每个编码器/解码器有八个矩阵集合)。这些集合中的每一个都是随机初始化的,在训练之后,每个集合都被用来将输入词嵌入(或来自较低编码器/解码器的向量)投影到不同的表示子空间中。

null
从上图可以看出,在多头注意力机制下,我们为每个头保持独立的 Q/K/V 权重矩阵,从而产生不同的 Q/K/V 矩阵,和之前一样,我们拿 X 乘以 [公式] / [公式] / [公式] ,如果我们做与上述相同的自注意力计算,只需要八次不同的权重矩阵运算,我们就会得到八个不同的 Z 矩阵。

null

这给我们带来了一点挑战。前馈层不需要 8 个矩阵,它只需要一个矩阵(由每一个单词的表示向量组成)。所以我们需要一种方法把这八个矩阵压缩成一个矩阵。那该怎么做?其实可以直接把这些矩阵拼接在一起,然后用一个附加的权重矩阵 W^O 与它们相乘。

null

这几乎就是多头自注意力的全部。这确实有好多矩阵,我们试着把它们集中在一个图片中,这样可以一眼看清。



null

既然我们已经摸到了注意力机制的这么多“头”,那么让我们重温之前的例子,看看我们在例句中编码“it”一词时,不同的注意力“头”集中在哪里:

null

当我们编码“it”一词时,一个注意力头集中在“animal”上,而另一个则集中在“tired”上,从某种意义上说,模型对“it”一词的表达在某种程度上是“animal”和“tired”的代表。

然而,如果我们把所有的 attention 都加到图示里,事情就更难解释了:

null

4.4 The Residuals and Layer normalization

在继续进行下去之前,我们需要提到一个编码器架构中的细节:在每个编码器中的每个子层(自注意力、前馈网络)的周围都有一个残差连接,并且都跟随着一个 Layer Normalization(层-归一化)步骤。

相关论文:
【1】Ba J L, Kiros J R, Hinton G E. Layer normalization[J]. arXiv preprint arXiv:1607.06450, 2016.

null

如果我们去可视化这些向量以及这个和自注意力相关联的 layer-norm 操作,那么看起来就像下面这张图描述一样:

null

解码器的子层也是这样样的。如果我们想象一个 2 层编码器-解码器结构的 Transformer,它看起来会像下面这张图一样:

null

4.5 Batch Normalization and Layer Normalization

Normalization 有很多种,但是它们都有一个共同的目的,那就是把输入转化成均值为 0 方差为 1 的数据。我们在把数据送入激活函数之前进行 normalization(归一化),因为我们不希望输入数据落在激活函数的饱和区。

(1)Batch Normalization

BN 的主要思想就是:在每一层的每一批数据上进行归一化。我们可能会对输入数据进行归一化,但是经过该网络层的作用后,我们的数据已经不再是归一化的了。随着这种情况的发展,数据的偏差越来越大,我的反向传播需要考虑到这些大的偏差,这就迫使我们只能使用较小的学习率来防止梯度消失或者梯度爆炸。BN 的具体做法就是对每一小批数据,在批这个方向上做归一化。

(2)Layer normalization

它也是归一化数据的一种方式,不过 LN 是在每一个样本上计算均值和方差,而不是 BN 那种在批方向计算均值和方差!公式如下:
image.png

null

5. Transformer Decoder 的结构

根据上面的总体结构图可以看出,Decoder 部分其实和 Encoder 部分大同小异,刚开始也是先添加一个位置向量 Positional Encoding,方法和 4.1 节一样,接下来接的是 masked mutil-head attetion,这里的 mask 也是 transformer 一个很关键的技术,下面我们会进行一一介绍。其余的层结构与 Encoder 一样,详细细节请看上面 Encoder 层的介绍。

5.1 masked mutil-head attetion

mask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。 Transformer 模型里面涉及两种 mask,分别是 padding mask 和 sequence mask。其中,padding mask 在所有的 scaled dot-product attention 里面都需要用到,而 sequence mask 只有在 Decoder 的 self-attention 里面用到。

(1)padding mask

什么是 padding mask 呢?因为每个批次输入序列长度是不一样的也就是说,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置,其实是没什么意义的,所以我们的 attention 机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。

具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 softmax,这些位置的概率就会接近 0!

而我们的 padding mask 实际上是一个张量,每个值都是一个 Boolean,值为 false 的地方就是我们要进行处理的地方。

(2)Sequence mask

sequence mask 是为了使得 decoder 不能看见未来的信息。也就是对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。因此我们需要想一个办法,把 t 之后的信息给隐藏起来。

那么具体怎么做呢?也很简单:产生一个上三角矩阵,上三角的值全为 0。把这个矩阵作用在每一个序列上,就可以达到我们的目的。

  • 对于 decoder 的 self-attention,里面使用到的 scaled dot-product attention,同时需要 padding mask 和 sequence mask 作为 attn_mask,具体实现就是两个 mask 相加作为 attn_mask。
  • 其他情况,attn_mask 一律等于 padding mask。

5.2 最终的线性变换和 Softmax 层

当 Decoder 层全部执行完毕后,怎么把得到的向量映射为我们需要的词呢,很简单,只需要在结尾再添加一个全连接层和 softmax 层,假如我们的词典是 1 万个词,那最终 softmax 会输出 1 万个词的概率,概率值最大的对应的词就是我们最终的结果。

null

上面这张图,底部以解码器组件产生的输出向量开始。之后它会转化出一个输出单词。

6. Transformer 动态流程图

编码器通过处理输入序列开启工作。顶端编码器的输出之后会变转化为一个包含向量 K(键向量)和 V(值向量)的注意力向量集 ,这是并行化操作。 这些向量将被每个解码器用于自身的“编码-解码注意力层”,而这些层可以帮助解码器关注输入序列哪些位置合适:

null

在完成编码阶段后,则开始解码阶段。解码阶段的每个步骤都会输出一个输出序列的元素(在这个例子里,是英语翻译的句子)。

接下来的步骤重复了这个过程,直到到达一个特殊的终止符号,它表示 transformer 的解码器已经完成了它的输出。每个步骤的输出在下一个时间步被提供给底端解码器,并且就像编码器之前做的那样,这些解码器会输出它们的解码结果 。另外,就像我们对编码器的输入所做的那样,我们会嵌入并添加位置编码给那些解码器,来表示每个单词的位置。

null

而那些解码器中的自注意力层表现的模式与编码器不同:在解码器中,自注意力层只被允许处理输出序列中更靠前的那些位置。在 softmax 步骤前,它会把后面的位置给隐去(把它们设为-inf)。

这个“编码器-解码器注意力层”工作方式基本就像多头自注意力层一样,只不过它是通过在它下面的层来创造 Queries 矩阵,并且从编码器的输出中取得 Keys、Values 矩阵。

7. Transformer 训练部分总结

现在我们已经了解了一个训练完毕的 Transformer 的前向过程,顺道看下训练的概念也是非常有用的。

在训练时,模型将经历上述的前向过程,当我们在标记训练集上训练时,可以对比预测输出与实际输出。

为了可视化,假设输出一共只有 6 个单词(“a”, “am”, “i”, “thanks”, “student”, “”)

null

图:模型的词表是在训练之前的预处理中生成的

一旦定义了词表,我们就能够构造一个同维度的向量来表示每个单词,比如 one-hot 编码,下面举例编码“am”。

null

图:举例采用 one-hot 编码输出词表

下面让我们讨论下模型的 loss 损失,在训练过程中用来优化的指标,指导学习得到一个非常准确的模型。

8. 损失函数

我们用一个简单的例子来示范训练,比如翻译“merci”为“thanks”。那意味着输出的概率分布指向单词“thanks”,但是由于模型未训练是随机初始化的,不太可能就是期望的输出。

null

由于模型参数是随机初始化的,未训练的模型输出随机值。我们可以对比真实输出,然后利用误差后传调整模型权重,使得输出更接近与真实输出。

如何对比两个概率分布呢?简单采用交叉熵(cross-entropy)或者 KL 散度(Kullback-Leibler divergence)中的一种。

鉴于这是个极其简单的例子,更真实的情况是,使用一个句子作为输入。比如,输入是“je suis étudiant”,期望输出是“i am a student”。在这个例子下,我们期望模型输出连续的概率分布满足如下条件:

  • 每个概率分布都与词表同维度。
  • 第一个概率分布对“i”具有最高的预测概率值。
  • 第二个概率分布对“am”具有最高的预测概率值。
  • 一直到第五个输出指向""标记。

null

图:对一个句子而言,训练模型的目标概率分布

在足够大的训练集上训练足够时间之后,我们期望产生的概率分布如下所示:

null

训练好之后,模型的输出是我们期望的翻译。当然,这并不意味着这一过程是来自训练集。注意,每个位置都能有值,即便与输出近乎无关,这也是 softmax 对训练有帮助的地方。

现在,因为模型每步只产生一组输出,假设模型选择最高概率,扔掉其他的部分,这是种产生预测结果的方法,叫做 greedy 解码。另外一种方法是 beam search,每一步仅保留最头部高概率的两个输出,根据这俩输出再预测下一步,再保留头部高概率的两个输出,重复直到预测结束。top_beams 是超参可试验调整。

9. 关于 Transformer 的若干问题

9.1 Transformer 为什么需要进行 Multi-head Attention?这样做有什么好处?Multi-head Attention 的计算过程?

原论文中说进行 Multi-head Attention 的原因是将模型分为多个头,形成多个子空间,可以让模型去关注不同方面的信息,最后再将各个方面的信息综合起来。其实直观上也可以想到,如果自己设计这样的一个模型,必然也不会只做一次 attention,多次 attention 综合的结果至少能够起到增强模型的作用,也可以类比 CNN 中同时使用多个卷积核的作用,直观上讲,多头的注意力有助于网络捕捉到更丰富的特征/信息。Multi-head Attention 的计算过程前面已经详细讲过。

9.2 Transformer 相比于 RNN/LSTM,有什么优势?为什么?

  • RNN 系列的模型,并行计算能力很差。RNN 并行计算的问题就出在这里,因为 T 时刻的计算依赖 T-1 时刻的隐层计算结果,而 T-1 时刻的计算依赖 T-2 时刻的隐层计算结果,如此下去就形成了所谓的序列依赖关系。
  • Transformer 的特征抽取能力比 RNN 系列的模型要好。具体实验对比可以参考: 放弃幻想,全面拥抱 Transformer:自然语言处理三大特征抽取器(CNN/RNN/TF)比较,张俊林,地址:https://zhuanlan.zhihu.com/p/54743941

但是值得注意的是,并不是说 Transformer 就能够完全替代 RNN 系列的模型了,任何模型都有其适用范围,同样的,RNN 系列模型在很多任务上还是首选,熟悉各种模型的内部原理,知其然且知其所以然,才能遇到新任务时,快速分析这时候该用什么样的模型,该怎么做好。

9.3 为什么说 Transformer 可以代替 seq2seq?

  • seq2seq 缺点: 这里用代替这个词略显不妥当,seq2seq 虽已老,但始终还是有其用武之地,seq2seq 最大的问题在于将 Encoder 端的所有信息压缩到一个固定长度的向量中 ,并将其作为 Decoder 端首个隐藏状态的输入,来预测 Decoder 端第一个单词(token)的隐藏状态。在输入序列比较长的时候,这样做显然会损失 Encoder 端的很多信息,而且这样一股脑的把该固定向量送入 Decoder 端,Decoder 端不能够关注到其想要关注的信息。上述两点都是 seq2seq 模型的缺点,后续论文对这两点有所改进,如著名的《Neural Machine Translation by Jointly Learning to Align and Translate》,虽然确确实实对 seq2seq 模型有了实质性的改进,但是由于主体模型仍然为 RNN(LSTM)系列的模型,因此模型的并行能力还是受限。
  • Transformer 优点: transformer 不但对 seq2seq 模型这两点缺点有了实质性的改进(多头交互式 attention 模块),而且还引入了 self-attention 模块,让源序列和目标序列首先“自关联”起来,这样的话,源序列和目标序列自身的 embedding 表示所蕴含的信息更加丰富,而且后续的 FFN 层也增强了模型的表达能力(ACL 2018 会议上有论文对 Self-Attention 和 FFN 等模块都有实验分析,见论文:《How Much Attention Do You Need?A Granular Analysis of Neural Machine Translation Architectures》),并且 Transformer 并行计算的能力是远远超过 seq2seq 系列的模型,因此我认为这是 transformer 优于 seq2seq 模型的地方。

9.4 Transformer 如何并行化的?

Transformer 的并行化我认为主要体现在 self-attention 模块,在 Encoder 端 Transformer 可以并行处理整个序列,并得到整个输入序列经过 Encoder 端的输出,在 self-attention 模块,对于某个序列 x_1, x_2, ...x_n,self-attention 模块可以直接计算 x_i, x_j 的点乘结果,而 RNN 系列的模型就必须按照顺序从 x_1 计算到 x_n

10. Reference

【1】【transformer】 你应该知道的 transformer,机器学习算法与自然语言处理出品,地址:https://mp.weixin.qq.com/s/lwAPIdIt98O7EgfMzi4G4Q
【2】Attention? Attention!,Lil'Log,地址:https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html#whats-wrong-with-seq2seq-model
【3】The Illustrated Transformer,地址:https://jalammar.github.io/illustrated-transformer/
【4】Transformer 各层网络结构详解!面试必备!(附代码实现),地址:https://mp.weixin.qq.com/s/NPkVJz7u0L4WWD_meZw3MQ
【5】图解 Transformer(完整版),地址:https://blog.csdn.net/longxinchen_ml/article/details/86533005
【6】[译] The Illustrated Transformer - Zewei Chu 的文章 - 知乎 https://zhuanlan.zhihu.com/p/75591049
【7】关于 Transformer 的若干问题整理记录 - Adherer 的文章 - 知乎 https://zhuanlan.zhihu.com/p/82391768
【8】深度学习中的注意力机制,地址:https://mp.weixin.qq.com/s/swLwla75RIQfyDDCPYynaw


本文地址:https://www.6aiq.com/article/1584719677724
本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出