Press "Enter" to skip to content

BERT系列之self-attention的计算

BERT基于transformer而成,而transformer的一个核心模块便是self-attention,在这里详细介绍一下self-attention及其计算过程;

 

一、What is self-attention?

 

The animal didn’t cross the street because it was too tired

 

举个例子,比如上方的句子中,我们要理解it具体指代的是什幺,很容易看出来,但是让机器识别出it的指代含义,却很难。因此,为了解决这种问题,便有了self-attention。

 

也就是 :Self-attention 关注于句子内部每一个单词对其他单词的权重。(而以前的attention机制则是关注句子之间单词的权重)

 

如下图,便是一个头的self-attention对上面句子的可视化图:

 

 

可以看到 经过了self-attention之后,it更关注于 The animal 。

 

二、Self-attention in details

 

下面详细讲述self-attention的计算过程

 

1.

 

 

首先,self-attention会计算出三个新的向量,在论文中,embedding向量的维度是512维,我们把这三个向量分别称为Query、Key、Value,这三个向量是用embedding向量分别与一个矩阵相乘得到的结果,这个矩阵是随机初始化的,纬度是(512,64),并会随着BP过程,这三个参数矩阵会不断的进行更新

 

2.

 

 

以计算thinking的self-attention值为例

计算K、Q、V之后,便如之前的所有的attention机制一样,计算一个单词之间的score,具体计算方法是:score=q :heavy_multiplication_x: k,如上图要计算thinking这个单词与自己的score那幺就是q 1 :heavy_multiplication_x: k 1 ,要计算machines对thinking对score那幺就是q 1 :heavy_multiplication_x: k 2 ;
为了避免softmax时,向量之间的点积过大,导致梯度被push到很小的区域,因此在此之前会有一个scaled的操作,也就是把上一步计算的score进行一次缩放,也就是除以根号下d k ,原论文中除以的是8;
接着便是softmax操作,将score转化为具体的概率
到现在为止,最开始计算的value vector还没有使用,所以这一步也就是将softmax的值:heavy_multiplication_x:v,比如图中,分别将thinking和machine的softmax值:heavy_multiplication_x:对应的value vector,再相加就得到了z 1 ,也就是最终输出的thinking的self-attention值。

3.矩阵的self-attention计算形式

 

 

事实上,在实际计算过程中,因为不可能一个vector一个vector的计算,因此都是把一个句子的所有单词转换后的embedding vector放到一个矩阵中,进行统一的计算,右边的计算公式,也就是前面整体计算公式的一个总结,在论文中也称之为 scaled dot-product attention

 

三、Multi-head attention

 

在attention is all you need(2017)这篇文章中,还提到了一个多头attention的机制,在论文中提到,这样做的优点就是 可以允许模型在不同的表示子空间里学习到相关的信息。

 

具体做法其实很简单,就是把原来单头的参数矩阵W K 、W Q 、W V ,由一份变成了多份,如上图,当有两个head时,就有了两种参数矩阵W 0Q 、W 0K 、W 0V ;W 1Q W、 1K 、W 1V 。然后分别将其与X(句子的单词embedding 矩阵)相乘,得到不同的K、 Q 、V。

接着经过了上文所说的scaled dot-product attention得到不同的z 0 ,z 1 …z 7 (论文中提到的是八头)

最后1)把得到的所有z vector 进行concate;2)将其与一个参数矩阵W 0 进行点乘,其中参数矩阵会随着模型一起进行训练;3)得到最终结果Z,其中Z也就捕获了所有头的信息

 

最后把之前的所有计算过程放在一张图(上图)中,也就十分清楚了。

 

 

我们再回过头看一下,文章开头的那个例子,可以看到使用了多头以后(左边是单头的可视化结果,中间的部分是两头的可视化结果,右边是八头的可视化结果),不同的头对于 it 的相关注的地方是不同的,比如单头attention中比较关注 The animal ,而两头attention中,有一个头更关注于 tired ,八头则各在自己对应的子空间有不同的关注部分。

 

Summery

self-attention的机制很有效,也有许多值得思考的地方, 比如:multi-head提出有一部分的原因可能是为了单头时可能出现信息的bias现象;
multi-head attention 中的头其实并没有一个有效的结合机制,彼此之间是独立的,那幺因此google在2019年有一篇叫做talking-heads attention的文章中,对此进行了改进;
最后一点,self-attention有一个致命的缺点,那就是它的计算量是很大的,尤其是多头的情况下,那幺多个头每个进行计算时,时间和空间的复杂度都是O(n 2 ),如果序列长度很长的话,会给gpu会带来很大的负担,因此关于如何减少self-attention的计算复杂性问题,有了很多的研究工作,比如sparse-attention。

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注