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

Posted duye

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Machine Translation无监督神经机器翻译论述相关的知识,希望对你有一定的参考价值。

Unsupervised NMT

概述

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

  • 仅仅由两份单语语料(不平行)训练出双语词典。这个的核心是学习一个旋转矩阵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的UNMT研究

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

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

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

  • Unsupervised neural machine translation.
  • Unsupervised machine translation us- ing monolingual corpora only.

在解释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,但是:

有以下几点不同:

  • 不采用word,而采用bpe,即首先对语料bpe处理,以得到的每一个token为单位进行处理,最后得到token的词向量。
  • 之前的工作大都对两份语料分别训练词向量,这样就不得不再去学习双语词典。然而在本系统中,做法是将两份预料混合于同一份文件中,打乱,再bpe处理,直接得到双语embeddings,但这样做有个前提,两语言必须相近,如欧洲语系,否则就不得不学习双语词典。另外,值得注意的是,这样做时,用bpe比用word效果更好。
  • 共享所有。在两种语言中,前面已经对embeddings共享了,在论文Unsupervised neural machine translation中共享了encoder,但decoder没有共享,但在这里,包括encoder、decoder,不管是auto-encoding还是S->T/T->S翻译系统汇总,都完全共享,当然这样做了相应的也要进行一些额外的处理。实验发现,共享之后效果很好。
  • 上面提到有额外的处理,为了解释清楚,首先看下源码,我加了中文注释:
# 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()
  • 可以看到,模型的初始化是实现一个语言模型来实现的,这个语言模型和之前的语言模型是有差异的,具体 来说,它是最小化下面这个函数再加一个score层实现的:

技术分享图片

下面说明训练过程。

模型的初始化,实现一个语言模型来初始化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,于是我发邮件问了原作者,得到的回应是:

技术分享图片

其他细节:

  • 模型的词向量是通过fastText实现的。
  • 模型既用了LSTM,结构和Unsupervised machine translation us- ing monolingual corpora only相同,也用了transformer结构,这个我不清楚,但transformer效果更好。

以上是关于Machine Translation无监督神经机器翻译论述的主要内容,如果未能解决你的问题,请参考以下文章

On the use of BERT for Neural Machine Translation论文阅读

On the use of BERT for Neural Machine Translation论文阅读

神经网络机器翻译Neural Machine Translation: Encoder-Decoder Architecture

神经网络机器翻译Neural Machine Translation: Attention Mechanism

神经网络机器翻译Neural Machine Translation: Attention Mechanism

神经网络机器翻译Neural Machine Translation: Encoder-Decoder Architecture