Transformer模型
最后更新于
这有帮助吗?
最后更新于
这有帮助吗?
参考:
机器翻译是从RNN开始跨入神经网络的,主要分:
Simple RNN
Contextualize RNN
Contextualized RNN with attention
Transformer
在这个编码-解码模型中,编码器将整个源序列压缩成一个向量(Encoder Output),源端信息和解码器之间唯一的联系为:压缩后的这个向量(Encoder Output)会作为解码器的初始状态(Initial State)输入,它带来的问题:随着解码器长度的增加,该向量(Encoder Output)的信息会出现衰减。
这种模型的两个问题:
源端序列不论长短都会被压缩成一个固定维度向量,而这个向量中关于源端序列末尾的token
信息更多,如果序列很长,最终可能“遗忘”了向量中开始部分的token
信息。
随着Decoder TimeStep信息增加,初始隐藏状态(Initial Hidden State)中包含Encoder Output相关信息会衰减,而解码器会“遗忘”源端序列信息,而更多地关注目标序列在timestep之前的token
信息。
为解决上述两个问题(Encoder Output随Decoder TimeStep增加而衰减),提出了加入context
的序列到序列RNN模型(RNN sequence to sequence),解码器在每个TimeStep
的输入上都加上一个context
上下文,于是在解码器执行的每一步时,都把源端的整个句子信息和目标端当前的token
一起输入到RNN中,防止源端context
信息随着TimeStep
的增长而衰减。
这种模型的问题:
context
对于每个TimeStep都是静态的(解码器端的最终隐藏状态, Final Hidden States,或是所有TimeStep的输出平均值),但每个解码器端的token
在解码时用到的context
真是一致的么?
在每个TimeStep输入到解码器的RNN结构中之前,都会用当前的输入token
的向量(vector
)和Encoder Output
中每一个位置的向量vector
作一个Attention
操作,这个操作的目的是计算当前token
和每个位置之间的相关度,从而决定每个位置的向量在最终TimeStep的context
中占的比重有多少,最终再加权平均:
注意力机制可以有不同的计算方式:
加性Attention
点积Attention
带参数的计算公式
点积Attention计算方式如:
上图中,和分别是query
和key
,其中,query
可看做M个维度为d的向量拼接,key
可以看做N个维度为d的向量拼接而成。表达式中的是缩放因子,它的作用是做归一化。
一个完整的Attention层涉及的参数有:
把分别映射到的线性变换矩阵
把输出的表达映射为最终输出的线性变换矩阵
Query和Key的作用得到的Attention权值作用到Value上,它们之前的关系如:
和的维度必须一致,和Query/Key的维度可以不一致。
和的长度必须一致,Key和Value本质上对应同一个Sequence在不同空间的表达。
Attention得到的的维度和Value的维度一致,长度和Query一致。
Output每个位置i
是由value
的所有位置的向量vector
加权平均之后的向量,而其权重是由位置为i
的query和key的所有位置经过Attention计算后得到的,权值的个数等于key/value
的长度。
在经典的Transformer结构中,假设线性映射之前的Query, Key, Value
为q,k,v
,映射之后的Q,K,V
,那么:
Self-Attention
的q,k,v
都是同一个输入,即当前序列上一层输出的高维表达。
Cross-Attention
的q
代表当前序列,k,v
是同一个输入,对应的是编码器最后一层的输出结果(对解码器每一层来说,保持不变)。
底层捕获的更多信息是Lexical-Level
级别的,而高层捕获的更多则是Semantic-Level
的关系。
query
对应的是需要被表达的序列(称为序列A),key
和value
对应的是原来表达A的序列(称为序列B),其中key
和query
是在同一高维空间中,value
不用在同一高维空间中,最终生成的output
和value
在同一高维空间中。
序列A和序列B在高维空间中的高维表达的每个位置分别和计算相似度,产生的权重作用于序列B在高维空间的高维表达,获得序列A在高维空间中的高维表达。
所以编码部分只存在于Self-Attention
,而解码部分存在Self-Attention
和Cross-Attention
。
Self-Attention:编码中的Self-Attention
的query,key,value
对应了源端序列(A和B是同一序列),解码器中的Self-Attention
的query,key,value
都对应了目标端序列。
Cross-Attention:编码器中的Cross-Attention
的query
对应了目标端序列,key,value
对应了源端序列(每一层中的Cross-Attention
用的都是编码器的最终输出)。
Transformer模型属于自回归模型,也就是说后面的token
推断是基于前边的token
的,解码器端的Mask的功能是为了保证训练阶段和推理阶段的一致性。推理阶段,token
按照从左到右的顺序推理,即,在推理TimeStep=T的token
时,解码器只能“看到”TimeStep < T的 T - 1个token
,不能和TimeStep大于自身的token
做Attention运算。为保证训练和推理的一致性,训练时要防止token
和它之后的token
做Attention运算。
多头Attention(Multi-Head Attention)。Attention是将query
和key
映射到同一高维空间中计算相似度,而多头Attention会把query
和key
映射到高维空间的不同子空间中中计算相似度。
不改变参数数量的情况下增强每一层的Attention的表现力
参数总量保持不变的情况下,同样的query,key,value
映射到原来的高维空间的不同子空间中执行Attention计算,最后一步合并不同子空间的Attention信息。
每一层经过了Attention运算之后,会有一个FFN,这个FFN的目标就是做空间变换,它包含了2层Linear Transformation层,中间激活函数使用ReLU。
FFN加入引入了非线性变换(ReLU激活函数),交换了Attention Output空间,从而增加模型表现力,如果去掉,模型效果会差很多。
位置编码层(Positional Encoding)存在于编码端(Encoder)和解码端(Decoder)的embedding之后,第一个Block之前,它十分重要,若没有这部分,Transformer模型就无法使用,它补充了Attention机制本身不能捕捉位置信息的缺陷。
Positional Embedding成分直接叠加到Embedding之上,使得每个token
的位置信息和它的语义信息(Embedding)充分融合,并被传递到后续所有经过复杂变换的序列表达中去。
模型输入编码器(Encoder)的每个token
对应的向量有2部分:
Positional Encoding
Embedding Output
Transformer的特性使得编码器(Encoder)的输入向量之间完全平等(不存在类似RNN中recurrent结构),token
的实际位置和positional encoding
唯一绑定,可通过对positional encoding
进行操作来改变token
在序列中的实际位置。
对inference阶段而言(参考下图)
图b中输入的Embedding部分没有变化,但Positional Encoding部分被打乱了顺序。
图c中的Positional Encoding部分没有变化,但Embedding部分被打乱了顺序。
其实两个图是完全等价的。
对train阶段而言(Learned Positional Encoding)
由于Positinal Encoding是迅联出来的,那么它在inference阶段代表哪个位置,完全由训练时的实际位置决定
例:在解码器中,Cross-Attention
模块有Mask,目的是防止token
和它之后的token
执行Attention
运算,即从左到右的模型,倘若此时突然想要从右到左的模型
在预处理阶段将序列翻转过来
在训练时将Mask策略换一下
原始论文中的Positional Encoding(PE)是正余弦函数,位置(pos)越小,波长越长,每一个位置对应的PE都是唯一的,使用正余弦函数作为PE,是因为这个可以使得模型学习到token之间的相对位置关系:对于任一偏移量k
,可以由的线性表示。
上述两个公式由前一项的线性组合得到,即通过某个线性变换矩阵就从k
得到了k+1
。
在每个Block中,最后出现的就是层归一化(Layer Normalization),这个是一个通用技术,其本质是规范化优化空间,加速收敛。
为了保证特征分布的稳定性(左),可加入Layer Normalization,这样可以加速模型的优化速度。