论文原文:On Using Very Large Target Vocabulary for Neural Machine Translation
我的研究方向是生成式文本自动摘要
,在读2016年Nallapati那篇经典论文的时候,遇到了文中所谓的LVT(large vocabulary ‘trick’)
问题,比较感兴趣就读了这篇论文的原文。由于基于神经网络的生成式文本摘要的原始模型就是从NMT迁移过来的,所以研究文本摘要有必要学好NMT模型。本文主要参考了这篇博客,但对其中的某些细节作出了更加具体的阐述。
1 问题简介
在NMT和相关系统中,一般情况下,词典构造方法是在target vocabulary中选择频率最高的K个词,超过这个数额的词,就表示为<UNK>
。然而,如果一个句子当中的<UNK>;
数量过多,性能会极具下降。本文提出了一种近似求解的算法,使得NMT系统可以使用一个较大的词表。并且在WMT14
评测上进行了对比试验。
2 问题阐述
现在比较流行的NMT系统都是基于Encoder-Decoder
架构的,简单来说,就是输入源语言的句子,Encoder
将其编码到一个中间的隐状态h,然后Decoder
再根据h生成最终的翻译句子。在训练时,根据机器生成的句子和参考句子最大化条件对数概率。
θ
∗
=
arg
max
θ
∑
n
=
1
N
∑
t
=
1
T
N
l
o
g
(
p
(
y
t
n
∣
y
<
t
n
,
x
n
)
)
\theta^{*}=\arg\max_{\theta}\sum_{n=1}^{N}\sum_{t=1}^{T_{N}}log(p(y_t^n|y_{<t}^n,x^n))
θ∗=argθmaxn=1∑Nt=1∑TNlog(p(ytn∣y<tn,xn))
这其中
x
x
x是输入Encoder
的序列,
y
y
y是Decode
r的输出,
t
t
t代表当前时间步,
T
n
Tn
Tn可以理解为句子的总长,
n
n
n为语料对的序号,
N
N
N可以理解为训练数据的总数。这个公式可以这样理解:
最内层是一个条件概率,在输入Encoder
的单词序列和当前时间步t之前Decoder
输出的单词序列的条件下,输出为target单词的概率。取log概率,然后对每个时间步的条件概率进行累和得到当前语料对输入单词序列条件下输出单词序列是目标句子的概率。然后对所有的训练数据的概率进行累和,得到模型在全部训练集上,给出输入得到输出为目标句子的条件概率。在不考虑过拟合的前提下,显然我们希望这个概率越大越好。所以取max,而此时的参数即为argmax。
其实在对上述公式更原始的叙述中,第二步,对时间步的累和应该为累乘才更合理。在论文Neural Machine Translation by Jointly Learning to Align and Translate中是这样表示的:
p
(
y
)
=
∏
t
=
1
T
p
(
y
t
∣
y
1
,
.
.
.
,
y
,
c
)
p(y)=\prod_{t=1}^Tp(y_t|{y_1,...,y},c)
p(y)=t=1∏Tp(yt∣y1,...,y,c)
这里的
c
c
c指的是Attention
机制中的上下文向量(Context Vector)
。将这个公式展开你将会得到类似隐式马尔可夫假设的推导过程中的某一步。马尔可夫假设输出只与前
k
k
k个隐层状态有关,这个公式就是前
t
−
1
t-1
t−1个输出
y
y
y都考虑的情况,所以公式很像。可能论文作者只是想表达一下这个意思,这并不是重点。
继续说,Encoder
中使用的是双向RNN,本文中使用的GRU
作为RNN单元的非线性函数,而Decoder
使用的是单向的GRU-RNN
。Encoder
在时间步t时的隐层状态ht,由前向和反向的时间步t时对应的隐层状态拼合而成。另外有一些论文中说时间步特指Decoder
,本文中是通用的。这里的Decoder
采用了Attention
机制。
Attention机制 最重要的就是上下文向量,它是对Encoder
编码后的所有隐层状态的一个加权和。原文中写的是convex sum
,让我有些摸不到头脑,我觉得这里用weighted sum
更合适些(和刚刚提到的另一篇论文一致)。公式如下:
c
i
=
∑
j
=
1
T
x
α
i
j
h
j
c_i=\sum_{j=1}^{T_{x}}\alpha_{ij}h_j
ci=j=1∑Txαijhj
其中对于每一个
h
j
h_j
hj的权重
α
i
j
\alpha_{ij}
αij计算如下:
α
i
j
=
e
x
p
(
e
i
j
)
∑
k
=
1
T
x
e
x
p
(
e
i
k
)
\alpha_{ij}=\frac{exp(e_{ij})}{\sum_{k=1}^{T_x}exp(e_{ik})}
αij=∑k=1Txexp(eik)exp(eij)
其中:
e
i
j
=
a
(
h
t
,
z
t
−
1
)
e_{ij}=a(h_t,z_{t-1})
eij=a(ht,zt−1)
其中
a
a
a的具体实现是一个简单的前馈神经网络。权重
α
i
j
\alpha_{ij}
αij根据Encoder
的第
i
i
i个隐层状态和Decoder
的第
j
−
1
j-1
j−1个隐层状态得到,是一个标量。Encoder
可以认为是将输入的单词(一般为词向量)进行编码,得到包含有在整个词表上的概率分布信息的隐层状态。Attention
对所有隐层状态加权求和,得到的是一个最终的概率分布,而这个概率分布更接近于权重大的那个隐层状态。相当于使得Decoder
在解码的某一步,先根据上一步的解码状态和所有的输入隐层状态,得到对输入更关注的点,概率分布就会接近该点的翻译结果。这样就解决了对输入的长期遗忘问题。这个公式使用softmax
也是为了使权重区分更加鲜明。
之前我们讨论的目标优化函数中的条件概率就可以表示如下:
p
(
y
t
∣
y
<
t
,
x
)
=
1
Z
e
x
p
[
w
t
a
r
g
e
t
T
ϕ
(
y
t
−
1
,
z
t
,
c
t
)
+
b
t
a
r
g
e
t
]
p(y_t|y_{<t},x)=\frac{1}{Z}exp[w_{target}^T\phi(y_{t-1},z_t,c_t)+b_{target}]
p(yt∣y<t,x)=Z1exp[wtargetTϕ(yt−1,zt,ct)+btarget]
Z
=
∑
k
:
y
k
∈
V
e
x
p
[
w
k
T
ϕ
(
y
t
−
1
,
z
t
,
c
t
)
+
b
k
]
Z=\sum_{k:y_k \in V}exp[w_k^T\phi(y_{t-1},z_t,c_t)+b_k]
Z=k:yk∈V∑exp[wkTϕ(yt−1,zt,ct)+bk]
这里的
ϕ
\phi
ϕ是一个仿射变换跟着一个非线性激活函数,原始的式子中target那里使用的是
t
t
t,让人和时间步的
t
t
t傻傻分不清。很明显这也是一个softmax
,那么问题来了,对于分数的底
Z
Z
Z,我们需要遍历整个词表才能计算得到。在词表很巨大时,这个Z就成为了模型的瓶颈。
注意这些公式并不是推导得到的,而是构造得到的,个人认为这种神经网络的假设是不能被演绎证明的。另外还要注意,对于词表过大,我们还听说过Beam search
。Beam search
和这个问题的区别:首先Beam search
是用于解码阶段的而不是训练阶段,其次它是用贪婪的方式对全局最优解进行近似,而它计算局部最优的时候还是会面临这个问题。这两个问题是不同层次上的。
3 解决方案
下面是本文的重点。我们已经知道模型的瓶颈就在于,计算Z需要遍历整个词表。为了探讨问题的本质,作者对条件概率的公式取log后求了一下梯度。这里我给出梯度的推导过程:
l
o
g
p
(
y
t
∣
y
<
t
,
x
)
=
l
o
g
1
Z
e
x
p
[
w
t
a
r
g
e
t
T
ϕ
(
y
t
−
1
,
z
t
,
c
t
)
+
b
t
a
r
g
e
t
]
=
w
t
a
r
g
e
t
T
ϕ
(
y
t
−
1
,
z
t
,
c
t
)
+
b
t
a
r
g
e
t
−
l
o
g
Z
log p(y_t|y_{<t},x)=log \frac{1}{Z}exp[w_{target}^T\phi(y_{t-1},z_t,c_t)+b_{target}] =w_{target}^T\phi(y_{t-1},z_t,c_t)+b_{target}-logZ
logp(yt∣y<t,x)=logZ1exp[wtargetTϕ(yt−1,zt,ct)+btarget]=wtargetTϕ(yt−1,zt,ct)+btarget−logZ
▽
l
o
g
p
(
y
t
∣
y
<
t
,
x
)
=
▽
[
w
t
a
r
g
e
t
T
ϕ
(
y
t
−
1
,
z
t
,
c
t
)
+
b
t
a
r
g
e
t
]
−
▽
l
o
g
Z
\bigtriangledown log p(y_t|y_{<t},x)=\bigtriangledown [w_{target}^T\phi(y_{t-1},z_t,c_t)+b_{target}]-\bigtriangledown logZ
▽logp(yt∣y<t,x)=▽[wtargetTϕ(yt−1,zt,ct)+btarget]−▽logZ
为了表示清晰,我们设:
ε
(
y
j
)
=
w
j
T
ϕ
(
y
t
−
1
,
z
t
,
c
t
)
+
b
j
\varepsilon(y_j)=w_j^T\phi(y_{t-1},z_t,c_t)+b_j
ε(yj)=wjTϕ(yt−1,zt,ct)+bj
(上式在原论文中下标有误)那么有:
▽
l
o
g
p
(
y
t
∣
y
<
t
,
x
)
=
▽
ε
(
y
t
)
−
▽
l
o
g
Z
\bigtriangledown log p(y_t|y_{<t},x)=\bigtriangledown\varepsilon(y_t)-\bigtriangledown logZ
▽logp(yt∣y<t,x)=▽ε(yt)−▽logZ
=
▽
ε
(
y
t
)
−
1
Z
▽
Z
=\bigtriangledown\varepsilon(y_t)-\frac{1}{Z}\bigtriangledown Z
=▽ε(yt)−Z1▽Z
=
▽
ε
(
y
t
)
−
1
Z
∑
k
:
y
k
∈
V
e
x
p
(
ε
(
y
k
)
)
▽
ε
(
y
k
)
=\bigtriangledown\varepsilon(y_t)-\frac{1}{Z}\sum_{k:y_k \in V}exp(\varepsilon(y_k)) \bigtriangledown \varepsilon(y_k)
=▽ε(yt)−Z1k:yk∈V∑exp(ε(yk))▽ε(yk)
=
▽
ε
(
y
t
)
−
∑
k
:
y
k
∈
V
e
x
p
(
ε
(
y
k
)
)
Z
▽
ε
(
y
k
)
=\bigtriangledown\varepsilon(y_t)-\sum_{k:y_k \in V}\frac{exp(\varepsilon(y_k))}{Z} \bigtriangledown \varepsilon(y_k)
=▽ε(yt)−k:yk∈V∑Zexp(ε(yk))▽ε(yk)
=
▽
ε
(
y
t
)
−
∑
k
:
y
k
∈
V
p
(
y
k
∣
y
<
t
,
x
)
▽
ε
(
y
k
)
=\bigtriangledown\varepsilon(y_t)-\sum_{k:y_k \in V}p(y_k|y_{<t},x)\bigtriangledown\varepsilon(y_k)
=▽ε(yt)−k:yk∈V∑p(yk∣y<t,x)▽ε(yk)
如果将
ε
\varepsilon
ε看做能量函数,则上式最终形式的第二项可以看做是能量函数的概率期望,即一个分布在整个词表上的期望意义上的梯度。于是可以用采样的方式,用样本的期望近似总体的期望,作者提出使用一个预先给定的分布
Q
Q
Q,和一个抽样的子集
V
’
V’
V’来近似。那么上式中的第二项约等于:
∑
k
:
y
k
∈
V
′
ω
k
∑
k
′
:
y
k
′
∈
V
′
ω
k
′
▽
ε
(
y
k
)
\sum_{k:y_k \in V'}\frac{\omega_k}{\sum_{k':y_{k'}\in V'}\omega_{k'}}\bigtriangledown\varepsilon(y_k)
k:yk∈V′∑∑k′:yk′∈V′ωk′ωk▽ε(yk)
其中:
ω
k
=
e
x
p
[
ε
(
y
k
)
−
l
o
g
Q
(
y
k
)
]
\omega_k=exp[\varepsilon(y_k)-logQ(y_k)]
ωk=exp[ε(yk)−logQ(yk)]
这里为了消去上式中的
−
l
o
g
-log
−log项,特意设分布
Q
Q
Q为:
Q
i
(
y
k
)
=
1
∣
V
i
′
∣
i
f
y
t
∈
V
i
′
o
t
h
e
r
w
i
s
e
0
Q_i(y_k)=\frac{1}{|V_i'|}\: if\:y_t \in V_i'\:otherwise\: 0
Qi(yk)=∣Vi′∣1ifyt∈Vi′otherwise0
于是分母与分子中的
Q
Q
Q值都相同,被消掉。这样我们就能近似地将那个引起瓶颈的式子表示为:
p
(
y
t
∣
y
<
t
,
x
)
=
e
x
p
[
w
t
T
ϕ
(
y
t
−
1
,
z
t
,
c
t
)
+
b
t
]
∑
k
:
y
k
∈
V
′
e
x
p
[
w
k
T
ϕ
(
y
t
−
1
,
z
t
,
c
t
)
+
b
k
]
p(y_t|y_{<t},x)=\frac{exp[w_t^T\phi(y_{t-1},z_t,c_t)+b_t]}{\sum_{k:y_k\in V'}exp[w_k^T\phi(y_{t-1},z_t,c_t)+b_k]}
p(yt∣y<t,x)=∑k:yk∈V′exp[wkTϕ(yt−1,zt,ct)+bk]exp[wtTϕ(yt−1,zt,ct)+bt]
关于抽样单词子集
V
′
V'
V′的形成,我的理解是:首先设定一个大小阈值threshold t
,在训练过程中将Decoder
的目标,即给定的reference中的词汇加入V’中,剩余不够阈值的再将原始的target vocabulary中最频繁出现的依次添加进来。这样做就能够保证对目标语句中含有的单词的参数总能够更新。根据Nallapati
引用这篇文章时的说法,应该是每一个mini-batch
的语料一起训练(参见上文中提到的式子中的n),那么
V
′
V'
V′就应该包含这个mini-batch
样本中的所有单词,由此可见
V
′
V'
V′的大小t也不能设的过小,但相对于几十万肯定是小多了。另外这么做给解码时选取
V
′
V'
V′集合造成了困难,所以可以干脆解码时仍遍历词表。
有人说这和word2vec
中的负采样有点像,但我觉得负采样还是和dropout
更像一些。