自注意力机制
输入为向量序列
[!question] 在图像识别的时候,假设输入的图像大小都是一样的。但如果输入是一组向量,并且输入的向量的数量是会改变的,即每次模型输入的序列长度都不一样,这个时候应该要怎么处理呢?
eg. 文字处理、声音信号
- one-hot encoding:看不到词汇之间的关系
- word embedding: 对每个词汇投影成一个向量
输入和输出数量相同
- 词性标注(Part-Of-Speech, POS)

输入为一个序列,输出为一个标签
- 情感分析

序列到序列
我们不知道应该输出多少个标签,机器要自己决定输出多少个标签
- 翻译
- 语音识别

自注意力运作原理
对第一种类型处理
与RNN那节一样,如果直接用FC的话,会丢失上下文信息。
对于这种问题,可以考虑将前后向量串起来丢到FC中
问题:window有长有短,按照最大的设置window,会导致FC参数太多
自注意力
自注意力模型会“吃”整个序列的数据,输入几个向量,它就输出几个向量
在注意力下的全连接网络不是只考虑一个非常小的范围或一个小的窗口,而是考虑整个序列的信息,再来决定现在应该要输出什么样的结果

自注意力模型不是只能用一次,可以叠加很多次。如图,self-attention -> FC -> self-attention。全连接网络专注于处理某一个位置的信息,自注意力把整个序列信息再处理一次。
运作
输入是一串的向量,这个向量可能是整个网络的输入,也可能是某个隐藏层的输出,用 $a$ 来表示它,代表它可能是前面已经做过一些处理,是某个隐藏层的输出。输入一组向量 $a$,自注意力要输出一组向量 $b$,每个 $b$ 都是考虑了所有的 $a$ 以后才生成出来的。
$b^1、b^2、b^3、b^4$ 是考虑整个输入的序列$a^1、a^2、a^3、a^4$ 才产生出来的。
$b^i$产生过程
根据$a^1$找出输入序列中与$a^1$有关的向量,怎么判断关联性?需要有一个计算关联度的模块
计算注意力的模块使用两个向量作为输入,直接输出数值 α,α 可以当做两个向量的关联的程度。
常见的计算$\alpha$的方法是做点积,将输入的两个向量分别乘上不同的矩阵,左边的乘上$W^q$,右边的乘上$W^k$,得到向量$q$和$k$后,再对两个向量做点积,得到标量$\alpha$
自注意力模型一般采用查询-键-值(Query Key-Value,QKV)模式。分别计算 $a^1$ 与 $a^2$、$a^3$、$a^4$ 之间的关联性 $α$。

把 $a^{1}$ 乘上 $W^{q}$ 得到 $q^1$。$q$ 称为查询(query),它就像是我们使用搜索引擎查找相关文章所使用的关键字,所以称之为查询。
接下来要去把 $a^2$、$a^3$、$a^4$ 乘上 $W^k$ 得到向量 $k$,向量 $k$ 称为键(key)。把查询 $q^1$ 跟键$k^2$ 算内积(inner-product)就得到 $α_{1,2}$,代表查询是 $q^1$ 提供的,键是 $k^2$ 提供的时候,$q^1$ 跟 $k^2$ 之间的关联性。关联性 $α$ 也被称为注意力的分数。后面同理。
一般$a^1$和自己也有关联性,故用$q^1$与$k^1$做内积得到$\alpha_{1,1}$
得到关联性之后,还需要过一层softmax(不一定要softmax,其他激活也可以)
$$
\alpha’{1,i}=\left( \frac{\exp \alpha{1,i}}{\sum_{j}^{} \exp(\alpha_{1,j})} \right)
$$
$\alpha$说明哪些向量与$a^1$最有关系。
再根据关联性抽取信息:
- 将向量$a^1,\dots,a^4$分别乘以矩阵$W^v$,得到新的向量$v^1,\dots,v^4$,将每个向量乘以注意力分数$\alpha’$再加起来
$$
b^1 = \sum_{i}^{}\alpha’_{1,i}v^i
$$
- 关联性大,那么$\alpha_{1,i}$就回答,对应的$v$就会主导抽取结果

矩阵计算角度



整理

唯一需要学习的内容是$W^k,W^q,W^v$,需要通过训练数据找到
多头自注意力
在一些任务,如翻译、语音识别等,用较多的头可以得到比较好的结果。但是需要多少个头是一个超参数
[!question] 为什么要多头
相关有很多种不同的形式,也许可以有多个$q$,不同的$q$负责不同种类的相关性,这就是多头注意力
简单来说,就是先得到$q$,再让$q$乘以两个不同的矩阵,得到$q^1,q^2$。$q^{i,1},q^{i,2}$代表两个头,1和2代表这个位置的第几个$q$,$i$代表的是位置。对$k,v$同理


