乐趣区

关于人工智能:背景-基于-Transformers-的编码器解码器模型

!pip install transformers==4.2.1
!pip install sentencepiece==0.1.95

Vaswani 等人在其名作 Attention is all you need 中独创了 基于 transformer 的编码器 - 解码器模型,现在已成为自然语言解决 (natural language processing,NLP) 畛域编码器 - 解码器架构的 事实标准

最近基于 transformer 的编码器 - 解码器模型训练这一方向涌现出了大量对于 预训练指标函数 的钻研, 例如 T5、Bart、Pegasus、ProphetNet、Marge 等,但它们所应用的网络结构并没有扭转。

本文的目标是 具体 解释如何用基于 transformer 的编码器 - 解码器架构来对 序列到序列 (sequence-to-sequence) 问题进行建模。咱们将重点关注无关这一架构的数学知识以及如何对该架构的模型进行推理。在此过程中,咱们还将介绍 NLP 中序列到序列模型的一些背景常识,并将 基于 transformer 的编码器 - 解码器架构合成为 编码器 解码器 这两个局部别离探讨。咱们提供了许多图例,并把 基于 transformer 的编码器 - 解码器模型的实践与其在 🤗 transformers 推理场景中的理论利用二者分割起来。请留神,这篇博文 解释如何训练这些模型 —— 咱们会在后续博文中涵盖这一方面的内容。

基于 transformer 的编码器 - 解码器模型是 表征学习 模型架构 这两个畛域多年研究成果的结晶。本文简要介绍了神经编码器 - 解码器模型的历史,更多背景常识,倡议读者浏览由 Sebastion Ruder 撰写的这篇精彩 博文。此外,倡议读者对 自注意力 (self-attention) 架构 有一个根本理解,能够浏览 Jay Alammar 的 这篇博文 温习一下原始 transformer 模型。

截至本文撰写时,🤗 transformers 库曾经反对的编码器 - 解码器模型有: T5BartMarianMT 以及 Pegasus,你能够从 这儿 获取相干信息。

本文分 4 个局部:

  • 背景 简要回顾了神经编码器 - 解码器模型的历史,重点关注基于 RNN 的模型。
  • 编码器 - 解码器 论述基于 transformer 的编码器 - 解码器模型,并论述如何应用该模型进行推理。
  • 编码器 论述模型的编码器局部。
  • 解码器 论述模型的解码器局部。

每个局部都建设在前一部分的根底上,但也能够独自浏览。

背景

自然语言生成 (natural language generation,NLG) 是 NLP 的一个子畛域,其工作个别可被建模为序列到序列问题。这类工作能够定义为寻找一个模型,该模型将输出词序列映射为指标词序列,典型的例子有 摘要 翻译。在下文中,咱们假如每个单词都被编码为一个向量表征。因而,\(n \) 个输出词能够示意为 \(n \) 个输出向量组成的序列:

$$
\mathbf{X}_{1:n} = {\mathbf{x}_1, \ldots, \mathbf{x}_n}
$$

因而,序列到序列问题能够示意为找到一个映射 \(f \),其输出为 \(n \) 个向量的序列,输入为 \(m \) 个向量的指标序列 \(\mathbf{Y}_{1:m} \)。这里,指标向量数 \(m \) 是先验未知的,其值取决于输出序列:

$$
f: \mathbf{X}_{1:n} \to \mathbf{Y}_{1:m}
$$

Sutskever 等 (2014) 的工作指出,深度神经网络 (deep neural networks,DNN)“只管灵便且弱小,但只能用于拟合输出和输入维度均固定的映射。”\({}^1 \)

因而,要用应用 DNN 模型 \({}^2 \) 解决序列到序列问题就意味着指标向量数 \(m \) 必须是先验已知的,且必须独立于输出 \(\mathbf{X}_{1:n} \)。这样设定必定不是最优的。因为对 NLG 工作而言,指标词的数量通常取决于输出内容 \(\mathbf{X}_{1:n} \),而不仅仅是输出长度 \(n \)。例如,一篇 1000 字的文章,依据内容的不同,有可能能够概括为 200 字,也有可能能够概括为 100 字。

2014 年,Cho 等人 和 Sutskever 等人 提出应用齐全基于递归神经网络 (recurrent neural networks,RNN) 的编码器 - 解码器模型来解决 序列到序列 工作。与 DNN 相比,RNN 反对输入可变数量的指标向量。上面,咱们深刻理解一下基于 RNN 的编码器 - 解码器模型的性能。

