Transformer

Transformer

  • 基于encoder-decoder结构实现特征提取
  • 直观认识
  • Encoder
    • 1 Positional Encoding
    • 2 Self Attention Mechanism
      • 2.1 Self Attention
      • 2.2 Multi-head self-attention
    • 3 残差连接和Layer Normalization
      • 3.1 什么是残差连接?
      • 3.2 Transformer中的残差连接
      • 3.3 Layer Normalization
      • 3.4 Transformer中的Layer Normalization
    • 4 Feed Forward Layer
    • 5 Position-wise feed-forward networks
  • Decoder
    • 1 Mask多头注意力
    • 2 多头注意力
  • Transformer整体看
  • Transformer的优缺点
  • 问题和思考
  • 我的问题

基于encoder-decoder结构实现特征提取

我们可以把原始数据喂到模型1,得到的输出记为feature1;然后把feature1喂到模型2,得到的输出记为feature2。从直觉的角度看,模型1对数据进行了一定程度的抽象,而模型2进行了更高程度的抽象。多层神经网络就是这种结构的具体实现,实践中的表现还不错。

一些人设计了这样一种2层模型:(1)各层可以是任意结构的模型;(2)原始数据、feature1、feature2的结构和含义根据场景定义。这种结构的模型被称为”encoder-decoder模型”,模型1叫做encoder,模型2叫做decoder。一般来说,encoder和decoder可以采用全连接神经网络、RNN等模型。

直观认识

Transformer与LSTM区别:
LSTM 的训练是迭代的、串行的,必须要等当前字处理完,才可以处理下一个字。
Transformer 的训练时并行的,即所有字是同时训练的,这样就大大增加了计算效率。Transformer 使用了位置嵌入来理解语言的顺序,使用自注意力机制和全连接层进行计算。

Transformer 模型主要分为两大部分,分别是 Encoder 和 Decoder。Encoder 负责把输入(语言序列)隐射成隐藏层,然后解码器再把隐藏层映射为自然语言序列。

以机器翻译为例:
Transformer_第1张图片
Encoder部分:
Transformer_第2张图片
下面的内容标题编号分别对应着图中 1,2,3,4 个方框的序号.

Encoder

将长度为N的序列的各自初始化的Embedding向量,转换成各自融合了全局语义的N个Embedding,即编码的过程。

EncoderN=6个相同的layer组成,layer指的就是上图左侧的单元,最左边有个“Nx”,这里是x6个。每个Layer由两个sub-layer组成,分别是multi-head self-attention mechanismfully connected feed-forward network。其中每个sub-layer都加了residual connectionnormalisation,因此可以将sub-layer的输出表示为:
在这里插入图片描述

1 Positional Encoding

比如:
a、难受!滑板坏了,水还洒身上了!
b、滑板坏了,难受!水还洒身上了!

位置嵌入的维度与词向量的维度是相同的,都是 embedding_dimensionmax_sequence_length属于超参数,指的是限定每个句子最长由多少个词构成.

Transformer 是以字作为输入,将字进行字嵌入之后,再与位置嵌入进行相加(不是拼接,就是单纯的对应位置上的数值进行加和).

两种不合适的方法:
(1)取 [0,1] 之间的数分配给每个字,其中 0 给第一个字,1 给最后一个字。相同的差值,在不同的句子中却不是同一个含义。
(2)线性的给每个时间步分配一个数字,也就是说,第一个单词被赋予 1,第二个单词被赋予 2,依此类推。这种方式也有很大的问题:1. 它比一般的字嵌入的数值要大,难免会抢了字嵌入的「风头」,对模型可能有一定的干扰;2. 最后一个字比第一个字大太多,和字嵌入合并后难免会出现特征在数值上的倾斜。

理想设计:

  • 它应该为每个字输出唯一的编码
  • 不同长度的句子之间,任何两个字之间的差值应该保持一致
  • 它的值应该是有界的
    在这里插入图片描述
    p o s pos pos 指的是一句话中某个字的位置,取值范围是 [0,max_sequence_length)
    i i i 指的是字向量的维度序号,取值范围是 [0,embedding_dimension / 2)
    d m o d e l d_{model} dmodel 指的是 embedding_dimension​ 的值

上述公式满足要求:
(1)它不是一个数字,而是一个包含句子中特定位置信息的 d d d 维向量
(2)这种嵌入方式没有集成到模型中,相反,这个向量是用来给句子中的每个字提供位置信息的,换句话说,我们通过注入每个字位置信息的方式,增强了模型的输入(其实说白了就是将位置嵌入和字嵌入相加,然后作为输入)

Position Encoding为何直接加到Embedding上?
答:可以从另一个视角来看这件事,相当于给每一个单词索引向量后面拼接一个one-hot位置索引向量,得到 [ x i , p i ] [x_i,p_i] [xipi] ,然后再经过Embedding矩阵W转换成每个单词相应的Embedding。根据分块矩阵,其等价于 W I ∗ x i + W p ∗ p i WI*x_i+Wp*p_i WIxi+Wppi ,而前一部分表示的就是单词的Word Embedding语义信息,后一部分表示位置信息。从而我们可以理解为什么直接相加。

2 Self Attention Mechanism

2.1 Self Attention

