transformer模型

转自:https://www.bilibili.com/video/BV1Mt411J734
https://github.com/aespresso/a_journey_into_math_of_ml

说到自然语言处理, 语言模型, 命名实体识别, 机器翻译, 可能很多人想到的LSTM等循环神经网络, 但目前其实LSTM起码在自然语言处理领域已经过时了, 在Stanford阅读理解数据集(SQuAD2.0)榜单里, 机器的成绩已经超人类表现, 这很大程度要归功于transformer的BERT预训练模型.

transformer是谷歌大脑在2017年底发表的论文attention is all you need中所提出的seq2seq模型. 现在已经取得了大范围的应用和扩展, 而BERT就是从transformer中衍生出来的预训练语言模型.

在我们开始之前, 允许我简单说一下目前自然语言处理领域的现状, 目前transformer模型已经得到广泛认可和应用, 而应用的方式主要是先进行预训练语言模型, 然后把预训练的模型适配给下游任务, 以完成各种不同的任务, 如分类, 生成, 标记等等, 预训练模型非常重要, 预训练的模型的性能直接影响下游任务的性能, 通过我制作的这几期视频, 我有信心让小伙伴们充分理解transformer并具备一定衍生模型的设计和编写能力.

1 Transformer 模型直观认识

首先来说一下transformer和LSTM的最大区别, 就是LSTM的训练是迭代的, 是一个接一个字的来, 当前这个字过完LSTM单元, 才可以进下一个字, 而transformer的训练是并行的, 就是所有字是全部同时训练的, 这样就大大加快了计算效率, transformer使用了位置嵌入 ( ) 来理解语言的顺序, 使用自注意力机制和全连接层来进行计算, 这些后面都会详细讲解.

transformer模型主要分为两大部分, 分别是编码器和解码器, 编码器负责把自然语言序列映射成为隐藏层(下图中第2步用九宫格比喻的部分), 含有自然语言序列的数学表达. 然后解码器把隐藏层再映射为自然语言序列, 从而使我们可以解决各种问题, 如情感分类, 命名实体识别, 语义关系抽取, 摘要生成, 机器翻译等等, 下面我们以机器翻译为例简单说一下下图的每一步都做了什么:

  1. 输入自然语言序列到编码器: Why do we work?(为什么要工作);
  2. 编码器输出到隐藏层, 再输入到解码器;
  3. 输入 <> (起始)符号到解码器;
  4. 得到第一个字"为";
  5. 将得到的第一个字"为"落下来再输入到解码器;
  6. 得到第二个字"什";
  7. 将得到的第二字再落下来, 直到解码器输出 <> (终止符), 即序列生成完成.
    transformer模型_第1张图片

我们这节课的内容限于编码器部分, 即把自然语言序列映射为隐藏层的数学表达的过程, 因为理解了编码器中的结构, 理解解码器就非常简单了,最重要的是BERT预训练模型只用到了编码器的部分, 也就是先用编码器训练一个语言模型, 然后再把它适配给其他五花八门的任务.

如果你不知道语言模型是什么, 没关系, 这丝毫不影响本节课内容的理解, 下次我们讲BERT的时候会讲.
而且我们用编码器就能够完成一些自然语言处理中比较主流的任务, 如情感分类, 语义关系分析, 命名实体识别等, 解码器的内容和序列到序列模型有机会我们会涉及到.

2 Transformer Block结构图

transformer模型_第2张图片
编码器的输入X是一个自然语言序列,它的维度是[batch size,sequence length],batch size是一次训练句子的个数,sequence length是句子的长度。它通过查阅字向量表或者其他方式得到每个字embedding dimension维的嵌入向量。

上面是一个transformer block,实际网络中可以堆叠多个block。

我们通过编码器输出的 X h i d d e n X_{hidden} Xhidden就是隐藏层,下面详细介绍每个模块。

2.1

由于transformer模型没有循环神经网络的迭代操作, 所以我们必须提供每个字的位置信息给transformer, 才能识别出语言中的顺序关系.

