Transformer结构是谷歌于2018年提出用于nlp的深度学习模型结构,同时成为了之后bert的基础,那么transformer到底是什么样子的,它的提出解决了什么问题,带来了什么变化,我们在下面详细解释。

Encoder-decoder结构

机器翻译遵循的模型一般是encoder-decoder结构,结构图如下所示
Alt

  • encoder是编码器,通常是RNN结构或者CNN结构(Image Captioning或者TextCNN),但是RNN或者CNN结构往往存在一些问题:
    • RNN结构由于存在前后依赖,无法进行并行计算
    • CNN难以捕捉全局信息
  • decoder是解码器,通常是RNN结构

因为以上的问题 ,Google提出使用attention结构来代替RNN和CNN的结构,这便是Transformer

    
    

Transformer结构

我们先来看Transfomer的结构图
在这里插入图片描述
如图左边部分便是transformer的encoder结构,右边便是decoder结构。突然看到这张图,可能很多人都很懵,那我们在下面的内容里面从各个子结构来详细解释这张图

    
    

Transformer的子结构

自注意力机制(Self attention)

如果你还不熟悉attention机制的话,请看这篇博文:
快速理解NLP中的Attention机制
我们现在把attention机制看作是:一个查询( Q Q Q)到一系列键值对( K → V K \to V KV)的映射,其中 Q ( q 1 , q 2 , q 3 . . . . , q n ) Q(q_1,q_2,q_3....,q_n) Q(q1,q2,q3....,qn)    Q ∈ R ( n , d k ) Q \in \mathbb R^{(n, d_k)} QR(n,dk)     K ( k 1 , k 2 , k 3 . . . . , k m ) K(k_1,k_2,k_3....,k_m) K(k1,k2,k3....,km)    K ∈ R ( m , d k ) K \in \mathbb R^{(m, d_k)} KR(m,dk)     V ( v 1 , v 2 , v 3 . . . . , v m ) V(v_1,v_2,v_3....,v_m) V(v1,v2,v3....,vm)    V ∈ R ( m , d v ) V \in \mathbb R^{(m, d_v)} VR(m,dv) _注意此处 Q , K Q,K Q,K_的向量长度是一样的。

所以attention的步骤主要包含3步:

  • Q K T QK^T QKT 这一步就是将 Q Q Q中的隐层向量和 K K K中的隐层向量相乘,得到n*m维的矩阵,表示二者的相似度
  • s o f t m a x ( Q K T ) d k \frac {softmax(QK^T)}{\sqrt {d_k}} dk softmaxQKT Q K T QK^T QKT进行softmax操作,得到n*m维的矩阵,表示输入的每个词在 q i q_i qi上的权重, d k \sqrt d_k d k是避免结果太大的scaled操作
  • 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) = \frac {softmax(QK^T)}{\sqrt {d_k}}V attention(QKV)=dk softmaxQKTV ,得到n* d v d_v dv的矩阵,其中每一列表示一个decoder的RNN单元的输入

Q = K = V Q=K=V Q=K=V时,这时的注意力机制就被称为自注意机制了,我们假设一个句子是 ( x 1 , x 2 , x 3 , … … , x t ) = Q = K = V (x_1,x_2,x_3,……,x_t)=Q=K=V (x1,x2,x3,,xt)=Q=K=V

  • x 1 x k T x_1{x_k}^T x1xkT就是 x 1 x_1 x1 x k x_k xk的点积,表示的是二者的相似程度
  • s o f t m a x ( x 1 K T ) d k \frac {softmax(x_1K^T)}{\sqrt {d_k}} dk softmaxx1KT表示 x 1 x_1 x1这个词和其他词相似度权重
  • x 1 ′ = s o f t m a x ( x 1 K T ) d k V {x_1}'=\frac {softmax(x_1K^T)}{\sqrt {d_k}}V x1=dk softmaxx1KTV表示新的 x 1 x_1 x1作为接下来的输入

采用self-attention作为神经网络的输入结构比使用RNN好在:

  • 每一层的计算复杂程度大大的降低
  • 避免了RNN前后的依赖,使得可以快速并行计算
  • 避免了太长句子的词语前后依赖给RNN带来的性能问题

Mask

实际的attention因为下面两个原因可能会遇到一些问题

  • 神经网络输入的单个样本要求是等长的
  • 为了保证句子长度一致,较短的句子我们可能采取补0的操作

补0的向量并没有实际含义,因此不能参与到attention的权重分配里面来,那我们该怎么做呢?请看下面的代码

In [2]: def softmax(x):
    ...:     x_exp = np.exp(x)
    ...:     return x_exp/np.sum(x_exp)
    ...:

In [3]: q = np.array([0.9, 0.7, 0.2])

In [4]: k = np.array([[0.2, 0.1, 0.7],[-100000,-100000,-100000]])

In [5]: softmax(np.dot(q, k.T))
Out[5]: array([1., 0.]))

明显当 k i k_i ki里面的元素都趋向于负无穷大时,第 i i i个词语的权重会接近于0
这就是mask操作,将补0的词语进行同上的处理使之无法参与attention计算
在这里插入图片描述
将Mask和注意力机制结合后的计算过程如上图所示,论文中称之为Scaled Dot-Product Attention

多头注意力(multi-head attention)

为了让模型有更多的表示子空间,transformer结构引入了multi-head attention。具体操作是在 Q , K , V Q,K,V Q,K,V进行attention操作之前,先对attention进行线性的变换

假设我们的输入是 ( Q , K , V ) (Q,K,V) (Q,K,V), 而且 Q = K = V Q=K=V Q=K=V     Q ∈ R ( m , d m o d e l ) Q \in \mathbb R^{(m,d_{model})} QR(m,dmodel)   K ∈ R ( m , d m o d e l ) K \in \mathbb R^{(m,d_{model})} KR(m,dmodel)   V ∈ R ( m , d m o d e l ) V \in \mathbb R^{(m,d_{model})} VR(m,dmodel)