常规的语言生成模型:下一个字的生成,依靠且只依靠上一个字的输出状态和当前输入的输入状态,也就是说,预测值在某一程度上说只跟上一个字关系大一些。每一个字的生成,会跟所有的字(encode的时候)都有关系,这就是所谓的“注意力”机制。整个文字的生成过程中,每一个字都可能会跟所有的字做加权,为什么是“可能”呢,因为有mask嘛,随机给屏蔽掉一些词,屏蔽掉的那就没办法顾及了。这样的好处有两个:

  1. 一是能“照顾”所有的词,也就是我们理解的“语境”,

比如:
句子1:“优秀!这就很优秀了!我做梦都没想到他这么175的个子能在中场投篮投进了!”;
句子2:“优秀!这就很优秀了!他这185的个子在篮下那么好的位置还是没进球!”。

同样位置的一个词“优秀!”,一模一样的字,它的意思的完全相反的(中华文化博大精深),自注意力机制就需要在即使后面说了一堆废话的基础上,还是能学出这个词是褒义还是贬义。换句话说,它在判断优秀是褒义还是贬义时,甚至需要看到最后几个关键语气的词,才能做出判断,而这个功能正是RNN系列模型做不到的!数学意义上可以叫做“贡献度”。

  1. 这样词就能并行计算了,至少这一步是可以并行计算了!

自注意力就是大致这样个流程,多头又是什么鬼!很简单,经过嵌入层后,每个词有多个维度(代码嵌入为768列),把这些维度均分成n_head(12)份,每一份都去做这么一件事,就是多头机制。简而言之,就是自注意力的模式,复制了几次,这个“几次”就是“多头”,12次就是12头。。。只不过,不是做复制,而是做拆分,均分成12次来进行注意力的计算。
在这里插入图片描述
对于self-attention来讲, Q ( Q u e r y ) , K ( K e y ) , V ( V a l u e ) Q(Query), K(Key), V(Value) Q(Query),K(Key),V(Value)三个矩阵均来自同一输入,首先我们要计算Q与K之间的点乘,然后为了防止其结果过大,会除以一个尺度标度 d k \sqrt{\smash[b]{d_k}} dk ,其中 d k d_k dk 为一个query和key向量的维度。再利用Softmax操作将其结果归一化为概率分布,然后再乘以矩阵V就得到权重求和的表示。该操作可以表示为 :
Transformer_第3张图片
注意: d k d_k dk是key的维数
★ \bigstar 首先,Q 与 K 进行了一个点积操作,这个其实就是我在Attention讲到的 score 操作
★ \bigstar 然后,Scale 操作,其实就是为了防止结果过大,除以一个尺度标度 d k \sqrt{\smash[b]{d_k}} dk , 其中 d k d_k dk 是 Q 中一个向量的维度;
★ \bigstar 再然后,Mask操作; Mask操作是将需要隐藏的数据设置为负无穷,这样经过后面的 Softmax 后就接近于 0,这样这些数据就不会对后续结果产生影响了。
★ \bigstar 最后经过一个 Softmax 层, 然后计算 Attention Value。softmax函数的性质。给定一组数组成的向量,softmax先将这组数的差距拉大(由于exp函数),然后归一化。它实质做的是一个soft版本的arg max操作,得到的向量接近一个one-hot向量(接近程度根据这组数的数量级有所不同)。

self-attention公式中的归一化有什么作用?
首先说明做归一化的原因,随着​ d k d_k dk 的增大, q . k q.k q.k ​点积后的结果也随之增大,这样会将softmax函数推入梯度非常小的区域,使得收敛困难(可能出现梯度消失的情况)(为了说明点积变大的原因,假设 q q q ​和​ k k k 的分量是具有均值0和方差1的独立随机变量,那么它们的点积 q . k = ∑ i = 1 d k q i k i q.k=\sum^{d_k}_{i=1} q_{i}k_{i} q.k=i=1dkqiki ​均值为0,方差为 d k d_k dk ​),因此为了抵消这种影响,我们将点积缩放​ 1 d k \frac{1}{\sqrt{d_k}} dk 1
Transformer_第4张图片
两个向量越相似, 他们的点积就越大,反之就越小(因为向量a点乘向量b等与||a|| ||b| |cosθ, 越相似,θ越小,点积就会越大)。

另一种复杂度相似但计算方法additive attention,在 d k d_k dk 很小的时候和dot-product结果相似, d k d_k dk大的时候,如果不进行缩放则表现更好,但dot-product的计算速度更快,进行缩放后可减少影响.

使用Self-Attention 有几个好处:

  1. 每一层的复杂度小 如果输入序列 n 小于表示维度 d 的话,Self-Attention 的每一层时间复杂度有优势。当 n 比较大时,作者也给出了解决方案,Self-Attention 中每个词不是和所有词计算 Attention,而是只与限制的 r 个词进行 Attention 计算。
  2. 并行 Multi-Head Attention 和 CNN 一样不依赖前一时刻的计算,可以很好的并行,优于 RNN。
  3. 长距离依赖 优于 Self-Attention 是每个词和所有词计算 Attention,所以不管他们中间有多长距离,最大路径长度都只是1,可以捕获长距离依赖关系。

Transformer中为什么使用Self Attention?
self-attention,也叫 intra-attention,是一种通过自身和自身相关联的attention机制,从而得到一个更好的 representation 来表达自身,self-attention可以看成一般attention的一种特殊情况。在self-attention中, Q = K = V Q=K=V Q=K=V ​,序列中的每个单词(token)和该序列中其余单词(token)进行attention计算。self-attention的特点在于无视词(token)之间的距离直接计算依赖关系,从而能够学习到序列的内部结构,实现起来也比较简单。