最后得到的$b^{i,1},b^{i,2}$需要再过一个矩阵才能得到$b^i$
位置编码
发现目前还没有考虑输入的位置对结果的影响,即每一个输入是出现在序列的最前面还是最后面?对一个自注意力层而言,它是完全没有这个信息的
即$q^1,q^2,q^3,q^4$的距离并没有进行特殊处理
但位置信息很重要,例如词性标注,动词很少在句首
故引入了位置编码
每一个位置设定一个vector,不同的位置就有不同的向量,用$e^i$来表示
于是用$e^i + a^i$来表示现在出现的位置在$i$这个位置
[!info] 这里不一定是 + ,在《Attention is all you need》里面是相加的形式,但是后来的RoPE就是乘的形式了

最早的位置编码是人设的,但在Attention文章中使用的是正弦函数和余弦函数产生位置向量
截断自注意力
在特定领域上,向量可能会很长。而在计算注意力矩阵时,计算复杂度是向量序列长度的平方。假设向量序列长度为$L$,则计算注意力矩阵$A’$需要$L \times L$次内积,如果$L$过大,计算量和需要的内存就会很大。不容易训练。
截断自注意力可以解决向量序列过长问题。只看一个小的范围。
在做自注意力的时候,也许没有必要让自注意力考虑一整个句子,只需要考虑一个小范围就好。(eg. 做语音辨识,如果要辨识某个位置的音标、内容,可以只看这句话和其前后范围的信息,并不需要看整段话)
对比自注意力和卷积神经网络
自注意力还可以被用在图像上。
到目前为止,在提到自注意力的时候,自注意力适用的范围是输入为一组向量的时候。
一张图像可以看作是一个向量序列,如图所示,一张分辨率为 5 × 10 的图像可以表示为一个大小为 5 × 10 × 3 的张量。
3 代表 RGB 这 3 个通道(channel),每一个位置的像素可看作是一个三维的向量,整张图像是5 × 10 个向量。所以可以换一个角度来看图像,图像其实也是一个向量序列,它既然也是一个向量序列,完全可以用自注意力来处理一张图像。

CNN: 简化版的self-attention,神经元只学习感受野内的信息
在做内积的时候,自注意力考虑的不是一个小的感受野范围,而是整个图像的信息。好像感受野是自动学出来的,网络自行决定感受野大小。
但更灵活的模型需要更多的数据进行学习,如果不够就容易过拟合。

随着资料量增多,self-attention效果会提高。
自注意力与RNN

区别1
假设把循环神经网络的输出跟自注意力的输出拿来做对比,就算使用双向循环神经网络还是有一些差别的。
如图,对于循环神经网络,如果最右边黄色的向量要考虑最左边的输入,它就必须把最左边的输入存在记忆里面,才能不“忘掉”,一路带到最右边,才能够在最后一个时间点被考虑。
但自注意力输出一个查询,输出一个键,只要它们匹配(match)得起来,“天涯若比邻”。自注意力可以轻易地从整个序列上非常远的向量抽取信息。
区别2
更主要的不同是,循环神经网络在处理输入、输出均为一组序列的时候,是没有办法并行化的。比如计算第二个输出的向量,不仅需要第二个输入的向量,还需要前一个时间点的输出向量。
当输入是一组向量,输出是另一组向量的时候,循环神经网络无法并行处理所有的输出,但自注意力可以。
自注意力输入一组向量,输出的时候,每一个向量是同时并行产生的,因此在运算速度上,自注意力会比循环神经网络更有效率。
图上的自注意力机制
图也可以看作是一堆向量,如果是一堆向量,就可以用自注意力来处理。
但把自注意力用在图上面,会有些地方不一样。图中的每一个节点(node)可以表示成一个向量。但我们不只有节点的信息,还有边(edge)的信息。
如果节点之间是有相连的,这些节点也就是有关联的。之前在做自注意力的时候,所谓的关联性是网络自己找出来的。但是现在既然有了图的信息,关联性就不需要机器自动找出来,图上面的边已经暗示了节点跟节点之间的关联性。
所以当把自注意力用在图上面的时候,我们可以在计算注意力矩阵的时候,只计算有边相连的节点就好。