在推理过程中,RNN 编码器通过间断更新其 隐含状态 \({}^3 \) 对输出序列 \(\mathbf{X}_{1:n} \) 进行编码。咱们定义解决完最初一个输出向量 \(\mathbf{x}_n \) 后的编码器隐含状态为 \(\mathbf{c} \)。因而,编码器次要实现如下映射:

$$
f_{\theta_{enc}}: \mathbf{X}_{1:n} \to \mathbf{c}
$$

而后,咱们用 \(\mathbf{c} \) 来初始化解码器的隐含状态,再用解码器 RNN 自回归地生成指标序列。

上面,咱们进一步解释一下。从数学角度讲,解码器定义了给定隐含状态 \(\mathbf{c} \) 下指标序列 \(\mathbf{Y}_{1:m} \) 的概率分布:

$$
p_{\theta_{dec}}(\mathbf{Y}_{1:m} |\mathbf{c})
$$

依据贝叶斯法令,上述散布能够合成为每个指标向量的条件散布的积,如下所示:

$$
p_{\theta_{dec}}(\mathbf{Y}_{1:m} |\mathbf{c}) = \prod_{i=1}^{m} p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{c})
$$

因而,如果模型架构能够在给定所有前驱指标向量的条件下对下一个指标向量的条件散布进行建模的话:

$$
p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{c}), \forall i \in \{1, \ldots, m\}
$$

那它就能够通过简略地将所有条件概率相乘来模仿给定暗藏状态 \(\mathbf{c} \) 下任意指标向量序列的散布。

那么基于 RNN 的解码器架构如何建模

\(p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{c}) \) 呢?

从计算角度讲,模型按序将前一时刻的外部隐含状态 \(\mathbf{c}_{i-1} \) 和前一时刻的指标向量 \(\mathbf{y}_{i-1} \) 映射到以后外部隐含状态 \(\mathbf{c}_i \) 和一个 logit 向量 \(\mathbf{l}_i \) (下图中以深红色示意):

$$
f_{\theta_{\text{dec}}}(\mathbf{y}_{i-1}, \mathbf{c}_{i-1}) \to \mathbf{l}_i, \mathbf{c}_i
$$

此处,\(\mathbf{c}_0 \) 为 RNN 编码器的输入。随后,对 logit 向量 \(\mathbf{l}_i \) 进行 softmax 操作,将其变换为下一个指标向量的条件概率分布:

$$
p(\mathbf{y}_i | \mathbf{l}_i) = \textbf{Softmax}(\mathbf{l}_i), \text{其中} \mathbf{l}_i = f_{\theta_{\text{dec}}}(\mathbf{y}_{i-1}, \mathbf{c}_{\text{prev}})
$$

更多无关 logit 向量及其生成的概率分布的详细信息,请参阅脚注 \({}^4 \)。从上式能够看出,指标向量 \(\mathbf{y}_i \) 的散布是其前一时刻的指标向量 \(\mathbf{y}_{i-1} \) 及前一时刻的隐含状态 \(\mathbf{c}_{i-1} \) 的条件散布。而咱们晓得前一时刻的隐含状态 \(\mathbf{c}_{i-1} \) 依赖于之前所有的指标向量 \(\mathbf{y}_0, \ldots, \mathbf{y}_{i- 2} \),因而咱们能够说 RNN 解码器 隐式 (_或间接_) 地建模了条件散布
\(p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{c}) \)。

指标向量序列 \(\mathbf{Y}_{1:m} \) 的概率空间十分大,因而在推理时,必须借助解码办法对 = \({}^5 \) 对 \(p_{\theta_{dec}}(\mathbf{Y}_{1:m} |\mathbf{c}) \) 进行采样能力高效地生成最终的指标向量序列。

给定某解码办法,在推理时,咱们首先从散布 \(p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{c}) \) 中采样出下一个输入向量; 接着,将其增加至解码器输出序列开端,让解码器 RNN 持续从
\(p_{\theta_{\text{dec}}}(\mathbf{y}_{i+1} | \mathbf{Y}_{0: i}, \mathbf{c}) \) 中采样出下一个输入向量 \(\mathbf{y}_{i+1} \),如此往返,整个模型就以 自回归 的形式生成了最终的输入序列。

