The Basic Model# 图 1 是有着标准 encoder-decoder 框架的 Transformer 模型。一个 Transformer encoder 包含数个堆叠的编码层 (或编码块),每个编码层有两个不同的子层,分别是子注意力子层和前馈神经网络子层 (F N N \ce{FNN} FNN )
图 1: transformer 的结构
假设源端序列为 x = x 1 … x m \mathbf{x}=x_1\ldots x_m x = x 1 … x m ,目标序列为 y = y 1 … y m \textbf{y}=y_1\ldots y_m y = y 1 … y m 。编码层的输入是 m m m 个向量的序列 h 1 … h m \mathbf{h}_1\ldots \mathbf{h}_m h 1 … h m ,每一个向量均为 d d d 维,我们将这些向量记作 H ∈ R m × d \textbf{H}\in \mathbb{R}^{m\times d} H ∈ R m × d 。自注意力子层首先对 H \textbf{H} H 做自注意力运算 A t t X s e l f ( ⋅ ) \ce{Att_{self}(\cdot)} Att X self ( ⋅ ) 得到输出 C \textbf{C} C :
C = A t t X s e l f ( H ) (1) \mathbf{C} = \ce{Att_{self}}(\mathbf{H})\tag{1} C = Att X self ( H ) ( 1 ) 其中 C \textbf{C} C 与 H \textbf{H} H 的大小一样,可以看作是输入的全新表征。随后对输出添加残差连接与层归一化模块,以此降低模型优化难度
原始 Transformer 模型采用后归一化 结构,先构建残差连接,再执行层归一化操作,具体形式如下:
H s e l f = L N o r m ( C + H ) (2) \mathbf{H}_{\ce{self}} = \ce{LNorm}(\mathbf{C} + \mathbf{H})\tag{2} H self = LNorm ( C + H ) ( 2 ) 其中 H \mathbf{H} H 表示残差连接,L N o r m ( ⋅ ) \ce{LNorm}(\cdot) LNorm ( ⋅ ) 表示层归一化函数。将公式 1 带入公式 2 我们有自注意力子层:
Layer s e l f ( H ) = H self = LNorm ( Att self ( H ) + H ) \begin{align} \text{Layer}_{\ce{self}}(\mathbf{H}) &= \mathbf{H}_{\text{self}} \nonumber \\ &= \text{LNorm}\left( \text{Att}_{\text{self}}(\mathbf{H}) + \mathbf{H} \right) \tag{3} \end{align} Layer self ( H ) = H self = LNorm ( Att self ( H ) + H ) ( 3 ) 自注意力子层的输出 H s e l f \mathbf{H}_{\ce{self}} H self 进入 FFN 子层,输出一个新的表示 H f f n ∈ R m × d \mathbf{H}_{\ce{ffn}}\in \mathbb{R}^{m \times d} H ffn ∈ R m × d 。它与自注意力子层的结构类似,只是将自注意力函数替换成 FFN 函数,即
Layer f f n ( H ) = H ffn = LNorm ( FFN ( H s e l f ) + H s e l f ) \begin{align} \text{Layer}_{\ce{ffn}}(\mathbf{H}) &= \mathbf{H}_{\text{ffn}} \nonumber \\ &= \text{LNorm}\left( \text{FFN}(\mathbf{H}_{\ce{self}}) + \mathbf{H}_\ce{self} \right) \tag{4} \end{align} Layer ffn ( H ) = H ffn = LNorm ( FFN ( H self ) + H self ) ( 4 ) 这里的 FFN ( ⋅ ) \text{FFN}(\cdot) FFN ( ⋅ ) 可以是任何含有非线性激活函数的前馈网络。最常用的 FFN ( ⋅ ) \text{FFN}(\cdot) FFN ( ⋅ ) 的结构是一个包含两层线性变换及中间 ReLU 激活函数的双层网络
对于深度模型,我们可以堆叠上述神经网路结构。假设第 l l l 层的输出是 H l \mathbf{H}^l H l ,它可以表示为 H l − 1 \mathbf{H}^{l-1} H l − 1 的函数,将其写作两个子层的表示:
H l = Layer ffn ( H self l ) H self l = Layer self ( H l − 1 ) \begin{align} \mathbf{H}^l &= \text{Layer}_{\text{ffn}}(\mathbf{H}^l_{\text{self}}) \tag{5} \\ \mathbf{H}^l_{\text{self}} &= \text{Layer}_{\text{self}}(\mathbf{H}^{l-1}) \tag{6} \end{align} H l H self l = Layer ffn ( H self l ) = Layer self ( H l − 1 ) ( 5 ) ( 6 ) 如果有 L L L 个编码层,那么 H L \mathbf{H}^L H L 就是 encoder 最终的输出。此时 H L \mathbf{H}^L H L 可以看作是输入序列经学习得到的上下文表征,H 0 \mathbf{H}^0 H 0 是 encoder 最初的输入。在循环和卷积模型中, H 0 \mathbf{H}^0 H 0 由输入序列的词嵌入组成,而 Transformer 采用了不同的输入表示方式,对位置信息进行显式编码。
decoder 的结构与 encoder 类似,由 L L L 个堆叠的解码层 组成。用 S l \mathbf{S}^l S l 表示第 l l l 层解码层的输出,我们可以通过下面的式子定义一个解码层:
S l = Layer ffn ( S cross l ) S cross l = Layer cross ( H L , S self l − 1 ) S self l = Layer self ( S l − 1 ) \begin{align} \mathbf{S}^l &= \text{Layer}_{\text{ffn}}(\mathbf{S}^l_{\text{cross}}) \tag{7} \\ \mathbf{S}^l_{\text{cross}} &= \text{Layer}_{\text{cross}}(\mathbf{H}^L, \mathbf{S}^{l-1}_{\text{self}}) \tag{8} \\ \mathbf{S}^l_{\text{self}} &= \text{Layer}_{\text{self}}(\mathbf{S}^{l-1}) \tag{9} \end{align} S l S cross l S self l = Layer ffn ( S cross l ) = Layer cross ( H L , S self l − 1 ) = Layer self ( S l − 1 ) ( 7 ) ( 8 ) ( 9 ) decoder 有 3 3 3 个子层。自注意力和 FFN 子层与 encoder 相同。L a y e r X c r o s s ( ⋅ ) \ce{Layer_{cross}}(\cdot) Layer X cross ( ⋅ ) 表示交叉注意力子层(也叫编码器-解码器子层),用于建模源端到目标端的转换过程
decoder 在每个目标端位置输出词汇表 V y V_y V y 上的概率分布。该过程通过 softmax 层实现:对 S L \mathbf{S}^L S L 执行线性变换后,经 softmax 归一化得到目标词的概率分布。具体而言,将 S L \mathbf{S}^L S L 映射为一个 n × ∣ V y ∣ n \times |V_y| n × ∣ V y ∣ 的矩阵 O \mathbf{O} O :
O = S L ⋅ W o (10) \mathbf{O} = \mathbf{S}^L \cdot \mathbf{W}_\ce{o} \tag{10} O = S L ⋅ W o ( 10 ) 其中 W o ∈ R d × ∣ V y ∣ \mathbf{W}_\ce{o}\in \mathbb{R}^{d\times |V_y|} W o ∈ R d × ∣ V y ∣ 是线性变换的参数矩阵
接着由下式给出 decoder 的输出:
[ Pr ( ⋅ ∣ y 0 , x ) ⋮ Pr ( ⋅ ∣ y 0 ⋯ y n − 1 , x ) ] = Softmax ( O ) = [ Softmax ( o 1 ) ⋮ Softmax ( o n ) ] \begin{align} \begin{bmatrix} \Pr(\cdot \mid y_0, \mathbf{x}) \\ \vdots \\ \Pr(\cdot \mid y_0 \cdots y_{n-1}, \mathbf{x}) \end{bmatrix} &= \text{Softmax}(\mathbf{O}) \nonumber \\ &= \begin{bmatrix} \text{Softmax}(\mathbf{o}_1) \\ \vdots \\ \text{Softmax}(\mathbf{o}_n) \end{bmatrix} \tag{11} \end{align} Pr ( ⋅ ∣ y 0 , x ) ⋮ Pr ( ⋅ ∣ y 0 ⋯ y n − 1 , x ) = Softmax ( O ) = Softmax ( o 1 ) ⋮ Softmax ( o n ) ( 11 ) o i \mathbf{o}_i o i 表示 O \mathbf{O} O 的第 i i i 个行向量,y 0 y_0 y 0 表示起始符 <SOS>。在这个模型中,给定 x \mathbf{x} x 时 y y y 的概率可按常规方式定义为:
log Pr ( y ∣ x ) = ∑ i = 1 n log Pr ( y i ∣ y 0 ⋯ y i − 1 , x ) (12) \log \Pr(\mathbf{y} \mid \mathbf{x}) = \sum_{i=1}^{n} \log \Pr(y_i \mid y_0 \cdots y_{i-1}, \mathbf{x})\tag{12} log Pr ( y ∣ x ) = i = 1 ∑ n log Pr ( y i ∣ y 0 ⋯ y i − 1 , x ) ( 12 ) 该方程与语言建模的通用形式类似:给定位置 i − 1 i - 1 i − 1 及之前的所有词,预测位置 i i i 的词。因此,目标输出序列相对输入序列在时间上向前偏移了一步:即解码器以 y 0 … y n − 1 y_0\ldots y_{n-1} y 0 … y n − 1 为输入,预测输出序列 y 1 … y n y_1\ldots y_n y 1 … y n
Transformer 架构存在多种变体,例如仅用编码器表征文本,称作纯编码器架构 ;仅用解码器生成文本,称作纯解码器架构 ;以及标准编解码架构,实现输入序列到输出序列的转换
Positional Encoding# 原始 Transformer 的 FFN 和注意力都忽略了序列模型的一个重要特点:词序对表达序列含义至关重要。这就意味着 encoder 和 decoder 对输入词的位置信息不敏感。一个简单的解决方法是在序列每个词的表示中加入位置编码,即一个词 x j x_j x j 可以表示为一个 d d d 维向量
e j = x j + P E ( j ) (13) \mathbf{e}_j = \mathbf{x}_j + \ce{PE}(j)\tag{13} e j = x j + PE ( j ) ( 13 ) 其中 x j ∈ R d \mathbf{x}_j \in \mathbb{R}^d x j ∈ R d 是词嵌入,可以通过标准嵌入模型得到。P E ( j ) ∈ R d \ce{PE}(j) \in \mathbb{R}^d PE ( j ) ∈ R d 是位置 j j j 的表示。原始 Transformer 使用的是正弦位置编码模型:
PE ( i , 2 k ) = sin ( i ⋅ 1 10000 2 k / d ) PE ( i , 2 k + 1 ) = cos ( i ⋅ 1 10000 2 k / d ) \begin{align} \text{PE}(i, 2k) &= \sin\left(i \cdot \frac{1}{10000^{2k/d}}\right) \tag{14} \\ \text{PE}(i, 2k+1) &= \cos\left(i \cdot \frac{1}{10000^{2k/d}}\right) \tag{15} \end{align} PE ( i , 2 k ) PE ( i , 2 k + 1 ) = sin ( i ⋅ 1000 0 2 k / d 1 ) = cos ( i ⋅ 1000 0 2 k / d 1 ) ( 14 ) ( 15 ) 式中的 P E ( i , k ) \ce{PE}(i,k) PE ( i , k ) 表示位置编码向量 P E ( i ) \ce{PE}(i) PE ( i ) 的第 k k k 个元素。位置编码的核心思想是通过连续函数区分不同位置,这里使用了不同频率的正弦与余弦函数。由于该编码基于单个位置直接计算,因此也被称为绝对位置编码 。
当我们得到了这些嵌入,序列 e 1 … e m \mathbf{e}_1 \ldots \mathbf{e}_m e 1 … e m 就可作为 encoder 的输入,即:
H 0 = [ e 1 ⋮ e m ] (16) \mathbf{H}_0 = \begin{bmatrix} \mathbf{e}_1 \\ \vdots \\ \mathbf{e}_m \end{bmatrix} \tag{16} H 0 = e 1 ⋮ e m ( 16 ) 同样也可定义 decoder 的输入
Multi-head Self-attention# 自注意力机制的使用,或许是 seq2seq 模型领域最重要的进展之一。它试图学习并利用所有输入对之间的直接交互关系。从表示学习的角度来看,自注意力模型假设位置 i i i 处的学习表示 c i \mathbf{c}_i c i 是序列中所有输入的加权和。因此,输出 c i \mathbf{c}_i c i 可表示为:
c i = ∑ j = 1 m α i , j h j (17) \mathbf{c}_i = \sum_{j=1}^{m} \alpha_{i,j} \mathbf{h}_j \tag{17} c i = j = 1 ∑ m α i , j h j ( 17 ) 其中 α i , j \alpha_{i,j} α i , j 是计算 i i i 处的表示时加在 h j \mathbf{h}_j h j 上的注意力权重。因此,我们可以将 c i \mathbf{c}_i c i 看作 i i i 处的全局上下文表示。α i , j \alpha_{i,j} α i , j 随模型的不同有多种定义方式,这里使用缩放点积注意力函数来计算:
α i , j = Softmax ( h i h j ⊤ / β ) = exp ( h i h j ⊤ / β ) ∑ k = 1 m exp ( h i h k ⊤ / β ) \begin{align} \alpha_{i,j} &= \text{Softmax}\left( \mathbf{h}_i \mathbf{h}_j^\top / \beta \right) \nonumber \\ &= \frac{\exp\left( \mathbf{h}_i \mathbf{h}_j^\top / \beta \right)}{\sum_{k=1}^{m} \exp\left( \mathbf{h}_i \mathbf{h}_k^\top / \beta \right)} \tag{18} \end{align} α i , j = Softmax ( h i h j ⊤ / β ) = ∑ k = 1 m exp ( h i h k ⊤ / β ) exp ( h i h j ⊤ / β ) ( 18 ) 缩放因子 β \beta β 通常设置为 d \sqrt d d
与传统循环和卷积模型相比,自注意力模型的一个优势是缩短了两个输入之间的计算 “距离”。图 2 展示了这些模型中的信息流。可以看到,给定位置 i i i 的输入,自注意力模型可以直接访问任何其他输入。相比之下,循环和卷积模型可能需要两步或更多步骤才能看到整个序列。
图 2: 循环,卷积和自注意力模型中的信息流
借助 QKV 注意力模型,我们可以从更通用的视角理解自注意力。假设存在一组由 κ \kappa κ 个查询向量组成的序列 Q = [ q 1 ⋮ q κ ] \mathbf{Q} = \begin{bmatrix} \mathbf{q}_1 \\ \vdots \\ \mathbf{q}_\kappa \end{bmatrix} Q = q 1 ⋮ q κ ,以及由 ψ \psi ψ 个键值对组成的序列 (K = [ k 1 ⋮ k ψ ] \mathbf{K} = \begin{bmatrix} \mathbf{k}_1 \\ \vdots \\ \mathbf{k}_\psi \end{bmatrix} K = k 1 ⋮ k ψ ,V = [ v 1 ⋮ v ψ ] \mathbf{V} = \begin{bmatrix} \mathbf{v}_1 \\ \vdots \\ \mathbf{v}_\psi \end{bmatrix} V = v 1 ⋮ v ψ )。模型的输出是一个向量序列,分别对应一个查询。QKV 注意力由下式给出:
Att qkv ( Q , K , V ) = Softmax ( Q K ⊤ d ) V (19) \operatorname{Att}_{\text{qkv}}(\mathbf{Q}, \mathbf{K}, \mathbf{V}) = \operatorname{Softmax}\left( \frac{\mathbf{Q}\mathbf{K}^\top}{\sqrt{d}} \right)\mathbf{V} \tag{19} Att qkv ( Q , K , V ) = Softmax ( d Q K ⊤ ) V ( 19 ) 我们可以将 QKV 注意力模型的输出写作一个行向量的序列:
C = [ c 1 ⋮ c κ ] = Att qkv ( Q , K , V ) \begin{align} \mathbf{C} &= \begin{bmatrix} \mathbf{c}_1 \\ \vdots \\ \mathbf{c}_\kappa \end{bmatrix} \nonumber \\ &= \operatorname{Att}_{\text{qkv}}(\mathbf{Q}, \mathbf{K}, \mathbf{V}) \tag{20} \end{align} C = c 1 ⋮ c κ = Att qkv ( Q , K , V ) ( 20 ) 要将此公式应用于自注意力,我们只需令:
H q = H W q H k = H W k H v = H W v \begin{align} \mathbf{H}^q &= \mathbf{H}\mathbf{W}^q \tag{21} \\ \mathbf{H}^k &= \mathbf{H}\mathbf{W}^k \tag{22} \\ \mathbf{H}^v &= \mathbf{H}\mathbf{W}^v \tag{23} \end{align} H q H k H v = H W q = H W k = H W v ( 21 ) ( 22 ) ( 23 ) 其中 W q , W k , W v ∈ R d × d \mathbf{W}^q,\mathbf{W}^k,\mathbf{W}^v \in \mathbb{R}^{d \times d} W q , W k , W v ∈ R d × d 表示 H \mathbf{H} H 的线性变换
现在可以对公式 1 进行改写:
C = Att self ( H ) = Att qkv ( H q , H k , H v ) = Softmax ( H q [ H k ] ⊤ d ) H v \begin{align} \mathbf{C} &= \operatorname{Att}_{\text{self}}(\mathbf{H}) \nonumber \\ &= \operatorname{Att}_{\text{qkv}}(\mathbf{H}^q, \mathbf{H}^k, \mathbf{H}^v) \nonumber \\ &= \operatorname{Softmax}\left( \frac{\mathbf{H}^q [\mathbf{H}^k]^\top}{\sqrt{d}} \right) \mathbf{H}^v \tag{24} \end{align} C = Att self ( H ) = Att qkv ( H q , H k , H v ) = Softmax ( d H q [ H k ] ⊤ ) H v ( 24 ) 这里 Softmax ( H q [ H k ] ⊤ d ) \operatorname{Softmax}\left( \frac{\mathbf{H}^q [\mathbf{H}^k]^\top}{\sqrt{d}} \right) Softmax ( d H q [ H k ] ⊤ ) 一个 m × m m \times m m × m 的矩阵,每一行表示输入所有位置的一个分布:
row i = [ α i , 1 … α i , m ] (25) \text{row } i = \begin{bmatrix} \alpha_{i,1} & \dots & \alpha_{i,m} \end{bmatrix} \tag{25} row i = [ α i , 1 … α i , m ] ( 25 ) 我们可以通过多头注意力 对自注意力进行改进。这种方法可以从学习多个低维特征子空间的角度来理解:它将输入投影到多个子空间中,并在每个子空间里学习独立的表示。具体来说,我们把整个输入空间投影到 τ \tau τ 个子空间中 (称作头 )。例如,我们将 H ∈ R m × d \mathbf{H} \in \mathbb{R}^{m \times d} H ∈ R m × d 转换成 τ \tau τ 个大小为 m × d τ m \times \frac{d}{\tau} m × τ d 的矩阵,记作 { H 1 h e a d , ⋯ , H τ h e a d } \{\mathbf{H}^{\ce{head}}_1,\cdots ,\mathbf{H}^{\ce{head}}_\tau\} { H 1 head , ⋯ , H τ head } 。注意力模型在每个头上应用一次,共计 τ \tau τ 次。最后,将所有模型运行的输出拼接起来,并通过一个线性变换进行整合。这一过程可以表示为:
C = Merge ( C 1 head , … , C τ head ) W c = Merge ( Att qkv ( H 1 q , H 1 k , H 1 v ) , … , Att qkv ( H τ q , H τ k , H τ v ) ) W c \begin{align} \mathbf{C} &= \operatorname{Merge}(\mathbf{C}_1^{\text{head}}, \dots, \mathbf{C}_\tau^{\text{head}})\mathbf{W}_c \tag{26} \\
&= \operatorname{Merge}\left( \operatorname{Att}_{\text{qkv}}(\mathbf{H}_1^q, \mathbf{H}_1^k, \mathbf{H}_1^v), \dots, \operatorname{Att}_{\text{qkv}}(\mathbf{H}_\tau^q, \mathbf{H}_\tau^k, \mathbf{H}_\tau^v) \right)\mathbf{W}_c
\tag{27}
\end{align} C = Merge ( C 1 head , … , C τ head ) W c = Merge ( Att qkv ( H 1 q , H 1 k , H 1 v ) , … , Att qkv ( H τ q , H τ k , H τ v ) ) W c ( 26 ) ( 27 ) 对每个头 h h h ,
C h head = Softmax ( H h q [ H h k ] ⊤ d ) H h v H h q = H W h q H h k = H W h k H h v = H W h v \begin{align} \mathbf{C}_h^{\text{head}} &= \operatorname{Softmax}\left( \frac{\mathbf{H}_h^q [\mathbf{H}_h^k]^\top}{\sqrt{d}} \right) \mathbf{H}_h^v \tag{28} \\ \mathbf{H}_h^q &= \mathbf{H} \mathbf{W}_h^q \tag{29} \\ \mathbf{H}_h^k &= \mathbf{H} \mathbf{W}_h^k \tag{30} \\ \mathbf{H}_h^v &= \mathbf{H} \mathbf{W}_h^v \tag{31} \end{align} C h head H h q H h k H h v = Softmax ( d H h q [ H h k ] ⊤ ) H h v = H W h q = H W h k = H W h v ( 28 ) ( 29 ) ( 30 ) ( 31 ) 式中的 M e r g e ( ⋅ ) \ce{Merge}(\cdot) Merge ( ⋅ ) 是 concat 函数,A t t X q k v ( ⋅ ) \ce{Att_{qkv}(\cdot)} Att X qkv ( ⋅ ) 是注意力函数,W h q , W h k , W h v ∈ R d × d r \mathbf{W}^q_h,\mathbf{W}^k_h,\mathbf{W}^v_h \in \mathbb{R}^{d \times \frac{d}{r}} W h q , W h k , W h v ∈ R d × r d 是查询,键和值从 d d d 维空间投射到 d τ \frac{d}{\tau} τ d 维空间的投影参数,因此 H h q , H h k , H h v , C h head \mathbf{H}_h^q, \mathbf{H}_h^k, \mathbf{H}_h^v, \mathbf{C}_h^{\text{head}} H h q , H h k , H h v , C h head 都是 m × d τ m \times \frac{d}{\tau} m × τ d 的矩阵。Merge ( C 1 head , … , C τ head ) \operatorname{Merge}(\mathbf{C}_1^{\text{head}}, \dots, \mathbf{C}_\tau^{\text{head}}) Merge ( C 1 head , … , C τ head ) 会生成一个 m × d m \times d m × d 的矩阵,通过线性映射 W c ∈ R d × d \mathbf{W}_c \in \mathbb{R}^{d \times d} W c ∈ R d × d 变换得到最终输出 C ∈ R m × d \mathbf{C} \in \mathbb{R}^{m \times d} C ∈ R m × d
Layer Normalization# 层归一化提供了一种简单有效的方法,通过以层为单位对隐藏层的激活值进行标准化,让神经网络的训练更加稳定。给定某一层的输出 h ∈ R d \mathbf{h} \in \mathbb{R}^d h ∈ R d ,通过下式来计算标准化输出 L N o r m ( h ) \ce{LNorm}(\mathbf{h}) LNorm ( h ) :
L N o r m ( h ) = α ⊙ h − μ σ + ϵ + β (32) \ce{LNorm}(\mathbf{h}) = \alpha \odot \frac{\mathbf{h} - \mu}{\sigma + \epsilon} + \beta\tag{32} LNorm ( h ) = α ⊙ σ + ϵ h − μ + β ( 32 ) 这里 μ ∈ R \mu \in \mathbb{R} μ ∈ R 和 σ ∈ R \sigma \in \mathbb{R} σ ∈ R 是激活值的标量均值和标准差。设 h k h_k h k 为 h \mathbf{h} h 的第 k k k 维,均值和方差的定义如下:
μ = 1 d ∑ k = 1 d h k σ = 1 d ∑ k = 1 d ( h k − μ ) 2 \begin{align} \mu &= \frac{1}{d} \sum_{k=1}^d h_k \tag{33} \\ \sigma &= \sqrt{\frac{1}{d} \sum_{k=1}^d (h_k - \mu)^2} \tag{34} \end{align} μ σ = d 1 k = 1 ∑ d h k = d 1 k = 1 ∑ d ( h k − μ ) 2 ( 33 ) ( 34 ) 这里 α ∈ R d \alpha \in \mathbb{R}^d α ∈ R d 和 β ∈ R d \beta \in \mathbb{R}^d β ∈ R d 是缩放和偏移参数,它们可以看作是层归一化的参数,与其它参数一起联合学习。σ \sigma σ 的基础上加上 ϵ \epsilon ϵ 来保证数值稳定性
假设 F ( ⋅ ) F(\cdot) F ( ⋅ ) 是神经网络子层,那么 F ( ⋅ ) F(\cdot) F ( ⋅ ) 的后归一化结构可表示为:
H out = L N o r m ( F ( H i n ) + H i n ) (35) \mathbf{H}_{\text{out}} = \ce{LNorm}\left( F(\mathbf{H}_{\ce{in}}) + \mathbf{H}_{\ce{in}} \right)\tag{35} H out = LNorm ( F ( H in ) + H in ) ( 35 ) H i n \mathbf{H}_{\ce{in}} H in 和 H o u t \mathbf{H}_{\ce{out}} H out 是该子层的输入和输出
另一种结合层归一化和残差连接的方式是前归一化,在 F ( ⋅ ) F(\cdot) F ( ⋅ ) 前执行 L N o r m ( ⋅ ) \ce{LNorm}(\cdot) LNorm ( ⋅ ) :
H out = F ( L N o r m ( H in ) ) + H in (36) \mathbf{H}_{\text{out}} = F\left( \ce{LNorm}(\mathbf{H}_{\text{in}}) \right) + \mathbf{H}_{\text{in}} \tag{36} H out = F ( LNorm ( H in ) ) + H in ( 36 ) 后归一化与前归一化 Transformer 模型均被广泛应用于自然语言处理任务。二者结构对比如图 3 所示
图 3: 前归一化和后归一化结构
总体而言,残差连接被认为是降低多层神经网络训练难度、提升训练稳定性的有效手段。从这个角度来看,前归一化 Transformer 更具优势:它遵循残差连接的设计思想,让输入可以完整旁路整个网络层;输入到输出的恒等映射特性,大幅简化了深度模型的优化难度
但从模型表达能力的角度考量,后归一化 Transformer 具备建模优势:它对残差连接的依赖程度更低,能让表征学习过程实现更复杂、精细的建模
Feed-forward Neural Networks# Transformer 中引入 FFN,部分原因在于可通过非线性变换对输入做处理,进而生成复杂输出。自注意力机制本身虽借助 softmax 函数具备一定非线性特性,但业界更普遍的做法是增设包含非线性激活函数与线性变换的网络层,以此引入非线性表达能力。给定一个输入 H i n ∈ R m × d \mathbf{H}_{\ce{in}} \in \mathbb{R}^{m \times d} H in ∈ R m × d 和输出 H o u t ∈ R m × d \mathbf{H}_{\ce{out}} \in \mathbb{R}^{m \times d} H out ∈ R m × d ,Transformer 中的 H o u t = F F N ( H i n ) \mathbf{H}_{\ce{out}} = \ce{FFN}(\mathbf{H}_{\ce{in}}) H out = FFN ( H in ) 有以下形式:
H out = H hidden W f + b f H hidden = ReLU ( H in W h + b h ) \begin{align}
\mathbf{H}_{\text{out}} &= \mathbf{H}_{\text{hidden}} \mathbf{W}_f + \mathbf{b}_f \tag{37} \\
\mathbf{H}_{\text{hidden}} &= \text{ReLU}\left( \mathbf{H}_{\text{in}} \mathbf{W}_h + \mathbf{b}_h \right) \tag{38} \end{align} H out H hidden = H hidden W f + b f = ReLU ( H in W h + b h ) ( 37 ) ( 38 ) 式中的 H hidden ∈ R m × d f f n \mathbf{H}_{\text{hidden}} \in \mathbb{R}^{m\times d_{\ce{ffn}}} H hidden ∈ R m × d ffn 代表隐状态,W h ∈ R d × d ffn \mathbf{W}_h \in \mathbb{R}^{d \times d_{\text{ffn}}} W h ∈ R d × d ffn , b h ∈ R d ffn \mathbf{b}_h \in \mathbb{R}^{d_{\text{ffn}}} b h ∈ R d ffn , W f ∈ R d ffn × d \mathbf{W}_f \in \mathbb{R}^{d_{\text{ffn}} \times d} W f ∈ R d ffn × d 和 b f ∈ R d \mathbf{b}_f \in \mathbb{R}^d b f ∈ R d 是参数。这是一个两层的 FFN,在第一层通过 ReLU ( ⋅ ) \text{ReLU}(\cdot) ReLU ( ⋅ ) 引入了非线性,第二层只有线性变换。Transformer 中通常会使用更大的隐藏层维度,例如常用设置为 d ffn = 4 d d_{\text{ffn}} = 4d d ffn = 4 d ,即每个隐藏表示的维度是输入维度的 4 4 4 倍。
Decoder-side Attention# decoder 层包含两种注意力子层:第一个是自注意力子层,第二个是交叉注意力子层。这些子层可以基于后归一化或前归一化结构,但在注意力函数的定义方式上有所不同。我们可以将解码层的交叉注意力子层和自注意力子层定义为:
S cross = Layer cross ( H enc , S self ) = LNorm ( Att cross ( H enc , S self ) + S self ) S self = Layer self ( S ) = LNorm ( Att self ( S ) + S ) \begin{align}
\mathbf{S}_{\text{cross}} &= \text{Layer}_{\text{cross}}(\mathbf{H}_{\text{enc}}, \mathbf{S}_{\text{self}}) \nonumber \\
&= \text{LNorm}\left( \text{Att}_{\text{cross}}(\mathbf{H}_{\text{enc}}, \mathbf{S}_{\text{self}}) + \mathbf{S}_{\text{self}} \right) \tag{39} \\ \mathbf{S}_{\text{self}} &= \text{Layer}_{\text{self}}(\mathbf{S}) \nonumber \\
&= \text{LNorm}\left( \text{Att}_{\text{self}}(\mathbf{S}) + \mathbf{S} \right) \tag{40} \end{align} S cross S self = Layer cross ( H enc , S self ) = LNorm ( Att cross ( H enc , S self ) + S self ) = Layer self ( S ) = LNorm ( Att self ( S ) + S ) ( 39 ) ( 40 ) 其中 S ∈ R n × d \mathbf{S} \in \mathbb{R}^{n \times d} S ∈ R n × d 是自注意力子层的输入,S c r o s s ∈ R n × d \mathbf{S}_{\ce{cross}} \in \mathbb{R}^{n \times d} S cross ∈ R n × d 和 S s e l f ∈ R n × d \mathbf{S}_{\ce{self}} \in \mathbb{R}^{n \times d} S self ∈ R n × d 是子层的输出,H e n c ∈ R m × d \mathbf{H}_{\ce{enc}} \in \mathbb{R}^{m \times d} H enc ∈ R m × d 是 encoder 的输出
与传统注意力模型一致,交叉注意力主要用于建模源序列与目标序列间的对应关系。A t t c r o s s ( ⋅ ) \ce{Att}_{\ce{cross}}(\cdot) Att cross ( ⋅ ) 基于 QKV 注意力机制,通过检索键值对集合得到输出。具体而言,查询、键、值分别由 S self \mathbf{S}_{\text{self}} S self 与 H enc \mathbf{H}_{\text{enc}} H enc 线性变换得到,定义如下:
S self q = S self W cross q H enc k = H enc W enc k H enc v = H enc W enc v \begin{align} \mathbf{S}_{\text{self}}^q &= \mathbf{S}_{\text{self}} \mathbf{W}_{\text{cross}}^q \tag{41} \\ \mathbf{H}_{\text{enc}}^k &= \mathbf{H}_{\text{enc}} \mathbf{W}_{\text{enc}}^k \tag{42} \\ \mathbf{H}_{\text{enc}}^v &= \mathbf{H}_{\text{enc}} \mathbf{W}_{\text{enc}}^v \tag{43} \end{align} S self q H enc k H enc v = S self W cross q = H enc W enc k = H enc W enc v ( 41 ) ( 42 ) ( 43 ) 其中 W c r o s s q , W e n c k , W e n c v ∈ R d × d \mathbf{W}^q_{\ce{cross}},\mathbf{W}^k_{\ce{enc}},\mathbf{W}^v_{\ce{enc}} \in \mathbb{R}^{d \times d} W cross q , W enc k , W enc v ∈ R d × d 是映射的参数,也就是说,查询向量基于 S self \mathbf{S}_{\text{self}} S self 定义,而键向量和值向量则基于 H e n c \mathbf{H}_{\ce{enc}} H enc 定义
接下来 A t t c r o s s ( ⋅ ) \ce{Att}_{\ce{cross}}(\cdot) Att cross ( ⋅ ) 定义为
A t t cross ( H enc , S self ) = A t t qkv ( S self q , H enc k , H enc v ) = S o f t m a x ( S self q [ H enc k ] ⊤ d ) H enc v \begin{align} \mathrm{Att}_{\text{cross}}(\mathbf{H}_{\text{enc}}, \mathbf{S}_{\text{self}}) &= \mathrm{Att}_{\text{qkv}}(\mathbf{S}_{\text{self}}^q, \mathbf{H}_{\text{enc}}^k, \mathbf{H}_{\text{enc}}^v) \nonumber \\ &= \mathrm{Softmax}\left( \frac{\mathbf{S}_{\text{self}}^q \left[ \mathbf{H}_{\text{enc}}^k \right]^\top}{\sqrt{d}} \right) \mathbf{H}_{\text{enc}}^v \tag{44} \end{align} Att cross ( H enc , S self ) = Att qkv ( S self q , H enc k , H enc v ) = Softmax ( d S self q [ H enc k ] ⊤ ) H enc v ( 44 ) A t t s e l f ( ⋅ ) \ce{Att}_{\ce{self}}(\cdot) Att self ( ⋅ ) 函数与 A t t c r o s s ( ⋅ ) \ce{Att}_{\ce{cross}}(\cdot) Att cross ( ⋅ ) 形式类似,它将 S \mathbf{S} S 的线性映射同时作为查询、键和值,具体形式如下:
A t t self ( S ) = A t t qkv ( S q , S k , S v ) = S o f t m a x ( S q [ S k ] ⊤ d + M ) S v \begin{align} \mathrm{Att}_{\text{self}}(\mathbf{S}) &= \mathrm{Att}_{\text{qkv}}(\mathbf{S}^q, \mathbf{S}^k, \mathbf{S}^v) \nonumber \\ &= \mathrm{Softmax}\left( \frac{\mathbf{S}^q \left[ \mathbf{S}^k \right]^\top}{\sqrt{d}} + \mathbf{M} \right) \mathbf{S}^v \tag{45} \end{align} Att self ( S ) = Att qkv ( S q , S k , S v ) = Softmax ( d S q [ S k ] ⊤ + M ) S v ( 45 ) 其中 S q = S W dec q \mathbf{S}^q = \mathbf{S}\mathbf{W}_{\text{dec}}^q S q = S W dec q , S k = S W dec k \mathbf{S}^k = \mathbf{S}\mathbf{W}_{\text{dec}}^k S k = S W dec k 以及 S v = S W dec v \mathbf{S}^v = \mathbf{S}\mathbf{W}_{\text{dec}}^v S v = S W dec v 是 S \mathbf{S} S 的参数为 W dec q , W dec k , W dec v ∈ R d × d \mathbf{W}_{\text{dec}}^q, \mathbf{W}_{\text{dec}}^k, \mathbf{W}_{\text{dec}}^v \in \mathbb{R}^{d \times d} W dec q , W dec k , W dec v ∈ R d × d 的线性映射
这个形式与 公式 20 相似。然而与 encoder 自注意力的一个关键区别是这里的模型必须遵守从左至右生成的规则 (图 4) 。
图 4: encoder 和 decoder 中的自注意力
也就是说,给定位置 i i i 处的目标词,模型只能看到左侧上下文的目标词 y 1 , ⋅ , y i − 1 y_1,\cdot,y_{i-1} y 1 , ⋅ , y i − 1 。为了强制实现这一点,我们在未归一化的权重矩阵 S q [ S k ] ⊤ d \frac{\mathbf{S}^q [\mathbf{S}^k]^\top}{\sqrt{d}} d S q [ S k ] ⊤ 中加入一个掩码变量 M \mathbf{M} M 。M \mathbf{M} M 和权重矩阵的大小都是 n × n n \times n n × n ,因此 M \mathbf{M} M 中的极大负值会抑制对应的注意力分数。为了在第 i i i 步禁止关注右侧上下文(未来的词),M \mathbf{M} M 定义如下:
M ( i , j ) = { 0 i ≥ j − ∞ i < j (46) M(i,j) = \begin{cases} 0 & i \ge j \\ -\infty & i < j \end{cases} \tag{46} M ( i , j ) = { 0 − ∞ i ≥ j i < j ( 46 ) 其中,M ( i , j ) M(i,j) M ( i , j ) 表示位置 i i i 和 j j j 之间对齐分数的偏置项
Training and Inference# Transformer 模型可以按照标准流程进行训练和使用。下面我们将介绍 Transformer 模型训练和推理中常用的一些技术:
学习率调度 。为在训练过程中动态调整学习率,Vaswani et al. [2017] 提出调度策略:先线性提升学习率,达到指定步数后再逐步衰减。其学习率计算公式形式如下
η = η 0 ⋅ min { n step − 0.5 , n step ⋅ ( n warmup ) − 1.5 } (47) \eta = \eta_0 \cdot \min\left\{ n_{\text{step}}^{-0.5},\ n_{\text{step}} \cdot \left(n_{\text{warmup}}\right)^{-1.5} \right\} \tag{47} η = η 0 ⋅ min { n step − 0.5 , n step ⋅ ( n warmup ) − 1.5 } ( 47 ) 其中 η 0 \eta_0 η 0 是初始学习率,n s t e p n_{\ce{step}} n step 是已执行的训练步数,n warmup n_{\text{warmup}} n warmup 表示预热步数。在前 n warmup n_{\text{warmup}} n warmup 步中,学习率 η \eta η 随训练推进而逐渐增大;在 n step = n warmup n_{\text{step}} = n_{\text{warmup}} n step = n warmup 时达到最大值,之后按反平方根函数衰减 (即 η 0 ⋅ n step − 0.5 \eta_0 \cdot n_{\text{step}}^{-0.5} η 0 ⋅ n step − 0.5 )
批处理与填充 。为了在全局优化与训练收敛之间取得平衡,通常的做法是使用一组数量较少的样本更新模型权重,这组样本称为 minibatch 。因此,我们可以采用批量版本的前向与反向计算流程:将整个 minibatch 一起使用,以获得梯度信息。这要求一个 minibatch 内的所有输入序列都存储在同一块内存区域中,以便被同时读取和处理
搜寻与缓存 。在测试时,我们需要在候选假设空间(即候选目标端序列空间)中进行搜索,以找出得分最高的假设:
y ^ = argmax y score ( x , y ) (48) \hat{y} = \underset{y}{\operatorname{argmax}} \ \text{score}(x, y) \tag{48} y ^ = y argmax score ( x , y ) ( 48 ) 其中,s c o r e ( x , y ) \ce{score}(x,y) score ( x , y ) 是给定源端序列 x x x 时,目标端序列 y y y 的模型得分。搜索算法大多可被视为一种从左到右的生成过程。如图 5 所示,我们可以使用缓存,将位置 < i < i < i 的所有状态均保存在缓存中,可被快速访问。在位置 i i i 处,我们仅需计算新增词元的状态,再更新缓存即可
图 5: decoder 中的缓存机制