【Machine Translation】无监督神经机器翻译论述

时间:2018-10-17 00:16:29   收藏:0   阅读:1120

Unsupervised NMT

概述

神经机器翻译系统取得了很好的翻译水平,但非常依赖于平行语料。目前已经有利用大量单语数据训练模型的研究,这其中包括:

Facebook的UNMT研究

在Facebook的论文Phrase-Based & Neural Unsupervised Machine Translation中对无监督机器翻译做了总结,他们将前人的无监督机器翻译系统的成功总结为以下三点:

  1. 初始化。通过近似翻译,对翻译系统认真初始化。例如有人通过双语词典,词到词的翻译初始化整个翻译系统,双语词典可以来自自己的学习,也可以利用一个已有的词典。
  2. 语言模型。利用语言模型提高翻译模型的质量,通过对句子加入噪声应用语言模型,衡量句子的自然程度,来提高翻译模型的质量。
  3. 迭代后向翻译。对S近似翻译生成T,将T后向翻译成S‘,S与S’的差异作为损失,训练T->S的翻译系统,反之亦然,迭代。

之后,Facebook提出了自己的无监督NMT系统,这项工作主要来源于两项前人工作,分别是:

在解释Facebook的模型之前,首先对这两篇论文的模型加以论述。

学习双语词典的过程示意图

技术分享图片

Unsupervised neural machine translation的研究

这个研究可以概括为下面这张图,解释的也很清楚。

技术分享图片

Unsupervised machine translation us- ing monolingual corpora only的研究

技术分享图片

技术分享图片下面提到的discriminator就是借鉴这里的,其作用描述为:

对抗学习。我们说了,我们就是要让中间语真正的成为一种“世界语言都通用的中间语言”,那么对于任何一个中间语词向量(就是encoder编码出的潜在共享表示),系统不该分辨出原输入到底是L1还是L2。这里采用了对抗学习的策略,引入一个discriminator,该辨别器(在该系统中就是一个二分类)就是用来辨别出中间语词向量来自于L1 or L2,那么,系统不断学习,通过”欺骗“这个discriminator,让discriminator越来越无法辨别,就达到了目的。因此,只要在此处也定义一个损失,该损失是discriminator辨别成功概率的负值,学习时考虑该损失,此问题也就得到了解决。

Facebook的研究

下面说明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,于是我发邮件问了原作者,得到的回应是:

技术分享图片

其他细节:

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!