基于 RNN 的编码器 - 解码器模型的一个重要特色是须要定义一些 非凡 向量,如 \(\text{EOS} \) (终止符) 和 \(\text{BOS} \) (起始符) 向量。\(\text{EOS} \) 向量通常意味着 \(\mathbf{x}_n \) 停止,呈现这个即“提醒”编码器输出序列已完结; 如果它呈现在指标序列中意味着输入完结,一旦从 logit 向量中采样到 \(\text{EOS} \),生成就实现了。\(\text{BOS} \) 向量用于示意在第一步解码时馈送到解码器 RNN 的输出向量 \(\mathbf{y}_0 \)。为了输入第一个 logit \(\mathbf{l}_1 \),须要一个输出,而因为在其之前还没有生成任何输出,所以咱们馈送了一个非凡的 \(\text{BOS} \) 输出向量到解码器 RNN。好,有点绕了!咱们用一个例子阐明一下。

上图中,咱们将编码器 RNN 编码器开展,并用绿色示意; 同时,将解码器 RNN 开展,并用红色示意。

英文句子 I want to buy a car,示意为 \) (\mathbf{x}_1 = \text{I} \),\(\mathbf{x}_2 = \text{want} \),\(\mathbf{x}_3 = \text{to} \),\(\mathbf{x}_4 = \text{buy} \),\(\mathbf{x}_5 = \text{a} \),\(\mathbf{x}_6 = \text{car} \),\(\mathbf{x}_7 = \text{EOS} \))。将其翻译成德语:“Ich will ein Auto kaufen”,示意为 \) (\mathbf{y}_0 = \text{BOS} \),\(\mathbf{y}_1 = \text{Ich} \),\(\mathbf{y}_2 = \text{will} \),\(\mathbf{y}_3 = \text {ein} \),\(\mathbf{y}_4 = \text{Auto} \),\(\mathbf{y}_5 = \text{kaufen} \),\(\mathbf{y}_6=\text{EOS} \))。首先,编码器 RNN 解决输出向量 \(\mathbf{x}_1 = \text{I} \) 并更新其隐含状态。请留神,对编码器而言,因为咱们只对其最终隐含状态 \(\mathbf{c} \) 感兴趣,所以咱们能够疏忽它的指标向量。而后,编码器 RNN 以雷同的形式顺次解决输出句子的其余部分: \(\text{want} \)、\(\text{to} \)、\(\text{buy} \)、\(\text{a} \)、\(\text{car} \)、\(\text{EOS} \),并且每一步都更新其隐含状态,直到遇到向量 \(\mathbf{x}_7={EOS} \) \({}^6 \)。在上图中,连贯开展的编码器 RNN 的程度箭头示意按序更新隐含状态。编码器 RNN 的最终隐含状态,由 \(\mathbf{c} \) 示意,其齐全定义了输出序列的 编码,并可用作解码器 RNN 的初始隐含状态。能够认为,解码器 RNN 以编码器 RNN 的最终隐含状态为条件。

为了生成第一个指标向量,将 \(\text{BOS} \) 向量输出给解码器,即上图中的 \(\mathbf{y}_0 \)。而后通过 语言模型头 (LM Head) 前馈层将 RNN 的指标向量进一步映射到 logit 向量 \(\mathbf{l}_1 \),此时,可得第一个指标向量的条件散布:

$$
p_{\theta_{dec}}(\mathbf{y} | \text{BOS}, \mathbf{c})
$$

最终采样出第一个指标词 \(\text{Ich} \) (如图中连贯 \( \mathbf{l}_1 \) 和 \(\mathbf{y}_1 \) 的灰色箭头所示)。接着,持续采样出第二个指标向量:

$$
\text{will} \sim p_{\theta_{dec}}(\mathbf{y} | \text{BOS}, \text{Ich}, \mathbf{c})
$$

依此类推,始终到第 6 步,此时从 \(\mathbf{l}_6 \) 中采样出 \(\text{EOS} \),解码实现。输入指标序列为 \(\mathbf{Y}_{1:6} = {\mathbf{y}_1, \ldots, \mathbf{y}_6} \), 即上文中的“Ich will ein Auto kaufen”。

