NLP学习笔记 Transformer简明介绍

Posted 半虹

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NLP学习笔记 Transformer简明介绍相关的知识,希望对你有一定的参考价值。

大家好,我是半虹,这篇文章来讲 Transformer \\textTransformer Transformer,想要获取更多相关文章,欢迎关注 自然语言处理 专栏


在之前的两篇文章中,我们介绍过序列到序列模型以及注意力机制在序列到序列模型中的应用

所谓序列到序列模型,就是那些输入是序列、输出也是序列的模型,这是从输入输出的角度来定义的

这些模型通常会使用编码器到解码器的架构,编码器用于处理输入序列,解码器用于生成输出序列

由于循环神经网络在处理序列数据时的优势,很多模型都会选择循环神经网络作为编码器和解码器


循环神经网络会逐步遍历序列,并通过隐状态的传递保存序列的历史信息,从而达到理解序列数据的目的

这是循环神经网络能够处理序列数据的关键,同时也是循环神经网络的局限所在

循环神经网络处理序列数据时需要逐步遍历,这是顺序性的,这个过程难以并行

此外,隐状态在长序列间进行传递容易丢失信息,使网络难以对长序列进行建模


另一方面,研究人员发现,注意力机制在序列到序列模型中的应用对性能的提升有很大帮助

后来就有人提出一个开创性的想法,能不能整个序列到序列模型就用注意力机制,不再基于循环神经网络

当然,我们知道这个尝试是成功了,这就是大名鼎鼎的 Transformer \\textTransformer Transformer Attention Is All You Need \\textAttention Is All You Need Attention Is All You Need

Transformer \\textTransformer Transformer 不仅使训练过程可以并行,而且还能对长序列进行建模!


Transformer \\textTransformer Transformer 虽然最初是在 NLP \\textNLP NLP 领域中提出的,但其后来应用到 CV \\textCV CV 领域也有亮眼的表现

可以说 Transformer \\textTransformer Transformer 中的注意力机制开创了 RNN \\textRNN RNN CNN \\textCNN CNN 之外的一种全新范式

下面将会从总体到细节逐步剖析 Transformer \\textTransformer Transformer 作为序列到序列模型时的运作方式


从本质上来说, Transformer \\textTransformer Transformer 是一个编码器到解码器架构,下图是编码器到解码器架构的示意图


图片左半部分是编码器,处理输入序列得到编码信息,右半部分是解码器,根据编码信息生成输出序列

这里需要特别注意的是,解码器一般都是自回归生成,这意味着解码器会将上一步输出作为下一步输入

所以在这里我们能看到,解码器会将偏移一步之后的输出序列作为其输入 ( Teacher Forcing \\textTeacher Forcing Teacher Forcing )


另外,编码器是由若干个编码层组成的,解码器是由若干个解码层组成的

Transformer \\textTransformer Transformer  出现之前,编码层和解码层大多都是基于循环神经网络进行设计

Transformer \\textTransformer Transformer  另辟蹊径,选择完全基于注意力机制进行设计,下图是其编码层和解码层的实现细节


如图所示,左半部分展示的是编码层的细节,右半部分展示的解码层的细节,二者皆有若干层堆叠

图中相同背景色的矩形框表示相同的子模块,大致上可以分为三种:

黄色背景的是多头注意力机制,绿色背景的是前馈神经网络,蓝色背景的是残差连接以及层正则化


运作步骤如下:

  1. 编码阶段
    1. 获取原始输入序列向量表示,将其作为编码层的输入
    2. 编码层操作大致上分为两步:
      1. 首先经过多头注意力机制,之后接残差连接和层正则化
      2. 然后经过前馈神经网络 ,之后接残差连接和层正则化
    3. 编码层有若干个,重复上述操作若干次
      这里要注意的是,上一个编码层的输出会用于下一个编码层的输入
      只有第一个编码层才以原始输入序列作为输入
  2. 解码阶段
    1. 获取偏移输出序列向量表示,将其作为解码层的输入
    2. 解码层操作大致上分为三步:
      1. 首先经过多头注意力机制,之后接残差连接和层正则化
      2. 然后经过多头注意力机制,之后接残差连接和层正则化
      3. 最后经过前馈神经网络 ,之后接残差连接和层正则化
    3. 解码层有若干个,重复上述操作若干次
      这里要注意的是,上一个解码层的输出会用于下一个解码层的输入
      只有第一个解码层才以偏移输出序列作为输入

下文会依次解析其中的核心操作,分别是:

