读完|图解Transformer,读完这篇就够了( 四 )



然而 , 它的优点是能够扩展到未知的序列长度(例如 , 当我们训练出的模型需要翻译远比训练集里的句子更长的句子时) 。
残差模块:
在继续进行下去之前 , 我们需要提到一个编码器架构中的细节:在每个编码器中的每个子层(自注意力、前馈网络)的周围都有一个残差连接 , 并且都跟随着一个“层-归一化”步骤 。
层-归一化步骤:
https://arxiv.org/abs/1607.06450
读完|图解Transformer,读完这篇就够了
本文插图

如果我们去可视化这些向量以及这个和自注意力相关联的层-归一化操作 , 那么看起来就像下面这张图描述一样:
读完|图解Transformer,读完这篇就够了
本文插图

解码器的子层也是这样样的 。 如果我们想象一个2 层编码-解码结构的transformer , 它看起来会像下面这张图一样:
读完|图解Transformer,读完这篇就够了
本文插图

解码组件:
既然我们已经谈到了大部分编码器的概念 , 那么我们基本上也就知道解码器是如何工作的了 。 但最好还是看看解码器的细节 。
编码器通过处理输入序列开启工作 。 顶端编码器的输出之后会变转化为一个包含向量K(键向量)和V(值向量)的注意力向量集。

这些向量将被每个解码器用于自身的“编码-解码注意力层” , 而这些层可以帮助解码器关注输入序列哪些位置合适:
读完|图解Transformer,读完这篇就够了
本文插图

在完成编码阶段后 , 则开始解码阶段 。 解码阶段的每个步骤都会输出一个输出序列(在这个例子里 , 是英语翻译的句子)的元素 。
接下来的步骤重复了这个过程 , 直到到达一个特殊的终止符号 , 它表示transformer的解码器已经完成了它的输出 。 每个步骤的输出在下一个时间步被提供给底端解码器 , 并且就像编码器之前做的那样 , 这些解码器会输出它们的解码结果。
另外 , 就像我们对编码器的输入所做的那样 , 我们会嵌入并添加位置编码给那些解码器 , 来表示每个单词的位置 。
读完|图解Transformer,读完这篇就够了
本文插图

而那些解码器中的自注意力层表现的模式与编码器不同:在解码器中 , 自注意力层只被允许处理输出序列中更靠前的那些位置 。 在softmax步骤前 , 它会把后面的位置给隐去(把它们设为-inf) 。
这个“编码-解码注意力层”工作方式基本就像多头自注意力层一样 , 只不过它是通过在它下面的层来创造查询矩阵 , 并且从编码器的输出中取得键/值矩阵 。
最终的线性变换和Softmax层:

解码组件最后会输出一个实数向量 。 我们如何把浮点数变成一个单词?这便是线性变换层要做的工作 , 它之后就是Softmax层 。
线性变换层是一个简单的全连接神经网络 , 它可以把解码组件产生的向量投射到一个比它大得多的、被称作对数几率(logits)的向量里 。
不妨假设我们的模型从训练集中学习一万个不同的英语单词(我们模型的“输出词表”) 。 因此对数几率向量为一万个单元格长度的向量——每个单元格对应某一个单词的分数 。
接下来的Softmax 层便会把那些分数变成概率(都为正数、上限1.0) 。 概率最高的单元格被选中 , 并且它对应的单词被作为这个时间步的输出 。
读完|图解Transformer,读完这篇就够了
本文插图

这张图片从底部以解码器组件产生的输出向量开始 。 之后它会转化出一个输出单词 。
训练部分总结:
既然我们已经过了一遍完整的transformer的前向传播过程 , 那我们就可以直观感受一下它的训练过程 。
在训练过程中 , 一个未经训练的模型会通过一个完全一样的前向传播 。 但因为我们用有标记的训练集来训练它 , 所以我们可以用它的输出去与真实的输出做比较 。

为了把这个流程可视化 , 不妨假设我们的输出词汇仅仅包含六个单词:“a”, “am”, “i”, “thanks”, “student”以及 “”(end of sentence的缩写形式) 。
读完|图解Transformer,读完这篇就够了
本文插图

我们模型的输出词表在我们训练之前的预处理流程中就被设定好 。
一旦我们定义了我们的输出词表 , 我们可以使用一个相同宽度的向量来表示我们词汇表中的每一个单词 。 这也被认为是一个one-hot 编码 。 所以 , 我们可以用下面这个向量来表示单词“am”:
读完|图解Transformer,读完这篇就够了
本文插图

例子:对我们输出词表的one-hot 编码
接下来我们讨论模型的损失函数——这是我们用来在训练过程中优化的标准 。 通过它可以训练得到一个结果尽量准确的模型 。


推荐阅读