2.2 Multi-head self-attention

Query,Key,Value首先进过一个线性变换,然后输入到放缩点积attention,注意这里要做h次,其实也就是所谓的多头,每一次算一个头。而且每次Q,K,V进行线性变换的参数W是不一样的。然后将h次的放缩点积attention结果进行拼接,再进行一次线性变换得到的值作为多头attention的结果。

原文中使用了 8 个 scaled dot-product attention ,在同一 multi-head attention 层中,输入均为 KQV ,同时进行注意力的计算,彼此之前参数不共享,最终将结果拼接起来,这样可以允许模型在不同的表示子空间里学习到相关的信息

简而言之,就是希望每个注意力头,只关注最终输出序列中一个子空间,互相独立。其核心思想在于,抽取到更加丰富的特征信息
Transformer_第5张图片
单头attention 的 Q/K/V 的shape和多头attention 的每个头的Qi/Ki/Vi的大小是不一样的,假如单头attention 的 Q/K/V的参数矩阵WQ/WK/WV的shape分别是512, 512,那么多头attention (假设8个头)的每个头的Qi/Ki/Vi的参数矩阵WQi/WKi/WVi大小是[512, 512/8].

多头注意力这一步骤的作用:
类比于CNN中使用多个滤波器的作用。
直观上讲,多头的注意力将模型分为多个头,形成多个子空间,可以让模型去关注不同方面的信息,最后再将各个方面的信息综合起来。有助于网络捕捉到更丰富的特征/信息,综合利用各方面的信息/特征。(head不要过多,适量就好)
Multi-Head其实不是必须的,去掉一些头效果依然有不错的效果(而且效果下降可能是因为参数量下降),这是因为在头足够的情况下,这些头已经能够有关注位置信息、关注语法信息、关注罕见词的能力了,再多一些头,无非是一种enhance或noise而已。

举一个不一定妥帖的例子:当你浏览网页的时候,你可能在颜色方面更加关注深色的文字**,而在字体**方面会去注意大的、粗体的文字。这里的颜色和字体就是两个不同的表示子空间。同时关注颜色和字体,可以有效定位到网页中强调的内容。

只有在Decoder中的Muti-head中才有 Mask 操作,而在Encoder中却没有,这是因为我们在预测第t个词时,需要将 t 时刻及以后的词遮住,只对前面的词进行 self-attention

3 残差连接和Layer Normalization

3.1 什么是残差连接?

神经网络越深越好吗?
理论上,在训练集上,深层网络不会比浅层网络差。但是为什么出现下面这种情况呢?随着层数增加,训练集上效果反而变差,这被称为退化问题。原因是随着网络越来越深,训练和优化变得越来越难,过深的网络会产生退化问题,效果反而不如相对较浅的网络。而残差网络可以解决这个问题,残差网络越深,训练集上效果越好

残差网络通过加入 shortcut connections,变得更加容易被优化。包含一个 shortcut connection 的几层网络被称为一个残差块(residual block)。残差块分成两部分直接映射部分和残差部分。

残差网络由残差块组成,一个残差块可以表示为:
在这里插入图片描述
Transformer_第6张图片
残差网络有什么好处呢?显而易见:因为增加了 x 项,那么该网络求 x 的偏导的时候,多了一项常数 1,所以反向传播过程,梯度连乘,也不会造成梯度消失。

3.2 Transformer中的残差连接

首先,Encoder 与Decoder中都有着很明显的残差连接,这种残差结构能够很好的消除层数加深所带来的信息损失问题。主要有两点,一是解决梯度消失的问题,二是解决权重矩阵的退化问题。

由于多层迭代结构会带来梯度消失或爆炸,深层网络的训练是比较困难的。为此,Transformer采用了残差连接。

通过将一部分的前一层的信息无差的传递到下一层,可以有效的提升模型性能——因为对于有些层,我们并不确定其效果是不是正向的。加了残差连接之后,我们相当于将上一层的信息兵分两路,一部分通过我们的层进行变换,另一部分直接传入下一层,再将这两部分的结果进行相加作为下一层的输出。这样的话,其实可以达到这样的效果:我们通过残差连接之后,就算再不济也至少可以保留上一层的信息,这是一个非常巧妙的思路。
在这里插入图片描述

3.3 Layer Normalization

Normalization 有很多种,但是它们都有一个共同的目的,那就是把输入转化成均值为 0 方差为 1 的数据。我们在把数据送入激活函数之前进行 Normalization(归一化),因为我们不希望输入数据落在激活函数的饱和区。

随着训练的进行,网络中的参数也随着梯度下降在不停更新。

  • 一方面,当底层网络中参数发生微弱变化时,由于每一层中的线性变换与非线性激活映射,这些微弱变化随着网络层数的加深而被放大(类似蝴蝶效应)。
  • 另一方面,参数的变化导致每一层的输入分布会发生改变,进而上层的网络需要不停地去适应这些分布变化,使得我们的模型训练变得困难。上述这一现象叫做 Internal Covariate Shift。

BN 的作者给 Internal Covariate Shift 的定义为:在深层网络训练过程中,由于网络中参数变化而引起内部节点数据分布发生变化的这一过程被称作 Internal Covariate Shift。

