基于 transformer 的编码器 - 解码器模型是 表征学习 和 模型架构 这两个畛域多年研究成果的结晶。本文简要介绍了神经编码器 - 解码器模型的历史,更多背景常识,倡议读者浏览由 Sebastion Ruder 撰写的这篇精彩 博文。此外,倡议读者对 自注意力 (self-attention) 架构 有一个根本理解,能够浏览 Jay Alammar 的 这篇博文 温习一下原始 transformer 模型。
本文分 4 个局部:
- 背景 – 简要回顾了神经编码器 - 解码器模型的历史,重点关注基于 RNN 的模型。
- 编码器 - 解码器 – 论述基于 transformer 的编码器 - 解码器模型,并论述如何应用该模型进行推理。
- 编码器 – 论述模型的编码器局部。
- 解码器 – 论述模型的解码器局部。
每个局部都建设在前一部分的根底上,但也能够独自浏览。这篇分享是第二局部 编码器 - 解码器。
编码器 - 解码器
2017 年,Vaswani 等人引入了 transformer 架构,从而催生了 基于 transformer 的编码器 - 解码器模型。
与基于 RNN 的编码器 - 解码器模型相似,基于 transformer 的编码器 - 解码器模型由一个编码器和一个解码器组成,且其编码器和解码器均由 残差注意力模块 (residual attention blocks) 重叠而成。基于 transformer 的编码器 - 解码器模型的要害翻新在于: 残差注意力模块无需应用循环构造即可解决长度 \(n \) 可变的输出序列 \(\mathbf{X}_{1:n} \)。不依赖循环构造使得基于 transformer 的编码器 - 解码器能够高度并行化,这使得模型在古代硬件上的计算效率比基于 RNN 的编码器 - 解码器模型高出几个数量级。
回顾一下,要解决 序列到序列 问题,咱们须要找到输出序列 \(\mathbf{X}_{1:n} \) 到变长输入序列 \(\mathbf{Y}_{1:m} \) 的映射。咱们看看如何应用基于 transformer 的编码器 - 解码器模型来找到这样的映射。
与基于 RNN 的编码器 - 解码器模型相似,基于 transformer 的编码器 - 解码器模型定义了在给定输出序列 \(\mathbf{X}_{1:n} \) 条件下指标序列 \(\mathbf{Y}_{1:m} \) 的条件散布:
$$
p_{\theta_{\text{enc}}, \theta_{\text{dec}}}(\mathbf{Y}_{1:m} | \mathbf{X}_{1:n})
$$
基于 transformer 的编码器局部将输出序列 \(\mathbf{X}_{1:n} \) 编码为 隐含状态序列 \(\mathbf{\overline{X}}_{1:n} \),即:
$$
f_{\theta_{\text{enc}}}: \mathbf{X}_{1:n} \to \mathbf{\overline{X}}_{1:n}
$$
而后,基于 transformer 的解码器负责建模在给定隐含状态序列 \(\mathbf{\overline{X}}_{1:n} \) 的条件下指标向量序列 \(\mathbf{Y}_{1:m} \) 的概率分布:
$$
p_{\theta_{dec}}(\mathbf{Y}_{1:m} | \mathbf{\overline{X}}_{1:n})
$$
依据贝叶斯法令,该序列散布可被合成为每个指标向量 \(\mathbf{y}_i \) 在给定隐含状态 \(\mathbf{\overline{X} }_{1:n} \) 和其所有前驱指标向量 \(\mathbf{Y}_{0:i-1} \) 时的条件概率之积:
$$
p_{\theta_{dec}}(\mathbf{Y}_{1:m} | \mathbf{\overline{X}}_{1:n}) = \prod_{i=1}^{m} p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{\overline{X}}_{1:n})
$$
因而,在生成 \(\mathbf{y}_i \) 时,基于 transformer 的解码器将隐含状态序列 \(\mathbf{\overline{X}}_{1:n} \) 及其所有前驱指标向量 \(\mathbf{Y}_{0 :i-1} \) 映射到 logit 向量 \(\mathbf{l}_i \)。而后经由 softmax 运算对 logit 向量 \(\mathbf{l}_i \) 进行解决,从而生成条件散布 \(p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{\overline{X}}_{1:n}) \)。这个流程跟基于 RNN 的解码器是一样的。然而,与基于 RNN 的解码器不同的是,在这里,指标向量 \(\mathbf{y}_i \) 的散布是 显式 (或间接) 地以其所有前驱指标向量 \(\mathbf{y}_0, \ldots, \mathbf{y}_{i-1} \) 为条件的,稍后咱们将具体介绍。此处第 0 个指标向量 \(\mathbf{y}_0 \) 仍示意为 \(\text{BOS} \) 向量。有了条件散布 \(p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{\overline{X} }_{1:n}) \),咱们就能够 自回归 生成输入了。至此,咱们定义了可用于推理的从输出序列 \(\mathbf{X}_{1:n} \) 到输入序列 \(\mathbf{Y}_{1:m} \) 的映射。
咱们可视化一下应用 基于 transformer 的编码器 - 解码器模型 _自回归_地生成序列的残缺过程。
上图中,绿色为基于 transformer 的编码器,红色为基于 transformer 的解码器。与上一节一样,咱们展现了如何将示意为 \((\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}) \) 的英语句子“I want to buy a car”翻译成示意为 \((\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}) \) 的德语句子“Ich will ein Auto kaufen”。
首先,编码器将残缺的输出序列 \(\mathbf{X}_{1:7} \) =“I want to buy a car”(由浅绿色向量示意) 解决为上下文相干的编码序列 \(\mathbf{\overline{X}}_{1:7} \)。这里上下文相干的意思是,举个例子 ,\(\mathbf{\overline{x}}_4 \) 的编码不仅取决于输出 \(\mathbf{x}_4 \) =“buy”,还与所有其余词“I”、“want”、“to”、“a”、“car”及“EOS”相干,这些词即该词的 上下文。
接下来,输出编码 \(\mathbf{\overline{X}}_{1:7} \) 与 BOS 向量 (即 \(\mathbf{y}_0 \)) 被一起馈送到解码器。解码器将输出 \(\mathbf{\overline{X}}_{1:7} \) 和 \(\mathbf{y}_0 \) 变换为第一个 logit \(\mathbf{l}_1 \) (图中以深红色显示),从而失去第一个指标向量 \(\mathbf{y}_1 \) 的条件散布:
$$
p_{\theta_{enc, dec}}(\mathbf{y} | \mathbf{y}_0, \mathbf{X}_{1:7}) = p_{\theta_{enc, dec}}(\mathbf{y} | \text{BOS}, \text{I want to buy a car EOS}) = p_{\theta_{dec}}(\mathbf{y} | \text{BOS}, \mathbf{\overline{X}}_{1:7})
$$
而后,从该散布中采样出第一个指标向量 \(\mathbf{y}_1 \) = \(\text{Ich} \) (由灰色箭头示意),失去第一个输入后,咱们会并将其持续馈送到解码器。当初,解码器开始以 \(\mathbf{y}_0 \) =“BOS”和 \(\mathbf{y}_1 \) =“Ich”为条件来定义第二个指标向量的条件散布 \(\mathbf{y}_2 \):
$$
p_{\theta_{dec}}(\mathbf{y} | \text{BOS Ich}, \mathbf{\overline{X}}_{1:7})
$$
再采样一次,生成指标向量 \(\mathbf{y}_2 \) =“will”。反复该自回归过程,直到第 6 步从条件散布中采样到 EOS:
$$
\text{EOS} \sim p_{\theta_{dec}}(\mathbf{y} | \text{BOS Ich will ein Auto kaufen}, \mathbf{\overline{X}}_{1:7})
$$
这里有一点比拟重要,咱们仅在第一次前向流传时用编码器将 \(\mathbf{X}_{1:n} \) 映射到 \(\mathbf{\overline{X}}_{1:n} \)。从第二次前向流传开始,解码器能够间接应用之前算得的编码 \(\mathbf{\overline{X}}_{1:n} \)。为分明起见,下图画出了上例中第一次和第二次前向流传所须要做的操作。
能够看出,仅在步骤 \(i=1 \) 时,咱们才须要将“I want to buy a car EOS”编码为 \(\mathbf{\overline{X}}_{1:7} \)。从 \(i=2 \) 开始,解码器只是简略地复用了已生成的编码。
在 🤗 transformers 库中,这一自回归生成过程是在调用 .generate()
办法时在后盾实现的。咱们用一个翻译模型来理论体验一下。
from transformers import MarianMTModel, MarianTokenizer
tokenizer = MarianTokenizer.from_pretrained("Helsinki-NLP/opus-mt-en-de")
model = MarianMTModel.from_pretrained("Helsinki-NLP/opus-mt-en-de")
# create ids of encoded input vectors
input_ids = tokenizer("I want to buy a car", return_tensors="pt").input_ids
# translate example
output_ids = model.generate(input_ids)[0]
# decode and print
print(tokenizer.decode(output_ids))
输入:
<pad> Ich will ein Auto kaufen
.generate()
接口做了很多事件。首先,它将 input_ids
传递给编码器。而后,它将一个预约义的标记连同已编码的 input_ids
一起传递给解码器 (在应用 MarianMTModel
的状况下,该预约义标记为 \(\text{<pad>} \) )。接着,它应用波束搜寻解码机制依据最新的解码器输入的概率分布 \({}^1 \) 自回归地采样下一个输入词。更多无关波束搜寻解码工作原理的详细信息,倡议浏览 这篇博文。
咱们在附录中退出了一个代码片段,展现了如何“从头开始”实现一个简略的生成办法。如果你想要齐全理解 自回归 生成的幕后工作原理,强烈建议浏览附录。
总结一下:
- 基于 transformer 的编码器实现了从输出序列 \(\mathbf{X}_{1:n} \) 到上下文相干的编码序列 \(\mathbf{\overline{X}}_{1 :n} \) 之间的映射。
- 基于 transformer 的解码器定义了条件散布 \(p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{\overline{X}}_{1:n}) \)。
- 给定适当的解码机制,能够自回归地从 \(p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{\overline{X}}_{1:n}), \forall i \in {1, \ldots, m} \) 中采样出输入序列 \(\mathbf{Y}_{1:m} \)。
太好了,当初咱们曾经大抵理解了 基于 transformer 的 编码器 - 解码器模型的工作原理。上面的局部,咱们将更深刻地钻研模型的编码器和解码器局部。更具体地说,咱们将确切地看到编码器如何利用自注意力层来产生一系列上下文相干的向量编码,以及自注意力层如何实现高效并行化。而后,咱们将具体解释自注意力层在解码器模型中的工作原理,以及解码器如何通过 穿插注意力 层以编码器输入为条件来定义散布 \(p_{\theta_{\text{dec}}}(\mathbf{y}_i | \mathbf{Y}_{0: i-1}, \mathbf{\overline{X}}_{1:n}) \)。在此过程中,基于 transformer 的编码器 - 解码器模型如何解决基于 RNN 的编码器 - 解码器模型的长程依赖问题的答案将变得不言而喻。
\({}^1 \) 能够从 此处 获取 "Helsinki-NLP/opus-mt-en-de"
的解码参数。能够看到,其应用了 num_beams=6
的波束搜寻。
敬请关注其余部分的文章。
英文原文: https://hf.co/blog/encoder-decoder
原文作者: Patrick von Platen
译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的利用及大规模模型的训练推理。
审校 / 排版: zhongdongy (阿东)