第一部分:基本含义
在处理输入序列(如一段文本或一张图片)时,模型可以有选择地关注输入的某些部分,而不是对所有部分一视同仁。这使得模型能够更有效地处理长序列,或是在不同的任务中灵活地选择相关信息进行计算。(从众多信息中选择出对当前任务目标更关键的信息),在深度学习中,主要是指(让神经网络能够更加关注图像中的重要特征,而不是整张图片)
大多数注意力机制都附着在Encoder-Decoder框架下
但是注意力机制是一种思想,本身并不依赖于任何框架
第二部分:使用的原因
前面我们提到过的循环神经网络中的Encoder-Decoder(机器翻译框架):
缺点:数据都被压缩到z里面了,这种压缩就会导致很多信息的损失,同时先输入的信息很有可能会被后输入的信息覆盖掉了,就会使解码的准确率上不去,序列越长,这种问题就会越明显,换句话说,中间变量z存在“信息瓶颈”的问题,就像一个瓶子的口一样,把这个瓶子卡住了。
我们的解决方法(NLP中的注意力机制),就是如何在每一时刻产生不同的中间变量zi,表示不同的关注区域,然后根据专注的区域产生下一个输出
第三部分:注意力机制的分类
- 隐式注意力:非常深的神经网络已经学会了一种形式的隐式注意
- 显式注意力(一般默认是这个):根据先前输入的记忆“权衡”其对输入的敏感度
- 软注意力:函数在其域内平滑变化,因此是可微的
渐变色就是软注意力机制
- 硬注意力:用随机抽样模型代替了确定性方法,不可微的
直接裁剪的这种叫做硬注意力。
第四部分:注意力机制在机器翻译中的使用
我们新引入的输出zi:
先计算e(ij)->再计算a(ij)->最后计算z(i)(最终得到的是一个数)
这个attention机制能够实现长期记忆的表达,建立了一种从编码器到译码器的映射关系
(上方的输入数据依赖于从下方的哪一个时刻去提取有用隐状态h信息)
第五部分:注意力的可视化
-
对齐(Alignment):
- 这里的对齐表示在生成翻译结果时,对输入序列和输出序列之间的对齐关系的可视化。对齐帮助模型在翻译时找到输入句子和输出句子之间的对应关系。
- 通过注意力机制,模型能够将输出中的某个词与输入中的相关部分对齐。
-
注意力权重的动态性:
- 图中的矩阵类似于一个“热力图”或权重矩阵。每个格子代表输入序列中某个词与输出序列中某个词的相关性,这种相关性是通过注意力权重动态计算出来的。
- 图中的亮度越高,表示注意力权重越高,也就是说该输入词与当前输出词有更强的关联性。
-
一对多的关系:
- 图中提到“允许一对多的关系”,意味着一个输出词可以与多个输入词建立强关联。例如,翻译红色区域那块,就会可能出现一对多的情况
- 这种灵活性使得注意力机制能够很好地处理语言中的模糊性和不同语言结构之间的差异。
第六部分:注意力怎么计算(注意力就是一种可以训练调整的权重)a(ij)
注意力Attention:就可以当作一种神经网络的输出;也可以当作衡量两种隐状态之间的“对齐”程度的分数
两个输入(两个输入的对齐),一个输出。
注意力就是衡量编码器隐状态与前一时刻解码器输出对齐的分数。
这个“注意”怎么理解:
这个主意就是指的是这个绿色小人站在“解码器”一端,去看“编码器”的一端的参数h1~h5,挑选有用重要的信息。
1. 点积注意力 (Dot-product Attention)
- 评分公式:
- 解释: 点积注意力是一种较为简单的方式,直接通过目标隐藏状态和源隐藏状态的点积来计算注意力分数。它通过两个向量的大小和方向来计算它们的对齐程度。
- 参考文献: Luong 2015
2. 缩放点积注意力 (Scaled Dot-product Attention)
- 评分公式:
- 解释: 缩放点积注意力是点积注意力的一种变体,它将得分除以源隐藏状态的维度 n 的平方根。这种缩放可以防止点积值过大,进而避免在应用 softmax 时出现梯度消失的问题。
- 参考文献: Vaswani 2017 (Transformer 模型)
3.基于内容的注意力 (Content-based Attention)余弦相似度的定义(Cosine Similarity)
- 评分公式:
- 解释: 该方法通过 余弦相似度 来衡量目标隐藏状态 s(t) 与源隐藏状态 h(t)之间的相似度。余弦相似度评估两个向量之间的夹角差异,重点关注向量的方向而非其大小。
- 参考文献: Graves 2014
4. 通用注意力 (General Attention)
- 评分公式:
- 解释: 通用注意力机制通过可训练的权重矩阵W(a) 对源隐藏状态 h(t)进行线性变换,之后将目标隐藏状态s(t)与变换后的源隐藏状态相乘,得到注意力分数。此方法与点积注意力类似,但引入了一个可学习的权重矩阵。
- 参考文献: Luong 2015
5. 基于位置的注意力 (Location-based Attention)
- 评分公式:
- 解释: 在基于位置的注意力机制中,注意力权重只依赖于目标隐藏状态 s(t),而不依赖于源隐藏状态h(t)。通过将权重矩阵W(a) 与目标隐藏状态s(t) 相乘并使用 softmax 函数得到注意力分数。
- 备注: 这种方法简化了对齐机制,仅依赖于目标的位置信息。
6. 加法注意力 (Additive Attention,也称 Bahdanau Attention)(这个最常用)
- 评分公式:
- 解释: 加法注意力(即 Bahdanau 注意力)通过可训练的参数矩阵 W(a) 和向量 v(a),对目标隐藏状态和源隐藏状态进行加权求和,然后通过非线性函数(tanh)来计算注意力分数。与其他方法相比,这种方式更加灵活,可以让网络动态学习对齐方式。
- 参考文献: Bahdanau 2015, Luong 2015
第七部分:全局注意力和局部注意力
Global Attention:在整个输入序列上计算注意力分数
Local Attention:只考虑输入单元/标记的一个子集
第八部分:自注意力机制
(1)基本含义
Self-Attention:序列自身的注意力
自我关注,自我照镜子
看看哪是自己的特长,哪是自己需要关注的,自己发现自己最擅长的地方
也可以表示成下面这个图的形式:
(2)为什么要用自注意力机制
比如一句话“The animal didn’t cross the street because it was too tired.”
其中我问:这个it指的是street还是animal?
作为人类,我们知道这个it是指的animal,但是如果是机器,很有可能会认为street,因为它更近。
所以我们的这个自注意力机制就派上用场了(它能够聚焦整个句子中的关键信息)
它会自动计算自注意力,也就是it和前面这些词的关联度,然后比较得到animal的关联度最高。
(3)怎么计算自注意力
借鉴数据库中的键值对。
计算得到的:q代表query,属于原先普通注意力机制中的y(i-1);k代表key,v代表value
比如x1是it,x2是Animal,x3是Street,我们通过自注意力来计算他们之间的“关联强度”,以x1为视角去观察x2和x3,如果算出的这个值比较大,就说明“给的关注比较多”
以it的视角去观察animal和street,可以看出来it和animal的关注更多
(4)注意力分数
当然我们也可以进行进一步的操作:
这个softmax之后的结果也叫做“注意力分数”
(5)注意力加权求和
之后再将得到的这个sum发送到前馈神经网络。
(6)自注意力矩阵计算
使用矩阵计算可以一次性出所有位置的Attention输出向量,
最终得到的这个注意力权重矩阵表示的就是 自身不同的单词、元素它们之间的一种注意力关系,从而让程序能够更好地理解这种长序列数据的内部关系。
第九部分:注意力机制的优点
- 解决了编码器到解码器之间信息传递的瓶颈问题
- 建立编码器状态和解码器间直接联系,消除了梯度消失问题
- 提供了更好的可解释性
第十部分:注意力和transformer
tranformer:编码器到解码器两个序列之间的一个转换器
注意力机制某种程度上就是transformer
第十一部分:键值对注意力
原先基本的注意力机制的缺点:
注意力分数score会仅基于隐藏状态在序列中的相对位置,而不是他们的内容,这样就限制模型关注相关信息的能力,进而可能会导致模型性能不佳,于是,人们借鉴数据库中的“键值对”思想来提出键值对注意力
现在我们的目的就是把“编码部分RNN”原先的隐藏层h变成“键”+“值”形成的键值对
更换之前的h.
其中这里的key可value都是根据输入的x进行某些非线性变换得到的,然后再去去计算score(a(ij)),这样就实现了键和值的分离
具体的非线性变换和计算score流程:
当key=value的时候,就退化成了原先的普通注意力计算方法
第十二部分:多头注意力机制
多头指的就是“多个查询”
在实际中就是:
下面这个是单头注意力机制
多头的就是:
有多个小人在这看,每个小人看的方式都不一样,就跟卷积神经网络中使用不同的卷积核一样,由于眼光和观念的差别,所以他们看的的重要性也有所差别。
第十三部分:注意力池化
(1)定义
注意力池化(Attention Pooling)是深度学习中一种机制,用于将输入的特征进行加权组合,使模型能够关注到输入中的关键部分,类似于传统卷积神经网络中的池化操作。注意力池化通过对输入特征(例如Query Q和Key K)的计算,生成注意力权重,利用这些权重对输入进行加权平均或加权求和,最终得到一个聚合的输出。
注意力池化会计算每个输入特征的重要性(通过注意力权重),然后根据这些权重对输入进行筛选,从而突出模型需要关注的部分,忽略不重要的部分。这种机制在自注意力(Self-Attention)机制中尤为常见,用于各种任务,如自然语言处理、图像识别等。
就像我们在第八部分(6)中一样,我们使用矩阵2x3Q和3x2T最终得到的矩阵为2x2,实现了降维。
(2)分类
①平均注意力池化
②高斯核回归池化
当x和xi之间差距越大,值f(x)越小,也就是当他们离得越远,注意力权重值越低
③可学习参数的注意力池化
这个里面的w属于超参数,是模型训练出来的。
第十四部分:注意力池化及代码实现
(1)注意力机制在线模拟网站
https://huggingface.co/spaces/exbert-project/exbert
输入一句话,然后在右边将鼠标指向某一个单词,在左边就会出现相应的连线,线段越粗就代表关系越强。
(2)代码实现
①绘制注意力热图的方法
import torch
import matplotlib.pyplot as plt
from torch import nn
from matplotlib import ticker
import warnings
warnings.filterwarnings("ignore")
# 绘制注意力热图
def show_attention(axis, attention):
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)
cax = ax.matshow(attention, cmap='bone')
if axis is not None:
ax.set_xticklabels(axis[0])
ax.set_yticklabels(axis[1])
ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(ticker.MultipleLocator(1))
plt.show()
②使用测试用例并设置初始化注意力权重矩阵
# 生成一个样例
sentence = 'I love deep learning more than machine learning'
tokens = sentence.split(' ')
attention_weights = torch.eye(8).reshape((8, 8)) + torch.randn((8, 8)) * 0.1 # 生成注意力权重矩阵
attention_weights
③展示自注意力热图(结合①②数据)
show_attention([tokens, tokens], attention_weights) # 展示自注意力热图
在这个图里面,颜色越浅代表注意力权重越大,我们也看到(白色部分最浅,权重最大,也就是自己对自己的权重是最大的)
④注意力池化
1.数据库生成
# 定义一个映射函数
def func(x):
return x + torch.sin(x) # 映射函数 y = x + sin(x)
n = 100 # 样本个数100
x, _ = torch.sort(torch.rand(n) * 10) # 生成0-10的随机样本并排序
y = func(x) + torch.normal(0.0, 1, (n,)) # 生成训练样本对应的y值,增加均值为0,标准差为1的扰动
x, y
2.图像绘制数据点
# 绘制曲线上的点
x_curve = torch.arange(0, 10, 0.1)
y_curve = func(x_curve)
plt.plot(x_curve, y_curve)
plt.plot(x, y, 'o')
plt.show()
3.使用平均池化方法
# 平均池化
y_hat = torch.repeat_interleave(y.mean(), n) # 将 y_train 中的元素进行复制,输入张量为 y.mean,重复次数为 n
plt.plot(x_curve, y_curve)
plt.plot(x, y, 'o')
plt.plot(x_curve, y_hat)
plt.show()
绿线是池化后的拟合效果,可以看到,平均池化效果不好。
4.使用高斯核函数池化方法
使用nadaraya-watson 核回归:
# nadaraya-watson 核回归
x_nw = x_curve.repeat_interleave(n).reshape((-1, n))
x_nw.shape, x_nw
代入公式得到注意力权重矩阵:
# 带入公式得到注意力权重矩阵
attention_weights = nn.functional.softmax(-(x_nw - x)**2 / 2, dim=1)
attention_weights.shape, attention_weights
可视化平均池化效果:
# y_hat 为注意力权重和 y 值的乘积,是加权平均值
y_hat = torch.matmul(attention_weights, y)
plt.plot(x_curve, y_curve)
plt.plot(x, y, 'o')
plt.plot(x_curve, y_hat)
plt.show()
可以看到拟合效果不错。.
⑤展现注意力热图
show_attention(None, attention_weights) # 展示注意力热图
我们可以看到,这个白色斜线上的颜色最浅,跟我们一开始的效果是一样的。