Self-Attention
核心公式
来源

自注意力的目的是考虑整个序列,但是又不希望把整个序列的所有信息包在一个窗口里,所以有一个特别的机制,用 来判断每个向量与 的关联程度
两个向量点积的结果在某种程度上可以反映两个向量的相似度。如图(a)方式,把输入的两个向量分别乘上两个不同的矩阵 、,得到两个向量 和 ,再把 和 做点积,把他们做逐元素的相乘,求和后就得到了 。这是计算 的一种方法,也是目前最常用的一种方法,另一种计算方式见图(b)
将各个向量的关联性计算出之后(一般自己与自己也会计算关联性), 除以 (防止 数值过大 softmax 梯度消失),对所有的关联性做一个 softmax 操作,即 , 得到
接下来我们要根据 ,去抽取出序列里面重要的信息。把向量 到 乘上 得到新的向量 到 ,乘上对应的注意力分数 ,求和,即 , 就得到了对应的 b
将上述过程向量化后,即得到了 Self-Attention 的核心公式
位置编码
需要考虑位置信息时,就要用到位置编码。位置编码为每一个位置设定一个位置向量,用 表示,上标 代表位置,不同的位置就有不同的向量
进阶版本
多头自注意力(multi-head self-attention)
相关有很多种不同的形式,所以也许可以有多个 ,不同的 负责不同种类的相关性
截断自注意力(truncated self-attention) 可以处理向量序列长度过大的问题。
各式各样的 self-attention
假设输入序列长度为 N,由于 QK 之间的 dot-product 计算,self-attention 的计算复杂度为 ,当 N 足够大,比如做图像问题时,一张 的图片,如果把每一个像素都当成一个像素点,N 就变成了 ,这也是 self-attention 的痛点。因此,提高 self-attention 的效率从而大幅度提高整个网络的效率是需要解决的一个问题。
我们在做文本翻译的时候,有时候在翻译当前的 token 时不需要整个 sequence 的输入,只需知道 token 两边的数据即可进行翻译,也就是做局部的 attention(local attention),这与 CNN 很相似
沿这个思路,当考虑的 token 从左右邻居变为左右间隔时,就变成了 stride attention
还有一种 global attention 的方式,就是选择 sequence 中的某些 token 作为 special token,或在 sequence 中增加 special token,让 special token 与序列产生全局的关系,非 special token 的 token 之间没有 attention
那么,哪一种 attention 的效果最好呢?我们可以把这几种 attention 融合使用,比如 longformer、big bird 等模型
Reformer 和 Routing Transformer 提出了一种 clustering 的方案,即先对 query 和 key 进行 cluster,只有属于同一类的 query 和 key 计算 attention
上面的方法都是人为设定哪些地方需要算 attention,哪些地方不需要,但这并不一定代表着最好效果。我们当然可以用 learn 的方式来获得哪些 attention 需要计算(Sinkhorn Sorting Network):训练一个网络,输入是 input sequence,输出是相同长度的 weight sequence,将所有 weight sequence 拼接起来,再经过转换,就可以得到一个哪些地方需要算 attention,哪些地方不需要算 attention 的矩阵。有一个细节是:某些不同的 sequence 可能经过 NN 输出同一个 weight sequence,这样可以大大减小计算量。
上述我们所讲的都是 的 Matrix,但是实际来说,这样的 Matrix 通常来说并不是满秩的,也就是说我们可以对原始的 矩阵降维,去掉一些 column,得到一个比较小的 Matrix。具体来说,从 N 个 key 中选出 K 个具有代表性的 key,然后和 query 做 dot-product(此处不选具有代表性的 query 是因为 query 和 output 是相对的,去掉 query 会损失信息)。选出具有代表性的 key 的方法有两种:第一种是直接对 key 做卷积(Compressed Attention),第二种是对 key 做一个 transform(Linformer)
值得一提的是,QKV的矩阵运算时,不同的矩阵运算顺序对于计算复杂度也有很大影响





















