1.0 引言
机器翻译 (MT)是借机器之力「自动地将一种自然语言文本(源语言)翻译成另一种自然语言文本(目标语言)」[1]。使用机器做翻译的思想最早由 Warren Weaver 于 1949 年提出。在很长一段时间里(20 世纪 50 年代到 80 年代), 机器翻译 都是通过研究源语言与目标语言的语言学信息来做的,也就是基于词典和语法生成翻译,这被称为基于规则的 机器翻译 (RBMT)。随着统计学的发展,研究者开始将统计模型应用于 机器翻译 ,这种方法是基于对双语文本 语料库 的分析来生成翻译结果。这种方法被称为统计 机器翻译 (SMT),它的表现比 RBMT 更好,并且在 1980 年代到 2000 年代之间主宰了这一领域。1997 年,Ramon Neco 和 Mikel Forcada 提出了使用「编码器-解码器」结构做 机器翻译 的想法 [2]。几年之后的 2003 年,蒙特利尔大学 Yoshua Bengio 领导的一个研究团队开发了一个基于 神经网络 的 语言模型 [3],改善了传统 SMT 模型的数据稀疏性问题。他们的研究工作为未来 神经网络 在 机器翻译 上的应用奠定了基础。
1.1 神经 机器翻译 的诞生
2013 年, Nal Kalchbrenner 和 Phil Blunsom 提出了一种用于 机器翻译 的新型端到端编码器-解码器结构 [4]。该模型可以使用卷积 神经网络 (CNN)将给定的一段源文本编码成一个连续的向量,然后再使用循环 神经网络 (RNN)作为解码器将该状态向量转换成目标语言。他们的研究成果可以说是神经 机器翻译 (NMT)的诞生;神经 机器翻译 是一种使用 深度学习 神经网络 获取自然语言之间的 映射 关系的方法。NMT 的非线性 映射 不同于线性的 SMT 模型,而且是使用了连接编码器和解码器的状态向量来描述语义的等价关系。此外,RNN 应该还能得到无限长句子背后的信息,从而解决所谓的「长距离重新排序(long distance reordering)」问题 [29]。但是,「梯度爆炸/消失」问题 [28] 让 RNN 实际上难以处理长距依存(long distance dependency);因此,NMT 模型一开始的表现并不好。
1.2 用于长距问题的记忆
一年后的 2014 年,Sutskever et al. 和 Cho et al. 开发了一种名叫 序列到序列 (seq2seq)学习的方法,可以将 RNN 既用于编码器也用于解码器 [5][6],并且还为 NMT 引入了长短时记忆(LSTM,是一种 RNN)。在门机制(gate mechanism)的帮助下(允许在 LSTM 中删除和更新明确的记忆),「梯度爆炸/消失」问题得到了控制,从而让模型可以远远更好地获取句子中的「长距依存」。
LSTM 的引入解决了「长距离重新排序」问题,同时将 NMT 的主要难题变成了「固定长度向量(fixed-length vector)」问题:如图 1 所示,不管源句子的长度几何,这个 神经网络 都需要将其压缩成一个固定长度的向量,这会在解码过程中带来更大的复杂性和不确定性,尤其是当源句子很长时 [6]。
1.3 注意、注意、注意
自 2014 年 Yoshua Bengio 的团队为 NMT 引入了「注意力(attention)」机制 [7] 之后,「固定长度向量」问题也开始得到解决。 注意力机制 最早是由 DeepMind 为图像分类提出的 [23],这让「 神经网络 在执行预测任务时可以更多关注输入中的相关部分,更少关注不相关的部分」[24]。当解码器生成一个用于构成目标句子的词时,源句子中仅有少部分是相关的;因此,可以应用一个基于内容的 注意力机制 来根据源句子动态地生成一个(加权的)语境向量(context vector)(如图 2 所示,紫色线的透明度表示 权重 大小)。然后网络会根据这个语境向量而不是某个固定长度的向量来预测词。自那以后,NMT 的表现得到了显著提升,「注意力编码器-解码器网络」已经成为了 NMT 领域当前最佳的模型。
1.4 NMT vs. SMT
尽管 NMT 已经在特定的翻译实验上取得了惊人的成就,但研究者还想知道能否在其它任务上也实现这样的优良表现,以及 NMT 是否确实能取代 SMT。因此,Junczys-Dowmunt et al. 在「United Nations Parallel Corpus」 语料库 上进行了实验,该 语料库 包含 15 个语言对和 30 个翻译方向;而通过 BLEU 分数(一种自动评估 机器翻译 的方法,分数越高越好 [33])对实验结果的测定,NMT 在这所有 30 个翻译方向上都得到了与 SMT 媲美或更好的表现。此外,在 2015 年的 Workshop on Statistical Machine Translation(WMT)比赛上,来自蒙特利尔大学的这个团队使用 NMT 赢得了英语-德语翻译的第一名和德语-英语、捷克语-英语、英语-捷克语翻译的第三名 [31]。
与 SMT 相比,NMT 可以联合训练多个特征,而无需先验的领域知识,这可以实现 zero-shot 翻译 [32]。除了更高的 BLEU 分数和更好的句子结构,NMT 还有助于减少 SMT 上常见的形态学错误、句法错误和词序错误。另一方面,NMT 还有一些需要解决的问题和挑战:训练和解码过程相当慢;对同一个词的翻译风格可能不一致;在翻译结果上还存在「 超出词汇表 (out-of-vocabulary)」的问题;「黑箱」的 神经网络 机制的可解释性很差;训练所用的 参数 大多数是根据经验选择的。
1.5 军备竞赛已经开始
因为 NMT 的特性及其相对于 SMT 的优势,产业界最近也开始采用 NMT 了:2016 年 9 月,谷歌大脑团队发布了一篇博客宣布已经在谷歌翻译产品的汉语-英语语言对上开始使用 NMT 替代基于短语的 机器翻译 (PBMT,这是一种 SMT)。其部署的 NMT 名叫谷歌神经 机器翻译 (GNMT),他们也在同一时间发布了一篇论文 [9],对该模型进行了详细的解释。在此之后还不到一年时间(2017 年)内,Facebook 人工智能 研究院(FAIR)便宣布了其使用 CNN 实现 NMT 的方法,可以实现与基于 RNN 的 NMT 近似的表现水平 [10][11],但速度却快 9 倍。作为回应,谷歌在 6 月份发布了一个完全基于 注意力机制 (attention)的 NMT 模型;这个模型既没有使用 CNN,也没有使用 RNN,而是完全基于 注意力机制 [12]。
其它科技巨头也都各有动作。比如亚马逊刚在 7 月份发布了他们使用 MXNet 的 NMT 实现 [13];微软在 2016 年谈论过他们对 NMT 的应用,尽管目前还未披露进一步的技术细节 [27]。 IBM Watson ( 机器翻译 领域的老将)、英伟达( 人工智能 计算的领军者)和 SYSTRAN( 机器翻译 先驱)[35] 全都或多或少地参与到了 NMT 的开发中。在东亚地区,中国这个 人工智能 领域的新星正在升起,百度、网易有道、腾讯、搜狗、讯飞、阿里巴巴等许多公司甚至已经部署了 NMT。它们全都拼尽全力想在 机器翻译 的下一轮演进中取得竞争优势。
2.0 GNMT实战
在见证了NMT在一两年内如雨后春笋般涌现到如今百花齐放的盛装之后,作为一个有探索精神的机器智能媒体,我们不禁想亲自体验尝试一番。于是我们选择了Google Research 7月发布的“使用 Tensor Flow从零开始构建神经 机器翻译 模型”的教程,遵循该教程尝试搭建自己的神经 机器翻译 模型。而为了成功建立这个 神经网络 翻译机,教程本身以及与之相关文献的阅读必不可少,教程的地址是 https://github.com/tensorflow/nmt,相对应的核心论文是[9]。在总体阅读过相关的教程与文献之后,我们开始为实验配置环境,这里我们可以使用conda或者virtualenv创建一个虚拟环境。 我们选择了较新的python3(注意 Tensor Flow在Windows平台下仅支持python3),包含的package主要是numpy和tensorflow。注意教程的撰写基于Linux/MacOS操作系统,如在Windows平台使用则需要自行做相关修改与调整。
2.1 【越南语-英语】翻译实验
数据集
通过命令将教程资源库下载至本地,并且使用下面的命令下载相关数据集:
nmt/scripts/download_iwslt15.sh /tmp/nmt_data
这个bash脚本会下载出四套越南语与英语的语料文件分别作为:训练集(train, 用来训练模型),开发集(dev, 类似 验证集 ,用来评估模型准确度,防止 过拟合 ),测试集(test, 用来测试模型的最终效果),以及词汇库(vocab, 由 语料库 里提取出的单词组成,通常选取语料中出现频率最高的30,000个词汇以获得更好的性能)
训练
使用教程提供的代码直接开始训练,相关超 参数 设置均取默认值
mkdir /tmp/nmt_model python -m nmt.nmt --src=vi --tgt=en --vocab_prefix=/tmp/nmt_data/vocab --train_prefix=/tmp/nmt_data/train --dev_prefix=/tmp/nmt_data/tst2012 --test_prefix=/tmp/nmt_data/tst2013 --out_dir=/tmp/nmt_model --num_train_steps=12000 --steps_per_stats=100 --num_layers=2 --num_units=128 --dropout=0.2 --metrics=bleu
我们可以看到,源语言(src)设置为越南语,目标语言(tgt)设置为英语,因此翻译方向是从越南语到英语。除了相关文件夹的预设外,超 参数 (hparams)如num_train_steps,steps_per_stats,num_layers,dropout都是之后可以自行根据实际训练情况调整修改的。评估指标使用“bleu”,这是 机器翻译 领域常用的一个可以基于翻译出句子与参考标准翻译之间的相似度自动计算出分的评分系统,详情可以参考[37]。
训练过程中,会有log显示训练进程的概况,示例如下:
global step 124200 lr 0.125 step-time 0.45s wps 1.01K ppl 68.58 bleu 2.00 global step 124300 lr 0.125 step-time 0.45s wps 1.02K ppl 72.64 bleu 2.00 global step 124400 lr 0.125 step-time 0.44s wps 1.02K ppl 68.00 bleu 2.00 global step 124500 lr 0.125 step-time 0.43s wps 1.02K ppl 70.78 bleu 2.00 global step 124600 lr 0.125 step-time 0.44s wps 1.02K ppl 69.46 bleu 2.00 global step 124700 lr 0.125 step-time 0.44s wps 1.01K ppl 67.75 bleu 2.00
该log所示从左到右依次是:lr 是 学习率 ; step-time 是 跑一个mini-batch所耗费的时间; wps 是每秒钟r的单词数量; ppl代表混淆度( perplexity ),这是一个类似于训练损失的指标,数值越低越好; bleu是评估模型的主要依据,显示翻译效果,数值越高越好
当然我们也可以使用命令打开 Tensor board来更生动地查看模型训练的情况:
tensorboard --port 22222 --logdir /tmp/nmt_model/
Tensor Board
Tensor Board是 Tensor Flow內建的可视化工具,我们可以通过观测其中特定 参数 的图像走势(在我们这个实验中位于“SCALARS”标签下,参考图1)来理解、调试以及优化训练模型。例如说, 如果我们看到“dev_ppl”(指的是开发集的混淆度- perplexity ,越低越好)这个指标接近于0或者在某一个值附近波动了很久(与此同时,“dev_bleu”这个 参数 也应当开始稳定在某一个值附近了),那意味着保持这样的 参数 继续训练下去不会再有太大意义了,此时通常可以选择:1.调整 参数 如learning rate继续训练;2.停止训练,存储模型。
除此以外, Tensor Board还可以自动生成一个名字域的图像(在“GRAPHs”标签下查看)可以帮助用户理解当前的模型结构
翻译/推理
我们的首次尝试是在个人笔记本电脑上进行的,但考虑到真正的训练耗时较长且会需要一个相对稳定的环境,所以我们的训练很快就转到了一个服务器上(仅包含CPU,没有GPU)。
训练会在达到我们预设的步数后自动停止,我们也可以如前文提到的一样在观察到 收敛 的时候 提前停止 训练。在训练结束后,可以使用训练好的模型进行翻译任务,而这个翻译过程又可以被称之为推理/解码。只要已经有存储档案(一个.ckpt文件,会在每次验证步骤之完成时自动生成),翻译推理也可以在训练过程中进行。
-- src: Some weeks he has a dozen different nationalities to contend with , but we are an easy group - Swiss , German , American and British - which divides easily at meal@@ times into two English speaking tables , one German . ref: 数周 以来 , 他 已经 应付 了 来自 十几个 国家 的 游客 , 不过 我们 是 一群 容易 应付 的 人 ( 瑞士人 、 德国人 、 美国 人 和 英国人 ) , 在 用餐 时 分为 两@@ 桌 英语 人群 和 一桌 德语 人群 , 十分 方便 。 nmt: 我们 俩 有 两个 不同 的 美国 、 德国 、 德国 、 德国 、 美国 、 德国 、 德国 、 德国 、 德国 和 德国 的 国家 都 很 容易 , 但 也 有 了 一些 简单 的 国家 . -- src: Ramos made a statement before leaving Hong Kong , saying that he had a friendly and happy meeting with his old friends in Hong Kong , and they discussed how to advance peace and cooperation between the two countries as individuals . ref: 拉莫斯 在 离开 香港 前 发表声明 , 形容 早前 在 香港 与 老朋友 的 会面 气氛 友好 愉快 , 双方 以 私人 身份 探讨 了 如何 推进 中@@ 菲 之间 的 和平 与 合作 。 nmt: 记者 们 在 会议 上 发表 了 个 健康 的 会议 , 并且 讨论 了 一个 更 健康 的 建议 .
推理翻译的结果样式类似上图,其中“src”是原句,“ref”是参考标准翻译(通常为人类翻译),“nmt”是训练出的模型所做的 机器翻译 结果。
这个最基础的模型在我们的服务器上跑了大约6个小时,最终的bleu分数停留在1.2左右。至此,我们成功地将“训练一个神经 机器翻译 模型”的基本流程流程走了下来,而我们推测导致最终的bleu分数如此低的原因可能有两个:
- 模型比较基础简单且没有包含“注意力”机制
- 超参数 设定仅为默认值
调整与改进
为了提高翻译模型的、构建更先进的神经 机器翻译 器,我们首先尝试了加入“ 注意力机制 ”(超 参数 设置中“attention = scaled_luong”)然后在同个语料上进行训练,这时bleu分数从1涨到了5。这算是一个提升但仍旧是一个较低的水平。真正的突破发生在我们精调了超 参数 之后。我们根据教程“benchmark”部分的设定,除了保留LuongAttention之外,超 参数 num_units从128提升到了512,learning rate设置为前8000步保持1.0,8000步后开始每1000步减半。总的训练步数保留为12,000(大约12个epochs),详情见下表。在这样的改动下对同个 语料库 进行训练,最终训练好的模型bleu分数跃升至24。这基本是一个我们想要看到的结果,也与教程里的说明比较一致(平均23.3分),我们的实验重现也至此告一段落。
2.2 【英语-中文】翻译实验
鉴于我们已经依照教程实现了较为理想的越-英神经 机器翻译 ,接下来自然就进入到了英中翻译的实现探索,而这里的首要任务便是找到一个合适的语料/数据集。经过一番探索,我们最终锁定了CWMT/WMT17 [38]官方推荐的英中平行 语料库 之一“casict2015”。这个 语料库 包含了200万个英中语句对(sentence pair),我们用它作为训练集。至于开发集和测试集,由于WMT17比赛官方使用的dev dataset和test dataset里有包含中英语句对,因此我们可以直接使用。
预处理
不同于前面的越南语翻英语是基于已经处理好的语料,我们找的中英翻译用语料在训练和验证等使用前均需要先做预处理。根据GNMT作者在github上的推荐,我们直接修改repo上英德翻译预处理的文件 (wmt16_en_de.sh) 以实现相关的预处理如下:
- 数据集如果是sgm格式的先转换成raw text格式
- 分词:将句子切割为一个个单词(token)便于分析处理
- 数据清理:删除坏数据,忽略掉那些不利于帮助翻译的无效词语,限制单词长度等
- 子词拆分:进一步将词语拆分成更小单位的“子词单元”(例如:语素,音素)以一定程度上处理“罕见词问题” [14] [15] [39] [40]
前三个预处理均使用“mosesdecoder”实现,这是目前最为流行的一个开源统计 机器翻译 工具-Moses中包含的 [51]。最后一个预处理-子词拆分是通过学习词语的“字节对编码”(Byte Pair Encoding - BPE)压缩算法进行的,词汇库(vocabulary)在这之后生成。
训练,翻译,与改进
与我们在预处理时采取的策略类似,我们对于这里涉及到的超 参数 设置都是基于教程里的英德翻译设置(存储于repo的文件“wmt16.json”)而定的。由于仅使用CPU做计算,整个训练过程非常缓慢,且我们的最终训练出的模型只取得了不到1的bleu分数。为了加快训练进程以更有效地调整模型,我们开始使用亚马逊的AWS云服务(EC2)作为我们的训练平台(包含NVIDIA GRID K520 GPU),因为GPU特别适用于大量词汇库或大隐藏层情况下的运算。 请注意,在设置环境时需要安装GPU版本的 Tensor Folow,如果在使用普通游戏显卡的个人计算机上运行,还需要额外安装合适版本的CUDA / cuDNN等工具包 [41]。
在AWS平台设置好之后,我们首先再次尝试了越南语-英语的训练和翻译,同样语料与 参数 设置的情况下,成功训练出了一个可取得bleu大约25分的模型,这与我们上次的成功实验结果基本一致,而训练的速度则比先前在CPU服务器上训练时快了一倍。
在确认一切设置无误之后,我们从以下几个方面入手开始了中英翻译的改进实验:
- 优化对于语料的预处理步骤:为了更好地对汉字进行分词,我们尝选择了用jieba[42]来替换mosesdecoder中内置的tokenizer。此外,我们也对mosesdecoder自带其他工具中的一些设置做了调整。例如工具包中“lowercase”(小写化)默认是关闭的,我们在这里选择对英文的预处理中开启此选项。
- 更换语料库 /数据集:尽管我们已经转移到了AWS平台以求更快的训练速度,但对于包含百万语句对的语料库 ,以我们使用的GPU算力训练通常还是会耗费数天。因此,我们决定缩减训练语料的大小,在一个更小的语料“News Commentary v12”(NCv12)上进行测试调参。这个语料库 仅包含20,000个英中语句对,方便训练时观察模型参数 的优劣选择。
- 调整超参数 :根据我们在越南语-英语的翻译实验中的经验,不同的超参数 设置可能会极大地影响训练出模型的效果(英越翻译的bleu分数从5分跃升至24分)。Facebook甚至曾使用数个月的时间通过上千组实验来调试他们神经机器模型训练的相关超参数 [43]。从实际表现来看,我们基于官方英德翻译使用的参数 设置并不能带来好的结果,因此,我们通过阅读一些现有的涉及到中英神经机器翻译 实验的论文 [22][44][45][47][48][49][50] 总结出了一套超参数 设置方法如下作为参考,重新训练我们的模型:
讨论
首先要提及的一个问题是,在我们初次尝试在AWS上训练模型的时候,产生了显存不足导致的错误。相应地,我们通过减少词汇库的大小来适配现有显存的大小。除此之外,我们发现训练过程中定期的模型自评会占用很大的时间,因此我们减少了训练时模型自评的频率来加速训练,由此导致的一个副作用就是bleu分数在下一次模型自评之前不会更新。
上述实验结果反映,我们训练出最好的模型也只能取得一个bleu 5分左右的成绩,这离一个有可读性的神经 机器翻译 器(bleu分数通常在20以上)还有不小距离,为了取得更好的成绩,我们有两条路线可走:
- 尝试替换GNMT为一个可能对中文更友好的神经机器翻译 训练工具包(我们的目标由国内清华大学自然语言处理 小组基于Theano框架开发的THUMT [36]),参考其相关设置与步骤,调试参数 ,并将训练结果与GNMT做对比
- 将同样的参数 设置运用在一个大得多的语料库 上:由于我们最新的结果是基于只有20,000句对的 “NCv12”语料,相比参考文献中一些动辄包含百万语句对的语料还是比较小的,因此我们可能会挑选一个更大的语料来训练模型
考虑到训练所需的时间成本,我们大概率会选择第一个解决方案。我们非常欢迎大家参与到实战中来并与我们分享讨论你们的更新或感想。另外如果你们曾经follow过这个教程但是失败了,也可以再试一次,因为原作者一直在更新这个repo来修复各种各样的bug。
3.0 中英翻译深挖与探索
由于前面在GNMT上测试的中英翻译效果并不理想,为了改进英中神经 机器翻译 的性能,我们决定给其他的神经 机器翻译 框架一些机会,测试了THUMT、OpenNMT、 以及 Tensor 2 Tensor Transformers (来自“Attention is All You Need”)三个框架,最后根据学习到的知识回归GNMT。
我们采用统一的语料来测试所有框架,且所有的实验都在同一平台上运行,具体细节如下:
数据集: UM-Corpus
- 选取了其中: News, Thesis, Education, Science 四个domain的语料
- 语料大小: 1,470,000 sentence pairs
- Dev set: 从整个语料库 的前4000 句对中截取了1000句对;
- Test set:从整个语料库 的后4000 句对中截取了1000句对;
- Train set: 整个语料库 的其余部分
实验平台:Amazon AWS EC2, p2 instance
- GPU: Tesla K80, 11G vRam
3.1 THUMT
link: http://thumt.thunlp.org/
THUMT是一个开源的神经 机器翻译 工具系统,由清华大学“ 自然语言处理 与社会人文计算实验室”基于Theano开发。我们选择THUMT作为继GNMT后首个尝试测试的系统主要是考虑到其背后开发团队实力雄厚且THUMT在设计时就是为中英翻译而开发的。此外,THUMT提供了用户手册( http://thumt.thunlp.org/static/THUMT.pdf)使其安装和设置非常的简单直接,因此,我们这里省略其安装步骤而直接提供实验相关的设置、结果以及讨论。
我们用THUMT跑了两组实验,具体的实验相关设置如下
预处理
- Tokenize: 英文使用mosesdecoder,中文使用Jieba+mosesdecoder
mosesdecoder/scripts/tokenizer/tokenizer.perl -q -a -l en
mosesdecoder/scripts/tokenizer/tokenizer.perl -q -a -l zh
- Clean data: 使用mosesdecoder对中英文语料进行清理,删去无用或过长/过短的单词
mosesdecoder/scripts/training/clean-corpus-n.perl
- Lowercase: 对英文使用mosesdecoder进行小写化处理,只需在调用“clean-corpus-n.perl”时设置参数 lc为1即可
超参数 设置
超 参数 的设置可在“THUMT/config/THUMT.config”文件中修改,我们大部分使用默认设置,仅有以下几项 参数 我们第一次实验使用了不同的 参数 ,而后在第二次实验调整到了与建议 参数 几乎相同的设置。
实验结果
【实验1】使用MLE(Maximum Likelihood Estimation, 最大似然估计 )跑到23W步左右时开始出现Nah故障(如下),bleu分数停在10分多;
[31 Aug 17:23:22 DEBUG] iteration 234648: cost = nan, grad_norm = nan, iter_time = 0.767, total_time: 70.337 hr [31 Aug 17:23:23 WARNING] There is an NaN!
我们紧接着读取最近的一个checkpoint使用MRT (Minimum Risk Training,最小风险训练)继续跑了3W步左右分数稳定在 11.6分上下便不再增长了。
【实验2】后来我们根据官方指导修改了超 参数 设置,起步效果好于实验1,但很快bleu score便不再增长,最终因停留在 8.43太久而被程序自动终止了训练(如下),与实验1不同的是这次实验并没有出现NaN故障
[03 Sep 21:02:12 INFO] iter 140000: 8.43 [03 Sep 21:02:12 INFO] Done! [03 Sep 21:02:12 INFO] No improvement for 100000 iterations. Stop training. [03 Sep 21:02:12 INFO] Saving model and status [03 Sep 21:02:19 INFO] The training is completed.
这里也可以看出THUMT的设置是100,000个iteration没有improvement的情况下训练会自动停止。
讨论
在实验过程中,我们不可避免地产生了一些问题和疑惑,都幸运地得到了来自清华THUMT开发团队的刘洋教授和张嘉成博士的解答,主要经验体现在如下几个方面:
关于数据集
在整个实验过程中,寻找一个合适的数据集十分不易,尤其是对于在这个领域没有太多经验的用户。我们通过实验也可以看出不同的 语料库 使用同样的系统出来的翻译效果也是各有不同,难以捉摸其规律。经清华(THU)学者确认,“ 语料库 对结果的影响很大,即使size差不多,领域的区别也能产生很大的差别”。而就学术界来说,不同的研究机构似乎都有着各自喜好的 语料库 (主要来源于LDC这个会员制付费平台),尤其在WMT官方还未开始发布中英翻译语料的时候。最近这一届WMT开始加入中英文 语料库 有望改变研究用 语料库 相对封闭这一现象。
除了 语料库 本身的选择之外,开发集和测试集的选择方面也有一定的弹性。一方面,开发、测试和训练集可以与训练集一起直接从一个统一的大语料里划分出来;另一方面,可以从别处另外选取相对独立的小语料作为开发和测试集。学术方面一般建议第一种方法保证测试集质量的同时方便不同实验配置下的横向比较。而据THU学者表示,他们在 中英翻译的任务上“通常会采用nist2002~nist2008中英评测集,这个测试集在翻译研究中比较常用,并且其每句中文对应4句英文参考译文,评测会更为准确。使用多参考译文情况下评测的BLEU值从数值上会比使用单参考译文会高很多。”所以对于有条件的用户或学者,还是推荐在这些数据上进行测试。
关于预处理
分词(tokenization)、数据清理(data clearn)、小写化处理(lowercase)均是常规的预处理步骤。BPE作为英文subword的工具,这里我们并没有使用,一是考虑到其比较耗时,二是不确定其对中文翻译效果的影响程度;而据THU学者表示,“BPE在某些情况下可能会有点帮助,不过提升不关键。” 这些均可以在数据进入THUMT系统之前作为预处理步骤进行,因此其官方手册里也并未提及。
关于超参数 设置
这里我们首先想谈的是batch size这个通常受硬件性能制约而又会很大程度上影响翻译质量的超 参数 。起初,我们的实验使用的是亚马逊AWS的g2实例,显存只有3G,当时我们使用THUMT在另一个数据集(ncv12)上只跑到了bleu 5分多的成绩;升级GPU后由于显存增大,我们换了更大的UM-corpus同时将batch size从4调整到了16,才有了前面的结果。我们由此推测影响结果的原因很可能在于① 语料库 变大了或者②batch size增大了。而根据清华学者的经验,“batch size太小(比如小于10或20)会严重损害翻译质量,但是batch size也不是越大效果越好,80的batch size足够了,继续增加对BLEU值影响不大。”
另一个值得一提的超 参数 是Adam Alpha,这其实就是使用Adam optimizer 时的 学习率 learning rate。THUMT中并没有使用其他框架中常见的衰减机制,而是用了冷启动(即没有设置adam alpha decay),因此训练初期的adam alpha会很低,然后在几千个iteration内逐渐恢复到配置中设置的数值。据THU研究者说明“这样会一定程度上缓解出现NAN的情况,不过并不能根治。NAN的出现和数据、超 参数 都有一定的关系,同时也具有一定的随机性(相同配置的两次实验可能一次出现NAN,一次不出现NAN),目前我们还没有办法准确地追踪到NAN出现的问题根源。下一个版本的THUMT中会增加dropout的功能,据我们观察dropout也能一定程度上减少NAN的出现。”同时他们也确认了正在对带衰减的方法进行实验,如果有效的话会加入到新版本THUMT中。
关于其他超 参数 的设置,我们在第二次实验的设置基本就是对前人实验的一个总结,初学者摸不清内在原理的时候可以考虑直接沿用,通常可以取得不错的效果。
结论
使用THUMT后,我们在中英翻译的道路上将最高Bleu分提升到了两位数,最高11.6分;而由于THUMT实验指导的步骤清晰明确, 参数 设置也统一,其开发团队在自己的数据集上是可以轻松取得20以上的高分的;因此我们目前认为最有可能导致低分的问题出在前期 语料库 本身的选择上,THU研究者也指出:“① 有条件的话使用公开的、常用的开发测试集; ② “有可能在前4000句中集中出现数据质量不高或数据bias的问题,可以将抽取方法改为从全数据中随机抽1000条”;③“MRT应该选择一个开发集上BLEU值最高的点开始训,而不是最近的一个checkpoint”
3.2 OpenNMT
link: http://opennmt.net/
OpenNMT是由Harvard和SYSTRAN合作开发的一个开源神经 机器翻译 工具,会考虑OpenNMT主要是由于其流行度。该工具基于Torch/PyTorch开发,有着广泛的受众以及活跃的社区。
预处理
Tokenization/分词、clean同THUMT,直接调用了mosesdecoder,而lowercase我们直接在OpenNMT自带的“preprocess.py”中进行了设置,划词并生成训练和开发集
python preprocess.py -lower -train_src ~/um_data/zh-en-training/train.tok.clean.en -train_tgt ~/um_data/zh-en-training/train.tok.clean.zh -valid_src ~/um_data/zh-en-training/dev.tok.clean.en -valid_tgt ~/um_data/zh-en-training/dev.tok.clean.zh -save_data data/zh-en
超参数 设置
由于我们测试的目的是对比不同NMT系统能力的差异,因此超 参数 主要参考THUMT中最终得出的标准进行设置,主要的 参数 设置如下:
-layers 2 -word_vec_size 620 -rnn_size 1000 -brnn_merge concat -batch_size 80 -epochs 20 // 这里每个epoch的步数是自动的 -optim adam -max_grad_norm 5 -dropout 0.2 -learning_rate 0.0005 -learning_rate_decay 0.998 -start_decay_at 10 // 从epoch 10开始递减learning rate
实验结果
不同于前面测试过的THUMT和GNMT会隔一段时间自动算分,OpenNMT默认的log只有accuracy的记录,并无bleu score。因此需要手动在需要时使用代码进行翻译并计算bleu分数
翻译:
python translate.py -model zh-en-model_acc_40.61_ppl_41.60_e3.pt -src ~/um_data/zh-en-training/dev.tok.clean.en -output output.zh -beam_size 10 -batch_size 10 -max_sent_length 80
调用mosdecoder计算Bleu score:
mosesdecoder/scripts/generic/multi-bleu.perl
实验结果基本与THUMT相似,经过若干epoch (这里epoch自动被设置为约18000 steps),得到的结果是:
BLEU = 6.27 BLEU = 7.44 BLEU = 8.25 BLEU = 8.64
3.3 Tensor 2 Tensor
link: https://github.com/tensorflow/tensor2tensor
Tensor 2 Tensor (T2T)是一个相对特殊的library,不同于前面使用过的基于两个RNN的GNMT、THUMT、 和OpenNMT,T2T是完全基于attention机制的,详情可以参考"Attention Is All You Need"这篇paper [12]。
环境配置
因为是完全不一样的framework,所以需要先配置环境,可以直接pip安装tensorflow和tensor2tensor
# Installs with tensorflow-gpu requirement pip install tensor2tensor[tensorflow_gpu]
或
# Installs with tensorflow (cpu) requirement pip install tensor2tensor[tensorflow]
安装之后通过 `t2t-trainer —registry_help` 看到各种配置好的任务,这里由于t2t是一个可以用于多种不同任务的framerwork(除 机器翻译 外,还可用于摘要、图像生成等任务),因此需要专门针对我们的需求配置任务,而tensor2tensor自身由社区添加了以wmt17为基础的英中翻译任务,使用的是我们先前尝试过的NC-v12语料,我们没有直接对其进行测试。而是依据其代码(tensor2tensor/tensor2tensor/data_generators/wmt.py)并参考了之前THUMT测试的 参数 进行设置,使用UM-corpus数据进行了测试,便于对比。
使用类装饰器 `@registry.register_problem`添加试验任务,以及函数装饰器`@registry.register_hparams`添加试验超 参数 。
之后在文件夹中添加`__init__.py`并import相对应文件,再次使用指令`t2t-trainer —registry_help`即可看到自定义试验以及超 参数 组:
HParams: translate: * translate_enzh_hparams_thumt ... Problems: translate: * translate_en_zh
实验的环境配置至此完成,具体可设置的超 参数 组可以参考`tensor2tensor/tensor2tensor/layers/common_hparams.py`和`tensor2tensor/tensor2tensor/models/transformer.py`
预处理
这里的划词部分我们可以通过自定义class Problem中的method generator函数来实现:
def generator(self, data_dir, tmp_dir, train): source_vocab_size = self.targeted_vocab_size target_vocab_size = self.targeted_vocab_size source_vocab = generator_utils.get_or_generate_txt_vocab( data_dir, vocab.%d.en % source_vocab_size, source_vocab_size, [train.tok.clean.en]) target_vocab = generator_utils.get_or_generate_txt_vocab( data_dir, vocab.%d.zh % target_vocab_size, target_vocab_size, [train.tok.clean.zh]) return bi_vocabs_token_generator( os.path.join(data_dir, train.tok.clean.en), os.path.join(data_dir, train.tok.clean.zh), source_vocab, target_vocab, EOS)
调用工具 t2t-datagen生成相应数据集:
t2t-datagen --t2t_usr_dir=~/t2t --data_dir=~/zh-en-training --tmp_dir=/tmp --problem=translate_en_zh
训练与结果
t2t-trainer --t2t_usr_dir=~/t2t --hparams_set=translate_enzh_hparams_thumt --problems=translate_en_zh --data_dir=~/zh-en-training --output_dir=~/t2t_zh-en --model=transformer --train_steps=360000 --local_eval_frequency=10000 --keep_checkpoint_max=5
t2t可以自行计算bleu score, 由于时间关系我们对tensor2tensor的试验只限于自定义试验的成功的运行。而鉴于初次测试训练结果一直停滞在Bleu score 0.85,我们没有耗费资源继续实验下去,而是回到了最初的GNMT。
3.4 Back2GNMT
在尝试过不同的framework后,我们对NMT的整体理解以及 参数 设置有了一个更加深入的认识,鉴于尝试不同框架并没有带来显著的提升(THUMT是其中效果最好的),我们决定带着学习到的 参数 设置知识,回到GNMT的训练,尤其是在我们更新了运行平台,可以匹配大部分同类实验 参数 设置的情况下。
预处理
实验依旧采用UM-corpus,进行如下预处理。
- 分词:使用 OpenNMT/tools中的tokenize.lua 脚本
-- 中文分词命令:
OpenNMT/tools/tokenize.lua -segment_alphabet_change -segment_alphabet Han < file > file.tok
-- 英文分词命令:
OpenNMT/tools/tokenize.lua -segment_alphabet_change < file > file.tok
- 数据清理:这里依然使用mosesdecoder:
mosesdecoder/scripts/training/clean-corpus-n.perl
- 生成词汇库:使用脚本 OpenNMT/tools/build_vocab.lua
OpenNMT/tools/build_vocab.lua -data file -vocab_size 30000
生成了30,000大小的词汇库。值得一提的是OpenNMT这个脚本生成词汇库的速度远远超过先前使用的subword-nmt包中的脚本 “get_vocab.py”。
超参数 设置
实验的超 参数 设置如下,基本参照THUMT的推荐设置
--num_units=620 --num_layers=2 --batch_size=64 --encoder_type=gnmt --attention=scaled_luong --attention_architecture=gnmt_v2 --unit_type=lstm --pass_hidden_state=true --optimizer =adam --learning_rate=0.0005 --num_train_steps=150000 --colocate_gradients_with_ops=true --init_op=uniform --init_weight=0.1 --forget_bias=1.0 --num_buckets=5 --beam_width=10 --dropout=0.2 --length_penalty_weight=1 --max_gradient_norm=5
实验结果与讨论
step 10000: ppl 37.32 bleu 4.02 step 30000: ppl 16.76 bleu 16.23 step 50000: ppl 9.08 bleu 19.40 step 70000: ppl 8.12 bleu 19.79 step 90000: ppl 8.69 bleu 20.41 step 110000:ppl 8.69 bleu 20.65
实验最终跑出了一个可以得到20.65相对高分的模型,我们将其相关 参数 设置与之前测试过的OpenNMT, THUMT和最初的GNMT实验做了一个横向对比如下:
可以看出,在模型原理相差不大的情况下, 参数 的设置以及语料的选择对训练的结果着实影响巨大,而最初我们效果不理想的原因可能二者兼有。此外,这些工具包的不断的自我更新也可能是导致翻译质量差距的原因之一。例如我们在GNMT实验中就曾遇到过同样设置第一次运行报错第二次运行成功的情况,而THUMT也在近期发布了其基于 Tensor Flow的实现并作为主推,相信可以取得更好的翻译效果。鉴于我们对目前总结出的 参数 设置已经比较有信心了,如果想要进一步提高模型的翻译质量,下一步还能比较容易做到的则是更换并扩大训练用语料。因此,有在上述基于包含2.2M句对的UM-Corpus实验的基础上,我们尝试了一个更大的数据集(AI Challenger [52],共9,903,244个语句对),并保持其他所有 参数 设置与先前一致,短暂的训练后确实也取得了一个更高的分数(如下)。
step 10000: ppl 14.48 bleu 9.66 step 20000: ppl 13.41 bleu 12.64 step 35000: ppl 12.46 bleu 16.08 step 45000: ppl 9.64 bleu 19.47 step 55000: ppl 9.97 bleu 23.02 step 66000: ppl 7.65 bleu 24.42 step 78000: ppl 8.38 bleu 25.10 step 90000: ppl 7.43 bleu 25.80 step 100000: ppl 7.24 bleu 26.06 step 110000: ppl 6.67 bleu 26.46
此模型做出的翻译已经基本达到了一个可阅读的效果,因此我们的中英神经 机器翻译 实验到此正式告一段落。总体来说,GNMT工业化应用比较成熟,且教程配合理论的解释比较具体,加之其可视化工具 Tensor board,较适合新手初尝NMT时实践;OpenNMT有着SYSTRAN和Harvard双重背书,加之开源较早,有一定的用户基础,forum比较活跃;而对于国内用户,尤其是对于中文相关的NMT任务,THUMT则会是一个更好的切入方向。完全基于 注意力机制 的 Tensor 2 Tensor (Transformer)需要更多的深入研究,习惯使用 MXNet 的用户可以考虑Amazon基于 MXNet 的Sockeye,其官方也发表了较为详细的教程[13];而Facebook基于CNN的Fairseq则适合更熟悉CNN结构的人尝鲜使用[10][11]。
4.0 NMT 就是未来吗?
在高速发展和高度竞争的环境中,NMT 技术正在取得显著的进展。在最近的 ACL 2017 会议上, 机器翻译 类别下接收的 15 篇论文全都与神经 机器翻译 有关 [34]。我们可以看到 NMT 还将在许多方面得到不断完善,其中包括:
- 罕见词问题 [14][15]
- 单语言数据使用 [16][17]
- 多语言翻译/多语言 NMT [18]
- 记忆机制 [19]
- 语言融合 [20]
- 覆盖问题 [21]
- 训练过程 [22]
- 先验知识 融合 [25]
- 多模态翻译 [26]
因此,我们有足够的理由相信 NMT 还将取得更大的突破,还将替代 SMT 逐渐发展成主流的 机器翻译 技术,并在不久的将来让全社会受益。
One more thing
为了帮你了解 NMT 的神奇之处,我们列出了一些 NMT 的开源实现,它们使用了不同的工具:
- Tensor flow [Google-GNMT]: https://github.com/tensorflow/nmt
- Torch [Facebook-fairseq]: https://github.com/facebookresearch/fairseq
- MXNet [Amazon-Sockeye]: https://github.com/awslabs/sockeye
- Theano [NEMATUS]: https://github.com/EdinburghNLP/nematus
- Theano [THUMT]: https://github.com/thumt/THUMT
- Torch [OpenNMT]: https://github.com/opennmt/opennmt
- PyTorch [OpenNMT]: https://github.com/OpenNMT/OpenNMT-py
- Matlab [StanfordNMT]: https://nlp.stanford.edu/projects/nmt/
- DyNet-lamtram [CMU]: https://github.com/neubig/nmt-tips
- EUREKA [MangoNMT]: https://github.com/jiajunzhangnlp/EUREKA-MangoNMT
如果你有兴趣进一步了解 NMT,我们鼓励你阅读参考文献中列出的论文:[5][6][7] 是必读的核心论文,能帮你了解什么是 NMT;[9] 是 NMT 的机制和实现的全面展示。此外,在人工智能站最近发布的《 人工智能 技术趋势报告》中, 机器翻译 也是一个重要篇章。
参考文献
[1] Russell, S. , & Norvig, P. (2003). Artificial Intelligence: A Modern Approach.
[2] Neco, R. P., & Forcada, M. L. (1997, June). Asynchronous translations with recurrent neural nets. In Neural Network s, 1997., International Conference on (Vol. 4, pp. 2535-2540). IEEE.
[3] Bengio, Y., Ducharme, R., Vincent, P., & Jauvin, C. (2003). A neural probabilistic language model. Journal of machine learning research, 3(Feb), 1137-1155.
[4] Kalchbrenner, N., & Blunsom, P. (2013, October). Recurrent Continuous Translation Models. In EMNLP (Vol. 3, No. 39, p. 413).
[5] Sutskever, I., Vinyals, O., & Le, Q. V. (2014). Sequence to sequence learning with neural networks. In Advances in neural information processing systems(pp. 3104-3112).
[6] Cho, K., Van Merriënboer, B., Gulcehre, C., Bahdanau, D., Bougares, F., Schwenk, H., & Bengio, Y. (2014). Learning phrase representations using RNN encoder-decoder for statistical machine translation. arXiv preprint arXiv:1406.1078.
[7] Bahdanau, D., Cho, K., & Bengio, Y. (2014). Neural machine translation by jointly learning to align and translate. arXiv preprint arXiv:1409.0473.
[8] A Neural Network for Machine Translation, at Production Scale. (2017). Research Blog. Retrieved 26 July 2017, from https://research.googleblog.com/2016/09/a-neural-network-for-machine.html
[9] Wu, Y., Schuster, M., Chen, Z., Le, Q. V., Norouzi, M., Macherey, W., ... & Klingner, J. (2016). Googles neural machine translation system: Bridging the gap between human and machine translation. arXiv preprint arXiv:1609.08144.
[10] Gehring, J., Auli, M., Grangier, D., & Dauphin, Y. N. (2016). A convolutional encoder model for neural machine translation. arXiv preprint arXiv:1611.02344.
[11] Gehring, J., Auli, M., Grangier, D., Yarats, D., & Dauphin, Y. N. (2017). Convolutional Sequence to Sequence Learning. arXiv preprint arXiv:1705.03122.
[12] Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., … & Polosukhin, I. (2017). Attention Is All You Need. arXiv preprint arXiv:1706.03762.
[13] Train Neural Machine Translation Models with Sockeye | Amazon Web Services. (2017). Amazon Web Services. Retrieved 26 July 2017, from https://aws.ama