358 Chapter 10. 基于循环神经网络的模型 肖桐 朱靖波
10.3 基于循环神经网络的翻译建模
早期神经机器翻译的进展主要来自两个方面:1)使用循环神经网络对单词序列
进行建模;2)注意力机制的使用。表10.6列出了 2013-2015 年间有代表性的部分研
究工作。从这些工作的内容上看,当时的研究重点还是如何有效地使用循环神经网
络进行翻译建模以及使用注意力机制捕捉双语单词序列间的对应关系。
表 10.6 2013-2015 期间神经机器翻译方面的部分论文
时间 作者 论文
2013
Kalchbrenner
和 Blunsom
Recurrent Continuous Translation Models
[453]
2014 Sutskever 等 Sequence to Sequence Learning with neural net-
works
[21]
2014 Bahdanau 等 Neural Machine Translation by Jointly Learning to
Align and Translate
[22]
2014 Cho 等 On the Properties of Neural Machine Translation
[467]
2015 Jean 等 On Using Very Large Target Vocabulary for Neural
Machine Translation
[468]
2015 Luong 等 Effective Approches to Attention-based Neural Ma-
chine Translation
[25]
可以说循环神经网络和注意力机制构成了当时神经机器翻译的标准框架。例如,
2016 年出现的 GNMT(Google’s Neural Machine Translation)系统就是由多层循环神
经网络(长短时记忆模型)以及注意力机制搭建,且在当时展示出很出色的性能
[456]
。
其中的很多技术也都为其它神经机器翻译系统的研发提供了很好的依据。
下面将会从基于循环神经网络的翻译模型入手,介绍神经机器翻译的基本方法。
之后,会对注意力机制进行介绍,同时也会介绍其在 GNMT 系统中的应用。
10.3.1 建模
同大多数自然语言处理任务一样,神经机器翻译要解决的一个基本问题是如何
描述文字序列,称为序列表示问题。例如,语音数据、文本数据的处理问题都可以被
看作经典的序列表示问题。如果把一个序列看作一个时序上的一系列变量,不同时
刻的变量之间往往是存在相关性的。也就是说,一个时序中某个时刻变量的状态会
依赖其他时刻变量的状态,即上下文的语境信息。下面是一个简单的例子,假设有
一个句子,但是最后的单词被擦掉了,如何猜测被擦掉的单词是什么?
中午 没 吃饭 ,又 刚 打 了 一 下午 篮球 ,我 现在 很 饿 ,我 想 。
10.3 基于循环神经网络的翻译建模 359
显然,根据上下文中提到的“没/吃饭”、“很/饿”,最佳的答案是“吃饭”或者
“吃东西”。也就是,对序列中某个位置的答案进行预测时需要记忆当前时刻之前的
序列信息,因此,循环神经网络应运而生。实际上循环神经网络有着极为广泛的应
用,例如语音识别、语言建模以及即将要介绍的神经机器翻译。
第九章已经对循环神经网络的基本知识进行过介绍,这里再回顾一下。简单来说,
循环神经网络由循环单元组成。对于序列中的任意时刻,都有一个循环单元与之对
应,它会融合当前时刻的输入和上一时刻循环单元的输出,生成当前时刻的输出。这
样每个时刻的信息都会被传递到下一时刻,这也间接达到了记录历史信息的目的。比
如,对于序列 x = {x
1
,...,x
m
},循环神经网络会按顺序输出一个序列 h = {h
1
,...,h
m
},
其中 h
i
表示 i 时刻循环神经网络的输出(通常为一个向量)。
图10.8展示了一个循环神经网络处理序列问题的实例。当前时刻循环单元的输
入由上一个时刻的输出和当前时刻的输入组成,因此也可以理解为,网络当前时刻
计算得到的输出是由之前的序列共同决定的,即网络在不断地传递信息的过程中记
忆了历史信息。以最后一个时刻的循环单元为例,它在对“开始”这个单词的信息
进行处理时,参考了之前所有词(“<sos> 让 我们”)的信息。
RNN Cell RNN Cell RNN Cell RNN Cell
<sos>
让
我们
开始
图 10.8 循环神经网络处理序列的实例
在神经机器翻译里使用循环神经网络也很简单。只需要把源语言句子和目标语
言句子分别看作两个序列,之后使用两个循环神经网络分别对其进行建模。这个过
程如图10.9所示。图中,下半部分是编码器,上半部分是解码器。编码器利用循环神
经网络对源语言序列逐词进行编码处理,同时利用循环单元的记忆能力,不断累积
序列信息,遇到终止符 <eos> 后便得到了包含源语言句子全部信息的表示结果。解
码器利用编码器的输出和起始符 <sos> 开始逐词地进行解码,即逐词翻译,每得到
一个译文单词,便将其作为当前时刻解码器端循环单元的输入,这也是一个典型的
神经语言模型的序列生成过程。解码器通过循环神经网络不断地累积已经得到的译
文的信息,并继续生成下一个单词,直到遇到结束符 <eos>,便得到了最终完整的译
文。
从数学模型上看,神经机器翻译模型与统计机器翻译模型的目标是一样的:在
给定源语言句子 x 的情况下,找出翻译概率最大的目标语言译文 ˆy,其计算如下式:
360 Chapter 10. 基于循环神经网络的模型 肖桐 朱靖波
0
你
知道
去 北京站 的 路
怎么
走
吗
⟨eos⟩
⟨sos⟩ Do you know the way to Beijing Railway Station
Do you know the way to Beijing Railway Station ⟨eos⟩
词嵌入层
循环单元
输出层
Softmax
LSTM
句子表示
图 10.9 基于循环神经网络翻译的模型结构
ˆy = arg max
y
P (y|x) (10.1)
这里,用 x = {x
1
,...,x
m
} 表示输入的源语言单词序列,y = {y
1
,...,y
n
} 表示生成的目
标语言单词序列。由于神经机器翻译在生成译文时采用的是自左向右逐词生成的方
式,并在翻译每个单词时考虑已经生成的翻译结果,因此对 P(y|x) 的求解可以转换
为下式:
P (y|x) =
n
Y
j=1
P (y
j
|y
<j
,x) (10.2)
其中,y
<j
表示目标语言第 j 个位置之前已经生成的译文单词序列。P (y
j
|y
<j
,x) 可以
被解释为:根据源语言句子 x 和已生成的目标语言译文片段 y
<j
= {y
1
,...,y
j−1
}, 生
成第 j 个目标语言单词 y
j
的概率。
求解 P (y
j
|y
<j
,x) 有三个关键问题(图10.10):
• 如何对 x 和 y
<j
进行分布式表示,即词嵌入。首先,将由 One-hot 向量表示的
源语言单词,即由 0 和 1 构成的离散化向量表示,转化为实数向量。可以把这
个过程记为 e
x
(·)。类似地,可以把目标语言序列 y
<j
中的每个单词用同样的方
式进行表示,记为 e
y
(·)。
• 如何在词嵌入的基础上获取整个序列的表示,即句子的表示学习。可以把词嵌
入的序列作为循环神经网络的输入,循环神经网络最后一个时刻的输出向量便
是整个句子的表示结果。如图10.10中,编码器最后一个循环单元的输出 h
m
被
看作是一种包含了源语言句子信息的表示结果,记为 C。
• 如何得到每个目标语言单词的概率,即译文单词的生成(Generation)。与神经
10.3 基于循环神经网络的翻译建模 361
语言模型一样,可以用一个 Softmax 输出层来获取当前时刻所有单词的分布,
即利用 Softmax 函数计算目标语言词表中每个单词的概率。令目标语言序列 j
时刻的循环神经网络的输出向量(或状态)为 s
j
。根据循环神经网络的性质,y
j
的生成只依赖前一个状态 s
j−1
和当前时刻的输入(即词嵌入 e
y
(y
j−1
))。同时
考虑源语言信息 C,P (y
j
|y
<j
,x) 可以被重新定义为:
P (y
j
|y
<j
,x) = P (y
j
|s
j−1
,y
j−1
,C) (10.3)
P (y
j
|s
j−1
,y
j−1
,C) 由 Softmax 实现,Softmax 的输入是循环神经网络 j 时刻的
输出。在具体实现时,C 可以被简单地作为第一个时刻循环单元的输入,即,当
j = 1 时,解码器的循环神经网络会读入编码器最后一个隐藏层状态 h
m
(也就
是 C),而其他时刻的隐藏层状态不直接与 C 相关。最终,P (y
j
|y
<j
,x) 被表示
为:
P (y
j
|y
<j
,x) =
(
P (y
j
|C,y
j−1
) j = 1
P (y
j
|s
j−1
,y
j−1
) j > 1
(10.4)
e
x
() e
x
() e
x
()
h
m−2
h
m−1
h
m
· · ·
· · ·
走
吗
⟨eos⟩
e
y
() e
y
() e
y
()
s
1
s
2
s
3
Softmax Softmax Softmax
· · ·
· · ·
· · ·
⟨sos⟩ Do you
Do you know
基于 RNN 的隐层状态 s
i
预测目标词的概率
通常,用 Softmax 函数
实现 P (y
i
|...)
每个词的 One-hot
离散化表示都被转化为
实数向量,即词嵌入
(e
x
() 和 e
y
() 函数)
源语编码器最后一个
循环单元的输出被
看作是句子的表示,
记为 C
图 10.10 求解 P (y
j
|y
<j
,x) 的三个基本问题
输入层(词嵌入)和输出层(Softmax)的内容已在第九章进行了介绍,因此这
里的核心内容是设计循环神经网络结构,即设计循环单元的结构。至今,研究人员
已经提出了很多优秀的循环单元结构。其中循环神经网络(RNN)是最原始的循环
单元结构。在 RNN 中,对于序列 x = { x
1
,...,x
m
},每个时刻 t 都对应一个循环单元,
它的输出是一个向量 h
t
,可以被描述为:
h
t
= f(x
t
U + h
t−1
W + b) (10.5)
其中 x
t
是当前时刻的输入,h
t−1
是上一时刻循环单元的输出,f(·) 是激活函数,U
和 W 是参数矩阵,b 是偏置。
虽然 RNN 的结构很简单,但是已经具有了对序列信息进行记忆的能力。实际上,
362 Chapter 10. 基于循环神经网络的模型 肖桐 朱靖波
基于 RNN 结构的神经语言模型已经能够取得比传统 n-gram 语言模型更优异的性能。
在机器翻译中,RNN 也可以做为入门或者快速原型所使用的神经网络结构。后面会
进一步介绍更加先进的循环单元结构,以及搭建循环神经网络中的常用技术。
10.3.2 长短时记忆网络
RNN 结构使得当前时刻循环单元的状态包含了之前时间步的状态信息。但是这
种对历史信息的记忆并不是无损的,随着序列变长,RNN 的记忆信息的损失越来越
严重。在很多长序列处理任务中(如长文本生成)都观测到了类似现象。对于这个
问题,研究人员提出了长短时记忆(Long Short-term Memory)模型,也就是常说的
LSTM 模型
[469]
。
LSTM 模型是 RNN 模型的一种改进。相比 RNN 仅传递前一时刻的状态 h
t−1
,
LSTM 会同时传递两部分信息:状态信息 h
t−1
和记忆信息 c
t−1
。这里,c
t−1
是新引
入的变量,它也是循环单元的一部分,用于显性地记录需要记录的历史内容,h
t−1
和
c
t−1
在循环单元中会相互作用。LSTM 通过“门”单元来动态地选择遗忘多少以前
的信息和记忆多少当前的信息。
LSTM
中所使用的门单元结构如图10.11所示,包括
遗忘门,输入门和输出门。图中 σ 代表 Sigmoid 函数,它将函数输入映射为 0-1 范围
内的实数,用来充当门控信号。
σ
h
t−1
x
t
c
t−1
(a) 遗忘门
σσ σ
Tanh
h
t−1
x
t
c
t−1
(b) 输入门
σσ σ
Tanh
X
σ
Tanh
h
t−1
x
t
c
t−1
c
t
(c) 记忆更新
σσ σ
Tanh
X
σ
Tanh
X
+
σ
Tanh
h
t−1
x
t
c
t−1
c
t
h
t
h
t
(d) 输出门
图 10.11 LSTM 中的门控结构
LSTM 的结构主要分为三个部分:
• 遗忘。顾名思义,遗忘的目的是忘记一些历史,在 LSTM 中通过遗忘门实现,其
结构如图10.11(a) 所示。x
t
表示时刻 t 的输入向量,h
t−1
是时刻 t −1 的循环单
元的输出,x
t
和 h
t−1
都作为 t 时刻循环单元的输入。σ 将对 x
t
和 h
t−1
进行筛
10.3 基于循环神经网络的翻译建模 363
选,以决定遗忘的信息,其计算如下:
f
t
= σ([h
t−1
,x
t
]W
f
+ b
f
) (10.6)
这里,W
f
是权值,b
f
是偏置,[h
t−1
,x
t
] 表示两个向量的拼接。该公式可以解
释为,对 [h
t−1
,x
t
] 进行变换,并得到一个实数向量 f
t
。f
t
的每一维都可以被理
解为一个“门”,它决定可以有多少信息被留下(或遗忘)。
• 记忆更新。首先,要生成当前时刻需要新增加的信息,该部分由输入门完成,其
结构如图10.11(b) 红色线部分,图中“
N
”表示进行点乘操作。输入门的计算
分为两部分,首先利用 σ 决定门控参数 i
t
,如公式(10.7),然后通过 Tanh 函数
得到新的信息
ˆ
c
t
,如公式(10.8):
i
t
= σ([h
t−1
,x
t
]W
i
+ b
i
) (10.7)
ˆ
c
t
= Tanh([h
t−1
,x
t
]W
c
+ b
c
) (10.8)
之后,用 i
t
点乘
ˆ
c
t
,得到当前需要记忆的信息,记为 i
t
⊙
ˆ
c
t
。接下来需要更新
旧的信息 c
t−1
,得到新的记忆信息 c
t
,更新的操作如图10.11(c) 红色线部分所
示,“
L
”表示相加。具体规则是通过遗忘门选择忘记一部分上文信息 f
t
,通
过输入门计算新增的信息 i
t
⊙
ˆ
c
t
,然后根据“
N
”门与“
L
”门进行相应的乘
法和加法计算,如公式(10.9):
c
t
= f
t
⊙c
t−1
+ i
t
⊙
ˆ
c
t
(10.9)
• 输出。该部分使用输出门计算最终的输出信息 h
t
,其结构如图10.11(d) 红色线部
分所示。在输出门中,首先将 x
t
和 h
t−1
通过 σ 函数变换得到 o
t
,如公式(10.10)。
其次,将上一步得到的新记忆信息 c
t
通过 Tanh 函数进行变换,得到值在 [-1,
1] 范围的向量。最后将这两部分进行点乘,具体如公式(10.11):
o
t
= σ([h
t−1
,x
t
]W
o
+ b
o
) (10.10)
h
t
= o
t
⊙Tanh(c
t
) (10.11)
LSTM 的完整结构如图10.12所示,模型的参数包括:参数矩阵 W
f
、W
i
、W
c
、
W
o
和偏置 b
f
、b
i
、b
c
、b
o
。可以看出,h
t
是由 c
t−1
、h
t−1
与 x
t
共同决定的。此外,
本节公式中激活函数的选择是根据函数各自的特点决定的。
10.3.3 门控循环单元
LSTM 通过门控单元控制传递状态,忘记不重要的信息,记住必要的历史信息,
在长序列上取得了很好的效果,但是其进行了许多门信号的计算,较为繁琐。门循环
单元(Gated Recurrent Unit,GRU)作为一个 LSTM 的变种,继承了 LSTM 中利用门
364 Chapter 10. 基于循环神经网络的模型 肖桐 朱靖波
σσ σ
Tanh
σ
Tanh
σ
Tanh
σ
Tanh
h
t−1
x
t
c
t−1
c
t
h
t
h
t
遗忘门
f
t
= σ([h
t−1
,x
t
]W
f
+ b
f
)
输入门
i
t
= σ([h
t−1
,x
t
]W
i
+ b
i
)
ˆ
c
t
= Tanh([h
t−1
,x
t
]W
c
+ b
c
)
记忆更新
c
t
= f
t
⊙c
t−1
+ i
t
⊙
ˆ
c
t
输出门
o
t
= σ([h
t−1
,x
t
]W
o
+ b
o
)
h
t
= o
t
⊙Tanh(c
t
)
图 10.12 LSTM 的整体结构
控单元控制信息传递的思想,并对 LSTM 进行了简化
[470]
。它把循环单元状态 h
t
和记
忆 c
t
合并成一个状态 h
t
,同时使用了更少的门控单元,大大提升了计算效率。
σ
h
t−1
x
t
(a) 重置门
σσ σ
1−
h
t−1
x
t
(b) 更新门
σσ σ
1−
σ
1−
Tanh
h
t−1
x
t
h
t
h
t
(c) 隐藏状态更新
图 10.13 GRU 中的门控结构
GRU 的输入和 RNN 是一样的,由输入 x
t
和 t −1 时刻的状态 h
t−1
组成。GRU
只有两个门信号,分别是重置门和更新门。重置门 r
t
用来控制前一时刻隐藏状态的
记忆程度,其结构如图10.13(a),其计算如公式(10.12)。更新门用来更新记忆,使用
一个门同时完成遗忘和记忆两种操作,其结构如图10.13(b),其计算如公式(10.13)。
r
t
= σ([h
t−1
,x
t
]W
r
) (10.12)
u
t
= σ([h
t−1
,x
t
]W
u
) (10.13)
当完成了重置门和更新门计算后,就需要更新当前隐藏状态,如图10.13(c) 所示。
在计算得到了重置门的权重 r
t
后,使用其对前一时刻的状态 h
t−1
进行重置 (r
t
⊙h
t−1
),
将重置后的结果与 x
t
拼接,通过 Tanh 激活函数将数据变换到 [-1,1] 范围内,具体计
10.3 基于循环神经网络的翻译建模 365
算为:
ˆ
h
t
= Tanh([r
t
⊙h
t−1
,x
t
]W
h
) (10.14)
ˆ
h
t
在包含了输入信息 x
t
的同时,引入了 h
t−1
的信息,可以理解为,记忆了当前
时刻的状态。下一步是计算更新后的隐藏状态也就是更新记忆,如下:
h
t
= h
t−1
⊙(1 −u
t
) +
ˆ
h
t
⊙u
t
(10.15)
这里,u
t
是更新门中得到的权重,将 u
t
作用于
ˆ
h
t
表示对当前时刻的状态进行“遗
忘”,舍弃一些不重要的信息,将 (1 −u
t
) 作用于 h
t−1
,用于对上一时刻隐藏状态进
行选择性记忆。
GRU 的输入输出和 RNN 类似,其采用与 LSTM 类似的门控思想,达到捕获长
距离依赖信息的目的。此外,GRU 比 LSTM 少了一个门结构,而且参数只有 W
r
、W
u
和 W
h
。因此,GRU 具有比 LSTM 高的运算效率,在系统研发中也经常被使用。
10.3.4 双向模型
前面提到的循环神经网络都是自左向右运行的,也就是说在处理一个单词的时
候只能访问它前面的序列信息。但是,只根据句子的前文来生成一个序列的表示是
不全面的,因为从最后一个词来看,第一个词的信息可能已经很微弱了。为了同时
考虑前文和后文的信息,一种解决办法是使用双向循环网络,其结构如图10.14所示。
这里,编码器可以看作由两个循环神经网络构成,第一个网络,即红色虚线框里的
网络,从句子的右边进行处理,第二个网络从句子左边开始处理,最终将正向和反
向得到的结果都融合后传递给解码器。
0
0
你
知道
去 北京站 的 路
怎么
走
吗
⟨eos⟩
⟨sos⟩ Do you know the way to Beijing Railway Station
Do you know the way to Beijing Railway Station ⟨eos⟩
反向
图 10.14 基于双向循环神经网络的机器翻译模型结构
双向模型是自然语言处理领域的常用模型,包括前几章提到的词对齐对称化、语
366 Chapter 10. 基于循环神经网络的模型 肖桐 朱靖波
言模型等中都大量地使用了类似的思路。实际上,这里也体现了建模时的非对称思
想。也就是,建模时如果设计一个对称模型可能会导致问题复杂度增加,因此往往
先对问题进行化简,从某一个角度解决问题。之后再融合多个模型,从不同角度得
到相对合理的最终方案。
10.3.5 多层神经网络
实际上,对于单词序列所使用的循环神经网络是一种很“深”的网络,因为从第
一个单词到最后一个单词需要经过至少与句子长度相当的层数的神经元。比如,一
个包含几十个词的句子也会对应几十个神经元层。但是,在很多深度学习应用中,更
习惯把对输入序列的同一种处理作为“一层”。比如,对于输入序列,构建一个 RNN,
那么这些循环单元就构成了网络的“一层”。当然,这里并不是要混淆概念。只是要
明确,在随后的讨论中,“层”并不是指一组神经元的全连接,它一般指的是网络结
构中逻辑上的一层。
单层循环神经网络对输入序列进行了抽象,为了得到更深入的抽象能力,可以把
多个循环神经网络叠在一起,构成多层循环神经网络。比如,图10.15就展示了基于
两层循环神经网络的解码器和编码器结构。通常来说,层数越多模型的表示能力越
强,因此在很多基于循环神经网络的机器翻译系统中一般会使用 4∼8 层的网络。但
是,过多的层也会增加模型训练的难度,甚至导致模型无法进行训练。第十三章还
会对这个问题进行深入讨论。
0
0
你
知道
去 北京站 的 路
怎么
走
吗
⟨eos⟩
⟨sos⟩ Do you know the way to Beijing Railway Station
Do you know the way to Beijing Railway Station ⟨eos⟩
堆叠
图 10.15 基于双层循环神经网络的机器翻译模型结构