首先我们先进行线性变换,假设进行attention操作的是 ( Q ∗ , K ∗ , V ∗ ) (Q^*,K^*, V^*) (QKV) 其中:

  • Q ∗ = Q W i Q Q^* = Q{W_i}^Q Q=QWiQ      W i Q ∈ R ( d m o d e l , d k ) {W_i}^Q \in \mathbb R^{(d_{model}, d_k)} WiQR(dmodel,dk)     Q ∗ ∈ R ( m , d k ) Q^* \in \mathbb R^{(m, d_k)} QR(m,dk)
  • K ∗ = K W i K K^* = K{W_i}^K K=KWiK     W i K ∈ R ( d m o d e l , d k ) {W_i}^K \in \mathbb R^{(d_{model}, d_k)} WiKR(dmodel,dk)     K ∗ ∈ R ( m , d k ) K^* \in \mathbb R^{(m, d_k)} KR(m,dk)
  • V ∗ = V W i V V^* = V{W_i}^V V=VWiV      W i V ∈ R ( d m o d e l , d v ) {W_i}^V \in \mathbb R^{(d_{model}, d_v)} WiVR(dmodel,dv)     K ∗ ∈ R ( m , d v ) K^* \in \mathbb R^{(m, d_v)} KR(m,dv)

然后, 进行 h h h次线性变换,得到 h h h个attention的结果:

  • h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) head_i = Attention(Q{W_i}^Q, K{W_i}^K, V{W_i}^V) headi=Attention(QWiQ,KWiK,VWiV)
  • h e a d i ∈ R ( m , d v ) head_i \in \mathbb R^{(m, d_v)} headiR(m,dv)

最后, 将上面的结果进行拼接,并乘 W O {W^O} WO

  • M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , h e a d 2 , . . . . . . , h e a d h ) W O MultiHead(Q,K,V) = Concat(head_1, head_2,......,head_h)W^O MultiHead(Q,K,V)=Concat(head1,head2,......,headh)WO
  • Concat后的向量的向量空间是 R ( m , h d v ) \mathbb R^{(m, hd_v)} R(m,hdv)
  • W O ∈ R ( h d v , d m o d e l ) W_O \in \mathbb R^{(hd_v, d_{model})} WOR(hdv,dmodel)

因此各位可以看到在经过Multi-head attention后,输出的维度会变回 ( m , d m o d e l ) (m, d_{model}) (m,dmodel) ,可以继续作为下一个self-attention的输入
在这里插入图片描述

位置编码(Positional Encoding)

上面的self-attention结构有一个重要的问题,那就是它忽略了词语之间的位置信息,不能体现词语的先后顺序。因此,论文引入了Positional Encoding的机制。即给每个词语一个位置向量。位置向量的计算方式如下:
在这里插入图片描述
P E ( p o s , k ) PE(pos, k) PE(pos,k)指的是第pos个词向量的第 k k k个元素的值
最后将词向量和位置向量进行拼接或者相加形成新的向量

Feed Forward

这其实就是对矩阵的每一个数字进行一个变换,可以理解为一维的卷积, x x x是矩阵中的每个数
在这里插入图片描述
    
    

Transformer详析

在这里插入图片描述
我们从encoder的左边的底部开始看

  • 接收输入后首先进行Positional Encoding,形成新的输入 I I I(即 Q , K , V Q,K,V QKV)
  • 此处有一个残差连接,将 I I I传递给Multi-Head的后面
  • Q,K,V进行多头注意力的处理,然后和之前的残差相加以及规范化
  • 上一步的结果进入feed forward层,这里也有个残差连接
  • 输出的结果继续和残差相加以及规范化得到encoder的输出

我们再来看decoder部分

  • 最低端是输入,需要提醒的是,这里的输入在训练和测试过程是不一样的,下面有详细说明
  • 接下来进入Masked Multi-Head Attention来做第一层的attention的处理,这里的masked和前面提到的mask是一样的,为了避免生成当前词时看到后面的词,具体怎么实现的,后面会有说明
  • 依然是加上残差连接传过来的值,然后作为Q进入下一层attention
  • 这一层attention接受encoder的输入作为K,V,然后进行attention(这里不是自注意),然后进行下一个Feed Forward计算
  • 继续加上残差连接,然后进入一个线性变换最后通过softmax输出当前句子各个词的概率分布

以上便是Transformer的整体结构
    
    

Transformer整体结构

真实的Transformer翻译模型的结构并非上述的一个encoder结构连接一个decoder结构,encoder和decoder都各有六个,连接方式如下图所示:
在这里插入图片描述
    
    

其他问题

transformer训练与测试过程的不同

transformer的训练和测试过程是有所不同的,体现在如下几个方面:

  • 训练是运算是并行的,而测试时运算是串行的
  • 训练时decoder的输入其实是整个groudtruth,在生成第 i i i个词时通过mask来使训练看不到 i i i之后的词;测试时这个时间步的decoder的输入是之前时间步的decoder生成的内容
  • 训练过程中,一个句子各个词的概率分布其实是通过上面的宏观结构一次生成的;在测试的时候上面的结构一次只能生成一个词的概率分布

mask的原理

mask其实让很多人难以理解,包括在attention阶段的mask以及masked multi-head attention,我接下来会写一篇新的博客详细介绍。

参考文档:attention is all you need
整体结构图片来源
其他图片来源

Logo

尧米是由西云算力与CSDN联合运营的AI算力和模型开源社区品牌,为基于DaModel智算平台的AI应用企业和泛AI开发者提供技术交流与成果转化平台。

更多推荐