现在定义一个位置嵌入的概念, 也就是 p o s i t i o n a l   e n c o d i n g positional \ encoding positional encoding, 位置嵌入的维度为 [ m a x   s e q u e n c e   l e n g t h ,   e m b e d d i n g   d i m e n s i o n ] [max \ sequence \ length, \ embedding \ dimension] [max sequence length, embedding dimension], 嵌入的维度和词向量的维度相同,所以我们计算出位置嵌入直接和词向量按位相加即可。 m a x   s e q u e n c e   l e n g t h max \ sequence \ length max sequence length属于超参数, 指的是限定的最大单个句长.

注意, 我们一般以字为单位训练transformer模型, 也就是说我们不用分词了, 首先我们要初始化字向量为 [ v o c a b   s i z e ,   e m b e d d i n g   d i m e n s i o n ] [vocab \ size, \ embedding \ dimension] [vocab size, embedding dimension], v o c a b   s i z e vocab \ size vocab size为总共的字库数量, e m b e d d i n g   d i m e n s i o n embedding \ dimension embedding dimension为字向量的维度, 也是每个字的数学表达.

在这里论文中使用了 s i n sin sin c o s cos cos函数的线性变换来提供给模型位置信息:
P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d model ) P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d model ) (eq.1) PE_{(pos,2i)} = sin(pos / 10000^{2i/d_{\text{model}}}) \quad PE_{(pos,2i+1)} = cos(pos / 10000^{2i/d_{\text{model}}})\tag{eq.1} PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)(eq.1)
上式中 p o s pos pos指的是句中字的位置, 取值范围是 [ 0 ,   m a x   s e q u e n c e   l e n g t h ) [0, \ max \ sequence \ length) [0, max sequence length), i i i指的是词向量的维度, 取值范围是 [ 0 ,   e m b e d d i n g   d i m e n s i o n ) [0, \ embedding \ dimension) [0, embedding dimension), 上面有 s i n sin sin c o s cos cos一组公式, 也就是对应着 e m b e d d i n g   d i m e n s i o n embedding \ dimension embedding dimension维度的一组奇数和偶数的序号的维度, 例如 0 , 1 0, 1 0,1一组, 2 , 3 2, 3 2,3一组, 分别用上面的 s i n sin sin c o s cos cos函数做处理, 从而产生不同的周期性变化, 而位置嵌入在 e m b e d d i n g   d i m e n s i o n embedding \ dimension embedding dimension维度上随着维度序号增大, 周期变化会越来越慢, 而产生一种包含位置信息的纹理, 就像论文原文中第六页讲的, 位置嵌入函数的周期从 2 π 2 \pi 2π 10000 ∗ 2 π 10000 * 2 \pi 100002π变化, 而每一个位置在 e m b e d d i n g   d i m e n s i o n embedding \ dimension embedding dimension维度上都会得到不同周期的 s i n sin sin c o s cos cos函数的取值组合, 从而产生独一的纹理位置信息, 模型从而学到位置之间的依赖关系和自然语言的时序特性.

下面画一下位置嵌入, 可见纵向观察, 随着 e m b e d d i n g   d i m e n s i o n embedding \ dimension embedding dimension增大, 位置嵌入函数呈现不同的周期变化.
transformer模型_第3张图片
transformer模型_第4张图片

2.2 ℎ


Attention Mask
transformer模型_第5张图片
注意, 在上面 s e l f   a t t e n t i o n self \ attention self attention的计算过程中, 我们通常使用 m i n i   b a t c h mini \ batch mini batch来计算, 也就是一次计算多句话, 也就是 X X X的维度是 [ b a t c h   s i z e ,   s e q u e n c e   l e n g t h ] [batch \ size, \ sequence \ length] [batch size, sequence length], s e q u e n c e   l e n g t h sequence \ length sequence length是句长, 而一个 m i n i   b a t c h mini \ batch mini batch是由多个不等长的句子组成的, 我们就需要按照这个 m i n i   b a t c h mini \ batch mini batch中最大的句长对剩余的句子进行补齐长度, 我们一般用 0 0 0来进行填充, 这个过程叫做 p a d d i n g padding padding.