综上所述,咱们通过将散布 \(p(\mathbf{Y}_{1:m} | \mathbf{X}_{1:n}) \) 合成为 \(f_{\theta_{\text{enc}}} \) 和 \(p_{\theta_{\text{dec}}} \) 的示意来建模基于 RNN 的 encoder-decoder 模型:

$$
p_{\theta_{\text{enc}}, \theta_{\text{dec}}}(\mathbf{Y}_{1:m} | \mathbf{X}_{1:n}) = \prod_{i=1}^{m} p_{\theta_{\text{enc}}, \theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{X}_{1:n}) = \prod_{i=1}^{m} p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{c}), \text{其中} \mathbf{c}=f_{\theta_{enc}}(X)
$$

在推理过程中,利用高效的解码办法能够自回归地生成指标序列 \(\mathbf{Y}_{1:m} \)。

基于 RNN 的编码器 - 解码器模型席卷了 NLG 社区。2016 年,谷歌发表用基于 RNN 的编码器 - 解码器繁多模型齐全取代其原先应用的的含有大量特色工程的翻译服务 (参见
此处)。

然而,基于 RNN 的编码器 - 解码器模型存在两个次要缺点。首先,RNN 存在梯度隐没问题,因而很难捕捉长程依赖性,参见 Hochreiter 等 (2001) 的工作。其次,RNN 固有的循环架构使得在编码时无奈进行无效的并行化, 参见 Vaswani 等 (2017) 的工作。


\({}^1 \) 论文的原话是“只管 DNN 具备灵活性和弱小的性能,但它们只能利用于输出和指标能够用固定维度的向量进行正当编码的问题”,用在本文时稍作调整。

\({}^2 \) 这同样实用于卷积神经网络 (CNN)。尽管能够将可变长度的输出序列输出 CNN,但指标的维度要么取决于输出维数要么须要固定为特定值。

\({}^3 \) 在第一步时,隐含状态被初始化为零向量,并与第一个输出向量 \(\mathbf{x}_1 \) 一起馈送给 RNN。

\({}^4 \) 神经网络能够将所有单词的概率分布定义为 \(p(\mathbf{y} | \mathbf{c}, \mathbf{Y}_{0 : i-1} \)。首先,其将输出 \(\mathbf{c}, \mathbf{Y}_{0: i-1} \) 转换为嵌入向量 \(\mathbf{y’} \),该向量对应于 RNN 模型的指标向量。随后将 \(\mathbf{y’} \) 送给“语言模型头”,行将其乘以 词嵌入矩阵 (即 \( \mathbf{Y}^{\text{vocab}} \)),失去 \(\mathbf{y’} \) 和词表 \(\mathbf{Y}^{\text{vocab}} \) 中的每个向量 \(\mathbf{y} \) 的类似度得分,生成的向量称为 logit 向量 \(\mathbf{l} = \mathbf{Y}^{\text{vocab}} \mathbf{y’} \),最初再通过 softmax 操作归一化成所有单词的概率分布: \(p(\mathbf{y} | \mathbf{c}) = \text{Softmax}(\mathbf{Y}^{\text{vocab}} \mathbf{y’}) = \text {Softmax}(\mathbf{l}) \)。

\({}^5 \) 波束搜寻 (beam search) 是其中一种解码办法。本文不会对不同的解码办法进行介绍,如对此感兴趣,倡议读者参考 此文。

\({}^6 \) Sutskever 等 (2014) 的工作对输出程序进行了逆序,对下面的例子而言,输出向量变成了 (\( \mathbf{x}_1 = \text{car} \),\(\mathbf{x}_2 = \text{a} \),\(\mathbf{x}_3 = \text{buy} \),\(\mathbf{x}_4 = \text{to} \),\(\mathbf{x}_5 = \text{want} \),\(\mathbf{x}_6 = \text{I} \),\(\mathbf{x}_7 = \text{EOS} \))。其动机是让对应词对之间的连贯更短,如能够使得 \(\mathbf{x}_6 = \text{I} \) 和 \(\mathbf{y}_1 = \text{Ich} \) 之间的连贯更短。该钻研小组强调,将输出序列进行逆序是他们的模型在机器翻译上的性能进步的一个要害起因。

敬请关注其余部分的文章。


英文原文: https://hf.co/blog/encoder-decoder

原文作者: Patrick von Platen

译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的利用及大规模模型的训练推理。

审校 / 排版: zhongdongy (阿东)

退出移动版