转载自Transformer原理,如侵联删

Transformer由论文Attention is All You Need提出,本文大部分内容来源于Transformer模型详解(图解最完整版),对于不理解的地方,我会加上个人注解。

1 Attention简介

1.1 Attention注意力机制

从“Attention”这个名字可以读出,Attention机制主要是对注意力的捕捉。Attention的原理与大脑处理信息有一些相似。比如看到下面这张图,短时间内大脑可能只对图片中的“锦江饭店”有印象,即注意力集中在了“锦江饭店”处。短时间内,大脑可能并没有注意到锦江饭店上面有一串电话号码,下面有几个行人,后面还有“喜运来大酒家”等信息。

Transformer原理-StubbornHuang Blog

所以,大脑在短时间内处理信息时,主要将图片中最吸引人注意力的部分读出来了,类似下面。

Transformer原理-StubbornHuang Blog

Attention的输入由三部分构成:Query、Key和Value。其中,(Key, Value)是具有相互关联的KV对,Query是输入的“问题”,Attention可以将Query转化为与Query最相关的向量表示。

Attention的计算主要分3步,如下图所示。

Transformer原理-StubbornHuang Blog

第一步:Query和Key进行相似度计算,得到Attention Score;

第二步:对Attention Score进行Softmax归一化,得到权值矩阵;

第三步:权重矩阵与Value进行加权求和计算。

Query、Key和Value的含义是什么呢?我们以刚才大脑读图为例。Value可以理解为人眼视网膜对整张图片信息的原始捕捉,不受“注意力”所影响。我们可以将Value理解为像素级别的信息,那么假设只要一张图片呈现在人眼面前,图片中的像素都会被视网膜捕捉到。Key与Value相关联,Key是图片原始信息所对应的关键性提示信息,比如“锦江饭店”部分是将图片中的原始像素信息抽象为中文文字和牌匾的提示信息。一个中文读者看到这张图片时,读者大脑有意识地向图片获取信息,即发起了一次Query,Query中包含了读者的意图等信息。在一次读图过程中,Query与Key之间计算出Attention Score,得到最具有吸引力的部分,并只对具有吸引力的Value信息进行提取,反馈到大脑中。就像上面的例子中,经过大脑的注意力机制的筛选,一次Query后,大脑只关注“锦江饭店”的牌匾部分。

再以一个搜索引擎的检索为例。使用某个Query去搜索引擎里搜索,搜索引擎里面有好多文章,每个文章的全文可以被理解成Value;文章的关键性信息是标题,可以将标题认为是Key。搜索引擎用Query和那些文章们的标题(Key)进行匹配,看看相似度(计算Attention Score)。我们想得到跟Query相关的知识,于是用这些相似度将检索的文章Value做一个加权和,那么就得到了一个新的信息,新的信息融合了相关性强的文章们,而相关性弱的文章可能被过滤掉。

1.2 cross-attention与self-attention

看完下文之后,就知道了Encoder部分中只存在self-attention,而Decoder部分中存在self-attention和cross-attention。这里提前解释一下,看完下文之后可以再回味这一小节。

  1. self-attention:encoder中的self-attention的query、key、value都对应了源端序列,decoder中的self-attention的query、key、value都对应了目标端序列。
  2. cross-attention:decoder中的cross-attention的query对应了目标端序列,key、value对应了源端序列(每一层中的cross-attention用的都是encoder的最终输出)

也就是说

Attention connecting between the encoder and the decoder is called cross-attention since keys and values are generated by a different sequence than queries. If the keys, values, and queries are generated from the same sequence, then we call it self-attention. The cross-attention mechanism allows output to focus attention on input when producing output while the self-attention model allows inputs to interact with each other.

下图是cross-attention的示意图。

Transformer原理-StubbornHuang Blog

下图是self-attention的示意图。

Transformer原理-StubbornHuang Blog

2 Transformer的核心思想

2.1 RNN缺陷

在没有Transformer以前,大家做神经机器翻译用的最多的是基于RNN的Encoder-Decoder模型:在没有Transformer以前,大家做神经机器翻译用的最多的是基于RNN的Encoder-Decoder模型:

Transformer原理-StubbornHuang Blog