但这时在进行 s o f t m a x softmax softmax的时候就会产生问题, 回顾 s o f t m a x softmax softmax函数 σ ( z ) i = e z i ∑ j = 1 K e z j \sigma (\mathbf {z} )_{i}={\frac {e^{z_{i}}}{\sum _{j=1}^{K}e^{z_{j}}}} σ(z)i=j=1Kezjezi, e 0 e^0 e0是1, 是有值的, 这样的话 s o f t m a x softmax softmax中被 p a d d i n g padding padding的部分就参与了运算, 就等于是让无效的部分参与了运算, 会产生很大隐患, 这时就需要做一个 m a s k mask mask让这些无效区域不参与运算, 我们一般给无效区域加一个很大的负数的偏置, 也就是:
z i l l e g a l = z i l l e g a l + b i a s i l l e g a l z_{illegal} = z_{illegal} + bias_{illegal} zillegal=zillegal+biasillegal
b i a s i l l e g a l → − ∞ bias_{illegal} \to -\infty biasillegal
e z i l l e g a l → 0 e^{z_{illegal}} \to 0 ezillegal0
经过上式的 m a s k i n g masking masking我们使无效区域经过 s o f t m a x softmax softmax计算之后还几乎为 0 0 0, 这样就避免了无效区域参与计算.

2.3 残差连接和

1). 残差连接:
我们在上一步得到了经过注意力矩阵加权之后的 V V V, 也就是 A t t e n t i o n ( Q ,   K ,   V ) Attention(Q, \ K, \ V) Attention(Q, K, V), 我们对它进行一下转置, 使其和 X e m b e d d i n g X_{embedding} Xembedding的维度一致, 也就是 [ b a t c h   s i z e ,   s e q u e n c e   l e n g t h ,   e m b e d d i n g   d i m e n s i o n ] [batch \ size, \ sequence \ length, \ embedding \ dimension] [batch size, sequence length, embedding dimension], 然后把他们加起来做残差连接, 直接进行元素相加, 因为他们的维度一致:
X e m b e d d i n g + A t t e n t i o n ( Q ,   K ,   V ) X_{embedding} + Attention(Q, \ K, \ V) Xembedding+Attention(Q, K, V)
在之后的运算里, 每经过一个模块的运算, 都要把运算之前的值和运算之后的值相加, 从而得到残差连接, 训练的时候可以使梯度直接走捷径反传到最初始层:
X + S u b L a y e r ( X ) (eq. 5) X + SubLayer(X) \tag{eq. 5} X+SubLayer(X)(eq. 5)

2). LayerNorm:
L a y e r N o r m a l i z a t i o n Layer Normalization LayerNormalization的作用是把神经网络中隐藏层归一为标准正态分布, 也就是 i . i . d i.i.d i.i.d独立同分布, 以起到加快训练速度, 加速收敛的作用:
μ i = 1 m ∑ i = 1 m x i j \mu_{i}=\frac{1}{m} \sum^{m}_{i=1}x_{ij} μi=m1i=1mxij
上式中以矩阵的行 ( r o w ) (row) (row)为单位求均值;
σ j 2 = 1 m ∑ i = 1 m ( x i j − μ j ) 2 \sigma^{2}_{j}=\frac{1}{m} \sum^{m}_{i=1} (x_{ij}-\mu_{j})^{2} σj2=m1i=1m(xijμj)2
上式中以矩阵的行 ( r o w ) (row) (row)为单位求方差;
L a y e r N o r m ( x ) = α ⊙ x i j − μ i σ i 2 + ϵ + β (eq.6) LayerNorm(x)=\alpha \odot \frac{x_{ij}-\mu_{i}} {\sqrt{\sigma^{2}_{i}+\epsilon}} + \beta \tag{eq.6} LayerNorm(x)=ασi2+ϵ xijμi+β(eq.6)
然后用每一行每一个元素减去这行的均值, 再除以这行的标准差, 从而得到归一化后的数值, ϵ \epsilon ϵ是为了防止除 0 0 0;
之后引入两个可训练参数 α ,   β \alpha, \ \beta α, β来弥补归一化的过程中损失掉的信息, 注意 ⊙ \odot 表示元素相乘而不是点积, 我们一般初始化 α \alpha α为全 1 1 1, 而 β \beta β为全 0 0 0.

2.4 整体结构

