自然语言处理之Transformer模型

一、Transformer原理

  • 针对Transformer进行机器翻译,编码器模块输入“Why do we work?”,需要输出“为什么工作?”:
    1)将待翻译的句子输入到编码器中,通过编码器得到隐藏层,输入到解码器;
    2)解码器初始输入“start”,结合隐藏层最先翻译得出“为”,将“为”落下来作为解码器输入继续翻译,得出“什”,以此类推,直到输出“end”表示翻译任务结束。
    在这里插入图片描述
  • transformer编码器和解码器结构基本一致,搞清楚编码器即可搞清楚解码器的结构。

1.1 编码器原理

  • 编码器结构如下图所示,分为4个部分进行讨论:
    在这里插入图片描述

1.1.1 位置嵌入或位置编码(Positional Encoding)

  • 由于transformer模型没有循环神经网络的迭代操作,所以我们必须提供每个字的位置信息给transformer,才能识别出语言中的顺序关系;
  • 位置嵌入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 max\ sequence max sequence属于超参数,指定限定的最大单个句长。一般以字为单位训练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] [vocabsize,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 m o d e l ) PE(_{pos, 2i})=sin(\frac{pos}{10000^{\frac{2i}{d_{model}}}}) PE(pos,2i)=sin(10000dmodel2ipos)
    P E ( p o s , 2 i + 1 ) = c o s ( p o s 1000 0 2 i d m o d e l ) PE(_{pos, 2i+1})=cos(\frac{pos}{10000^{\frac{2i}{d_{model}}}}) PE(pos,2i+1)=cos(10000dmodel2ipos)
    上式中, 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],针对 e m b e d d i n g   d i m e n s i o n embedding\ dimension embedding dimension中奇数位置和偶数位置的维度序号,分别采用sin和cos进行位置编码。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import math

def get_positional_encoding(max_seq_len, embed_dim):
    #初始化一个positional encoding
    #max_seq_len:最大序列长度
    #embed_dim:字嵌入维度
    positional_encoding=np.array([
        [pos/np.power(10000,2*i/embed_dim) for i in range(embed_dim)]
        if pos!=0 else np.zeros(embed_dim) for pos in range(max_seq_len)
    ])
    positional_encoding[1:,0::2]=np.sin(positional_encoding[1:,0::2])
    positional_encoding[1:,1::2]=np.cos(positional_encoding[1:,1::2])
    return positional_encoding

在这里插入图片描述

plt.figure(figsize=(8,5))
plt.plot(positional_encoding[1:,1],label='dimension 1')
plt.plot(positional_encoding[1:,2],label='dimension 2')
plt.plot(positional_encoding[1:,3],label='dimension 3')
plt.legend()
plt.xlabel('sequence length')
plt.ylabel('period of positional encoding')

在这里插入图片描述

  • 上图可知,位置嵌入 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维度上都会得到不同周期的sin和cos函数的取值组合,可以产生独一无二的纹理位置信息,模型从而学到位置之间依赖关系和自然语言的时序特征。

