1.注意力机制原理
上一篇博文介绍了如何使用Tensorflow来搭建一个简单的NMT模型,但那只是一个初级的模型。下面我们通过加入注意力机制(attention mechanism)来使得其变得更加高级一点。
关于什么时注意力机制呢,笔者就按照谷歌NMT开源文档中的说明来简单介绍一下。首先,最初注意力是由Bahdanau等人在2015年提出的,紧接着Luong等人又对其进行了改进,然后就出现了很多的版本。之所以要提出注意力机制就是为了解决当解码的序列太长时,越到后面效果就越差。因为在未引入注意力机制之前,解码时仅仅只依靠上一时刻的输出而忽略了编码阶段每个时刻的输出(“称之为记忆”)。注意力机制的思想在于,希望在解码的时刻能够参考编码阶段的记忆,对上一时刻输出的信息做一定的处理(也就是只注意其中某一部分),然后再喂给下一时刻做解码处理。这样就达到了解码当前时刻时,仅仅只接受与当前时刻有关的输入,类似与先对信息做了一个筛选(注意力选择)。
2. 计算步骤
如图p0109所示,图中右边的输入部分的实线表示是训练时的输入,虚线表示预测时的输入。注意向量(attention vector)是由解码部分每个时刻的计算产生的,此处以计算第一个时刻为例。
(1) 首先将当前时刻的状态
h
t
h_t
ht同编码部分的记忆状态(
h
‾
1
,
h
‾
2
,
⋯
,
h
‾
s
′
\overline{h}_1,\overline{h}_2,\cdots,\overline{h}_{s^{\prime}}
h1,h2,⋯,hs′)逐个进行相似度计算,然后进行一个正则化:
α
t
s
=
exp
(
s
c
o
r
e
(
h
t
,
h
ˉ
s
)
)
∑
s
′
=
1
S
exp
(
s
c
o
r
e
(
h
t
,
h
ˉ
s
′
)
)
[Attention weights]
{\alpha _{ts}} = \frac{{\exp (score({h_t},{{\bar h}_s}))}}{{\sum\nolimits_{s' = 1}^S {\exp (score({h_t},{{\bar h}_{s'}}))}}}\;\;\;\;\;\;\;\;\;\text{[Attention weights]}
αts=∑s′=1Sexp(score(ht,hˉs′))exp(score(ht,hˉs))[Attention weights]
其中
s
c
o
r
e
score
score就是相似度计算函数,并且比较通用的有如下两种做法:
s
c
o
r
e
(
h
t
,
h
‾
s
)
=
{
h
t
T
W
h
‾
s
,
[Luong’s multiplicative style]
v
T
t
a
n
h
(
w
1
h
t
+
w
2
h
‾
s
)
,
[Bahdanau’s additive style]
score(h_t,\overline{h}_s)= \begin{cases} h^T_tW\overline{h}_s, & \text{[Luong's multiplicative style]}\\ v^Ttanh(w_1h_t+w_2\overline{h}_s),&\text{[Bahdanau's additive style]} \end{cases}
score(ht,hs)={htTWhs,vTtanh(w1ht+w2hs),[Luong’s multiplicative style][Bahdanau’s additive style]
当然这两种方式再Tensorflow中都被实现了;
(2) 在计算得到attention weights之后就开始计算context vector (实质就是权重和):
c
t
=
∑
s
α
t
s
h
‾
s
[Context vector]
c_t=\sum_s\alpha_{ts}\overline{h}_s\;\;\;\;\;\;\;\;\;\text{[Context vector]}
ct=s∑αtshs[Context vector]
(3) 第三步就是计算attention vector:
α
t
=
f
(
c
t
,
h
t
)
=
t
a
n
h
(
W
c
[
c
t
;
h
t
]
)
[Attention vector]
\alpha_t=f(c_t,h_t)=tanh(W_c[c_t;h_t])\;\;\;\;\;\;\;\;\;\text{[Attention vector]}
αt=f(ct,ht)=tanh(Wc[ct;ht])[Attention vector]
完成attention vector的计算之后就是全连接层,然后与正确label构造得到损失函数做分类处理,将预测得到的输出喂给下一时刻得到下一个 h t h_{t} ht,之后就又是重复上面3个步骤了。当然,这一切都被封装在tensorflow中了。
3. 使用示例
# attention_states: [batch_size, max_time, num_units]
attention_states = tf.transpose(encoder_outputs, [1, 0, 2])
# Create an attention mechanism
attention_mechanism = tf.contrib.seq2seq.LuongAttention(
num_units, attention_states,
memory_sequence_length=source_sequence_length)
decoder_cell = tf.contrib.seq2seq.AttentionWrapper(
decoder_cell, attention_mechanism,
attention_layer_size=num_units)
简单的示例就是如上这样,不过这样看了之后还是没有整体的把握。所以完整用法见带注意力机制的Seq2Seq翻译模型。
源码戳此处