标签:sync super val update seq img parallel += 来源
神经机器翻译系统取得了很好的翻译水平,但非常依赖于平行语料。目前已经有利用大量单语数据训练模型的研究,这其中包括:
仅仅由两份单语语料(不平行)训练出双语词典。这个的核心是学习一个旋转矩阵W,使得两份语料的词向量空间对齐,再进行一些调整更好的对齐两词向量空间,最后进行单词到单词的翻译,即生成了双语词典。
对偶学习的思想。有些研究里也提出迭代后向翻译,但思想是类似的,即通过翻译模型生成假的平行语料,再利用该平行语料训练模型,迭代此过程。
利用第三种语言。翻译模型依赖于大量的语料数据,但有些语言对的可用数据是很少的。这时,可以利用第三种语言如英语,训练A和英语翻译、B和英语翻译,从而实现A和B的翻译。值得注意的是,Google’s Multilingual Neural Machine Translation System实现了一对多和多对一翻译。
翻译系统多采用seq2seq结构,encoder将各种语言编码到特征空间,将其训练成“世界通用语言”,再由decoder翻译到指定语言。上面的Google’s Multilingual Neural Machine Translation System即根据添加一个标记“en-fr”指定系统是将en翻译到fr。类似的还有许多人研究了共享编码器、解码器参数的影响,发现效果不错。
去噪自编码器的使用,即将添加噪声的句子通过auto-encoding恢复自身。
用强的语言模型来优化翻译模型,语言模型衡量一个句子自然程度。
使用bpe而不是word,发现效果不错。
相关的研究还包括利用少量双语数据来优化/启动训练。
在Facebook的论文Phrase-Based & Neural Unsupervised Machine Translation中对无监督机器翻译做了总结,他们将前人的无监督机器翻译系统的成功总结为以下三点:
之后,Facebook提出了自己的无监督NMT系统,这项工作主要来源于两项前人工作,分别是:
在解释Facebook的模型之前,首先对这两篇论文的模型加以论述。
这个研究可以概括为下面这张图,解释的也很清楚。
下面提到的discriminator就是借鉴这里的,其作用描述为:
对抗学习。我们说了,我们就是要让中间语真正的成为一种“世界语言都通用的中间语言”,那么对于任何一个中间语词向量(就是encoder编码出的潜在共享表示),系统不该分辨出原输入到底是L1还是L2。这里采用了对抗学习的策略,引入一个discriminator,该辨别器(在该系统中就是一个二分类)就是用来辨别出中间语词向量来自于L1 or L2,那么,系统不断学习,通过”欺骗“这个discriminator,让discriminator越来越无法辨别,就达到了目的。因此,只要在此处也定义一个损失,该损失是discriminator辨别成功概率的负值,学习时考虑该损失,此问题也就得到了解决。
下面说明Facebook的模型
Facebook提出的UNMT主要结构类似于Unsupervised machine translation us- ing monolingual corpora only,但是:
# initialize experiment / load data / build model
logger = initialize_exp(params)
data = load_data(params)
#建立一个encoder、一个decoder、一个discriminator和一个lm(语言模型)
encoder, decoder, discriminator, lm = build_mt_model(params, data)
# initialize trainer / reload checkpoint / initialize evaluator
#初始化训练器,用上面建立的模型
trainer = TrainerMT(encoder, decoder, discriminator, lm, data, params)
trainer.reload_checkpoint()
trainer.test_sharing() # check parameters sharing
evaluator = EvaluatorMT(trainer, data, params)
# evaluation mode
if params.eval_only:
evaluator.run_all_evals(0)
exit()
# language model pretraining
# 语言模型预训练,语言模型使用过降噪自编码器实现的
if params.lm_before > 0:
logger.info("Pretraining language model for %i iterations ..." % params.lm_before)
trainer.n_sentences = 0
for _ in range(params.lm_before):
for lang in params.langs:
trainer.lm_step(lang)
trainer.iter()
# define epoch size
if params.epoch_size == -1:
params.epoch_size = params.n_para
assert params.epoch_size > 0
# start training
# 迭代训练
for _ in range(trainer.epoch, params.max_epoch):
logger.info("====================== Starting epoch %i ... ======================" % trainer.epoch)
trainer.n_sentences = 0
while trainer.n_sentences < params.epoch_size:
# 训练discriminator
for _ in range(params.n_dis):
trainer.discriminator_step()
# 训练语言模型
# lambda_lm是语言模型产生的loss作为总loss的系数,如果为0,则表明不训练语言模型了
if params.lambda_lm > 0:
for _ in range(params.lm_after):
for lang in params.langs:
trainer.lm_step(lang)
# MT training (parallel data)
# 平行语料模型训练,这是个可选项,可以用来加入一些双语预料训练模型,
# 也可以直接用来训练双语语料
if params.lambda_xe_para > 0:
for lang1, lang2 in params.para_directions:
trainer.enc_dec_step(lang1, lang2, params.lambda_xe_para)
# MT training (back-parallel data)
# 反向训练,双面是正向,这个是训练反向
if params.lambda_xe_back > 0:
for lang1, lang2 in params.back_directions:
trainer.enc_dec_step(lang1, lang2, params.lambda_xe_back, back=True)
# autoencoder training (monolingual data)
# 对每一个语言训练自编码,loss系数是lambda_xe_mono
# 值得注意的是,lambda_xe_mono是衰减的,
# 也即训练到最后,自编码的损失已经不考虑了,变成了完全训练翻译系统
if params.lambda_xe_mono > 0:
for lang in params.mono_directions:
trainer.enc_dec_step(lang, lang, params.lambda_xe_mono)
# AE - MT training (on the fly back-translation)
# 动态反向翻译
if params.lambda_xe_otfd > 0 or params.lambda_xe_otfa > 0:
# start on-the-fly batch generations
# 生成假的平行语料
if not getattr(params, ‘started_otf_batch_gen‘, False):
otf_iterator = trainer.otf_bt_gen_async()
params.started_otf_batch_gen = True
# update model parameters on subprocesses
# 在subprocess上更新模型参数,上面生成了平行语料
if trainer.n_iter % params.otf_sync_params_every == 0:
trainer.otf_sync_params()
# get training batch from CPU
# 得到训练的batch
before_gen = time.time()
batches = next(otf_iterator)
trainer.gen_time += time.time() - before_gen
# training
# 最重要的训练
for batch in batches:
lang1, lang2, lang3 = batch[‘lang1‘], batch[‘lang2‘], batch[‘lang3‘]
# 2-lang back-translation - autoencoding
if lang1 != lang2 == lang3:
trainer.otf_bt(batch, params.lambda_xe_otfa, params.otf_backprop_temperature)
# 2-lang back-translation - parallel data
elif lang1 == lang3 != lang2:
trainer.otf_bt(batch, params.lambda_xe_otfd, params.otf_backprop_temperature)
# 3-lang back-translation - parallel data
elif lang1 != lang2 and lang2 != lang3 and lang1 != lang3:
trainer.otf_bt(batch, params.lambda_xe_otfd, params.otf_backprop_temperature)
trainer.iter()
模型的初始化,实现一个语言模型来初始化encoder-decoder参数。
之后,模型进入迭代训练,每一步,都先训练discriminator,这个的作用就不说了,他实际上只更新了encoder参数,之后,再训练一次语言模型,更新参数,这是个可选项,默认不训练。然后训练auto-encoding,更新encoder和decoder参数,由于我们最后的目的是训练语言模型,这一步对整个encoder-decoder系统的作用其实是衰减的,由它产生的loss更新参数的影响越来越弱,直到最后只训练翻译模型。这里,对auto-encoding的loss的影响是通过参数--lambda_xe_mono实现的,它的默认值是lambda_xe_mono ‘0:1,100000:0.1,300000:0‘ ,表示迭代从0到100000,参数从1线性衰减到0.1,从100000到300000,参数从0.1线性衰减到0。
其他的过程就是不断生成伪双语数据和迭代后向翻译的过程,通过不断更新参数,最后训练的encoder-decoder既可以将S->T,又可以将T->S。很神奇,amazing。前面提到的Google’s Multilingual Neural Machine Translation System也是一个encoder-decoder,但他们的工作中至少添加了一个标记“en-fr”指示目标语言是什么,而Facebook竟然忽略了,最后效果还很好。
一开始我真不敢相信竟然只有一个encoder和decoder,于是我发邮件问了原作者,得到的回应是:
【Machine Translation】无监督神经机器翻译论述
标签:sync super val update seq img parallel += 来源
原文地址:https://www.cnblogs.com/duye/p/9800969.html