BN 就是为了解决这一问题,一方面可以简化计算过程,一方面经过规范化处理后让数据尽可能保留原始表达能力。

BN 的主要思想是:在每一层的每一批数据上进行归一化。
Transformer_第7张图片
以上便是Batch Normalization。

那么什么是 Layer Normalization 呢?它也是归一化数据的一种方式,不过 LN 是在每一个样本上计算均值和方差,而不是 BN 那种在批方向计算均值和方差!
Transformer_第8张图片

3.4 Transformer中的Layer Normalization

其次,有一个Layer Normalization过程,通过对层的激活值的归一化 ( μ = 0 , σ = 1 ) (μ=0,σ=1) (μ=0σ=1),可以加速模型的训练过程,使其更快的收敛,这在神经网络中其实也是很常见的手段,也是很经典的一篇文章。
LayerNormlization的作用是把神经网络中隐藏层归一化为标准正态分布,起到加快训练速度,加速收敛的作用。类似于BatchNormlization,但是与BatchNormlization不同的是前者是以行为单位(每一行减去每一行的均值然后除以每一行的标准差),后者是一个Batch为单位(每一个元素减去Batch的均值然后除以Batch的标准差)。

规范化层的作用:
它是所有深层网络模型都需要的标准网络层,因为随着网络层数的增加,通过多层的计算后输出可能开始出现过大或过小的情况,这样可能会导致学习过程出现异常,模型可能收敛非常慢。因此都会在一定层后接规范化层进行数值的规范化,使其特征数值在合理范围内

4 Feed Forward Layer

然后,数据经过了一个前馈神经网络, 该前馈神经网络采用了两个线性变换,激活函数为Relu,公式如下:
在这里插入图片描述
FeedFarword包含两层全连接。更具体地:全连接1 -> Relu -> dropout -> 全连接2

Feed Forward Layer 其实就是简单的由两个前向全连接层组成,核心在于,Attention模块每个时间步的输出都整合了所有时间步的信息,而Feed Forward Layer每个时间步只是对自己的特征的一个进一步整合,与其他时间步无关。

实现线性变换和 Relu 激活函数。
需要注意的是,多头注意力模块输出的是全部输入序列的编码——对全连接层来说,这个序列的元素是独立的,因此这里可以用并行计算的方式提升模型的运行速度。

作用:
考虑注意力机制可能对复杂过程的拟合程度不够, 通过增加两层网络来增强模型的能力.

5 Position-wise feed-forward networks

要是提供非线性变换。Attention输出的维度是 [bsz * seq_len, num_heads * head_size] ,第二个sub-layer是个全连接层,之所以是position-wise是因为过线性层时每个位置 i 的变换参数是一样的。
Transformer_第9张图片
所有的参数,都跟序列的长度n没有任何关系,只要模型参数学好了,我们改变序列长度n也照样可以跑通。
Transformer_第10张图片
从输入开始,再从头理一遍单个encoder这个过程:

  1. 输入xx
  2. 做一个层归一化: x1 = norm(x)
  3. 进入多头self-attention: x2 = self_attention(x1)
  4. 残差加成:x3 = x + x2
  5. 再做个层归一化:x4 = norm(x3)
  6. 经过前馈网络: x5 = feed_forward(x4)
  7. 残差加成: x6 = x3 + x5输出x6

Decoder

Transformer_第11张图片 Transformer_第12张图片

decoder的输入输出和解码过程:
输出:对应i位置的输出词的概率分布
输入:encoder的输出 & 对应i-1位置decoder的输出。所以中间的attention不是self-attention,它的K,V来自encoderQ来自上一位置decoder的输出
解码:这里要注意一下,训练和预测是不一样的。在训练时,解码是一次全部decode出来,用上一步的ground truth来预测(mask矩阵也会改动,让解码时看不到未来的token);而预测时,因为没有ground truth了,需要一个个预测。

Transformer的encoder在处理序列数据时,主要依靠注意力机制来捕捉数据中的时空关联信息。Decoder则在encoder的基础上增加了时间循环机制,获得了更强的序列数据建模能力

1 Mask多头注意力

Mask机制有两种,一种叫padding mask,作用是使每一批次的句子长度一致。Padding mask在所有的self-attention中都会用到,不管是Encoder还是Decoder中。另一种叫sequence mask,是Decoder的self-attention中特有的mask。

传统的Seq2Seq模型使用的多时RNN,RNN的特点是输入数据是单个的,且按照时序的,单词是逐个被解码出来的,在t时刻,我们只能拥有t时刻之前的信息,无论怎样也获取不到来自未来时刻的信息。而Transformer中使用Attention替换RNN,模型训练的时候,直接把ground truth整个序列作为decoder端的输入,在Decoder输入数据时,输入的是一整句,这其中包含了等待被预测的后续的序列信息,因此需要将注意力矩阵中主对角线以上的元素进行Mask。

padding mask 在所有的 scaled dot-product attention 里面都需要用到,而 sequence mask 只有在 decoder 的 self-attention 里面用到。

Padding Mask
对输入序列进行对齐。把补齐位置的值加上一个非常大的负数(负无穷)