上图中的 Encoder-Decoder 模型将德语短语转换为英语短语。让我们把它分解一下:

  • 编码器解码器都是递归神经网络。
  • 在编码器中的每个时间步骤,递归神经网络从输入序列获取词向量(x_{i}),从前一个时间步骤中获取一个隐状态(H_{i})。
  • 隐状态在每个时间步骤中更新。
  • 最后一个单元的隐状态称为语境矢量(context vector)。它包含有关输入序列的信息。
  • 然后将该语境矢量传递给解码器,然后使用它生成目标序列(英文短语)。

Encoder-Decoder模型当然很成功,在2018年以前用它是用的很多的。而且也有很强的能力。但是RNN天生有缺陷,只要是RNN,就会有梯度消失问题,核心原因是有递归的方式,作用在同一个权值矩阵上,使得如果这个矩阵满足条件的话,其最大的特征值要是小于1的话,那就一定会出现梯度消失问题。后来的LSTM和GRU也仅仅能缓解这个问题Encoder-Decoder模型当然很成功,在2018年以前用它是用的很多的。而且也有很强的能力。但是RNN天生有缺陷,只要是RNN,就会有梯度消失问题,核心原因是有递归的方式,作用在同一个权值矩阵上,使得如果这个矩阵满足条件的话,其最大的特征值要是小于1的话,那就一定会出现梯度消失问题,后来的LSTM和GRU也仅仅能缓解这个问题,并不能彻底解决这个问题。

2.2 Transformer为什么优于RNN

那如果要获得比RNN更进一步能力的提升,那怎么办呢?Transformer给了我们一种答案。

Transformer中抛弃了传统的CNN和RNN,整个网络结构完全是由Attention机制组成。 作者采用Attention机制的原因是考虑到RNN(或者LSTM,GRU等)的计算限制为是顺序的,也就是说RNN相关算法只能从左向右依次计算或者从右向左依次计算,这种机制带来了两个问题:

  1. 顺序计算的过程中信息会丢失,尽管LSTM等门机制的结构一定程度上缓解了长期依赖的问题,但是对于特别长期的依赖现象,LSTM依旧无能为力。
  2. 时间片t的计算依赖t-1时刻的计算结果,这样限制了模型的并行能力。

Transformer的提出解决了上面两个问题:

  1. 首先它使用了Attention机制,将序列中的任意两个位置之间的距离缩小为一个常量。因为在集成信息的时候,当前单词和句子中任意单词都发生了联系,所以一步到位就把这个事情做掉了。不像RNN需要通过隐层节点序列往后传,也不像CNN需要通过增加网络深度来捕获远距离特征,Transformer在这点上明显方案是相对简单直观的。
  2. 其次它不是类似RNN的顺序结构,因此具有更好的并行性,符合现有的GPU框架。注意这里的并行性,Transformer encoder与decoder在训练过程中都可以并行化,主要借助了teacher force与masked self attention,具体可以参考下文。至于在推理过程中,encoder可以并行化,但是decoder是step by step的,无法并行化。

2.3 整体结构

首先介绍 Transformer 的整体结构,下图是 Transformer 用于中英文翻译的整体结构:

Transformer原理-StubbornHuang Blog

可以看到 Transformer 由 Encoder 和 Decoder 两个部分组成,各包含 6 个 block。它的工作流程大体如下:

第一步:获取输入句子的每一个单词的表示向量 xx单词的 Embedding(从原始数据提取出来的Feature) 和单词位置的 Embedding 相加得到。

Transformer原理-StubbornHuang Blog

第二步:将得到的单词表示向量矩阵 (如上图所示,每一行是一个单词的表示 x) 传入 Encoder 中,经过 6 个 Encoder block 后可以得到句子所有单词的编码信息矩阵 C,如下图。单词向量矩阵用X_{n,d}表示, n 是句子中单词个数,d 是表示向量的维度 (论文中 d=512)。每一个 Encoder block 输出的矩阵维度与输入完全一致。

Transformer原理-StubbornHuang Blog

第三步:将 Encoder 输出的编码信息矩阵 C 传递到 Decoder 中,Decoder 依次会根据当前翻译过的单词 1~ i 翻译下一个单词 i+1,如下图所示。在使用的过程中,翻译到单词 i+1 的时候需要通过 Mask (掩盖) 操作遮盖住 i+1 之后的单词。

Transformer原理-StubbornHuang Blog

