注意力机制
写在前面
参考书籍
Aston Zhang, Zachary C. Lipton, Mu Li, Alexander J. Smola. Dive into Deep Learning. 2020.
简介 - Dive-into-DL-PyTorch (tangshusen.me)
注意力机制
source code: NJU-ymhui/DeepLearning: Deep Learning with pytorch (github.com)
use git to clone: https://github.com/NJU-ymhui/DeepLearning.git
/attention
visualization.py batch_matrix.py nadaraya_watson.py score.py bahdanau.py multi_head.py self_attention.py position_encoding.py
注意力机制(Attention Mechanism)是一种在神经网络中用于提升模型性能和效率的重要技术,特别是在处理序列数据和复杂输入时。它通过让模型专注于输入的特定部分,从而提高对相关信息的利用。
其核心思想是:在处理数据时,模型不需要对所有输入数据赋予相等的关注,而是根据上下文动态调整关注的重点。
查询、键和值
查询
:自主性提示
键
:非自主性提示
值
:感官输入
非自主性提示
指的是输入数据的特征,类似于感官输入,可以使用全连接层或汇聚层(如最大汇聚层或平均汇聚层)来处理。
自主性提示
在注意力机制中被称为查询(query),用于引导模型的注意力方向。
注意力机制的工作原理
- 给定一个查询(自主性提示),注意力机制通过计算查询与多个键(非自主性提示)的匹配程度,决定哪些值(感官输入)应该被关注。
- 每个值(感官输入)都有一个对应的键。模型根据查询和键的匹配情况,通过注意力汇聚来选择最相关的值。
即通过训练引导模型朝着指定方向搜索来加快效率,提升精确度
注意力的可视化
code
import torch |
output

批量矩阵乘法
为了更有效地计算小批量数据的注意力,我们可以使用批量矩阵乘法
假设第一个小批量有n个矩阵,A1, A2, …, An,形状为a * b,第二个小批量也有n个矩阵B1, B2, …, Bn,形状为b * c,它们的批量矩阵乘法结果为A1B1, A2B2, …, AnBn,因此我们利用两个三维张量(A1, A2, …, An) (B1, B2, …, Bn),形状分别为(n, a, b) (n, b, c),批量矩阵乘法后的形状为(n, a, c)
torch.bmm(...)
:批量矩阵乘法
code
import torch |
output
torch.Size([2, 1, 6]) |
注意力汇聚
目前,我们已经知道,查询(自主性提示)和键(非自主性提示)之间的交互形成了注意力汇聚;而注意力汇聚有选择地聚合了值(感官输入)从而确定了最后的输出。本节将介绍注意力汇聚的一些细节,以便了解其工作方式。
Nadaraya-Watson核回归
Nadaraya-Watson核回归模型可用于演示带有注意力机制的机器学习。
我们用这样一个函数来模拟生成数据

其中噪声ϵ ~ N(0, 0.5^2)
code
import torch |
output
50 |
基于平均汇聚的拟合结果图

基于非参数的注意力汇聚的拟合结果图

基于非参数的注意力可视化

epoch 1, loss: 45.345715 |
损失值迭代结果图

基于参数的注意力汇聚拟合结果图

基于参数的注意力可视化

注意力评分函数
在之前的例子中,代入softmax函数中的公式(高斯核的指数部分)可以视作评分函数。
掩蔽softmax操作
在某些情况下,并非所有的值都应该被纳入注意力汇聚中,为了仅将有意义的词元作为值来获取注意力汇聚,可以指定一个有效序列长度(词元数量),以便过滤无意义值。
code
import torch |
output
tensor([[[0.4078, 0.5922, 0.0000, 0.0000], |
加性注意力
一般来说,当查询和键是不同长度的向量时,可以使用加性注意力作为评分函数。
一般做法:将查询和键连接起来后送入一个多层感知机,该感知机有一个隐藏层,隐藏层单元数是一个超参数,使用tanh作为激活函数。
code
import torch |
output
tensor([[[ 2.0000, 3.0000, 4.0000, 5.0000]], |

缩放点积注意力
使用点积可以得到计算效率更高的评分函数,但是点积要求查询和键具有相同的长度。
缩放点积注意力的配分函数是

实践中,我们常通过小批量来提高计算效率,例如基于n个查询和m个键-值对计算注意力,其中查询和键的长度为d,值的长度为v,则查询Q、键K和值V的缩放点积注意力为

具体推导见11.3. Attention Scoring Functions — Dive into Deep Learning 1.0.3 documentation (d2l.ai)
code
import math |
output
tensor([[[ 2.0000, 3.0000, 4.0000, 5.0000]], |

Bahdanau注意力

首先定义Bahdanau注意力,实现循环神经网络编码器-解码器;事实上,我们只需要重新定义解码器即可。
code
class AttentionDecoder(d2l.Decoder): |
接下来,实现带有Bahdanau注意力的循环神经网络解码器
code
# TBD 先去看循环神经网络 |
多头注意力
模型原理及理论知识详见11.5. Multi-Head Attention — Dive into Deep Learning 1.0.3 documentation (d2l.ai)
下面主要介绍实现
code
import torch |
output
MultiHeadAttention( |
自注意力和位置编码
自注意力
有了注意力机制之后,我们将词元序列输入注意力池中,以便同一组词元同时充当查询、键和值。具体来说,每个查询都会关注所有的键-值对并生成一个注意力输出。由于查询、键和值来自同一组输入,因此被称为自注意力。
code
import torch |
output
MultiHeadAttention( |
位置编码
自注意力为了并行计算放弃了顺序处理元素,为了使用序列的顺序信息,可以在输入表示中添加位置编码。
接下来介绍基于正弦函数和余弦函数的固定位置编码。

code
import torch |
output

绝对位置信息和相对位置信息
主要为理论介绍,详见11.6. Self-Attention and Positional Encoding — Dive into Deep Learning 1.0.3 documentation (d2l.ai)
Transformer
TBD(等学完循环神经网络回来补~)