3 Model Architecture
大多数自然语言转换模型都有一个encoder-decoder结构:
- encoder: 把输入的离散符号序列x=(x1,...,xn)x=(x_1,...,x_n)x=(x1,...,xn)转换为连续值序列z=(z1,...,zn)z=(z_1,...,z_n)z=(z1,...,zn)
- decoder: 生成输出符号序列(y1,...,ym)(y_1,...,y_m)(y1,...,ym)
每一步模型都是自回归的,即之前生成的符号序列会作为额外的输入,用来生成下一个输出。
3.1 Encoder and Decoder Stacks
- Encoder:
1.由6个基本层堆叠起来,每个基本层包含两个子层:multi-head self-attention mechanism和fully connected feed-forward network 。
2.每个子层有一个残差连接(residual connection),然后有一个归一化层(layer normalization)。
3.每个子层的输出是:LayerNorm(x+Sublayer(x))LayerNorm(x+Sublayer(x))LayerNorm(x+Sublayer(x))
Sublayer(x)是子层sub-layer的函数。
4.嵌入层和子层输出的维度都是512。 - Decoder:
1.同样由6个基本层堆叠起来。
2.每个基本层除了两个子层以外,还有第三个子层:对于encoder stack的输出进行multi-head attention。
3.同样,每个子层有一个残差连接(residual connection),然后有一个归一化层(layer normalization)。
4.修订decoder的self-attention sub-layer 来保留位置。因为输出的嵌入层由偏移了一个位置。确保对i位置的预测值只取决于已知的在i之前的输出。
3.2 Attention
Attention函数可以描述为:将query和一组key-value pairs映射到output。
query, keys, values和output都是向量。output是values的加权和,权重由query与对应key的一个兼容性函数计算得到。
3.2.1 Scaled Dot-Product Attention
输入由dkd_kdk维的queries和keys,dvd_vdv维的values组成。
计算query和所有keys的点积,每个都除以dk\sqrt{d_k}dk,然后再通过一个softmax function获得values的权重。计算出输出矩阵为:
Attention(Q,K,V)=softmax(QKTdk)VAttention(Q,K,V)=softmax(\frac{QK^T}{\sqrt{d_k}})VAttention(Q,K,V)=softmax(dkQKT)V
Q∈Rn×dk,K∈Rm×dk,V∈Rm×dvQ\in R^{n\times d_k},K\in R^{m\times d_k},V\in R^{m\times d_v}Q∈Rn×dk,K∈Rm×dk,V∈Rm×dv
如果逐个向量来看:
Attention(qt,K,V)=∑s=1m1Zexp(<qt,ks>dk)vsAttention(q_t,K,V)=\sum\limits_{s=1}^{m}\frac{1}{Z}exp(\frac{<q_t,k_s>}{\sqrt{d_k}})v_sAttention(qt,K,V)=s=1∑mZ1exp(dk<qt,ks>)vs
其中Z是归一化因子。事实上q,k,v分别是query,key,value的简写,K,V是一 一对应的,它们就像是key-value的关系,那么上式的意思就是通过qtq_tqt这个query,通过与各个ksk_sks内积的并softmax的方式,来得到qtq_tqt与各个vsv_svs的相似度,然后加权求和,得到一个dvd_vdv维的向量。其中因子dk\sqrt{d_k}dk起到调节作用,使得内积不至于太大(太大的话softmax后就非0即1了,不够“soft”了)。
最后得到dvd_vdv维的输出。
3.2.2 Multi-Head Attention
用h次不同的线性变换将dmodeld_{model}dmodel维的keys,values和queries分别映射成dkd_kdk维,dkd_kdk维和dvd_vdv维。然后把它并行代入注意力机制,产生h×dvh\times d_vh×dv维的输出。然后再拼起来,通过一个线性变换得到最后的输出。
headi=Attention(QWiQ,KWiQ,VWiV)head_i=Attention(QW_i^Q,KW_i^Q,VW_i^V) headi=Attention(QWiQ,KWiQ,VWiV)MultiHead(Q,K,V)=Concat(head1,...,headh)WO
MultiHead(Q,K,V)=Concat(head_1,...,head_h)W^OMultiHead(Q,K,V)=Concat(head1,...,headh)WO其中WiQ∈Rdmodel×dk,WiV∈Rdmodel×dk,WiV∈Rdmodel×dv,WO∈Rhdv×dmodelW_i^Q\in R^{d_{model}\times d_k},W_i^V\in R^{d_{model}\times d_k},W_i^V\in R^{d_{model}\times d_v},W^O\in R^{hd_v\times d_{model}}WiQ∈Rdmodel×dk,WiV∈Rdmodel×dk,WiV∈Rdmodel×dv,WO∈Rhdv×dmodel
“多头”(Multi-Head),就是只多做几次同样的事情(参数不共享),然后把结果拼接。
在该文章中,采用h=8h=8h=8个平行的attention layers。dk=dv=dmodel/h=64d_k=d_v=d_{model}/h=64dk=dv=dmodel/h=64。因为每个head维数的降低,所以和原来维数的单头注意力机制的计算成本是同一量级的。
3.2.3 Applications of Attention in our Model
The Transformer在三个地方用到了multi-head attention:
1.在"encoder-decoder attention"层,queries来自前一个decoder层,memory keys和values来自于encoder的output。这使得decoder的每个位置都去关注输入序列的所有位置。
2.encoder包括self-attention层。在self-attention层中,所有的keys,values和queries都来自同一个地方(在这篇paper中),是encoder的前一层的output,使得encoder的每个位置都能够关注到encoder前一层的所有位置。
3.类似的,decoder也有self-attention层,让decoder的每个位置都能关注到该层以及该层之前的(decoder的)所有位置。
3.3 Position-wise Feed-Forward Networks
除了attention子层以外,encoder和decoder的每一层都包含一个全连接的feed-forward网络,分别且相同地应用到每个position,由两个线性变换组成,两个线性变换中间由一个RELU激活函数连接。FFN(x)=max(0,xW1+b1)W2+b2FFN(x)=max(0,xW_1+b_1)W_2+b_2FFN(x)=max(0,xW1+b1)W2+b2不同位置的线性变换是一样的,但是层与层之间的参数不一样。另外一种描述的方式是:kernel size为1的两次卷积。input和output的维度都是dmodel=512d_{model}=512dmodel=512,中间层的维度是dff=2048d_{ff}=2048dff=2048,可以这样理解:每个 dmodeld_{model}dmodel 维向量 x 在此先由 xW1+b1xW_1+b_1xW1+b1 变为dffd_{ff}dff维的 x’,再经过max(0,x′)W2+b2max(0,x')W_2+b_2max(0,x′)W2+b2 回归 d_model 维。之后再是一个residual connection。输出 size 仍是 [sequencelength,dmodel][sequence length, d_{model}][sequencelength,dmodel]。
3.4 Embeddings and Softmax
3.5 Positional Encoding
由于本文的模型结构没有使用任何递归结构或卷积结构,为了让模型能利用输入序列的顺序信息,必须引入某种能表达输入序列每个部分的绝对或相对位置的信息才行。文章采取的方法是位置编码(positional encoding),在送入encoder和decoder之前,先对输入进行编码,位置编码的维度和embeddings的维度一致,为dmodeld_{model}dmodel。所以两者可以相加。
结合位置向量和词向量有几个可选方案,可以把它们拼接起来作为一个新向量,也可以把位置向量定义为跟词向量一样大小,然后两者加起来。在这篇文章中采用的是把两者加起来。
具体来说,采用正弦和余弦函数进行编码。 PE(pos,2i)=sin(pos/100002i/dmodel)PE_{(pos,2i)}=sin(pos/10000^{2i/d_{model}})PE(pos,2i)=sin(pos/100002i/dmodel) PE(pos,2i+1)=cos(pos/100002i/dmodel)PE_{(pos,2i+1)}=cos(pos/10000^{2i/d_{model}})PE(pos,2i+1)=cos(pos/100002i/dmodel)
pospospos是位置,iii是维度。
选择这个函数的原因是:也能学习到相对位置的信息。
对于任意固定的offset k,PEpos+kPE_{pos+k}PEpos+k都能表示成PEposPE_{pos}PEpos的线性函数。
(可能是)由于存在:
sin(α+β)=sinαcosβ+cosαsinβsin(\alpha + \beta)=sin\alpha cos\beta+cos\alpha sin\betasin(α+β)=sinαcosβ+cosαsinβcos(α+β)=cosαcosβ−sinαsinβcos(\alpha + \beta)=cos\alpha cos\beta-sin\alpha sin\betacos(α+β)=cosαcosβ−sinαsinβ
还有三角函数具有周期性。