上图 Decoder 接收了 Encoder 的编码矩阵 C,然后首先输入一个翻译开始符 ““,预测第一个单词 “I”;然后输入翻译开始符 ““ 和单词 “I”,预测单词 “have”,以此类推。这是 Transformer 使用时候的大致流程,接下来是里面各个部分的细节。

2.3.1 输入

Transformer 中单词的输入表示 x单词 Embedding位置 Embedding (Positional Encoding)相加得到。

Transformer原理-StubbornHuang Blog

2.3.2 单词 Embedding

单词的 Embedding 有很多种方式可以获取,例如可以采用 Word2Vec、Glove 等算法预训练得到,也可以在 Transformer 中训练得到(比如fairseq的翻译模型就利用了torch.nn.Embedding进行Embedding并训练)。

2.3.3 位置 Embedding

Transformer 中除了单词的 Embedding,还需要使用位置 Embedding 表示单词出现在句子中的位置。因为 Transformer 不采用 RNN 的结构,而是使用全局信息,不能利用单词的顺序信息,而这部分信息对于 NLP 来说非常重要。所以 Transformer 中使用位置 Embedding 保存单词在序列中的相对或绝对位置。

位置 Embedding 用 PE表示,PE 的维度与单词 Embedding 是一样的。PE 可以通过训练得到,也可以使用某种公式计算得到。在 Transformer 中采用了后者,计算公式如下:

\begin{array}{c}{{P E_{(p o s,2i)}=\sin\left(p o s/1000^{2i/d}\right)}}\\ {{P E_{(p o s,2i+1)}=\cos\left(p o s/1000^{2i/d}\right)}}\end{array}

其中,pos 表示单词在句子中的位置,d 表示 PE的维度 (与词 Embedding 一样),2i 表示偶数的维度,2i+1 表示奇数维度 (即 2i≤d, 2i+1≤d)。使用这种公式计算 PE 有以下的好处:

  • 使 PE 能够适应比训练集里面所有句子更长的句子,假设训练集里面最长的句子是有 20 个单词,突然来了一个长度为 21 的句子,则使用公式计算的方法可以计算出第 21 位的 Embedding。
  • 可以让模型容易地计算出相对位置,对于固定长度的间距 k,PE(pos+k) 可以用 PE(pos) 计算得到。因为 Sin(A+B) = Sin(A)Cos(B) + Cos(A)Sin(B), Cos(A+B) = Cos(A)Cos(B) - Sin(A)Sin(B)。

将单词的词 Embedding 和位置 Embedding 相加,就可以得到单词的表示向量 xx 就是 Transformer 的输入。

2.4 Self-Attention(自注意力机制)

Transformer原理-StubbornHuang Blog

上图是论文中 Transformer 的内部结构图,左侧为 Encoder block,右侧为 Decoder block。红色圈中的部分为 Multi-Head Attention,是由多个 Self-Attention组成的,可以看到 Encoder block 包含一个 Multi-Head Attention,而 Decoder block 包含两个 Multi-Head Attention (其中有一个用到 Masked)。Multi-Head Attention 上方还包括一个 Add & Norm 层,Add 表示残差连接 (Residual Connection) 用于防止网络退化,Norm 表示 Layer Normalization,用于对每一层的激活值进行归一化。

因为 Self-Attention是 Transformer 的重点,所以我们重点关注 Multi-Head Attention 以及 Self-Attention,首先详细了解一下 Self-Attention 的内部逻辑。

2.4.1 Self-Attention 结构

Transformer原理-StubbornHuang Blog

上图是 Self-Attention 的结构,在计算的时候需要用到矩阵Q(查询),K(键值),V(值)。在实际中,Self-Attention 接收的是输入(单词的表示向量x组成的矩阵X) 或者上一个 Encoder block 的输出。而Q,K,V正是通过 Self-Attention 的输入进行线性变换得到的。

2.4.2 Q, K, V 的计算

Self-Attention 的输入用矩阵X进行表示,则可以使用线性变阵矩阵WQ,WK,WV计算得到Q,K,V。计算如下图所示,注意 X, Q, K, V 的每一行都表示一个单词。

Transformer原理-StubbornHuang Blog

2.4.3 Self-Attention 的输出

得到矩阵 Q, K, V 之后就可以计算出 Self-Attention 的输出了,计算的公式如下(先计算括号内+softmax,然后乘上V):