Sequence mask
使得 decoder 不能看见未来的信息。确保了对位置i的预测只依赖于小于i位置的已知输出。
具体做法:产生一个上三角矩阵,上三角的值全为0,把这个矩阵作用在每一个序列上。

  • 对于 decoder 的 self-attention,里面使用到的 scaled dot-product attention,同时需要padding mask 和 sequence mask 作为attn_mask,具体实现就是两个mask相加作为attn_mask。
  • 其他情况,attn_mask 一律等于 padding mask。

Transformer_第13张图片
绿色部分和棕色部分结构基本相同——区别是,负责处理历史输出的绿色部分,为了避免模型在训练阶段把“未知”信息作为输入,添加了一个屏蔽模块。可以把绿色部分叫做历史信息处理模块;棕色部分叫做语义向量处理模块。当解码器运行到第i时间步时,第i个输出以及之后的输出还没有计算出来,因此不能作为历史信息处理模块的输入(否则会发生数据泄露)。在训练阶段,我们会将i时间步及以后的输出全部置零——看起来像“盖住”了这部分信息一样,因此这个操作被称为“maksed”。换句话说,当编码器运行到第i个时间步时,历史信息处理模块的输入是时间步i之前的输出序列

接下来,把编码器的输出和历史信息处理模块的输出拼接起来,喂到与编码器同结构的下游模块中;最后,结果线性变换和softmax的就是英文单词的概率分布

输入:上一时间步的输出Embedding。

输出:经过Masked自注意力机制后的Embedding(已经融合了前几个时间步的预测内容),其含义表示当前需要翻译的内容。

2 多头注意力

将Masked注意力产生的向量作为Query,和已经编码好的特征向量(Encoder的输出)作为K和V,计算注意力,从而得到当前需要翻译的内容和特征向量的对应关系,从而表示出当前时间步的状态。该部分的attention就是seq2seq框架中一般的attention过程。
Transformer_第14张图片
这个模块就跟seq2seq with attention中的机制一样,目的就在于让Decoder端的单词(token)给予Encoder端对应的单词(token)“更多的关注(attention weight)

Transformer整体看

Tansformer可以被看做是基于RNN的encoder-decoder的升级版:它把RNN的神经元替换为带有更多先验知识的注意力机制模块。另外,transformer还有几个特殊的地方:(1)Vaswani设计了位置编码机制,以让注意力机制具有快速刻画“顺序”的能力;(2)为了避免训练过程中发生数据泄露,transformer为decoder配置了mask,以屏蔽“未来的数据”;(3)transformer采用了残差连接,可以支撑深度模型的有效训练,进而提升了模型能力的上限;(4)多头注意力等部分可以并行计算,速度较快。

从整体上来讲,Transformer实现的是:通过叠加注意力网络和全连接层,得到了一个优化的特征向量,该特征向量:

  1. 关注到了序列中每一部分与其它部分的关联。
  2. 关注到了序列中每一部分与已经输出的部分结果直接的关联。
  3. 网络中的Feed Forward层实现了非线性和深度的叠加,使该结构没有丢失传统深度网络的优势。
  4. 残差连接引入(在E-D层的注意力网络上),使输入到全连接层的向量包括了Inputs和Outputs(done)的信息。

最后通过这个特征向量,经过一个线性变换层和softmax层,输出结果。

(0)输入嵌入
Transformer_第15张图片
“我为什么吃饭”
数据维度是[_, _, _],_ 的大小由 Word2Vec 算法决定,Tranformer 采用 512 长度的字向量。所以 X embedding  X_{\text {embedding }} Xembedding 的维度是 [1, 7, 512]

(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 X=Embedding.Lookup(X)+Positional.Encoding X=Embedding.Lookup(X)+Positional.Encoding

(2)自注意力机制
Q = L i n e a r q ( X ) = X W Q Q=Linear_q(X)=XW_Q Q=Linearq(X)=XWQ
K = L i n e a r k ( X ) = X W K K=Linear_k(X)=XW_K K=Lineark(X)=XWK
V = L i n e a r v ( X ) = X W V V=Linear_v(X)=XW_V V=Linearv(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 ) X_{attention}=Self.Attention(Q,K,V) Xattention=Self.Attention(Q,K,V)

(3)self-attention 残差连接与 Layer Normalization
X a t t e n t i o n = X + X a t t e n t i o n X_{attention}=X+X_{attention} Xattention=X+Xattention
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 ) X_{attention}=LayerNorm(X_{attention}) Xattention=LayerNorm(Xattention)

(4) FeedForward,是两层线性映射并用激活函数激活,比如说 R e L U ReLU ReLU
X h i d d e n = L i n e a r ( R e L U ( L i n e a r ( X a t t e n t i o n ) ) ) X_{hidden}=Linear(ReLU(Linear(X_{attention}))) Xhidden=Linear(ReLU(Linear(Xattention)))

(5)FeedForward 残差连接与 Layer Normalization
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)

Transformer的优缺点