经过上面3个步骤, 我们已经基本了解到来 t r a n s f o r m e r transformer transformer编码器的主要构成部分, 我们下面用公式把一个 t r a n s f o r m e r   b l o c k transformer \ block transformer block的计算过程整理一下:

1). 字向量与位置编码:
X = E m b e d d i n g L o o k u p ( X ) + P o s i t i o n a l E n c o d i n g (eq.2) X = EmbeddingLookup(X) + PositionalEncoding \tag{eq.2} X=EmbeddingLookup(X)+PositionalEncoding(eq.2)
X ∈ R b a t c h   s i z e   ∗   s e q .   l e n .   ∗   e m b e d .   d i m . X \in \mathbb{R}^{batch \ size \ * \ seq. \ len. \ * \ embed. \ dim.} XRbatch size  seq. len.  embed. dim.

2). 自注意力机制:
Q = L i n e a r ( X ) = X W Q Q = Linear(X) = XW_{Q} Q=Linear(X)=XWQ
K = L i n e a r ( X ) = X W K (eq.3) K = Linear(X) = XW_{K} \tag{eq.3} K=Linear(X)=XWK(eq.3)
V = L i n e a r ( X ) = X W V V = Linear(X) = XW_{V} V=Linear(X)=XWV
X a t t e n t i o n = S e l f A t t e n t i o n ( Q ,   K ,   V ) (eq.4) X_{attention} = SelfAttention(Q, \ K, \ V) \tag{eq.4} Xattention=SelfAttention(Q, K, V)(eq.4)

3). 残差连接与 L a y e r   N o r m a l i z a t i o n Layer \ Normalization Layer Normalization
X a t t e n t i o n = X + X a t t e n t i o n (eq. 5) X_{attention} = X + X_{attention} \tag{eq. 5} Xattention=X+Xattention(eq. 5)
X a t t e n t i o n = L a y e r N o r m ( X a t t e n t i o n ) (eq. 6) X_{attention} = LayerNorm(X_{attention}) \tag{eq. 6} Xattention=LayerNorm(Xattention)(eq. 6)

4). 下面进行 t r a n s f o r m e r   b l o c k transformer \ block transformer block结构图中的第4部分, 也就是 F e e d F o r w a r d FeedForward FeedForward, 其实就是两层线性映射并用激活函数激活, 比如说 R e L U ReLU ReLU:
X h i d d e n = A c t i v a t e ( L i n e a r ( L i n e a r ( X a t t e n t i o n ) ) ) (eq. 7) X_{hidden} = Activate(Linear(Linear(X_{attention}))) \tag{eq. 7} Xhidden=Activate(Linear(Linear(Xattention)))(eq. 7)

5). 重复3).:
X h i d d e n = X a t t e n t i o n + X h i d d e n X_{hidden} = X_{attention} + X_{hidden} Xhidden=Xattention+Xhidden
X h i d d e n = L a y e r N o r m ( X h i d d e n ) X_{hidden} = LayerNorm(X_{hidden}) Xhidden=LayerNorm(Xhidden)
X h i d d e n ∈ R b a t c h   s i z e   ∗   s e q .   l e n .   ∗   e m b e d .   d i m . X_{hidden} \in \mathbb{R}^{batch \ size \ * \ seq. \ len. \ * \ embed. \ dim.} XhiddenRbatch size  seq. len.  embed. dim.

小结:
我们到现在位置已经讲完了transformer的编码器的部分, 了解到了transformer是怎样获得自然语言的位置信息的, 注意力机制是怎样的, 其实举个语言情感分类的例子, 我们已经知道, 经过自注意力机制, 一句话中的每个字都含有这句话中其他所有字的信息, 那么我们可不可以添加一个空白字符到句子最前面, 然后让句子中的所有信息向这个空白字符汇总, 然后再映射成想要分的类别呢? 这就是BERT, 我们下次会讲到.

BERT的预训练中, 我们给每句话的句头加一个特殊字符, 然后句末再加一个特殊字符, 之后模型预训练完毕之后, 我们就可以用句头的特殊字符的 h i d d e n   s t a t e hidden \ state hidden state完成一些分类任务了.

你可能感兴趣的:(nlp)