1.1.2 自注意力机制(self attention mechanism)

  • 对于一个句子 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],即 X ∈ R b a t c h   s i z e ∗ s e q u e n c e   l e n g t h X\in R^{batch\ size*sequence\ length} XRbatch sizesequence length,对句子中包含的文字进行词嵌入并与位置嵌入相加,得到最终 e m b e d d i n g embedding embedding的维度为 [ 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 = 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 X_{embedding}=Embedding Lookup(X)+PositionalEncoding Xembedding=EmbeddingLookup(X)+PositionalEncoding
    得到 X e m b e d d i n g ∈ R 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 X_{embedding}\in R^{batch\ size*sequence\ length*embedding\ dimension} XembeddingRbatch sizesequence lengthembedding dimension
  • 接下来为了学到多重含义的表达,对 X e m b e d d i n g X_{embedding} Xembedding做线性映射,即分配三个权重, W Q , W K , W V ∈ R e m b e d . d i m ∗ e m b e d . d i m W_Q, W_K, W_V\in R^{embed.dim*embed.dim} WQ,WK,WVRembed.dimembed.dim,线性映射之后行程三个矩阵 Q , K , V Q, K, V Q,K,V,和线性变换之前 X e m b e d d i n g X_{embedding} Xembedding的维度一致。
    Q = L i n e a r ( X e m b e d d i n g ) = X e m b e d d i n g W Q Q=Linear(X_{embedding})=X_{embedding}W_Q Q=Linear(Xembedding)=XembeddingWQ
    K = L i n e a r ( X e m b e d d i n g ) = X e m b e d d i n g W K K=Linear(X_{embedding})=X_{embedding}W_K K=Linear(Xembedding)=XembeddingWK
    V = L i n e a r ( X e m b e d d i n g ) = X e m b e d d i n g W V V=Linear(X_{embedding})=X_{embedding}W_V V=Linear(Xembedding)=XembeddingWV
#矩阵相乘
X: [batch_size, len, embedding_size]
W: [embedding_size, hidden_dimension]
XW = [batch_size, len, hidden_dimension]

在这里插入图片描述

  • 下面准备进行多头注意力机制(将矩阵分割成多个head),即Multi head attention,引入超参数head的数量 n u m   o f   h e a d s num\ of\ heads num of heads,即参数 h h h注意embedding dimension必须整除h,因为我们要把embedding dimension分割成h份。分割之后 Q , K , V Q, K, V Q,K,V的维度变为 [ b a t c h   s i z e , s e q u e n c e   l e n g t h , h , e m b e d d i n g   d i m e n s i o n / h ] [batch\ size, sequence\ length, h, embedding\ dimension/h] [batch size,sequence length,h,embedding dimension/h],之后我们把 Q , K , V Q, K, V Q,K,V s e q u e n c e   l e n g t h sequence\ length sequence length h h h进行转置,转置后的 Q , K , V Q, K, V Q,K,V的维度变为 [ b a t c h   s i z e , h , 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 / h ] [batch\ size, h, sequence\ length, embedding\ dimension/h] [batch size,h,sequence length,embedding dimension/h]
  • 拿出其中一个head进行演示, Q Q Q的一个head点乘 K K K的一个head的转置,得到 c 1 c 1 c1c1 c1c1表示句子中第一个字和第一个字的注意力,以此类推。结果矩阵的第一行表示句子中第一个字与句子中其他的字之间的相关程度;第二行表示句子中第二个字与句子中其他的字之间的相关程度。对角线表示字本身之间的相关程度。对求出的矩阵中每一行进行归一化,采用softmax进行归一化,即每个字与句子中的其他字的相关性的和为1。
    在这里插入图片描述
  • 向量点积的含义是向量越相似点积越大。 同理,如果2个字的意思比较相近,那么对应的字向量的点积就会越大;如果意思不相关,点积越小。
    在这里插入图片描述
  • 注意力矩阵计算如下图所示:
    在这里插入图片描述
    A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q, K, V)=softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dk QKT)V
  • 上式中就是注意力机制,我们先求出 Q K T QK^T QKT。也就是求出注意力矩阵,然后用注意力矩阵给 V V V加权, d k \sqrt{d_k} dk 是为了把注意力矩阵变为标准正态分布,使得 s o f t m a x softmax softmax归一化后的结果更加稳定,以便反向传播时候获取平衡的梯度。最后得到的注意力矩阵尺寸为 [ b a t c h   s i z e , h , 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 / h ] [batch\ size, h, sequence\ length, embedding\ dimension/h] [batch size,h,sequence length,embedding dimension/h]
  • 一个小trick:Attention Mask:
  • 在上面self attention计算过程中,我们通常使用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中最大的句长对剩余的句子进行 p a d d i n g padding padding,一般采用0填充。
  • 这是在进行 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 , e 0 = 1 \sigma(z_i)=\frac{e^{z_i}}{\sum_{j=1}^K e^{z_j}}, e^0=1 σ(zi)=j=1Kezjezi,e0=1

在这里插入图片描述

  • 这样 s o f t m a x softmax softmax中被padding的部分就参与了运算,就等于是让无效的部分参与了运算,为了不让无效的区域参与运算,我们一般给无效的padding区域添加一个负数的偏置,即:
    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 , b i a s i l l e g a l ⇒ − ∞ z_{illegal}=z_{illegal}+bias_{illegal},bias_{illegal}\Rightarrow -\infty zillegal=zillegal+biasillegalbiasillegal
    这样的话在进行 s o f t m a x softmax softmax之前无效区域取值为0,在进行 s o f t m a x softmax softmax之后无效区域取值为0 e z i l l e g a l = 0 e^{z_{illegal}}=0 ezillegal=0,从而避免了无效的区域参与计算。

1.1.3 Add&Norm

  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 ) X+SubLayer(X) X+SubLayer(X)
  2. Layer Norm:
    Layer Normalization的作用是把神经网络中隐藏层其中的一行归一化为标准正态分布,以加快训练速度,加快收敛的作用,以矩阵的行(row)为单位求均值:
    μ i = 1 m ∑ i = 1 m x i j \mu_i=\frac{1}{m}\sum_{i=1}^m x_{ij} μi=m1i=1mxij
    以矩阵的行(row)求方差:
    σ i 2 = 1 m ∑ j = 1 m ( x i j − μ i ) 2 \sigma_i^2=\frac{1}{m}\sum_{j=1}^m (x_{ij}-\mu_i)^2 σi2=m1j=1m(xijμi)2
    然后用每一行的每一个元素减去这行的均值,再除以这行的标准差,从而得到归一化后的数值,式中 ϵ \epsilon ϵ是为了防止分母为0。
    L a y e r N o r m a l ( x ) = α ⋅ x i j − μ i σ i 2 + ϵ + β LayerNormal(x)=\alpha\cdot\frac{x_{ij}- \mu_i}{\sqrt{\sigma_i^2+\epsilon}}+\beta LayerNormal(x)=ασi2+ϵ xijμi+β
    引入 α \alpha α β \beta β两个可训练的参数来弥补归一化过程中损失的信息, ⋅ \cdot 点注意表示元素相乘,其中 α \alpha α β \beta β的维度与 x x x的维度一致。

1.1.4 Feed Forward基于位置的前馈网络-全连接

  • 将输入形状由 ( b , n , d ) (b, n, d) (b,n,d)变换成 ( b n , d ) (bn, d) (bn,d) ,作用两个全连接层,输出形状由 ( b n , d ) (bn, d) (bn,d)变换成 ( b , n , d ) (b, n, d) (b,n,d),等价于两层核窗口为1的一维卷积层。

1.1.5 transformer block编码器总结

在这里插入图片描述

https://www.bilibili.com/video/BV1sE411Y7cP?spm_id_from=333.337.search-card.all.click

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值