优点:

  1. self-attention模型更可解释,attention结果的分布表明了该模型学习到了一些语法和语义信息
  2. 可以直接计算每个词之间的相关性,不需要通过隐藏层传递
  3. 可以并行计算,可以充分利用GPU资源
    缺点:
  4. 实践上:有些 RNN 轻易可以解决的问题 transformer 没做到,比如复制string,或者推理时碰到的sequence长度比训练时更长(因为碰到了没见过的position embedding)
  5. 局部信息的获取不如RNN和CNN强
  6. 位置信息编码存在问题:在使用词向量的过程中,会做如下假设:对词向量做线性变换,其语义可以在很大程度上得以保留,也就是说词向量保存了词语的语言学信息(词性、语义)。然而,位置编码在语义空间中并不具有这种可变换性,它相当于人为设计的一种索引。那么,将这种位置编码与词向量相加,就是不合理的,所以不能很好地表征位置信息。
  7. 顶层梯度消失:Transformer 模型实际上是由一些残差模块与层归一化模块组合而成。目前最常见的 Transformer 模型都使用了LN,即层归一化模块位于两个残差模块之间。因此,最终的输出层与之前的 Transformer 层都没有直连通路,梯度流会被层归一化模块阻断。

问题和思考

1. transformer是如何处理可变长度数据的?
对不等长的数据,按照最长或者固定长度进行补齐,利用padding mask机制,补齐的数据并不参与训练;和 RNN 的mask机制一样。RNN是通过time step 方式处理的,transformer通过计算attention得分矩阵处理的。

2. Transformer为什么Q和K使用不同的权重矩阵生成,为何不能使用同一个值进行自身的点乘?
使用Q/K/V不相同可以保证在不同空间进行投影,增强了表达能力,提高了泛化能力。如果K和Q使用不同的值的话, A对B的重要程度是Key(A) * Query(B), 而B对A的重要程度是Key(B) * Query(A)。 可以看出, A对B的重要程度与B对A的重要程度是不同的。 然而, 如果K和Q是一样的, 那么A对B的重要程度和B对A的重要程度是一样的。

3.Transformer计算attention的时候为何选择点乘而不是加法?两者计算复杂度和效果上有什么区别?
为了计算更快。矩阵加法在加法这一块的计算量确实简单,但是作为一个整体计算attention的时候相当于一个隐层,整体计算量和点积相似。在效果上来说,从实验分析,两者的效果和dk相关,dk越大,加法的效果越显著。

4.为什么在进行softmax之前需要对attention进行scaled(为什么除以dk的平方根),并使用公式推导进行讲解。
在输入数量较大时,softmax将几乎全部的概率分布都分配给了最大值对应的标签。也就是说极大的点积值将整个 softmax 推向梯度平缓区,使得收敛困难,梯度消失为0,造成参数更新困难。

5.在计算attention score的时候如何对padding做mask操作?
这里是因为padding 都是0,e0=1, 但是softmax的函数,也会导致为padding的值占全局一定概率,mask就是让这部分值取无穷小,让他再softmax之后基本也为0,不去影响非attention socore的分布

6.Transformer在哪里做了权重共享,为什么可以做权重共享?好处是什么?
Transformer在两个地方进行了权重共享:
(1)Encoder和Decoder间的Embedding层权重共享;
(2)Decoder中Embedding层和FC层权重共享。

对于(1),《Attention is all you need》中Transformer被应用在机器翻译任务中,源语言和目标语言是不一样的,但它们可以共用一张大词表,对于两种语言中共同出现的词(比如:数字,标点等等)可以得到更好的表示,而且对于Encoder和Decoder,嵌入时都只有对应语言的embedding会被激活,因此是可以共用一张词表做权重共享的。
对于(2),Embedding层可以说是通过onehot去取到对应的embedding向量,FC层可以说是相反的,通过向量(定义为 x)去得到它可能是某个词的softmax概率,取概率最大(贪婪情况下)的作为预测值。

那哪一个会是概率最大的呢?在FC层的每一行量级相同的前提下,理论上和 x 相同的那一行对应的点积和softmax概率会是最大的(可类比本文问题1)。

因此,Embedding层和FC层权重共享,Embedding层中和向量 x 最接近的那一行对应的词,会获得更大的预测概率。实际上,Decoder中的Embedding层和FC层有点像互为逆过程。

通过这样的权重共享可以减少参数的数量,加快收敛。

7.不考虑多头的原因,self-attention中词向量不乘QKV参数矩阵,会有什么问题?
Self-Attention的核心是用文本中的其它词来增强目标词的语义表示,从而更好的利用上下文的信息。

self-attention中,sequence中的每个词都会和sequence中的每个词做点积去计算相似度,也包括这个词本身。

对于 self-attention,一般会说它的 q=k=v,这里的相等实际上是指它们来自同一个基础向量,而在实际计算时,它们是不一样的,因为这三者都是乘了QKV参数矩阵的。那如果不乘,每个词对应的q,k,v就是完全一样的。

在相同量级的情况下,qi与ki点积的值会是最大的(可以从“两数和相同的情况下,两数相等对应的积最大”类比过来)。

那在softmax后的加权平均中,该词本身所占的比重将会是最大的,使得其他词的比重很少,无法有效利用上下文信息来增强当前词的语义表示。

而乘以QKV参数矩阵,会使得每个词的q,k,v都不一样,能很大程度上减轻上述的影响。

当然,QKV参数矩阵也使得多头,类似于CNN中的多核,去捕捉更丰富的特征/信息成为可能。

8.Self-Attention 的时间复杂度是怎么计算的?
Self-Attention时间复杂度 O ( n 2 ⋅ d ) O(n^2\cdot{d}) O(n2d),这里,n是序列的长度,d是embedding的维度。

Self-Attention包括三个步骤:相似度计算,softmax和加权平均,它们分别的时间复杂度是:

