课程内容概述
- 重要概念和公式回顾
- 机器翻译
- 机器翻译任务中的一些新颖的RNN模型
- GRU(Gated Recurrent Units)
- LSTM(Long Short-Term Memories)
内容回顾
下图是之前的课程所提到过的一些模型的损失函数。
多层神经网络的前向传播和反向传播过程。
RNN、交叉熵误差、批梯度下降
机器翻译
早期的机器翻译使用的都是基于规则的方法。后来在上世纪90年代开始,机器翻译的方法通常使用基于统计的方法,核心思想就是在平行语料库上学习一个概率模型。在后来深度学习开始盛行后,机器翻译任务又可以用深度学习中的模型来解决。
基于统计的机器翻译系统
基于统计的机器翻译一般使用贝叶斯定理来求得最大化的后验概率:
e
^
=
a
r
g
m
a
x
e
p
(
e
∣
f
)
=
a
r
g
m
a
x
e
p
(
f
∣
e
)
p
(
e
)
\hat{e}=argmax_ep(e|f)=argmax_ep(f|e)p(e)
e^=argmaxep(e∣f)=argmaxep(f∣e)p(e)
这里的
f
f
f 代表源语言法语,
e
e
e 代表目标语言英语(当然这两个也可以是别的语言)。
公式中的
p
(
f
∣
e
)
p(f|e)
p(f∣e) 是一个翻译模型,
p
(
e
)
p(e)
p(e) 是之前提到过的语言模型。
翻译过程如上图所示,将源语言通过翻译模型生成一些对应的目标语言的片段,然后通过语言模型来找出更合理通顺的表达,最后用一个decoder来生成最终的翻译结果。
翻译模型
上图所示的翻译系统由三个模块构成,所以要实现一个翻译系统,首先要建立一个翻译模型。
第一步:找到两种语言的词和短语之间的映射关系(alignment)
要找出这样的映射关系并不简单,因为两种语言不可能所有的词之间都是一一对应的关系,可能有些语言中的词在另一个语言中找不到对应的词,也有可能一个词会在另一个语言中对应多个词,甚至可能存在多对多的关系(短语对短语)。
分析语序
分析这种映射关系除了要找到对应的词或者短语外,还需要考虑映射后的词在句子中的位置,因为不同的语言可能存在不同的语序,不可能只根据词在源语言的位置就推断出映射后的词在目标语言的位置。很多翻译过程很可能是下图所示的这样。
搜索合适的翻译组合
在一个翻译系统中,源语言中的每个词可能都对应着目标语言中的多个词,而不同词之间又会产生非常多的组合,导致组合爆炸。所以这个问题实际上是一个复杂的搜索问题,这个搜索过程需要一个好的语言模型,目标是搜索出一个最合理最符合语言习惯的翻译结果。
传统的机器翻译系统是一个十分复杂的系统,往往都由很多独立训练的子模块构成,并且在训练前要进行大量的特征工程,所以构建一个机器翻译系统需要大量的人力和时间。
基于深度学习的机器翻译
与传统的由多模块构成的机器翻译系统不同,深度学习中最重要的一个性质是它的端到端的学习方式,在深度学习中我们可以仅构造一个模型,只关心最后的目标函数,所有的内容都可以用一个模型来学习。
RNN实现机器翻译模型
在机器翻译中,我们所采用的深度学习模型通常是encoder-decoder结构的,我们可以通过上节课所介绍的RNN模型来实现一个最简单的机器翻译模型。
下图就是由RNN实现的一个Encoder-Decoder模型。
Decoder隐藏层的状态仍使用softmax函数得到概率分布,并最小化预测结果与目标词的交叉熵误差。
在Encoder部分中,隐藏层的值是由上一时刻的隐藏层的值和当前时刻的输入决定的,而在Decoder中没有了输入,隐藏层的值只取决于上一时刻隐藏层的值,最后再将Decoder的隐藏层使用softmax计算概率分布预测结果。
当然,这是一个最简单的模型,所以它存在一些缺点。比如对于普通的RNN来说,当要处理的序列很长时,它很难完全记忆前面所有的词,通常它的记忆距离只有5~6个词,所以这个模型可能只适合处理较短的句子,无法处理很长的序列。
RNN机器翻译模型的扩展
-
在Encoder和Decoder中训练不同的参数 W W W
-
Decoder中每次计算隐藏层值的时候在参数中加入Encoder最后的隐藏层状态(记作 c c c)和上一时刻Decoder预测的词( y t − 1 y_{t-1} yt−1),也就是下图所示的过程。
问题:在计算 h t h_t ht 的时候已经考虑了 h t − 1 h_{t-1} ht−1,为什么还要在参数中加入 y t − 1 y_{t-1} yt−1?
- 为了能够让 s o f t m a x softmax softmax 过程的权重 W S W^S WS 也能对隐藏层的结果产生影响
- 在实践中可以防止Decoder重复输出相同的单词
-
使用更深层的RNN
-
训练双向的Encoder
-
将训练序列逆向输入
- 能够减少开头的一些单词在Encoder和Decoder中的距离,便于优化(避免梯度消失问题)
GRU
主要思想:
- 保留记忆来捕捉长距离的依赖关系
- 反向传播时误差信息根据输入以不同的强度进行传播
GRU与普通的RNN最大的不同之处就在于它有两个门:update gate和reset gate
GRU在计算两个门的值的过程也类似于RNN计算隐藏层状态的过程。其中的非线性激活函数使用
s
i
g
m
o
i
d
sigmoid
sigmoid 函数,将范围限制在
[
0
,
1
]
[0,1]
[0,1]区间内(可以理解为一种概率),并且两个门在计算过程中也分别使用不同的权值。
在GRU中,某一时刻
t
t
t 的隐藏层状态
h
t
h_t
ht 由两个部分决定,一是上一时刻的隐藏层状态
h
t
−
1
h_{t-1}
ht−1 和融合了当前时刻输入
x
t
x_t
xt 的新的记忆内容
h
~
t
\tilde{h}_t
h~t。用公式表示为:
h
~
t
=
t
a
n
h
(
W
x
t
+
r
t
∘
U
h
t
−
1
)
\tilde{h}_t=tanh(Wx_t+r_t\circ Uh_{t-1})
h~t=tanh(Wxt+rt∘Uht−1)
h
t
=
z
t
∘
h
t
−
1
+
(
1
−
z
t
)
∘
h
~
t
h_t=z_t\circ h_{t-1}+(1-z_t)\circ \tilde{h}_t
ht=zt∘ht−1+(1−zt)∘h~t
其中的
∘
\circ
∘ 表示之前提到过的
H
a
d
a
m
a
r
d
Hadamard
Hadamard 积,也就是按元素相乘。
公式很直观地表示了这两个门的作用,更新门的值决定了时刻 t t t 的更新值是否考虑之前时刻的隐藏层的值,重置门决定了 t t t 时刻的更新是否要重置隐藏层的内容,即之前记忆的内容有多少能够作用到新的状态中。
有了这两个门,GRU模型可以自主地去学习对于之前的内容是否遗忘、是否保留,这是普通的RNN所不能做到的(RNN只是在每次计算时单纯的将前一时刻的状态和当前的输入相加)。不仅如此,GRU还能很大程度上改善RNN的梯度消失问题,使得我们可以在长序列上进行训练。
LSTM
相比于GRU,LSTM的结构更加复杂一些。具体来讲就是将GRU的门从两个增加到了三个:Forget gate、Input gate、Output gate。实际上每个门的计算过程和GRU中的两个门一样,而后面的计算中引入了cell的概念,在cell中控制遗忘和输入保留。具体计算过程如下图所示:
LSTM中每个门的作用如下:
- input gate:决定新的输入状态 c ~ t \tilde{c}_{t} c~t 或者 x t x_{t} xt 对当前的状态有多大程度的影响
- forget gate:遗忘过去状态的程度(为0时完全遗忘过去的状态)
- output gate:将预测需要的内容和需要保留在循环中的内容分离
我们可以结合图来理解LSTM的结构:
单个时刻的单元可以表示成这样:
整体的网络结构:
LSTM如何改善梯度消失的问题?
- LSTM的结构能够使RNN更容易保存多个时间步骤之前的信息。
- LSTM无法根除梯度消失或者梯度爆炸的问题,但它能够让更容易地学习序列中的长距离依赖。
- 从公式中来看, c t c_t ct 和 c t − 1 c_{t-1} ct−1 之间的传递过程包括相加和 H a d a m a r d Hadamard Hadamard 积,不会出现连乘,因此在这条路径上能够避免梯度消失,但是如果在其他的计算路径中出现了累乘,那么在那些路径上仍然会产生梯度消失。
GRU和LSTM的区别?
从GRU和LSTM的结构可以看出GRU比LSTM少了一个门,因此GRU参数更少,在计算过程中就会比LSTM更有效率。而在效果上二者并没有表现出非常明显的差异,通常我们可以在开始的时候使用LSTM,如果之后对效率有更高的要求,那么就可以转换为GRU。
模型的发展
LSTM和GRU都是非常强大且十分流行的模型,当然,与普通的RNN相同,LSTM和GRU也可以在深度上进行扩展,并且LSTM和GRU还可以做很多的调整和改进,后来人们在RNN或者LSTM的基础上构造了很多先进的语言模型,模型的困惑度在逐步地降低,也能够捕获越来越多的语义和语法信息。