详解 一文看懂Transformer( 二 )


简单来说就是输入的向量x,分别与三个矩阵相乘得到 Q , K , V Q,K,V Q,K,V,也就是query,key,value
这里x的大小是[2,512], W Q W^Q WQ的大小是[512,64],所以得到的结果是[2,64],如果输入是三个单词,那就是[3,64]
然后Q和 K T K^T KT相乘得到注意力分数,再做一个映射,然后再与V相乘,就得到了自注意力的输出 。
这里为什么要除以一个根号下dk(dk就是K的维度,也就是64),是因为公式中计算矩阵Q和K每一行向量的内积,为了防止内积过大,因此除以向量维度的平方根 。
这里注意,我们假设输入的尺寸是[3,512],计算得到的Q,K,V都是同样的尺寸[3,64],然后Q乘以 K T K^T KT就得到[3,3]大小,再乘以V:[3,64],最终得到的结果是[3,64]大小 。
这个V其实就相当于,输入向量本身,注意力分数就是考虑了全部的相关性,V与注意力分数相乘,就是相当于输入序列考虑了所有的单词,然后进行有侧重的调整 。
这就是自注意力机制,那么多头自注意力机制就是使用多组Q,K,V,来得到多个结果,最后拼接在一起 。
假设我们用8个头,那么就会得到8个[3,64]的矩阵,cat在一起就是[3,64*8]=[3,512]大小 。
但是我们还是需要[3,64]的大小,所以将这个结果再乘以一个权重矩阵[512,64]的,就能变回原来的大小了 。
最终的Z就作为后面模块的输入 。
mask
这里强调一个东西 mask
我们的输入数据是一个单词序列 。那么每个单词被编码后,得到的是不同长度的词向量 。
有的长,有的短,这个时候我们就会做补齐操作,一般是填充0 。0乘以其他数字也是0,所以我们经过自注意力得到的结果里面也有很多0,然后在我们进行的时候就有问题了 。是指数运算,e 0 = 1 e^0=1 e0=1是有值的,所以这些填充的0会影响到计算结果 。
这就相当于让无效的部分参与了运算 。因此需要做一个 mask 操作,让这些无效的区域不参与运算,一般是给无效区域加一个很大的负数偏置,趋近于 ? ∞ -∞ ?∞,这样的话再做,他就会趋近于0,就不会影响到结果 。
这个就叫做 mask 。具体的做法就是我们有一个mask矩阵,不需要mask的位置是False,需要mask的位置是True,然后在我们计算出注意力分数之后,对已经计算好的,按照mask矩阵,填-1e9 。下一步计算的时候,被设置成-1e9的数对应的值~0,被忽视 。
Add & Norm
经过自注意力机制之后呢,图上写着Add & Norm
Add的意思就是一个残差连接,
Norm 的意思是归一化,但是这里要注意,这里不是我们图像里面常用的Batch (BN)
Batch 的目的是使我们的一批(Batch) map满足均值为0,方差为1的分布规律 。
BN对整个Batch进行操作,就是对每一列进行操作 。啥意思呢,假设=3,有三行数据,分别是身高,体重,年龄 。
BN是对每一列做归一化,使其满足均值为0,方差为1的分布规律
而Layer (LN)则是对每一行进行归一化 。
这里看起来不太合理,对每一行进行归一化就乱了 。但是nlp领域很适合LN 。
因为我们每一行是一句话,所以对每一行做归一化是合理的,相反对每一列做归一化是不合理的 。
这里我解释的不一定对,大家可以搜一些别的资料看看 。反正这个就是做归一化的 。
公式表示如下:
Feed
这里比较简单,就是一个两层的神经网络,先线性变换,过一个ReLU,然后再线性变换即可 。
公式表示如下:
X是输入,Feed最终得到的输出矩阵的维度与X一致 。
W1和W2的大小取反即可 。假设输入X大小是[3,64],那么W1取[64,1024],W2取 [1024,64] 。
(3,64)x(64,1024)x(1024,64)=(3,64)大小不变 。