From c324a304aaba3af126e0b21d0909a0dbe7dd7332 Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Tue, 3 Jan 2017 11:21:33 +0800 Subject: [PATCH] update machine translation readme.md by comments --- machine_translation/README.md | 54 +++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/machine_translation/README.md b/machine_translation/README.md index 489f561..b27d365 100644 --- a/machine_translation/README.md +++ b/machine_translation/README.md @@ -38,15 +38,15 @@ La dispute fait rage entre les grands constructeurs aéronautiques à propos de ``` - 第一行的“0”和第6行的“1”表示翻译第几条法语句子。 - 其他六行列出了翻译结果,其中右起第一列是生成的英语句子,右起第二列是该条英语句子的得分(从大到小),右起第三列是该条句子的序号。 -- 另外有两个特殊表示:``表示句子的结尾,`unk`表示无法识别(即不在训练字典中)的单词。 +- 另外有两个特殊表示:``表示句子的结尾,``表示无法识别(即不在训练字典中)的单词。 ## 模型概览 -本节依次介绍GRU,双向RNN模型,NMT中典型的“编码器-解码器”(Encoder-Decoder)框架和“注意力”(Attention)机制,以及集束搜索(Beam Search)算法。 +本节依次介绍GRU(Gated Recurrent Unit,门控循环单元),双向RNN模型,NMT中典型的“编码器-解码器”(Encoder-Decoder)框架和“注意力”(Attention)机制,以及集束搜索(Beam Search)算法。 ### GRU -GRU(Gated Recurrent Unit,门控循环单元)\[[1](#参考文献)\]是Cho等人在LSTM上提出的简化版本,如下图所示。GRU单元只有两个门,分别是重置门(Reset Gate)和更新门(Update Gate),用于控制记忆内容是否能继续保存下去。 +GRU\[[1](#参考文献)\]是Cho等人在LSTM上提出的简化版本,如下图所示。GRU单元只有两个门,分别是重置门(Reset Gate)和更新门(Update Gate),用于控制记忆内容是否能继续保存下去。


图2. GRU门控循环单元 @@ -56,9 +56,9 @@ GRU(Gated Recurrent Unit,门控循环单元)\[[1](#参考文献)\]是Cho ### 双向RNN模型 -理论上,RNN $t$时刻的输出编码了所有到$t$时刻之前的历史信息。然而,标准的神经网络通常都忽略了未来时刻的上下文信息。因此,如果能像访问历史上下文信息一样来访问未来上下文信息,很多序列学习任务都能从中获益。双向RNN就是解决这一问题的一种简单有效的方法,由Bengio等人在论文\[[1](#参考文献),[3](#参考文献)\]中提出。 +理论上,RNN $t$时刻的输出,编码了所有到$t$时刻之前的历史信息。然而,标准的神经网络通常都忽略了未来时刻的下文信息。因此,如果能像访问历史上文信息一样来访问未来下文信息,很多序列学习任务都能从中获益。双向RNN就是解决这一问题的一种简单有效的方法,由Bengio等人在论文\[[1](#参考文献),[3](#参考文献)\]中提出。 -双向RNN的每一个训练序列,向前和向后分别是两个循环神经网络(RNN),而且都连接着一个输出层。这个结构提供给输出层:输入序列中每一个点完整的过去和未来的上下文信息。下图展示的是一个按时间步展开的双向循环神经网络。该网络包含一个前向(forward)和一个后向(backward)RNN,其中有六个权值:输入到前向隐层和后向隐层($w_1, w_3$),隐层到隐层自己($w_2,w_5$),前向隐层和后向隐层到输出层($w_4, w_6$)。注意,该网络的前向隐层和后向隐层之间没有信息流。 +双向RNN的每一个训练序列,向前和向后分别是两个循环神经网络(RNN),而且都连接着一个输出层。这个结构提供给输出层:输入序列中每一个点完整的过去和未来的下文信息。下图展示的是一个按时间步展开的双向循环神经网络。该网络包含一个前向(forward)和一个后向(backward)RNN,其中有六个权值:输入到前向隐层和后向隐层($w_1, w_3$),隐层到隐层自己($w_2,w_5$),前向隐层和后向隐层到输出层($w_4, w_6$)。注意,该网络的前向隐层和后向隐层之间没有信息流。


@@ -76,40 +76,46 @@ GRU(Gated Recurrent Unit,门控循环单元)\[[1](#参考文献)\]是Cho #### 编码器 编码阶段分为三步: -- 独热编码(one-hot coding,1-of-K coding)表示:将源语言句子$x=\left \{ x_1,x_2,...,x_T \right \}$的每个词表示成一个向量$w_i\epsilon R^{\left | V \right |,i=1,2,...,T}$ (T暂不包括句子结束标记``)。这个向量的维度与词汇表大小$\left | V \right |$ 相同,并且只有一个维度上有值1(该位置对应该词在词汇表中的位置),其余全是0。 +- 独热编码(one-hot coding,1-of-K coding)表示:将源语言句子$x=\left \{ x_1,x_2,...,x_T \right \}$的每个词表示成一个向量$w_i\epsilon R^{\left | V \right |},i=1,2,...,T$ (T暂不包括句子结束标记``)。这个向量的维度与词汇表大小$\left | V \right |$ 相同,并且只有一个维度上有值1(该位置对应该词在词汇表中的位置),其余全是0。 - 映射到低维语义空间的词向量:独热编码表示存在两个问题,1)生成的向量维度往往很大,容易造成维数灾难;2)无法刻画词与词之间的关系(如语义相似性,也就是无法很好地表达语义)。因此,需再映射到低维的语义空间,由一个固定维度的稠密向量(称为词向量)表示。记映射矩阵为$C\epsilon R^{K\times \left | V \right |}$,用$s_i=Cw_i$表示第$i$个词的词向量,向量维度$K$通常取100-500之间。 -- 用RNN压缩源语言词序列:这一过程的计算公式为$h_i=\varnothing _\theta \left ( h_{i-1}, s_i \right )$,其中$h_0$是一个全零的向量,最后得到的$h_T$就是整个源语言句子的压缩表示。 +- 用RNN编码源语言词序列:这一过程的计算公式为$h_i=\varnothing _\theta \left ( h_{i-1}, s_i \right )$,其中$h_0$是一个全零的向量,最后得到的$h_T$就是整个源语言句子的编码。 + +编码阶段也可使用双向GRU,即一个词的隐层状态不仅编码了前面词的信息,还编码了后面词的信息。具体来说,前向GRU按照词序列$(x_1,x_2,...,x_T)$的顺序依次编码源语言端词,并得到一系列隐层状态$(\overrightarrow{h_1},\overrightarrow{h_2},...,\overrightarrow{h_T})$。类似得,后向GRU按照$(x_T,x_{T-1},...,x_1)$的顺序依次压缩源语言端词,得到$(\overleftarrow{h_1},\overleftarrow{h_2},...,\overleftarrow{h_T})$。最后对于词$x_i$,通过连接两个GRU的结果得到它的隐层状态,即$h_i=\left [ \overrightarrow{h_i^T},\overleftarrow{h_i^T} \right ]^{T}$。 + +

+
+图5. 使用双向GRU的编码器 +

#### 解码器 -解码阶段的总体思路是:根据源语言句子的压缩表示$c$、当前单词$u_i$和当前RNN隐层状态$z_i$,计算出下一个隐层状态$z_{i+1}$。然后用softmax归一化得到概率分布$p_{i+1}$,以此采样出单词$u_{i+1}$。不断重复上述操作,直到获得句子结束标记``或超过RNN循环次数为止。 +解码阶段的总体思路是:根据源语言句子的上下文向量(context vector)c、解码出来的第$i$个单词$u_i$和$i$时刻RNN的隐层状态$z_i$,计算出下一个隐层状态$z_{i+1}$,然后用softmax归一化得到概率分布$p_{i+1}$。训练模式时,根据$p_{i+1}$和目标语言词在字典中的标签计算代价,重复上述操作,直到目标语言序列中的所有词处理完毕。生成模式时,根据$p_{i+1}$采样出单词$u_{i+1}$,重复上述操作,直到获得句子结束标记``或超过句子的最大生成长度为止。 $z_i$的计算公式如下: + $$z_{i+1}=\phi _{\theta '}\left ( c,u_i,z_i \right )$$ -其中$c=h_T$是源语言句子的压缩表示,$z_0$是一个全零的向量,$u_0$是源语言句子的结束标记``。 + +其中$c=h_T$是源语言句子的上下文向量,$z_0$是一个全零的向量,$u_0$是源语言句子的结束标记``。 概率分布公式如下: + $$p\left ( u_i|u_{ -
-图5. 基于注意力机制的编码器 -

+可见,源语言句子的上下文向量由原来的$c$变成了第$i$个$c_i$,即针对每一个待解码的词$u_i$,都有一个特定的$c_i$与之对应。$c_i$的计算公式如下: -#### 基于注意力机制的解码器 +$$c_i=\sum _{j=1}^{T}\mathbf{a}_{ij}h_j, \mathbf{a}_i=\left[ \mathbf{a}_{i1},\mathbf{a}_{i2},...,\mathbf{a}_{iT}\right ]$$ -与简单的解码器不同,这里$z_i$的计算公式为: -$$z_{i+1}=\phi _{\theta '}\left ( c_i,u_i,z_i \right )$$ -可见,源语言句子的压缩表示由原来的$c$变成了$c_i$,即针对每一个目标词$y_i$,都有一个特定的$c_i$与之对应。其中$c_i$可以通过各个$h_i$的加权平均得到:$c_i=\sum _{j=1}^{T}\mathbf{a}_{ij}h_j$,$\mathbf{a}_i=\left[ \mathbf{a}_{i1},\mathbf{a}_{i2},...,\mathbf{a}_{iT}\right ]$为权重(具体权重计算公式见\[[3](#参考文献)\])。 +从公式中可以看出,注意力机制即是通过对各个$h_j$进行加权平均实现的,其中权重$a_{ij}$表示待解码的词$u_i$对每个源词语$h_i$不同程度的注意力。具体权重计算公式见\[[3](#参考文献)\]。


@@ -409,7 +415,7 @@ settings( size=word_vector_dim, param_attr=ParamAttr(name='_source_language_embedding')) ``` - 2.3 用双向GRU压缩源语言序列,将结果拼接成$\mathbf{h}$。 + 2.3 用双向GRU编码源语言序列,将结果拼接成$\mathbf{h}$。 ```python src_forward = simple_gru(input=src_embedding, size=encoder_size) @@ -420,13 +426,13 @@ settings( 3. 接着,定义基于注意力机制的解码器框架。 - 3.1 对源语言序列压缩后的结果,过一个前馈神经网络(Feed Forward Neural Network)。该层是3.3中`simple_attention`函数内部的一个计算步骤,但由于每个时间步该层的计算过程都一样,所以这里提取到外面单独计算以节省时间。 + 3.1 对源语言序列编码后的结果,过一个前馈神经网络(Feed Forward Neural Network)。该层是3.3中`simple_attention`函数内部的一个计算步骤,但由于每个时间步该层的计算过程都一样,所以这里提取到外面单独计算以节省时间。 ```python with mixed_layer(size=decoder_size) as encoded_proj: encoded_proj += full_matrix_projection(input=encoded_vector) ``` - 3.2 取源语言序列压缩后的最后一个词(即反向GRU的第一个词)传给解码阶段的RNN。即$\mathbf{c_0}=\mathbf{h_T}$。 + 3.2 取源语言序列编码后的最后一个词(即反向GRU的第一个词)传给解码阶段的RNN。即$\mathbf{c_0}=\mathbf{h_T}$。 ```python backward_first = first_seq(input=src_backward) @@ -439,7 +445,7 @@ settings( - decoder_mem记录了前一个时间步的隐层状态$z_i$,其初始状态是decoder_boot,即$\mathbf{z_0}=\mathbf{c_0}$)。 - context通过调用`simple_attention`函数,实现公式$c_i=\sum {j=1}^{T}\mathbf{a}{ij}h_j$。其中,enc_vec是$h_j$,enc_proj见3.1,权重$\mathbf{a}{ij}$的计算已经封装在`simple_attention`函数中。 - - decoder_inputs记录了针对该目标词的源语言句子的压缩表示$c_i$,和当前目标词current_word(即$u_i$)。 + - decoder_inputs记录了针对该目标词的源语言句子的编码$c_i$,和当前目标词current_word(即$u_i$)。 - gru_step通过调用`gru_step_layer`函数,在decoder_inputs和decoder_mem上做了激活操作,即实现公式$z_{i+1}=\phi _{\theta '}\left ( c_i,u_i,z_i \right )$。 - 最后,使用softmax归一化计算单词的概率,将out结果返回,即实现公式$p\left ( u_i|u_{