传统Seq2Seq+Attention实现机器翻译

实验软件和硬件环境:

1、 硬件环境:

个人PC
华为云 modelArts 云计算资源 CPU:8核 64GiB+GPU:1 * nvidia-p100

2、 软件环境:

Python 3.7
Tensorflow 1.8.0
Anaconda3
完整代码及数据有待更新上传


声明:创作不易,未经授权不得复制转载
statement:No reprinting without authorization


内容:

  1. 理解并实践神经机器翻译模型(英-中),用 TensorFlow 框架实现 seq2seq 神经网络中英文机器翻译模型
  2. 加入biRNN、Attention 机制并理解原理
  3. 比较不同模型的翻译结果,用 blue 指标评测翻译结果
    实验原理和方法:

一、基础模块原理介绍——Encoder到Decoder的Seq2Seq模型

Seq2Seq模型

(一)最基础的Seq2Seq模型包含了三个部分:

(1)Encoder
(2)Decoder
(3)连接两者的中间状态向量


Seq2Seq模型

Encoder通过学习输入,将其编码成一个固定大小的状态向量S,继而将S传给 Decoder,Decoder再通过对状态向量S的学习来进行输出。每一个box代表了一个RNN单元,通常是LSTM或者GRU

(二)传统seg2sea弊端:

1、编码为固定大小状态向量的过程实际上是一个信息“信息有损压缩”过程
2、随着sequence length的增加,意味着时间维度上的序列很长,RNN模型也会出现梯度弥散(使用LSTM或GRU解决),而且当输入序列非常长时,模型难以学到合理的向量表示。
3、连接Encoder和Decoder模块的仅仅是一个固定大小的状态向量,这使得Decoder无法直接去关注到输入信息的更多细节。

(三)改进:

加入Attention、Bi-directional encoder layer等

一、基础模块原理介绍——attention 和 biRNN 简单介绍

• Attention机制:打破了传统编码器-解码器结构在编解码时都依赖于内部一个固定长度向量的限制。
• 通过保留encoder对输入序列的中间输出结果,然后训练一个模型来对这些输入进行选择性的学习,并且在模型输出时将输出序列与之进行关联。
• 通俗的解释: attention机制就是将encoder的每一个隐藏状态设定一个权重,根据权重的不同决定decoder输出更侧重于哪一个编码状态。
• biRNN:使得当前的输出不仅可以利用之前的序列元素的信息,还可以依赖之后的序列元素的信息;对于NMT而言能充分利用“上下文”信息,提升翻译效果。

右为加入Attention

二、代码实现细节介绍 ——data set 数据集

• 中英平行语料:train.txt 80000对中英文平行语料 + valid.txt 2500对中英文平行语料
• 训练数据统计信息:

• -----English Text-----

• Number of sentences: 80000
• Average number of words in a sentence: 24.446491070178595
• Max number of words in a sentence: 54

• -----Chinese Text-----

• Number of sentences: 80000
• Average number of words in a sentence: 24.778384432311352
• Max number of words in a sentence: 96

• 中英平行语料:train.txt 80000对中英文平行语料 + valid.txt 2500对中英文平行语料
• 训练数据统计信息:

• 分词处理:

• 英文分词:使用NLTK工具包(nltk-3.4) 中文分词:使用pyltp工具包(0.2.1)

二、代码实现细节介绍——encoder端双向rnn代码实现

• 主要核心函数代码(基于tensorflow强大的工具包):
构建RNN单元:

single_cell = tf.contrib.rnn.BasicLSTMCell(num_units, forget_bias=forget_bias) 
# or tf.contrib.rnn.GRUCell(num_units)       [num_units为单元输出向量维度]
single_cell = tf.contrib.rnn.DropoutWrapper(cell=single_cell,input_keep_prob=1.0-dropout)  
# 可用来将dropout应用到rnn单元上

拼接构成biRNN:

num_bi_layers = num_layers // 2
fw_cell = self._build_encoder_cell(hparams, num_bi_layers)
bw_cell = self._build_encoder_cell(hparams, num_bi_layers)

bi_outputs, bi_state = tf.nn.bidirectional_dynamic_rnn(
                    fw_cell, bw_cell, encoder_emb_in, dtype=scope.dtype,
                    sequence_length=self.iterator.source_sequence_length,
                    time_major=True, swap_memory=True)
                
encoder_outputs = tf.concat(bi_outputs, -1)
bi_encoder_state = bi_state

Tf实现birnn的思想也很简单:


image.png

其实本质就是做了两次reverse:
• 第一次reverse:将输入序列进行reverse,然后送入dynamic_rnn做一次运算.
• 第二次reverse:将上面dynamic_rnn返回的outputs进行reverse,保证正向和反向输出 对应位置的 输入是一致的 是对上的.
• 最后合并output元组返回

二、代码实现细节介绍——Attention和Beam Search代码实现

Tf提供了库包装函数:

attention_mechanism = tf.contrib.seq2seq.LuongAttention( )
cell = tf.contrib.seq2seq.AttentionWrapper(cell, attention_mechanism,
                                                   attention_layer_size=num_units,
                                                   alignment_history=alignment_history,
                                                   output_attention=True,
                                                   name='attention')
my_decoder  = tf.contrib.seq2seq.BeamSearchDecoder(cell=cell, embedding …beam_width…)

二、代码实现细节介绍——对于Attention的理解与实现原理

• 将之前传统的只将最后一个rnn单元的输出传递给decoder,改为将序列上的每一个单元的输出信息都进行传递,并加以权重让其对decoder端的每个单元的输出产生影响。
• 通过在encoder和decoder之间构造一个隐藏的全连接网络来实现,将encoder的outputs输入该网络,输出权重信息(不同权重表示不同的attention),并在反向传播的同时也更新该全连接网络的权重,直到其生成的attention信息能很好的指导decoder解析生成正确的字符。
• Attention机制会使网络的参数增加,训练难度增加且更不易收敛,但其带来的收益也很大。

二、代码实现细节介绍——attention实现代码分析

image.png

补充:Teacher forcing 技巧——feeding the target as the next input (decoder序列位置1上输入<start>字符,而后每个位置上的输入并不以前一步的输出作为输入而是将真实值输入,可加快训练。

二、代码实现细节介绍——Beam Search集束搜索和mask

• Beam Search(集束搜索):在decoder解码选择单词时,每次只考虑前top B个结果,例如先找到句子第一个词的最可能B种,而后假设字典大小为10000,B=3,第二步时就有10000x3=30000种可能,选择前三种。B = 1时相当于贪婪搜索。
• Loss+mask:因为一个batch中句子的长度通常是不一样的,一个batch中不足长度的位置需要进行填充(pad)补0,最后生成句子计算loss时需要忽略那些原本是pad的位置的值,即只保留mask中值为1位置的值,忽略值为0位置的值。
• 函数:tf.sequence_mask()

三、实际训练调参及结果对比——可调的参数

•   是否加入attention
•   是否使用 birnn 构造 encoder
•   Encoder的层数
•   src_max_len:输入句子序列最大长度
•   tgt_max_len:输出句子序列最大长度
•   num_units:rnn单元输出维度
•   Optimizer:优化方法(sgd/adam)
•   learning_rate:学习率
•   num_train_steps:训练总轮数
•   init_weight:网络参数初始化权重参数
•   unit_type: LSTM or GRU
•   forget_bias:rnn单元参数初始化偏置
•   Dropout:(0.0 —1.0)
•   batch_size:批大小
•   beam_width:集束宽

三、实际训练调参及结果对比——一些影响较小的参数最优值

•    self.src_max_len = 50
•    self.tgt_max_len = 35
•    self.optimizer = ‘sgd’ (相比于自适应的跟可靠些)
•   self.num_train_steps = 50000
•    self.init_weight = 0.1
•    self.dropout = 0.2
•    self.batch_size = 128
•    self.beam_width = 5(训练时知道最优解用不到)
•     self.learning_rate = 0.2 (使用了learning_rate_decay,训练时会自动动态调整)
•    self.forget_bias = 1.0

三、实际训练调参及结果对比——结果对比

result

三、实际训练调参及结果对比——结果分析

• 1、attention 和 biRnn 的使用较显著的提升了结果。
• 2、适当的增加网络层数以及LSTM单元内部计算向量维度(也是输出维度num_units)能够对结果有一些提升,但是对于数据集较小时,不易太大,否则会不收敛等
• 3、RNN感觉还是比较神奇的,其训练也比其它网络一般更费时,一般都得10个epoch以上才完整收敛,但其实最终的模型大小也就几十M一般,不像一个cnn随便就上百M(可能受益于rnn单元的参数共享)。

三、实际训练调参及结果对比——部分结果展示

image.png

四、GUI设计与展示

• 利用pyqt搭建一个简单的Chinese-English的NMT应用,可以对输入的中文或英文利用已经训练好的model进行翻译。
• 输入示例:
• Chinese: 这件紧身T恤衫可显现你结实、线条优美的手臂和性感的肩膀。


image.png

• 输入示例:
• English: all our winchman are well trained and'skilled'skilful proficient practiced in handling winches .


image.png

五、实际训练调参及结果对比——Reference参考资料

1、理论知识参考

https://zhuanlan.zhihu.com/p/37148308 (传统Seq2Seq )
https://zhuanlan.zhihu.com/p/40920384 (Seq2Seq Attention模型)
https://zhuanlan.zhihu.com/p/37290775 (attention + birnn)
https://zhuanlan.zhihu.com/p/36029811?group_id=972420376412762112 (beam search)
https://blog.csdn.net/uhauha2929/article/details/83019995 (mask_loss)

2、代码参考:

https://github.com/VectorFist/RNN-NMT
https://github.com/OpenNMT/OpenNMT-tf
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb
https://github.com/NELSONZHAO/zhihu/tree/master/mt_attention_birnn

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335