Transformer原理-StubbornHuang Blog

公式中计算矩阵QK每一行向量的内积,为了防止内积过大,因此除以d_{k}的平方根,Q乘以K的转置后,得到的矩阵行列数都为 n,n 为句子单词数,这个矩阵可以表示单词之间的 attention 强度。下图为Q乘以K^T,1234表示的是句子中的单词

Transformer原理-StubbornHuang Blog

得到QK^T之后,使用 Softmax 计算每一个单词对于其他单词的 attention 系数,公式中的 Softmax 是对矩阵的每一行进行 Softmax,即每一行的和都变为 1。

Transformer原理-StubbornHuang Blog

得到 Softmax 矩阵之后可以和V相乘,得到最终的输出Z

Transformer原理-StubbornHuang Blog

上图中 Softmax 矩阵的第 1 行表示单词 1 与其他所有单词的 attention 系数,最终单词 1 的输出Z_{1}等于所有单词i的值V_{i}根据attention系数的比例加在一起得到,如下图所示:

Transformer原理-StubbornHuang Blog

2.5 Multi-Head Attention

在上一步,我们已经知道怎么通过 Self-Attention 计算得到输出矩阵 Z,而 Multi-Head Attention 是由多个 Self-Attention 组合形成的,下图是论文中 Multi-Head Attention 的结构图。

Transformer原理-StubbornHuang Blog

从上图可以看到 Multi-Head Attention 包含多个 Self-Attention 层,首先将输入X分别传递到 h 个不同的 Self-Attention 中(也就是说会有8个不同的V、K、Q),计算得到 h 个输出矩阵Z。下图是 h=8 时候的情况,此时会得到 8 个输出矩阵Z

Transformer原理-StubbornHuang Blog

得到 8 个输出矩阵 Z1Z8 之后,Multi-Head Attention 将它们拼接在一起 (Concat),然后传入一个Linear层,得到 Multi-Head Attention 最终的输出Z

Transformer原理-StubbornHuang Blog

可以看到 Multi-Head Attention 输出的矩阵Z与其输入的矩阵X的维度是一样的。

2.6 Encoder结构

Transformer原理-StubbornHuang Blog

上图红色部分是 Transformer 的 Encoder block 结构,可以看到是由 Multi-Head Attention, Add & Norm, Feed Forward, Add & Norm 组成的。刚刚已经了解了 Multi-Head Attention 的计算过程,现在了解一下 Add & Norm 和 Feed Forward 部分。

2.6.1 Add & Norm

Add & Norm 层由 Add 和 Norm 两部分组成,其计算公式如下(以下分别表示上图红色部分第一个和第二个Add & Norm 层):

Transformer原理-StubbornHuang Blog

其中 X 表示 Multi-Head Attention 或者 Feed Forward 的输入,MultiHeadAttention(X) 和 FeedForward(X) 表示输出 (输出与输入 X 维度是一样的,所以可以相加)。

AddX+MultiHeadAttention(X)或者X+FeedForward(X),是一种残差连接,通常用于解决多层网络训练的问题,可以让网络只关注当前差异的部分,在 ResNet 中经常用到:

Transformer原理-StubbornHuang Blog

Norm指 Layer Normalization,通常用于 RNN 结构,Layer Normalization 会将每一层神经元的输入都转成均值方差都一样的,这样可以加快收敛

2.6.2 Feed Forward

Feed Forward 层比较简单,是一个两层的全连接层,第一层的激活函数为 Relu,第二层不使用激活函数,对应的公式如下。

Transformer原理-StubbornHuang Blog

X是输入,Feed Forward 最终得到的输出矩阵的维度与X一致。

2.6.3 组成 Encoder

通过上面描述的 Multi-Head Attention, Feed Forward, Add & Norm 就可以构造出一个 Encoder block,Encoder block 接收输入矩阵X_{(n\times d)},并输出一个矩阵O_{(n \times d)}。通过多个 Encoder block 叠加就可以组成 Encoder。

第一个 Encoder block 的输入为句子单词的表示向量矩阵,后续 Encoder block 的输入是前一个 Encoder block 的输出,最后一个 Encoder block 输出的矩阵就是编码信息矩阵 C,这一矩阵后续会用到 Decoder 中。

Transformer原理-StubbornHuang Blog

2.7 Decoder 结构

Transformer原理-StubbornHuang Blog

