在(编码器—解码器(seq2seq))里,解码器在各个时间步依赖相同的上下文向量来获取输入序列信息。当编码器为循环神经网络时,上下文向量来⾃它最终时间步的隐藏状态。
现在,让我们再次思考那一节提到的翻译例子:输⼊为英语序列“They”“are”“watching”“.”,输出为法语序“Ils”“regardent”“.”。不难想到,解码器在⽣成输出序列中的每一个词时可能只需利用输入序列某一部分的信息。例如,在输出序列的时间步1,解码器可以主要依赖“They”“are”的信息来生成“Ils”,在时间步2则主要使用来自“watching”的编码信息⽣成“regardent”,最后在时间步3则直接映射句号“.”。这看上去就像是在解码器的每一时间步对输入序列中不同时间步的表征或编码信息分配不同的注意力一样。这也是注意力机制的由来。
仍然以循环神经网络为例,注意⼒机制通过对编码器所有时间步的隐藏状态做加权平均来得到上下文向量。解码器在每一时间步调整这些权重,即注意力权重,从而能够在不同解码时间步分别关注输⼊序列中的不同部分并编码进相应时间步的上下文向量(每个解码时间步都有一个上下文向量,是不一样的)。本节我们将讨论注意⼒机制是怎么工作的。
在(编码器—解码器(seq2seq))⾥我们区分了输入序列或编码器的索引t与输出序列或解码器的索引t’ 。解码器在时间步t’的隐藏状态
s
t
′
=
g
(
y
t
′
−
1
,
c
,
s
t
′
−
1
)
s_{t'}=g(y_{t'-1}, c, s_{t'-1})
st′=g(yt′−1,c,st′−1), 其中
y
t
′
−
1
y_{t'-1}
yt′−1是上⼀时间步t’-1的输出的表征, 且任⼀时间步t’使用相同的上下文向量c(一般是编码器最后时刻的隐藏状态)。但在注意力机制中,解码器的每⼀时间步将使用可变的上下文向量。记
c
t
′
c_{t'}
ct′是解码器在时间步t’的上下文向量,那么解码器在该时间步的隐藏状态可以改写为:
这⾥的关键是如何计算上下文向量
c
t
′
c_{t'}
ct′和如何利用它来更新隐藏状态
s
t
′
s_{t'}
st′ 。下⾯将分别描述这两个关键点。
1. 计算上下文向量
我们先描述第⼀个关键点,即计算背景变量。下图描绘了注意力机制如何为解码器在时间步2计算上下文向量。⾸先,函数a根据解码器在时间步1的隐藏状态(上一时刻的隐藏状态作为query)和编码器在各个时间步的隐藏状态计算softmax 运算的输⼊。softmax运算输出概率分布并对编码器各个时间步的隐藏状态做加权平均,从⽽得到上下文向量。
具体来说,令编码器在时间步t的隐藏状态为
h
t
h_t
ht,且总时间步数为T。那么解码器在时间步t’的上下文向量为所有编码器隐藏状态的加权平均:
其中给定t’时,权重
α
t
′
t
\alpha_{t't}
αt′t在t=1,…,T的值是一个概率分布。为了得到概率分布,我们可以使⽤softmax运算:
现在,我们需要定义如何计算上式中softmax运算的输⼊
e
t
t
′
e_{tt'}
ett′. 由于
e
t
t
′
e_{tt'}
ett′同时取决于解码器的时间步t’和编码器的时间步t ,我们不妨以解码器在时间步t’-1的隐藏状态
s
t
′
−
1
s_{t'-1}
st′−1(query)与编码器在时间步t的隐藏状态
h
t
h_t
ht(key)为输⼊,并通过函数a计算
e
t
′
t
e_{t't}
et′t:
这里a有多种选择,如果两个输入向量⻓度相同,⼀个简单的选择是计算它们的内积,
a
(
s
,
h
)
=
s
T
h
a(s,h)=s^Th
a(s,h)=sTh(点积注意力)。⽽最早提出注意力机制的论⽂则将输入连结后通过含单隐藏层的多层感知机变换:
其中
v
,
W
s
,
W
h
v,W_s,W_h
v,Ws,Wh都是可以学习的模型参数。
- 矢量化计算
我们还可以对注意力机制采⽤更⾼效的⽮量化计算。广义上,注意力机制的输入包括查询项以及⼀一对应的键项和值项,其中值项是需要加权平均的一组项。在加权平均中,值项的权重来自查询项以及与该值项对应的键项的attention计算。
在上面的例子中,查询项为解码器的隐藏状态,键项和值项均为编码器(各时间步)的隐藏状态。 让我们考虑一个常见的简单情形,即编码器和解码器的隐藏单元个数均为h ,且函数
a
(
s
,
h
)
=
s
T
h
a(s,h)=s^Th
a(s,h)=sTh。假设我们希望根据解码器单个隐藏状态
s
t
′
−
1
∈
R
h
s_{t'-1}\in R^h
st′−1∈Rh和编码器所有隐藏状态
h
t
∈
R
h
,
t
=
1
,
.
.
.
,
T
h_t\in R^h, t=1,...,T
ht∈Rh,t=1,...,T来计算上下文向量
c
t
′
∈
R
h
c_{t'}\in R^h
ct′∈Rh. 我们可以将查询项矩阵
Q
∈
R
1
×
h
Q\in R^{1\times h}
Q∈R1×h设为
s
t
′
−
1
T
s^T_{t'-1}
st′−1T, 并令键项矩阵
K
∈
R
T
×
h
K\in R^{T\times h}
K∈RT×h和值项矩阵
V
∈
R
T
×
h
V\in R^{T\times h}
V∈RT×h相同且第t⾏均为
h
t
T
h_t^T
htT, 我们只需要通过⽮量化计算:
即可算出转置后的上下文向量
c
t
′
T
c^T_{t'}
ct′T. 当查询项矩阵Q的行数为n时,上式将得到n行的输出矩阵。输出矩阵与查询项矩阵在相同行上⼀一对应。(mini-batch运算)
2. 更新隐藏状态
现在我们描述第二个关键点,即更新隐藏状态。以⻔控循环单元为例,在解码器中我们可以对 (门控循环单元(GRU))中门控循环单元的设计稍作修改,从⽽变换上一时间步t’-1的输出
y
t
′
−
1
y_{t'-1}
yt′−1、和隐藏状态
s
t
′
−
1
s_{t'-1}
st′−1和当前时间步t’的含注意力机制的上下文向量
c
t
′
c_{t'}
ct′.解码器在时间步t’的隐藏状态为:
其中的重置门、更新⻔和候选隐藏状态分别为:
其中含下标的W和b分别为⻔控循环单元的权重参数和偏差参数。
3. 发展
本质上,注意力机制能够为表征中较有价值的部分分配较多的计算资源。这个有趣的想法自提出后得到了快速发展,特别是启发了依靠注意力机制来编码输入序列并解码出输出序列的Transformer模型的设计(纯使用注意力机制,self-attention )。Transformer抛弃了卷积神经网络和循环神经⽹络的架构。它在计算效率上比基于循环神经网络的编码器—解码器模型通常更具明显优势。含注意力机制的Transformer的编码结构在后来的BERT预训练模型中得以应用并令后者⼤放异彩:微调后的模型在多达11项⾃然语⾔处理任务中取得了当时最先进的结果。不久后,同样是基于Transformer设计的GPT-2模型于新收集的语料数据集预训练后,在7个未参与训练的语言模型数据集上均取得了当时最先进的结果。除了⾃然语⾔处理领域,注意力机制还被广泛用于图像分类、⾃动图像描述、唇语解读以及语⾳识别。
4. 总结
1)可以在解码器的每个时间步使⽤不同的上下文向量,并对输入序列中不同时间步编码的信息分配不同的注意力(权重)。
2)⼴义上,注意⼒机制的输入包括查询项以及⼀一对应的键项和值项。
3)注意力机制可以采用更为⾼效的⽮量化计算。