Self-Attention(自注意力机制) - bilibili
value 是一个 d 维的向量; 现分析 n 个 value:
self-attention 的目的是为了使每个 value 带上所有 value 的信息,也就是所有 value 加权相加,相似部分的权重大些,无关部分的权重小些。
权重即是各 value 与 value 之间的相似度,只需每个 value 都与所有 value 做内积就可得到,内积大说明两个value夹角小,含义相似;如果各value之间正交,比如one-hot编码,那么只有自己和自己乘结果是1,其余都是0。
用矩阵运算表示就是“自己乘以自己的转置” (n,d)⋅(n,d)ᵀ→(n,n),得到 nxn 的注意力分数方阵
把这套机制放到Attention运算中,queries 和 keys 都等于 values。
但是这些权重是不变的,因为每次 querys 都等于 keys,对协方差矩阵做完softmax 得到的分布总是一样的?
doubt: 实验:两个矩阵分别自己和自己做矩阵乘法,然后做softmax,观察两个结果
如果仅凭 values 自己调整,要达到任务所需的向量表示,可能速度太慢,所以分别给 q,k,v 加了一层线性变换,反向传播时也调整这个线性层的权重,让 value 的新词向量更快的移动到准确的位置。“从而提升模型的拟合能力1"。
Self-attention 中每一个 input 都与所有 input 做内积,没有考虑到 input 的顺序,所以原始文本的顺序信息丢失了,所以需要位置编码 1
例子:
两个单词 thinking 与 machines,分别乘上 Wq, Wk, Wv 得到线性变换后的 queries (q1,q2), keys (k1,k2), values (v1,v2)
s11 = q1 × k1, s12 = q1 × k2; 然后 s11, s12 做scale,再做softmax得到两个权值 s11’ (0.88), s12’ (0.12), 则 z1 = s11’ × v1 + s12’ × v2 就是 thinking 的新的向量表示。
对于 thinking,初始的词向量(one-hot, Elmo)为 x1,这个x1 与其他词的向量正交,无关,不包含其他单词的任何信息,对 thinking machines 这两个词做完 self-attention 之后,thinking 新的词向量带上了 machines 的信息,带上了多少呢?带上了 machines 与 thinking 相似的部分。或者说:这个新词向量蕴含了 thinking machines 这句话对于 thinking 而言哪个词更重要的信息。
新的词向量包含了整个句子所有单词的信息,重要的单词占比多一点。
Attention 与 Self-attention 区别:
QKV相乘就是注意力,只是一种运算,但并没有规定 QKV 是怎么来的。通过一个查询变量 Q 去找到 V 里面比较重要的东西:QK相乘求相似度 S,然后 SV 相乘得到 V 的新的向量表示(对于词向量,则它包含了句法/语义特征)。Q 可以是任何一个东西,V也是任何一个东西,K 往往是和V 同源的
自注意力要求 QKV 同源,QKV 是对同一个 X 乘上了不同的权重矩阵,做了不同的线性变换,使它们在空间中岔开了,X 就是一个词向量,但它表达的信息可能没那么准确,通过反向传播调整它们的权重矩阵,把它们移动了合适的位置上,这个位置的词向量可以为我的任务准确地分配各部分的重要性。
交叉注意力机制:Q 和 V 不同源,但 K 和 V 同源
Self-Attention 代码实现pytorch 1
|
|
Multi-head self-attention:
|
|
Self-Attention - TF 2
|
|
Multi-head self-attention 3
|
|
Refer: