大家好,我是半虹,这篇文章来讲 Transformer\text{Transformer},想要获取更多相关文章,欢迎重视 自然语言处理 专栏
在之前的两篇文章中,咱们介绍过序列到序列模型以及注意力机制在序列到序列模型中的应用
所谓序列到序列模型,便是那些输入是序列、输出也是序列的模型,这是从输入输出的角度来定义的
这些模型一般会运用编码器到解码器的架构,编码器用于处理输入序列,解码器用于生成输出序列
由于循环神经网络在处理序列数据时的优势,很多模型都会挑选循环神经网络作为编码器和解码器
循环神经网络会逐渐遍历序列,并经过隐状况的传递保存序列的历史信息,然后到达了解序列数据的意图
这是循环神经网络可以处理序列数据的要害,一起也是循环神经网络的限制所在
循环神经网络处理序列数据时需要逐渐遍历,这是次序性的,这个进程难以并行
此外,隐状况在长序列间进行传递容易丢掉信息,使网络难以对长序列进行建模
另一方面,研究人员发现,注意力机制在序列到序列模型中的应用对功能的提升有很大帮助
后来就有人提出一个创始性的主意,能不能整个序列到序列模型就用注意力机制,不再依据循环神经网络
当然,咱们知道这个测验是成功了,这便是大名鼎鼎的 Transformer\text{Transformer},AttentionIsAllYouNeed\text{Attention Is All You Need}
Transformer\text{Transformer} 不仅使练习进程可以并行,而且还能对长序列进行建模!
Transformer\text{Transformer} 虽然最初是在 NLP\text{NLP} 范畴中提出的,但其后来应用到 CV\text{CV} 范畴也有亮眼的体现
可以说 Transformer\text{Transformer} 中的注意力机制创始了 RNN\text{RNN} 和 CNN\text{CNN} 之外的一种全新范式
下面将会从整体到细节逐渐分析 Transformer\text{Transformer} 作为序列到序列模型时的运作办法
从本质上来说,Transformer\text{Transformer} 是一个编码器到解码器架构,下图是编码器到解码器架构的示意图
图片左半部分是编码器,处理输入序列得到编码信息,右半部分是解码器,依据编码信息生成输出序列
这儿需要特别注意的是,解码器一般都是自回归生成,这意味着解码器会将上一步输出作为下一步输入
所以在这儿咱们能看到,解码器会将偏移一步之后的输出序列作为其输入 ( TeacherForcing\text{Teacher Forcing} )
别的,编码器是由若干个编码层组成的,解码器是由若干个解码层组成的
在 Transformer\text{Transformer} 呈现之前,编码层和解码层大多都是依据循环神经网络进行规划
而 Transformer\text{Transformer} 另辟蹊径,挑选彻底依据注意力机制进行规划,下图是其编码层和解码层的完成细节
如图所示,左半部分展现的是编码层的细节,右半部分展现的解码层的细节,二者皆有若干层堆叠
图中相同布景色的矩形框表明相同的子模块,大致上可以分为三种:
黄色布景的是多头注意力机制,绿色布景的是前馈神经网络,蓝色布景的是残差衔接以及层正则化
运作进程如下:
- 编码阶段
- 获取原始输入序列向量表明,将其作为编码层的输入
- 编码层操作大致上分为两步:
- 首要经过多头注意力机制,之后接残差衔接和层正则化
- 然后经过前馈神经网络 ,之后接残差衔接和层正则化
- 编码层有若干个,重复上述操作若干次;这儿要注意的是,上一个编码层的输出会用于下一个编码层的输入,只要第一个编码层才以原始输入序列作为输入
- 解码阶段
- 获取偏移输出序列向量表明,将其作为解码层的输入
- 解码层操作大致上分为三步:
- 首要经过多头注意力机制,之后接残差衔接和层正则化
- 然后经过多头注意力机制,之后接残差衔接和层正则化
- 终究经过前馈神经网络 ,之后接残差衔接和层正则化
- 解码层有若干个,重复上述操作若干次;这儿要注意的是,上一个解码层的输出会用于下一个解码层的输入,只要第一个解码层才以偏移输出序列作为输入
下文会依次解析其间的中心操作,分别是:
序号 | 操作 | 呈现进程 |
---|---|---|
1 | 获取序列向量表明 |
1.1 、2.1
|
2 | 多头注意力机制 |
1.2.1 、2.2.1 、2.2.2
|
3 | 前馈神经网络 |
1.2.2 、2.2.3
|
4 | 残差衔接 |
1.2.1 、1.2.2 、2.2.1 、2.2.2 、2.2.3
|
5 | 层正则化 |
1.2.1 、1.2.2 、2.2.1 、2.2.2 、2.2.3
|
1、获取序列向量表明
咱们知道,自然语言是无法直接作为模型输入的,所以第一步首要要把自然语言转化成向量表明
一般来说,只需将序列经过嵌入层得到对应序列中每个词元的可学习向量即可,详细如下图所示:
这样的做法在 RNN\text{RNN} 或 CNN\text{CNN} 架构中没有问题,但 Transformer\text{Transformer} 的 Attention\text{Attention} 是无法建模方位信息的
为了补偿这个缺点,在获取序列向量表明时需要额定参加方位信息:
如图所示,每个词元经过词元嵌入层得到语义表明,每个词元的方位经过方位嵌入层得到方位表明
然后对应的语义表明和方位表明经过相加的办法进行融合以得到终究表明:ei=ti+pi,i=1,2,⋯e_{i} = t_{i} + p_{i},\ i = 1, \ 2,\ \cdots
当然你也可以用拼接的办法对两个表明进行融合,相加仅仅论文中的规划
可是需要注意的是,假如用相加的办法进行融合,语义表明和方位表明的维度有必要要是一样的
事实上,在论文中为了完成便利,一起也是为了进行残差衔接
在编码层和解码层的每个子模块,其输入输出向量的特征维度都是一样的,详细来说特征维度 d=512d = 512
下面是本节的终究一个问题,怎么获得方位表明?
最简略的办法便是像语义表明一样,经过嵌入层得到一个可学习的向量,然后经过数据来练习
可是,论文提出可以经过公式直接核算方位表明,详细的核算公式如下:
关于词元方位 pp,方位向量的维度为 dd,向量中的第 2i2i 和 2i+12i+1 维核算公式如上所示
一个例子如下:
经过上述办法获得方位表明有以下优点:
- 可以直接核算得到,无需数据进行练习
- 每个词元方位的向量表明都是仅有不变的
- 使模型可以处理比练习集长的序列
- 使模型易于学习到词元之间的相对关系,由于 PE(p+k)\text{PE}(p+k) 可由 PE(p)\text{PE}(p) 线性组合得到
2、多头注意力机制
多头注意力机制是整个模型的中心,且不说多头是什么操作,咱们先来看注意力机制是啥
在上一篇文章中,咱们讲过注意力机制在序列到序列模型中的应用,这儿仍是以翻译为例引入
假定现在咱们要进行中译英使命,将 机器学习
翻译成 Machine Learning
当生成 Machine
时,模型其实应该将更多权重放在 机器
二字
当生成 Learning
时,模型其实应该将更多权重放在 学习
二字
注意力机制在本质上是依据当时查询以不同的权重抽取序列中的信息
序列中的每个元素会有一个键向量用于匹配,还有一个值向量表明其蕴含的信息
当给定查询向量时,会经过以下两个进程得到终究要抽取的信息向量
首要,核算查询向量与每个键向量之间的匹配分数
然后,以匹配分数作为权重对一切值向量加权求和
其间最要害的部分便是打分函数的规划,简略来说便是怎么衡量查询向量和键向量之间的匹配程度
在 Transformer\text{Transformer} 中所运用的打分函数是 scaleddotproduct\text{scaled dot product},其核算公式如下:score(Q,K)=QKTdk\text{score}(Q, K) = \frac{QK^T}{\sqrt{d_k}}
其间,QQ 为查询向量,KK 为键向量,dkd_k 为键向量维度,以下是一些细节的回答
-
为什么要做 scale\text{scale}?
假定 qq、kk 都是均值为 00、方差为 11 的独立随机变量,那么二者点积 q⋅kq \cdot k 的均值为 00、而方差为 dkd_k
假如 dkd_k 越大,那么点积方差越大,经过 softmax\text{softmax} 之后,散布变得峻峭,梯度变小
-
二是为什么规划 scale\text{scale} 的值是 1dk\frac{1}{\sqrt{d_k}}?
假定 qq、kk 都是均值为 00、方差为 11 的独立随机变量,那么二者点积 q⋅kq \cdot k 的均值为 00、而方差为 dkd_k
假如将点积乘上缩放因子 1dk\frac{1}{\sqrt{d_k}},可以使得方差稳定在 11,这是由于 D(q⋅kdk)=dk(dk)2=1D(\frac{q \cdot k}{\sqrt{d_k}}) = \frac{d_k}{(\sqrt{d_k})^2} = 1
当查询向量来自序列自身时,此时的注意力机制被称为自注意力机制
序列中的每个元素对应三个向量,一是查询向量,二是键向量,三是值向量,那么怎么得到这些向量呢
简略的话,可以直接将序列元素的向量表明一起作为上述向量,也可以将其经过不同的线性映射后得到
下面是自注意力机制的运作进程
在自注意力机制中,每个元素都会依据自身查询来获取序列的上下文信息,然后得到对应的向量表明
比照循环神经网络,二者都可用于编码序列,其不同之处在于自注意力机制可以并行地编码序列
这是由于序列中每个元素的注意力核算之间并没有依赖关系,因而可以经过矩阵运算来并行加快
反观循环神经网络则需要经过在序列中逐渐传递隐状况来获取序列的上下文信息,这个进程不能并行
回到模型,Transformer\text{Transformer} 中共有三种注意力机制,对应到运行进程分别是 1.2.1
、2.2.1
、2.2.2
1.2.1
是编码器自注意力机制,查询向量来自编码器,键向量、值向量也来自编码器
2.2.1
是解码器自注意力机制,查询向量来自解码器,键向量、值向量也来自解码器
2.2.2
是解码器外注意力机制,查询向量来自解码器,键向量、值向量则来自编码器
上述的三种注意力机制都会带有填充掩码 padding mask
这是由于神经网络在进行练习时,一般是以批量为单位的,可是同一批量里的序列一般长短不一
为了进行矩阵运算,需要用预先定义好的占位符,将同一批量里的序列填充到统一长度
但是,在核算注意力权重散布时,咱们并不期望给这些占位符分配注意力权重
因而,在查询向量和键向量核算匹配分数后,将占位符的匹配分数设置为一个极小的值是合理的
解码器自注意力机制还有一个共同的掩码 decoder mask
这是由于解码进程是自回归的,便是在生成当时的词元时,只能看到之前的词元,不能看到之后的词元
假如直接运用注意力机制的话,那么在核算当时的词元时,会用自身查询与序列一切词元核算匹配分数
这样做显然是一个做弊的行为,运用什么办法可以防止呢
咱们只需要将当时词元与之后词元的匹配分数设置为一个极小的值即可,如此就能确保练习和预测行为一致
至此终于把注意力机制介绍完了,终究再来看一下多头注意力机制是啥
上述介绍的注意力机制,序列中的每个元素都会对应一组查询、键、值向量,然后进行一次注意力核算
为了增强模型表达能力,序列中的每个元素可映射到多组查询、键、值向量,然后分别进行注意力核算
咱们期望不同的映射可以在不同的特征空间学习到不同的信息,以此到达增强模型表达能力的意图
终究,多个特征空间中注意力核算的成果将会被拼接起来,然后经过一个线性映射得到终究的输出
3、前馈神经网络
前馈神经网络是为了增强模型的表达能力而规划的,将原有的向量表明映射到一个更好的特征空间
在本模型中,前馈神经网络由两个线性映射和一个激活函数组成,详细的公式表达如下:
其间,Linear\text{Linear} 是线性映射,ReLU\text{ReLU} 是激活函数,W1W_1、b1b_1、W2W_2、b2b_2 都是可学习的参数
输入的 XX 特征维度是 512512,经过第一个线性映射后变为 20482048,经过第二个线性映射后变回 512512
4、残差衔接
残差衔接有助于缓解深层网络在练习时呈现的梯度问题,其间心思维非常简略,示意图如下所示:
输入经过某个模块得到输出后,再将原始输入与模块输出相加才得到终究输出
5、层正则化
一般来说,正则化的作用是确保数据特征散布稳定,然后加快模型的收敛速度
常用的正则化办法包括以下两种:
-
BatchNorm
:批正则化,对一切样本的每个特征做正则化,一般用于CV
范畴 -
LayerNorm
:层正则化,对每个样本的一切特征做正则化,一般用于NLP
范畴
在本模型中运用的正则化办法是层正则化
上述的描述或许仍是有些笼统,下面会用例子比照来讲两种正则化办法的异同
关于二维的状况,给定数据为:[B, F]
-
BatchNorm
:正则化维度:[1, *]
,表明对每个F
在一切[B]
上做正则化 -
LayerNorm
:正则化维度:[*, 1]
,表明对每个B
在一切[F]
上做正则化
关于三维的状况,给定数据为:[B, S, F]
-
BatchNorm
:正则化维度:[1, 1, *]
,表明对每个F
在一切[B, S]
上做正则化 -
LayerNorm
:正则化维度:[*, 1, 1]
,表明对每个B
在一切[S, F]
上做正则化
关于三维的状况,给定数据为:[B, H, W, C]
-
BatchNorm
:正则化维度:[1, 1, 1, *]
,表明对每个C
在一切[B, H, W]
上做正则化 -
LayerNorm
:正则化维度:[*, 1, 1, 1]
,表明对每个B
在一切[H, W, C]
上做正则化
关于一个批量数据,输入序列的长度一般是不相等的
当序列长度变化较大时 ,运用 BatchNorm
练习得到的参数波动会很大
所以在处理序列数据时 ,挑选 LayerNorm
是更合适的
好啦,本文到此结束,感谢阅览!
假如你觉得这篇文章还不错的话,欢迎点赞、收藏、重视,你的支持是对我最大的鼓舞 (/\)