基于Encoder-Decoder模式的机器翻译模型原理及实现

基于Encoder-Decoder模式的机器翻译模型原理及实现

关键词: Encoder-Decoder, LSTM, WordEmbedding

转换

在机器学习领域,有很多任务是把一种样式的序列映射成另外一种样式的序列,比如把一种语言翻译成另一种语言,把一段语音转换成一段文本,给一段文字生成一句话简介,或者把一张图片转换成一段对图片内容的文字描述等。这些任务都可以看作是Seq2Seq类型的任务,也就是从一个Sequence转换成另一个Sequence。对Seq2Seq类型的任务,经常采用Encoder-Decoder模型来解决。

理论背景

Encoder-Decoder方法最早在论文《Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation》中提出,该论文使用了两个RNN网络来完成机器翻译(Statistical Machine Translation: SMT)工作,第一个RNN网络把一串符号序列编码成一个固定长度的向量表示,第二个RNN网络把这个固定长度的向量解码成目标符号序列。通过联合训练这两个RNN网络,使得对于输入序列,得到输出序列的条件概率最大化,如下图所示:

Encoder-Decoder结构

该论文的另一个创新点是在RNN网络中首次使用了GRU网络节点(Gated Recurrent Unit),GRU节点和LSTM以及Bi-LSTM节点同属于RNN类型网络节点的变种,它们在计算输入序列中某个元素的输出时,会同时考虑这一步的输入,前一步或者后一步的输出等信息,相当于把序列中时序的信息包括进来,对于像是SMT这种有时序概念的输入效果显著。相比如LSTM和Bi-LSTM的三个状态门input-gate、forget-gate、output-gate,GRU简化成了两个状态门reset-gate和update-gate,过程更加简单。

LSTM计算公式

GRU计算公式

论文《Sequence to Sequence Learning with Neural Networks》在论文1的基础上,将Encoder过程的一层GRU隐藏层,改成四层的LSTM隐藏层,使得模型在处理长句子时效果更好,这很容易理解,LSTM相比GRU能学到序列中距离更远的两个元素之间的关联信息,而且层数越多,能记忆的信息也越多,所以处理长句子效果优于GRU。同时,该论文通过将输入序列倒序作为Encoder过程输入的方式,如输入序列“I like cat”倒序成“cat like I”,而Decoder顺序不变的方式,提高了Encoder的输出向量和Decoder结果之间的相关性,也起到了提升效果的作用。

前面提到的两篇论文有个共同点,它们通过Encoder处理输入序列生成固定长度的中间向量,该中间向量对Decoder过程输出序列中任意一个元素的作用都是均等的,比如将“I like cat”翻译成“我喜欢猫”时,翻译目标为“喜欢”或翻译目标为“猫”时,中间向量的作用是相同的,也就是一种注意力分散模型。
注意力分散模型
而实际上,翻译目标“喜欢”时“like”分量起的作用要大于“I”或者“cat”,同理翻译目标“猫”时“cat”分量作用要大于其他单词。为了弥补这个缺陷,论文《Neural Machine Translation by Jointly Learning to Align and Translate》提出了Attention机制,使得经过Encoder生成的中间向量包含了位置信息,在Decoder过程中处理不同输出序列时,不同位置的输入分量所占的权重不同,距离越近的元素权重越大,也就是所谓的注意力(Attention)越高。

注意力模型

通过这种方式,使得距离某个单词距离近的单词影响力高于距离远的单词的影响力,从而解决了这个问题。如将“Tom Chase Jerry”翻译成“汤姆追逐杰瑞”,在翻译“杰瑞”时,“Jerry”起到的作用肯定要比“Tom”“Chase”都要高。

注意力的例子

代码实现

接下来我们利用Tensorflow实现一个基于Encoder-Decoder架构的机器翻译模型,并对代码进行简要分析。

代码分为两个大的部分,train过程和predict过程,train过程代表训练过程,predict过程代表预测过程。本文将介绍train过程,predict过程类似。

Train过程根据Encoder-Decoder结构又分为两部分,Encoder部分和Decoder部分。

Encoder部分代码:

def build_encoder(self):
    encode_scope_name = 'encoder'
    with tf.variable_scope(encode_scope_name):
        # 构建单个的LSTMCell,同时添加了Dropout信息
        encode_cell = self.build_single_cell()

        ## 首先将原始输入替换成embedding表示,然后经过一个全连接的网络层,然后作为tf.nn.dynamic_rnn的输入
        # 生成初始化embedding矩阵
        self.encode_embedding = self.init_embedding(encode_scope_name)

        # 将输入句子转换成embedding表示
        self.encoder_inputs_embedded = tf.nn.embedding_lookup(params=self.encode_embedding, ids=self.train_encode_inputs)

        # 构造一个全连接层,含有hidden_units个隐藏节点
        fully_connected_input_layer = Dense(self.hidden_units, dtype=self.data_type, name='encoder_input_projection')

        # 将embedding数据过一遍全连接层,计算过程大致是:outputs = activation(inputs.kernel + bias) 
        self.encoder_inputs_embedded = fully_connected_input_layer(self.encoder_inputs_embedded)

        # 将这个embedding信息作为tf.nn.dynamic_rnn的输入
        self.encoder_outputs, self.encoder_output_state = tf.nn.dynamic_rnn(cell=encode_cell,
                                                                            inputs=self.encoder_inputs_embedded,
                                                                            sequence_length=self.train_encode_inputs_length,  # 存储每句话的实际长度
                                                                            dtype=self.data_type
  • 1
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值