相似度计算可以看作大小为(n,d)和(d,n)的两个矩阵相乘: ( n , d ) ∗ ( d , n ) = O ( n 2 ⋅ d ) (n,d)*(d,n)=O(n^2\cdot{d}) (n,d)(d,n)=O(n2d) ,得到一个(n,n)的矩阵

softmax就是直接计算了,时间复杂度为 O ( n 2 ) O(n^2) O(n2)

加权平均可以看作大小为(n,n)和(n,d)的两个矩阵相乘: [公式] ,得到一个(n,d)的矩阵

因此,Self-Attention的时间复杂度是 O ( n 2 ⋅ d ) O(n^2\cdot{d}) O(n2d)

这里再分析一下Multi-Head Attention,它的作用类似于CNN中的多核。多头的实现不是循环的计算每个头,而是通过 transposes and reshapes,用矩阵乘法来完成的。

因此Multi-Head Attention时间复杂度也是 O ( n 2 ⋅ d ) O(n^2\cdot{d}) O(n2d) ,复杂度相较单头并没有变化,主要还是transposes and reshapes 的操作,相当于把一个大矩阵相乘变成了多个小矩阵的相乘。

9.简单描述一下Transformer中的前馈神经网络?使用了什么激活函数?相关优缺点?
前馈神经网络采用了两个线性变换,激活函数为Relu.
优点:

  • SGD算法的收敛速度比 sigmoid 和 tanh 快;(梯度不会饱和,解决了梯度消失问题)
  • 计算复杂度低,不需要进行指数运算;
  • 适合用于后向传播。
    缺点:
  • ReLU的输出不是zero-centered;
  • ReLU在训练的时候很”脆弱”,一不小心有可能导致神经元”坏死”。

10.Transformer 相比于 RNN/LSTM,有什么优势?为什么?
(1) RNN 系列的模型,并行计算能力很差, 但其实真实的耗时从业务上来讲,长query,transformer更快,短query,lstm更快。
(2)Transformer 的特征抽取能力比 RNN 系列的模型要好,transform可以动态建立输入序列的长程依赖关系,类似于一层全链接。

11.Transformer是如何训练的?测试阶段如何进行测试呢?

  • Transformer训练过程与seq2seq类似,首先Encoder端得到输入的encoding表示,并将其输入到Decoder端做交互式attention,之后在Decoder端接收其相应的输入,经过多头self-attention模块之后,结合Encoder端的输出,再经过FFN,得到Decoder端的输出之后,最后经过一个线性全连接层,就可以通过softmax来预测下一个单词(token),然后根据softmax多分类的损失函数,将loss反向传播即可,所以从整体上来说,Transformer训练过程就相当于一个有监督的多分类问题。
  • 需要注意的是,Encoder端可以并行计算,一次性将输入序列全部encoding出来,但Decoder端不是一次性把所有单词(token)预测出来的,而是像seq2seq一样一个接着一个预测出来的。

而对于测试阶段,其与训练阶段唯一不同的是Decoder端最底层的输入。

12.Transformer如何并行化的?
Transformer的并行化我认为主要体现在self-attention模块,在Encoder端Transformer可以并行处理整个序列,并得到整个输入序列经过Encoder端的输出,在self-attention模块,对于某个序列​ x 1 , x 2 , . . . , x n x_1,x_2,...,x_n x1,x2,...,xn,self-attention模块可以直接计算​ x i , x j x_i,x_j xixj 的点乘结果,而RNN系列的模型就必须按照顺序从 x 1 x_1 x1 ​计算到 x 2 x_2 x2 ​。

13.Transformer的一些思考
(1)单词之间的距离为1 传统的lstm和rnn等是存在文本的长依赖问题的,且输出小于等于输入的个数 transformer在self attention的驱动下,注意力的计算只依赖于单词本身, 所以将单词之间的距离缩短为1,减少计算量的同时,带来的是精度的飞跃
(2)attention机制 文本中的注意力和图像邻域的注意力有异曲同工之妙
Transformer_第16张图片
图中所示的是attention-unet的结构,上方的是他的attention机制的说明 可以看到,大致步骤为:

  1. 原始feature map与同层的短接feature map融合
  2. relu+sigmoid得到新的feature map
  3. 新的feature map融合底层的短接feature map作为当前的注意力指导分割进行

而本节中的self attentin模块儿 QKV三个向量都是从X衍生的底层语义QK运算得到分数加上映射激活相当于提取高级语义,再与低级语义进行注意力的增强

有get到其中的相同之处吗? 这是我对于处理图像和文本方面的注意力机制的思考和总结:高级特征(或语义)结合底层特征(或语义)可以增加对某些特征的注意力,提升精度

我的问题

  • 语言建模和机器翻译数据的数据特点是什么?其他领域是否有类似的数据?
  • 序列型数据是否能用attention?
  • 是不是所有序列型数据都可以使用attention?
  • 什么情形下序列型数据需要attention来提升性能?
  • attention是对于一条循环的序列来看待的,还是一次循环?
  • model的维度为什么是512维?

2.自注意可用于阅读理解、抽象总结、文本蕴涵和学习任务独立的句子表征。
-抽象总结是否可以看作是特征提取?

3.Transformer是第一个完全依靠自我注意来计算其输入和输出的表示而不使用序列对齐的rnn或卷积的转导模型。