序号操作出现步骤
1获取序列向量表示1.1    、2.1
2多头注意力机制1.2.12.2.12.2.2
3前馈神经网络1.2.22.2.3
4残差连接1.2.11.2.22.2.12.2.22.2.3
5层正则化1.2.11.2.22.2.12.2.22.2.3

1、获取序列向量表示

我们知道,自然语言是无法直接作为模型输入的,所以第一步首先要把自然语言转化成向量表示

一般来说,只需将序列经过嵌入层得到对应序列中每个词元的可学习向量即可,具体如下图所示:


这样的做法在 RNN \\textRNN RNN CNN \\textCNN CNN 架构中没有问题,但 Transformer \\textTransformer Transformer Attention \\textAttention Attention 是无法建模位置信息的

为了弥补这个缺陷,在获取序列向量表示时需要额外加入位置信息


如图所示,每个词元经过词元嵌入层得到语义表示,每个词元的位置经过位置嵌入层得到位置表示

然后对应的语义表示和位置表示通过相加的方式进行融合以得到最终表示: e i = t i + p i ,   i = 1 ,   2 ,   ⋯ e_i = t_i + p_i,\\ i = 1, \\ 2,\\ \\cdots ei=ti+pi, i=1, 2, 


当然你也可以用拼接的方法对两个表示进行融合,相加只是论文中的设计

但是需要注意的是,如果用相加的方法进行融合,语义表示和位置表示的维度必须要是一样的

事实上,在论文中为了实现方便,同时也是为了进行残差连接

在编码层和解码层的每个子模块,其输入输出向量的特征维度都是一样的,具体来说特征维度 d = 512 d = 512 d=512


下面是本节的最后一个问题,如何获得位置表示?

最简单的方法就是像语义表示一样,经过嵌入层得到一个可学习的向量,然后通过数据来训练

但是,论文提出可以通过公式直接计算位置表示,具体的计算公式如下:
PE ( p , 2 i ) = sin ⁡ ( p   /   1000 0 2 i / d ) PE ( p , 2 i + 1 ) = cos ⁡ ( p   /   1000 0 2 i / d ) \\beginalign \\textPE(p, 2i) &= \\sin (p\\ /\\ 10000^2i/d) \\\\ \\textPE(p, 2i + 1) &= \\cos (p\\ /\\ 10000^2i/d) \\endalign PE(p,2i)PE(p,2i+1)=sin(p / 100002i/d)=cos(p / 100002i/d)
对于词元位置 p p p,位置向量的维度为 d d d,向量中的第 2 i 2i 2i 2 i + 1 2i+1 2i+1 维计算公式如上所示

一个例子如下:


通过上述方式获得位置表示有以下优点

  • 可以直接计算得到,无需数据进行训练
  • 每个词元位置的向量表示都是唯一不变的
  • 使模型能够处理比训练集长的序列
  • 使模型易于学习到词元之间的相对关系,因为 PE ( p + k ) \\textPE(p+k) PE(p+k) 可由 PE ( p ) \\textPE(p) PE(p) 线性组合得到

2、多头注意力机制

多头注意力机制是整个模型的核心,且不说多头是什么操作,我们先来看注意力机制是啥

在上一篇文章中,我们讲过注意力机制在序列到序列模型中的应用,这里还是以翻译为例引入

假设现在我们要进行中译英任务,将 机器学习 翻译成 Machine Learning

当生成 Machine   时,模型其实应该将更多权重放在 机器 二字

当生成 Learning 时,模型其实应该将更多权重放在 学习 二字


注意力机制在本质上是根据当前查询以不同的权重抽取序列中的信息

序列中的每个元素会有一个键向量用于匹配,另有一个值向量表示其蕴含的信息

当给定查询向量时,会通过以下两个步骤得到最终要抽取的信息向量

首先,计算查询向量与每个键向量之间的匹配分数

然后,以匹配分数作为权重对所有值向量加权求和


其中最关键的部分就是打分函数的设计,简单来说就是如何衡量查询向量和键向量之间的匹配程度

Transformer \\textTransformer Transformer 中所使用的打分函数是 scaled dot product \\textscaled dot product scaled dot product,其计算公式如下: score ( Q , K ) = Q K T d k \\textscore(Q, K) = \\fracQK^T\\sqrtd_k score(Q,K)=dk QKT

其中, Q Q Q 为查询向量, K K K 为键向量, d k d_k dk 为键向量维度,以下是一些细节的解答