上一篇文章 从 RNN 到 Attention 我们在RNN的Encoder-Decoder框架下引入了Attention 机制,用来解决 RNN 模型中梯度下降以及性能瓶颈问题,如下图所示:
上图就是引入了 Attention 机制的 Encoder-Decoder 框架。上图不再只有一个单一的语义编码C,而是有多个 C1, C2, C3这样的编码。当预测 Y1 时,Y1的注意力是放在 C1上,那咱们就用 C1 作为语义编码,当预测 Y2 时,Y2 的注意力集中在 C2 上,那咱们就用 C2 作为语义编码,以此类推,就模拟了人类的注意力机制。
我们虽然讲了 RNN 中 Attention 的原理,但是是基于 Encoder-Decoder 框架来介绍的,Attention机制并不是一定要基于 Encoder-Decoder 框架,那么他的本质思想是什么呢?
一、Attention
Attention 机制最早是在计算机视觉里应用的,随后在 NLP 领域也开始应用了,真正发扬光大是在 NLP 领域,因为 2018 年 BERT 和 GPT 的效果出奇的好,进而走红。而 Transformer 和 Attention 这些核心开始被大家重点关注。
如果用图来表达 Attention 的位置大致是下面的样子:
Attention(注意力),从它的命名方式看,很明显借鉴了人类的注意力机制,他的核心逻辑就是“从关注全部到关注重点”
将有限的注意力集中在重点信息上,从而节省资源,快速获得最有效的信息。
Attention 机制可以更加好的解决序列长距离依赖问题,并且具有并行计算能力
但是,Attention 并不一定要在 Encoder-Decoder 框架下使用的,他是可以脱离 Encoder-Decoder 框架的。
- 下面的图片则是脱离 Encoder-Decoder 框架后的原理图解:
- Attention 原理的3步分解:
通过 Query (查询对象) 这个信息从 Values (被查询对象)中筛选出重要信息,简单点说,就是计算 Query 和 Values 中每个信息的相关程度。
通过上图,Attention 通常可以进行如下描述,表示为将 Query(Q) 和 key-value pairs(把 Values 拆分成了键值对的形式) 映射到输出上,其中 query、每个 key、每个 value 都是向量,输出是 V (被查询对象)中所有 values 的加权,其中权重是由 Query 和每个 key 计算出来的,计算方法分为三步:
第一步:Query与每一个Key计算相似性得到相似性评分s
第二步:将s评分进行softmax转换成[0,1]之间的概率分布
第三步:将[a1,a2,a3…an]作为权值矩阵对Value进行加权求和得到最后的Attention值
总公式如下:
具体步骤如下:
讲个故事,帮助理解:
- 图书管(source)里有很多书(value),为了方便查找,我们给书做了编号(key)。当我们想要了解漫威(query)的时候,我们就可以看看那些动漫、电影、甚至二战(美国队长)相关的书籍。
- 为了提高效率,并不是所有的书都会仔细看,针对漫威来说,动漫,电影相关的会看的仔细一些(权重高),但是二战的就只需要简单扫一下即可(权重低)。
- 当我们全部看完后就对漫威有一个全面的了解了。
二、Self - Attention
2.1 Attention 和 Self - Attention的区别
1. Attention:
传统的Attention机制发生在 Target的元素 和 Source中的所有元素 之间。
在一般任务的Encoder-Decoder框架中,输入 Source 和输出 Target 内容是不一样的,比如对于英 - 中机器翻译来说,Source是英文句子,Target是对应的翻译出的中文句子。
2. Self - Attention
Self - Attention 顾名思义,指的不是 Target 和 Source 之间的 Attention 机制,而是 Source 内部元素之间或者 Target 内部元素之间发生的 Attention 机制,其具体计算过程是一样的,只是计算对象发生了变化而已,相当于是 Query=Key=Value,计算过程与attention一样。
(例如在Transformer中在计算权重参数时,将文字向量转成对应的 QKV,只需要在 Source 处进行对应的矩阵操作,用不到Target中的信息。)
自注意力机制是注意力机制的变体,其减少了对外部信息的依赖,更擅长捕捉数据或特征的内部相关性
自注意力机制在文本中的应用,主要通过计算单词间的互相影响,解决长距离依赖问题。
下图是self-attention的一个例子:
我们想知道这句话中的 its,在这句话里 its 指代的是什么,与哪一些单词相关,那么就可以将 its 作为 Query,然后将这一句话作为 Key 和 Value 来计算 attention 值,找到与这句话中 its 最相关的单词。通过 self-attention 我们发现 its 在这句话中与之最相关的是 Law 和 application
总结区别:
- Self-attention 关键点在于,规定K-Q-V三者都来源于 X。通过 X 找到 X 中的关键点。可以看作 QKV 相等,都是由词向量线性变换得到的,并不是 Q=V=K=X,而是 X 通过 Wk、Wq、Wv 线性变换而来。
- Attention 是通过一个查询变量 Q 找到 V 里面重要信息,K 由 V 变幻而来,QK=A ,AV = Z(注意力值) ,Z 其实是 V 的另一种表示,也可以称为词向量,具有句法和语意特征的 V
- 也就是说,self-attention 比 attention 约束条件多了两个:
(1) Q=K=V(同源)
(2) Q,K,V需要遵循attention的做法
2.2 引入自注意力机制的目的
神经网络接收的输入是很多大小不一的向量,并且不同向量向量之间有一定的关系,但是实际训练的时候无法充分发挥这些输入之间的关系而导致模型训练结果效果极差。
例如:
机器翻译问题(序列到序列的问题,机器自己决定多少个标签)
词性标注问题(一个向量对应一个标签)
语义分析问题(多个向量对应一个标签)等文字处理问题
2.3 Self-Attention详解
对于每一个输入向量a,经过蓝色部分 self-attention 之后都输出一个向量b,这个向量 b 是考虑了所有的输入向量对 a1 产生的影响才得到的,这里有四个词向量a对应就会输出四个向量b。
如下图所示:
- 上图看起来复杂,实际上是在计算a1 跟 [a1,a2,a3,a4] 分别的相似度,最后得出 b1 。 a1~a4,可能是input 也可能是 hidden layer的 output。
- a1~a4属于整个 source 的信息,这一步是在计算整个 source 信息之间的关系
- 以 a1 为例,分别点积(Dot-product)两个参数矩阵 Wq 和 Wk,得到q1和k1。(q = query,k =key)
- a1,1代表a1与a1的相似度或关连程度;a1,2代表a1与a2的相似度或关连程度;同理a1,3和a1,4。
- 在得到各向量与a1的相关程度之后,用 softmax 计算出一个attention distribution,这样就把相关程度归一化,通过数值就可以看出哪些向量是和a1最有关系。
V与Q和K同理,V1 = WV * a1,
如果 a1 和 a2 关联性比较高, α1,2 就比较大,那么,得到的输出 b1 就可能比较接近 v2 ,即 attention score决定了该 vector 在结果中占的分量;
矩阵形式解析
把 4 个输入 a 拼成一个矩阵 I,这个矩阵有4个 column,也就是a1到a4,I 乘上相应的权重矩阵W,得到相应的矩阵Q、K、V,分别表示query,key和value。
三个 W 矩阵 (Wq、 Wk 和 Wv)是我们需要学习的参数。
- 利用得到的 Q 和 K 计算每两个输入向量之间的相关性,也就是计算attention的值α, α的计算方法有多种,通常采用点乘的方式。
- 矩阵A中的每一个值记录了对应的两个输入向量的Attention的大小α,A' 是经过 softmax 归一化后的矩阵。
利用得到的A' 和V,计算每个输入向量 a 对应的 self-attention 层的输出向量 b
对self-attention操作过程做个总结,输入是I,输出是O
三、Multi-head Self-attention
Self-attention 的进阶版本 Multi-head Self-attention,多头自注意力机制
因为相关性有很多种不同的形式,有很多种不同的定义,所以有时不能只有一个q,要有多个q,不同的q负责不同种类的相关性。就像语言信息里,语法句意特征非常复杂,仅仅一层 QKV 是不足以处理复杂任务的。
上面这个图中,有两个head,代表这个问题有两种不同的相关性。
同样,k 和 v 也需要有多个,两个k、v的计算方式和q相同,都是先算出来ki和vi,然后再乘两个不同的权重矩阵。
那么算出来q、k、v之后怎么做 self-attention 呢?
和上面的过程一样,只不过是1类的一起做,2类的一起做,两个独立的过程,算出来两个b(bi1,bi2).
这只是两个 head 的例子,有多个head过程也一样,都是分开算b。
最后,把 bi1 和 bi2 拼接成矩阵再乘权重矩阵 W,得到b^i,也就是这个self-
attention向量ai的输出,如下图所示:
四、Positional Encoding
在训练 self attention 的时候,实际上对于位置的信息是缺失的,没有前后的区别,上面讲的 a1,a2,a3 不代表输入的顺序,只是指输入的向量数量,不像 RNN,对于输入有明显的前后顺序。 Self-attention 是同时输入,同时输出。
如何在Self-Attention里面体现位置信息呢?
为了解决 Attention 丢失的序列顺序信息,Transformer 的提出者提出了 Position Embedding,也就是对于输入 X 进行 Attention 计算之前,在 X 的词向量中加上位置信息,也就是说 X的词向量为:
Xfinal_embedding = Embedding + Positional Embedding
换一种表示方式:
五、Self-Attention的拓展
5.1 Self-attention vs RNN
引入Self Attention后更容易捕获句子中长距离的相互依赖的特征。
RNN 或者 LSTM,需要按顺序进行序列计算,对于远距离的相互依赖的特征,要经过若干时间步步骤的信息累积才能将两者联系起来,而距离越远,有效捕获的可能性越小。
Self - Attention 在计算过程中会直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,所以远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征。
此外,Self Attention 对于增加计算的并行性也有直接帮助作用。正好弥补了attention机制的两个缺点,这就是为何Self - Attention逐渐被广泛使用的主要原因。
5.2 Self-attention vs CNN
Self-Attention 其实可以看作一种基于全局信息的 CNN 。
- 传统 CNN 的卷积核是认为规定的,只能提取卷积核内的信息进行图像特征提取,但 Self-Attention 关注 source 内部特征信息,可以从全局角度出发,去 “学习” 出最合适的一个“卷积核”,最大化的提取图像特征信息。
- 在数据量小的情况下,Self-Attention 的训练效果差,不如 CNN ;
- 在数据量大的情况下,Self-Attention 的训练效果好,胜过 CNN ;
5.3 Self-attention 的优点
- 参数少:相比于 CNN、RNN ,其参数更少,复杂度更小。所以对算力的要求也就更小。
- 速度快:Attention 解决了 RNN及其变体模型 不能并行计算的问题。Attention 机制每一步计算不依赖于上一步的计算结果,因此可以和 CNN 一样并行处理。
- 效果好:在 Attention 机制引入之前,有一个问题大家一直很苦恼:长距离的信息会被弱化,就好像记忆能力弱的人,记不住过去的事情是一样的。
六、Masked Self-attention
Transformer 用到了 Masked Self Attention 模型,需要结合 Transformer 的动态流程解释,因此在下一篇Transformer 的文章中讲解。
mask 就是沿着对角线把灰色的区域用 0 覆盖掉,不给模型看到未来的信息,如下图所示,并且在做完 softmax 之后,横轴结果合为 1
一句话简单概括:Decoder 做 Mask,是为了让训练阶段和测试阶段行为一致,不会出现间隙,不给模型看到未来的信息,避免过拟合。