5.对于不同词的重要性每一时刻都是动态的吗?那么究竟应该关注哪些时刻的encoder状态呢?而且关注的强度是多少呢?

5.“构想一种打分机制,结合输入和正在预测的输出联合计算当前时刻的Attention:那么以前一时刻t-1的decoder状态和某个encoder状态为参数,输出得分,即在BiLSTM的基础上又额外算了一种权重c,然后利用c,在所有输入的上下文+已经预测的结果去预测下一时刻”

Transformer_第17张图片

9.Mask
Transformer_第18张图片
10.Masked Self-Attention
确保了对位置i的预测只依赖于小于i位置的已知输出。
Transformer_第19张图片

11.代码解读

  • Positional Encoding
  • Pad Mask(针对句子不够长,加了pad,因此需要对pad进行mask)
  • Subsequence Mask(Decoder input不能看到未来时刻单词信息,因此需要mask)
  • ScaledDotProductAttention(计算context vector)
  • Multi-Head Attention
  • FeedForward Layer
  • Encoder Layer
  • Encoder
  • Decoder Layer
  • Decoder
  • Transformer

Transformer_第20张图片
13.
Transformer_第21张图片

Transformer_第22张图片

14. A t t e n t i o n Attention Attention是将 Q u e r y Query Query K e y Key Key映射到同一高维空间中去计算相似度

15.为什么Attention公式中要有缩放因子 1 d k \frac{1}{\sqrt{d_k}} dk 1
答:缩放因子的作用是归一化
假设 Q M × d , K N × d Q_{M\times{d}},K_{N\times{d}} QM×dKN×d里的元素的均值为0,方差为1,那么 A T = Q K A^T=Q^K AT=QK中元素的均值为0,方差为。当d变得很大时, 中的元素的方差也会变得很大,如果 A A A中的元素方差很大,那么 s o f t m a x ( A ) softmax(A) softmax(A)的分布会趋于陡峭(分布的方差大,分 s o f t m a x ( A ) softmax(A) softmax(A)布集中在绝对值大的区域)。总结一下就是的分布会和 d d d有关。因此 A A A中每一个元素乘上 1 d k \frac{1}{\sqrt{d_k}} dk 1后,方差又变为1。这使得 s o f t m a x ( A ) softmax(A) softmax(A)的分布”陡峭“程度与解耦,从而使得训练过程中梯度值保持稳定。

16.点积
Transformer_第23张图片
A,B两个向量的点积的大小是由夹角决定的,当夹角越大,值就越小,90度的时候为0,夹角越小,值越大,点积越大,当两个向量重合的时候,点积最大。也就是说两个向量越相似,相似度越大,点积越大。

17.每一层经过attention之后,还会有一个FFN,这个FFN的作用就是空间变换。FFN包含了2层linear transformation层,中间的激活函数是ReLu。

  • attention层的output最后会和W相乘,为什么这里又要增加一个2层的FFN网络?
    答:FFN的加入引入了非线性(ReLu激活函数),变换了attention output的空间, 从而增加了模型的表现能力。把FFN去掉模型也是可以用的,但是效果差了很多。

18.在文本处理领域,对Transformer的改进:
问题:因为基于Transformer的模型均采用"我全都要看"型的attention机制,即每一个token都要与其他所有token进行交互,无论是空间还是时间复杂度都高达 O ( n 2 ) O(n^2) O(n2),所以要降低模型复杂度

解决方法:
(1)直接将文本进行切分,会导致不同Text Segment之间无法进行交互,因而存在大量的信息丢失。
(2)Longformer:每一个token只对固定窗口大小附近的token进行local attention(局部注意力)。并且Longformer针对具体任务,在原有local attention的基础上增加了一种global attention(全局注意力)。三种新的attention机制:滑窗机制,空洞滑窗机制,融合全局信息的滑窗机制

19.

20.什么是预训练?
假设已有A训练集,先用A对网络进行预训练,在A任务上学会网络参数,然后保存以备后用,当来一个新的任务B,采取相同的网络结构,网络参数初始化的时候可以加载A学习好的参数,其他的高层参数随机初始化,之后用B任务的训练数据来训练网络,当加载的参数保持不变时,称为"frozen",当加载的参数随着B任务的训练进行不断的改变,称为“fine-tuning”,即更好地把参数进行调整使得更适合当前的B任务
优点:当任务B的训练数据较少时,很难很好的训练网络,但是获得了A训练的参数,会比仅仅使用B训练的参数更优

22.为什么multi-head attention后面要加一个ffn?
类比cnn网络中,cnn block和fc交替连接,效果更好。相比于单独的multi-head attention,在后面加一个ffn,可以提高整个block的非线性变换的能力。

参考:
【NLP】Transformer模型原理详解.
4.6 Transformer编码器部分实现–多头注意力机制.
关于Transformer的那些个为什么.
transformer问题整理(参考知乎大佬内容).
Transformer 中的细节探讨.
用放大镜看Transformer——总体和各个模块的结构到底是什么样的.
Transformer随笔:作用、原理与结构。.
Transformer结构理解及一些细节!.
关于Transformer的若干问题整理记录.
Transformer 优缺点分析.
Transformer 知识点理解.
transfomer的组成-残差连接和层归一化.
Transformer 代码完全解读!.
论文解读 | Transformer 原理深入浅出.
Transformer详解encoder.

你可能感兴趣的:(深度学习,transformer,机器翻译,深度学习)