上图红色部分为 Transformer 的 Decoder block 结构,与 Encoder block 相似,但是存在一些区别:

  • 包含两个 Multi-Head Attention 层。
  • 第一个 Multi-Head Attention 层采用了 Masked 操作。
  • 第二个 Multi-Head Attention 层的K, V矩阵使用 Encoder 的编码信息矩阵C进行计算,而Q使用上一个 Decoder block 的输出计算。
  • 最后有一个 Softmax 层计算下一个翻译单词的概率。

2.7.1 第一个 Multi-Head Attention

Decoder block 的第一个 Multi-Head Attention 采用了 Masked 操作,因为在翻译的过程中是顺序翻译的,即翻译完第 i 个单词,才可以翻译第 i+1 个单词。通过 Masked 操作可以防止第 i 个单词知道 i+1 个单词之后的信息。下面以 “我有一只猫” 翻译成 “I have a cat” 为例,了解一下 Masked 操作。

下面的描述中使用了类似 Teacher Forcing 的概念,在 Decoder 的时候,是需要根据之前的翻译,求解当前最有可能的翻译,如下图所示。首先根据输入 ““ 预测出第一个单词为 “I”,然后根据输入 “ I” 预测下一个单词 “have”。

Transformer原理-StubbornHuang Blog

Decoder 可以在训练的过程中使用 Teacher Forcing 并且并行化训练,即将正确的单词序列 ( I have a cat) 和对应输出 (I have a cat) 传递到 Decoder。那么在预测第 i 个输出时,就要将输出序列第 i+1 之后的单词掩盖住(输入序列不需要遮挡),注意 Mask 操作是在 Self-Attention 的 Softmax 之前使用的,下面用 0 1 2 3 4 5 分别表示 “ I have a cat“。

第一步:先介绍 Decoder 的输入矩阵和 Mask 矩阵,输入矩阵包含 “ I have a cat” (0, 1, 2, 3, 4) 五个单词的表示向量,Mask 是一个 5×5 的矩阵。在 Mask 可以发现单词 0 只能使用单词 0 的信息,而单词 1 可以使用单词 0, 1 的信息,即只能使用之前的信息(从图中可以看出,Mask操作必须放在Softmax之前,否则还是利用到了之后的信息)。

Transformer原理-StubbornHuang Blog

第二步:接下来的操作和之前的 Self-Attention 一样,通过输入矩阵X计算得到Q,K,V矩阵。然后计算Q和K^{T}的乘积QK^{T}

Transformer原理-StubbornHuang Blog

第三步:在得到QK^{T}之后需要进行 Softmax,计算 attention score,我们在 Softmax 之前需要使用Mask矩阵遮挡住每一个单词之后的信息,遮挡操作如下:

Transformer原理-StubbornHuang Blog

也有可能不是按位相乘,而是让QK^{T}中mask0的对应位置,是一个极小值,这样这些位置在经过softmax后,值仍然很小。

得到 MaskQK^{T}之后在MaskQK^{T}上进行 Softmax,每一行的和都为 1。但是单词 0 在单词 1, 2, 3, 4 上的 attention score 都为 0。

第四步:使用 MaskQK^{T}与矩阵 V相乘,得到输出 Z,则单词 1 的输出向量 Z_{1}是只包含单词 1 信息的。

Transformer原理-StubbornHuang Blog

为什么说这样可以保证单词 1 的输出向量Z_{1}是只包含单词 1 信息的,可以看如下这个图理解这个矩阵相乘。

Transformer原理-StubbornHuang Blog

第五步:通过上述步骤就可以得到一个 Mask Self-Attention 的输出矩阵Z_{i},通过 Multi-Head Attention 拼接多个输出Z_{i},然后计算得到第一个 Multi-Head Attention 的输出ZZ与输入X维度一样。

2.7.2 Multi-Head Attention

Decoder block 第二个 Multi-Head Attention 变化不大, 主要的区别在于其中 Self-Attention 的 K, V矩阵不是使用 上一个 Decoder block 的输出计算的,而是使用 Encoder 的编码信息矩阵 C 计算的。

根据 Encoder 的输出 C计算得到 K, V,根据上一个 Mask Multi-Head Attention的输出 Z 计算 Q (因为此时得到的Z已经经过了mask,所以无需再次mask了),后续的计算方法与之前描述的一致。

