注意力机制
本文是笔者《动手学深度学习》的学习笔记,如有谬误,请随时指出。
查询、键和值
人类的注意力方式可以分为两种:自主性的注意力和非自主性的注意力。
- 非自主性的注意力:无意识间注意到的,比如说一群白色的物品之间有一个黑色的物品,这会使你无意识的注意到黑色物品。
- 自主性的注意力:有意识的去注意的,比如说在一面挂满相片的墙上,想要找到你自己的照片,此时你脑子里有一个查询,于是依次去比对墙上的照片,直到找到跟你脑子里的自己最像的照片。
而我们在这里讨论的注意力机制,是对自主性注意力的建模。基本上服从以下几个步骤:
- 出现一个查询
- 将查询和已经存在的键比对
- 找到最感兴趣的那个键(对于感兴趣的定义有很多),输出他的值
Nadaraya-Watson 核回归
首先我们考虑一个回归问题,给定一组数据
{
(
x
i
,
y
i
)
}
i
=
1
n
\{(x_i, y_i)\}_{i=1}^n
{(xi,yi)}i=1n,其中
y
i
=
2
sin
(
x
i
)
+
x
i
0.8
+
ϵ
y_i = 2\sin (x_i)+x_i^{0.8}+\epsilon
yi=2sin(xi)+xi0.8+ϵ
其中
ϵ
∼
N
(
0
,
0.5
)
\epsilon\sim\mathcal{N}(0, 0.5)
ϵ∼N(0,0.5),
n
=
50
n=50
n=50。我们需要根据这些数据预测任意新输入
x
x
x的输出
y
^
=
f
(
x
)
\hat{y}=f(x)
y^=f(x)。
平均汇聚
我们使用最简单的估计其来解决
f
(
x
)
=
1
n
∑
i
=
1
n
y
i
f(x) = \frac{1}{n}\sum_{i=1}^n y_i
f(x)=n1i=1∑nyi
此时估计效果很差
或许你此时会认为,这当然很差,这么做的意义是什么?让我们用注意力机制的角度来看这个问题,把数据集 { ( x i , y i ) } i = 1 n \{(x_i, y_i)\}_{i=1}^n {(xi,yi)}i=1n看成注意力机制中的若干个键值对, f ( x ) f(x) f(x)的输入值就代表一个查询,此时预测流程可以看作:
- 给定一个查询 x x x
- 将查询和已经存在的键 x i x_i xi比对
- 找到最感兴趣的那个键(此时我们对所有的键都不感兴趣,或者说对所有键感兴趣的程度都一样),因此我们就给每一个键 x i x_i xi的值 y i y_i yi赋予了一个 1 / n 1/n 1/n的权重,然后累加起来,就有了上述的结果
非参数注意力汇聚
显然之前的平均汇聚不好的原因是,它并没有有效的将键和值进行比对,简单的认为所有的键都一样,这显然不对,因此我们可以采用如下方法:
f
(
x
)
=
∑
i
=
1
n
K
(
x
−
x
i
)
∑
j
=
1
n
K
(
x
−
x
j
)
y
i
f(x) = \sum_{i=1}^n \frac{K(x-x_i)}{\sum_{j=1}^n K(x-x_j)}y_i
f(x)=i=1∑n∑j=1nK(x−xj)K(x−xi)yi
其中
K
K
K是核函数,当我们取
K
K
K为高斯核函数
K
(
u
)
=
1
2
π
exp
(
−
u
2
2
)
K(u) = \frac{1}{\sqrt{2\pi}}\exp (-\frac{u^2}{2})
K(u)=2π1exp(−2u2)
此时有
f
(
x
)
=
∑
i
=
1
n
exp
(
1
2
(
x
−
x
i
)
2
)
∑
j
=
1
n
exp
(
−
1
2
(
x
−
x
j
)
2
)
y
i
=
∑
i
=
1
n
softmax
(
−
1
2
(
x
−
x
i
)
2
)
y
i
f(x) = \sum_{i=1}^n\frac{\exp(\frac{1}{2}(x-x_i)^2)}{\sum_{j=1}^n\exp(-\frac{1}{2}(x-x_j)^2)}y_i = \sum_{i=1}^n\text{softmax}(-\frac{1}{2}(x-x_i)^2)y_i
f(x)=i=1∑n∑j=1nexp(−21(x−xj)2)exp(21(x−xi)2)yi=i=1∑nsoftmax(−21(x−xi)2)yi
这个式子的意思是:当一个键
x
i
x_i
xi距离查询
x
x
x越近,那么对于的值
y
i
y_i
yi的权重就越大,显然这样设定更加合理,此时最后的结果为
可以看出结果好了一些,但是误差依然较大,这大概是由于数据量不够导致的(这种方法又称非参数的Nadaraya‐Watson核回归,具有一致性(consistency):如果有足够的数据,此模型会收敛到最优结果)
受此启发,我们可以抽象出一个更通用的注意力汇聚的公式
f
(
x
)
=
∑
i
=
1
n
α
(
x
,
x
i
)
y
i
f(x) = \sum_{i=1}^n \alpha(x, x_i)y_i
f(x)=i=1∑nα(x,xi)yi
其中
α
(
x
,
x
i
)
\alpha(x, x_i)
α(x,xi)称为注意力权重,根据具体情况自定义。但需要保证注意力权重是一个有效的概率分布:值非负,总和为1。
带参数的注意力汇聚
尽管非参数的Nadaraya‐Watson核回归具有一致性,但是如之前所见,数据不够时,误差依然较大,因此我们可以引入可学习参数
w
w
w
f
(
x
)
=
∑
i
=
1
n
softmax
(
−
1
2
(
(
x
−
x
i
)
w
)
2
)
y
i
f(x) = \sum_{i=1}^n \text{softmax}\left(-\frac{1}{2}((x-x_i)w)^2\right)y_i
f(x)=i=1∑nsoftmax(−21((x−xi)w)2)yi
设置目标函数为均方误差损失函数,将其最小化后结果为
可以看出虽然更加贴近原始曲线,但是有些过拟合了
注意力评分函数
回顾之前的注意力汇聚公式
f
(
x
)
=
∑
i
=
1
n
α
(
x
,
x
i
)
y
i
f(x) = \sum_{i=1}^n \alpha(x, x_i)y_i
f(x)=i=1∑nα(x,xi)yi
其中
α
(
x
,
x
i
)
\alpha(x, x_i)
α(x,xi)应该需要可以很好描述查询
x
x
x和键
x
i
x_i
xi之间的相似程度,但是需要注意的是,他还需要是一个有效的概率分布,若干数值转化为概率分布的一个常用的方法是
softmax
\text{softmax}
softmax函数,因此,注意力汇聚函数
f
f
f常常写成这样
f
(
q
,
(
k
1
,
v
1
)
,
…
,
(
k
m
,
v
m
)
)
=
∑
i
=
1
m
softmax
(
a
(
q
,
k
i
)
)
v
i
f(\mathbf{q},(\mathbf{k}_1, \mathbf{v}_1), \ldots, (\mathbf{k}_m,\mathbf{v}_m)) = \sum_{i=1}^m\text{softmax}(a(\mathbf{q}, \mathbf{k}_i))\mathbf{v}_i
f(q,(k1,v1),…,(km,vm))=i=1∑msoftmax(a(q,ki))vi
实际上用来衡量查询
x
x
x和键
x
i
x_i
xi之间的相似程度是注意力评分函数
a
(
q
,
k
)
a(\mathbf{q}, \mathbf{k})
a(q,k)。
加性注意力
一般来说,当查询和键是不同长度的矢量时,可以使用加性注意力作为评分函数。给定查询
q
∈
R
q
\mathbf{q}\in\mathbb{R}^q
q∈Rq和键
k
∈
R
k
\mathbf{k}\in\mathbb{R}^k
k∈Rk,加性注意力的评分函数为
a
(
q
,
k
)
=
w
v
⊤
tanh
(
W
q
q
+
W
k
k
)
∈
R
a(\mathbf{q}, \mathbf{k}) = \mathbf{w}_v^\top \tanh(\mathbf{W}_q\mathbf{q}+\mathbf{W}_k\mathbf{k})\in\mathbb{R}
a(q,k)=wv⊤tanh(Wqq+Wkk)∈R
其中可学习参数为
W
q
∈
R
h
×
q
,
W
k
∈
R
h
×
k
\mathbf{W}_q\in\mathbb{R}^{h\times q}, \mathbf{W}_k\in\mathbb{R}^{h\times k}
Wq∈Rh×q,Wk∈Rh×k和
w
v
∈
R
h
\mathbf{w}_v\in\mathbb{R}^h
wv∈Rh
缩放点积注意力
使用点积可以得到计算效率更高的评分函数,但是点积操作要求查询和键具有相同的长度
d
d
d。缩放点积注意力的评分函数为:
a
(
q
,
k
)
=
q
⊤
k
d
a(\mathbf{q}, \mathbf{k}) = \frac{\mathbf{q}^\top \mathbf{k}}{\sqrt{d}}
a(q,k)=dq⊤k
其中除以
d
\sqrt{d}
d是为了消除点积的大小与向量长度的相关性,同时点积也能够衡量两个向量的相似程度,由于在欧式空间下,两个向量的内积相当于两个向量的夹角余弦值乘以两个常数,夹角越小可以认为两个向量越相似,因此我们可以用点积来衡量两个向量的相似程度。
刚刚突然脑子一抽,不知道为什么
u
⊤
v
=
∥
u
∥
∥
v
∥
cos
(
θ
)
\mathbf{u}^\top \mathbf{v} = \|\mathbf{u}\|\|\mathbf{v}\|\cos(\theta)
u⊤v=∥u∥∥v∥cos(θ)
简单的证明了一下
∥
u
−
v
∥
2
=
∥
u
∥
2
+
∥
v
∥
2
−
2
∥
u
∥
∥
v
∥
cos
(
θ
)
(
u
−
v
)
⊤
(
u
−
v
)
=
∥
u
∥
2
+
∥
v
∥
2
−
2
∥
u
∥
∥
v
∥
cos
(
θ
)
−
2
u
⊤
v
=
−
2
∥
u
∥
∥
v
∥
cos
(
θ
)
u
⊤
v
=
∥
u
∥
∥
v
∥
cos
(
θ
)
\begin{aligned} \|\mathbf{u}-\mathbf{v}\|^2 &= \|\mathbf{u}\|^2+\|\mathbf{v}\|^2-2\|\mathbf{u}\|\|\mathbf{v}\|\cos(\theta)\\ (\mathbf{u}-\mathbf{v})^\top(\mathbf{u}-\mathbf{v}) &= \|\mathbf{u}\|^2+\|\mathbf{v}\|^2-2\|\mathbf{u}\|\|\mathbf{v}\|\cos(\theta)\\ -2\mathbf{u}^\top\mathbf{v} &= -2\|\mathbf{u}\|\|\mathbf{v}\|\cos(\theta)\\ \mathbf{u}^\top \mathbf{v} &= \|\mathbf{u}\|\|\mathbf{v}\|\cos(\theta) \end{aligned}
∥u−v∥2(u−v)⊤(u−v)−2u⊤vu⊤v=∥u∥2+∥v∥2−2∥u∥∥v∥cos(θ)=∥u∥2+∥v∥2−2∥u∥∥v∥cos(θ)=−2∥u∥∥v∥cos(θ)=∥u∥∥v∥cos(θ)
Bahdanau 注意力
这里描述的Bahdanau注意力模型,和之前提到的seq2seq模型结构相同,只不过上下文变量
c
\mathbf{c}
c在解码时间步
t
′
t'
t′会被
c
t
′
c_{t'}
ct′替换:
c
t
′
=
∑
t
=
1
T
α
(
s
t
′
−
1
,
h
t
)
h
t
\mathbf{c}_{t'} = \sum_{t=1}^T\alpha(\mathbf{s}_{t'-1},\mathbf{h}_t)\mathbf{h}_t
ct′=t=1∑Tα(st′−1,ht)ht
其中,时间步
t
′
−
1
t'-1
t′−1时的解码器隐状态
s
t
′
−
1
\mathbf{s}_{t'-1}
st′−1时查询,编码器的隐状态
h
t
\mathbf{h}_t
ht既是键也是值。
多头注意力
在实践中,当给定相同的查询、键和值的集合时,我们希望模型可以基于相同的注意力机制学习到不同的行
为,然后将不同的行为作为知识组合起来,捕获序列内各种范围的依赖关系(例如,短距离依赖和长距离依
赖关系)。
因此我们可以将查询、键和值用多个可学习的线性变换映射到不同的空间中,以获得不同的注意力
h
i
\mathbf{h}_i
hi,每个注意力头
h
i
\mathbf{h}_i
hi计算方法为
h
i
=
f
(
W
i
(
q
)
q
,
(
W
i
(
k
)
k
1
,
W
i
(
v
)
v
1
)
,
…
,
(
W
i
(
k
)
k
m
,
W
i
(
v
)
v
m
)
)
\mathbf{h}_i = f(\mathbf{W}_i^{(q)}\mathbf{q}, (\mathbf{W}_i^{(k)}\mathbf{k}_1,\mathbf{W}_i^{(v)}\mathbf{v}_1), \ldots, (\mathbf{W}_i^{(k)}\mathbf{k}_m,\mathbf{W}_i^{(v)}\mathbf{v}_m))
hi=f(Wi(q)q,(Wi(k)k1,Wi(v)v1),…,(Wi(k)km,Wi(v)vm))
最后将
h
h
h个注意力头连结,然后进行一个线性变换
Output
=
W
o
[
h
1
⋮
h
h
]
\text{Output} = \mathbf{W}_o\begin{bmatrix}\mathbf{h}_1\\ \vdots \\ \mathbf{h}_h\end{bmatrix}
Output=Wo
h1⋮hh
自注意力和位置编码
自注意力
很简单,就是说查询,键和值都是它自己。给定一个输入序列
x
1
,
…
,
x
n
\mathbf{x}_1, \ldots, \mathbf{x}_n
x1,…,xn,其中
y
i
\mathbf{y}_i
yi代表
x
i
\mathbf{x}_i
xi对应的自注意力的输出
y
i
=
f
(
x
i
,
(
x
1
,
x
1
)
,
…
,
(
x
n
,
x
n
)
)
\mathbf{y}_i=f(\mathbf{x}_i, (\mathbf{x}_1, \mathbf{x}_1),\ldots, (\mathbf{x}_n, \mathbf{x}_n))
yi=f(xi,(x1,x1),…,(xn,xn))
自注意力的时间复杂度为 O ( n 2 d ) O(n^2 d) O(n2d),而卷积神经网络和循环神经网络的时间复杂度分别为 O ( k n d 2 ) , O ( n d 2 ) O(knd^2), O(nd^2) O(knd2),O(nd2),可见自注意力遇到长序列时耗时很大,而CNN和RNN遇到维度高的序列时耗时很大。
位置编码
由于自注意力时并行计算的,因此丢失了数据的顺序信息,为此我们应该添加上顺序信息。假设输入
X
∈
R
n
×
d
\mathbf{X}\in\mathbb{R}^{n\times d}
X∈Rn×d代表一个序列中
n
n
n个词元的
d
d
d维嵌入表示。位置编码使用相同形状的位置嵌入矩阵
P
∈
R
n
×
d
\mathbf{P}\in\mathbb{R}^{n\times d}
P∈Rn×d,因此编码后的输入信息为
X
+
P
\mathbf{X}+\mathbf{P}
X+P
现在我们只需要考虑编码方式即可。我们先不加解释的直接给出结果,矩阵第
i
i
i行、第
2
j
2j
2j列和第
2
j
+
1
2j+1
2j+1列上的元素为:
p
i
,
2
j
=
sin
(
i
1000
0
2
j
/
d
)
p_{i, 2j}=\sin\left(\frac{i}{10000^{2j/d}}\right)
pi,2j=sin(100002j/di)
p
i
,
2
j
+
1
=
cos
(
i
1000
0
2
j
/
d
)
p_{i, 2j+1}=\cos\left(\frac{i}{10000^{2j/d}}\right)
pi,2j+1=cos(100002j/di)
可以看出第6列和第7列之前只是相当于加了一个平移( sin \sin sin和 cos \cos cos的区别),而第 8 8 8列和第 6 6 6列相比,周期变得更长了。
我认为位置编码设计成这样的原因有两个:
- 模仿二进制编码的形式,回想一下二进制同步计数器的方波(数电内容),个人认为平滑之后就是正弦波
- 能够通过线性变换将一个位置的位置编码,投影到另一个位置上,使得模型能够学习得到这样的信息
绝对位置信息
考虑使用最原始的二进制编码来记录位置信息,如果单个数据的维度为 d d d,那么最长能统计的序列长度为 2 d 2^d 2d,比如第7条的数据的位置编码为111,将其加在原数据上即可。
在二进制表示中,较高比特位的交替频率低于较低比特位,与下面的热图所示相似,只是位置编码通过使用
三角函数在编码维度上降低频率。由于输出是浮点数,因此此类连续表示比二进制表示法更节省空间。
相对位置信息
对于任何确定的位置偏移
δ
\delta
δ,位置
i
+
δ
i+\delta
i+δ处的位置编码可以用线性投影位置
i
i
i处的位置编码来表示。令
ω
j
=
1
/
1000
0
2
j
/
d
\omega_j=1/10000^{2j/d}
ωj=1/100002j/d,对于确定的
d
e
l
t
a
delta
delta,任何一对
(
p
i
,
2
j
,
p
i
,
2
j
+
1
)
(p_{i, 2j}, p_{i, 2j+1})
(pi,2j,pi,2j+1)都可以线性投影到
(
p
i
+
δ
,
2
j
,
p
i
+
δ
,
2
j
+
1
)
(p_{i+\delta, 2j}, p_{i+\delta, 2j+1})
(pi+δ,2j,pi+δ,2j+1):
[
cos
(
δ
ω
j
)
sin
(
δ
ω
j
)
−
sin
(
δ
ω
j
)
cos
(
δ
ω
j
)
]
[
p
i
,
2
j
p
i
,
2
j
+
1
]
=
[
p
i
+
δ
,
2
j
p
i
+
δ
,
2
j
+
1
]
\begin{align*} \begin{bmatrix} \cos(\delta\omega_j) & \sin(\delta\omega_j)\\ -\sin(\delta\omega_j) & \cos(\delta\omega_j) \end{bmatrix}\begin{bmatrix} p_{i, 2j}\\ p_{i, 2j+1} \end{bmatrix} = \begin{bmatrix} p_{i+\delta, 2j}\\ p_{i+\delta, 2j+1} \end{bmatrix} \end{align*}
[cos(δωj)−sin(δωj)sin(δωj)cos(δωj)][pi,2jpi,2j+1]=[pi+δ,2jpi+δ,2j+1]
Transformer
这一部分只是简单的介绍一下Transformer的结构
上图中没有介绍过的只有逐位前馈网络和规范化部分
基于位置的前馈网络
实际上就是一个普通的MLP,对每个单独向量做一次MLP即可
规范化
假设一个小批次的样本为 ( X 1 , … , X b ) (\mathbf{X}_1, \ldots, \mathbf{X}_b) (X1,…,Xb),其中 b b b是批大小, X i ∈ R n × d \mathbf{X}_i\in\mathbb{R}^{n\times d} Xi∈Rn×d, n n n代表序列长度, d d d代表词元嵌入维度。
这里采用的是层归一化的方法,也就是对每个 X i \mathbf{X}_i Xi进行归一化。