这样做的好处是在 Decoder 的时候,每一位单词都可以利用到 Encoder 所有单词的信息 (这些信息无需 Mask)。

2.7.3 Softmax 预测输出单词

Decoder block 最后的部分是利用 Softmax 预测下一个单词,在之前的网络层我们可以得到一个最终的输出 Z,因为 Mask 的存在,使得单词 0 的输出Z_{0}只包含单词 0 的信息,如下:

Transformer原理-StubbornHuang Blog

Softmax 根据输出矩阵的每一行预测下一个单词:

Transformer原理-StubbornHuang Blog

下动图能够更好的解释这个过程:

Transformer原理-StubbornHuang Blog
  1. 给Decoder输入Encoder对整个原始句子embedding的结果和一个特殊的开始符号。Decoder 将产生预测,在我们的例子中应该是 ”I”。
  2. 给Decoder输入Encoder的embedding结果和 I,在这一步Decoder应该产生预测 am。
  3. 给Decoder输入Encoder的embedding结果和 I am,在这一步Decoder应该产生预测a。
  4. 给Decoder输入Encoder的embedding结果和 I am a,在这一步Decoder应该产生预测student。
  5. 给Decoder输入Encoder的embedding结果和 I am a student, Decoder应该生成句子结尾的标记,Decoder 应该输出。
  6. 然后Decoder生成了,翻译完成。

这就是 Decoder block 的定义,与 Encoder 一样,Decoder 是由多个 Decoder block 组合而成。

2.8 Transformer 总结

  • Transformer 与 RNN 不同,可以比较好地并行训练。
  • Transformer 本身是不能利用单词的顺序信息的,因此需要在输入中添加位置 Embedding,否则 Transformer 就是一个词袋模型了。
  • Transformer 的重点是 Self-Attention 结构,其中用到的 Q, K, V矩阵通过输出进行线性变换得到。
  • Transformer 中 Multi-Head Attention 中有多个 Self-Attention,可以捕获单词之间多种维度上的相关系数 attention score。

3 Attention在Transformer中的应用

文章一开始解释了Self-Attention和Multi-Head Attention。通过对Transformer模型的深入解读,可以看到,模型一共使用了三种Multi-Head Attention:

  1. Encoder Block中使用的Attention。第一个Encoder Block的Query、Key和Value来自训练数据经过两层Embedding转化,之后的Encoder Block的Query、Key和Value来自上一个Encoder Block的输出。
  2. Decoder Block中的第一个Attention。与Encoder Block中的Attention类似,只不过增加了Mask,在预测第i个输出时,要将第i+1之后的单词掩盖住。第一个Decoder Block的Query、Key和Value来自训练数据经过两层Embedding转化,之后的Decoder Block的Query、Key和Value来自上一个Decoder Block的输出。
  3. Decoder Block中的第二个Attention。这是一个 Encoder-Decoder cross Attention,它建立起了 Encoder 和 Decoder 之间的联系,Query来自第2种 Decoder Attention的输出,Key和Value 来自 Encoder 的输出。

4 Transformer中的mask

Transformer中有多个mask,这里总结下。

整个模型中使用到的mask主要就是source mask和target mask。

4.1 source mask

  • source长短不一而无法形成batch,因此引入了pad。将source mask传入到encoder中,让attention在计算softmax(\frac{QK^T}{\sqrt{d_{k}} } )时,pad位置的值不起作用。
  • 同时这个mask还需要传入到每个decoderLayer第二个multi-head attention模块中,就是防止来自encoder的key和来自decoder的query在计算多头注意力的时候算了target中的词和source中pad的权重

4.2 target mask

需要分training和testing进行讨论

  • 训练时,用于防止target的ground truth长短不一引入pad造成的误差,以及避免在自回归时看到正在预测的字和以后字的ground truth
  • 测试时,逻辑上decoder不需要target mask,但出于编程方便的考虑引入mask,假装用于防止看到后面的ground truth,target mask的最后两维的shape和目前生成出来的序列长度相同,但实际上每次都会有一些重复运算在里面,比如目前在预测第10个词时,第1-9个词还需要重新算一遍。核心原因是:模型在写的时候主要考虑的是训练,执行一次attention函数翻译完一个batch的所有句子,而测试时必须是单个或多个句子word by word进行计算

参考