[机器翻译]——pivot-based zero-shot translation based on fairseq

news2025/1/17 6:19:36

文章目录

  • 前言
  • 翻译到en
    • 生成"伪"的、到英语的数据文件
    • 把每一个zs语言对翻译到en
    • 从fairseq-generate生成的文件中,抽取纯en文件
  • 把en数据和所有zs语言对的tgt数据形成平行语料,然后做预处理
    • 形成en到tgt的平行语料
    • 预处理
  • 在en到tgt语言的"伪"平行语料上评估pivot zs translation的性能
  • direct zs translation VS pivot-based zs translation

前言

由于any2en和en2any的同时训练,一方面,encoder端将不同语种编码成国际语(靠近英语?);另一方面,decoder具备把encoder输出翻译成任意一种语言的能力,因此,multilingual translation model具备any2any的翻译能力。由于实际并没有使用除了以英语为中心以外的平行语料进行训练,这种翻译又被称为zero-shot translation。
multilingual translation model做zero-shot translation主要有两种方式:

  • direct zs translation:即直接把要翻译的tgt语种告诉decoder,直接生成(会出现严重的off-target问题)
  • pivot-based zs translation:即先把src翻译成en,再把en翻译成tgt(一个强zs translation baseline)

本文记录使用fairseq工具,完成pivot-based zs translation的代码步骤。考虑de-fr的pivot-based zero-shot translation,主要分为以下三步:

  • 把de的语料翻译成en
  • 对翻译得到的en做预处理,并和fr的语料组成平行语料
  • 在en-fr的"伪"平行语料上评估zs translation的性能

本文使用opus100,考虑的zs语言对为:ar-de ar-fr ar-nl ar-ru ar-zh de-fr de-nl de-ru de-zh fr-nl fr-ru fr-zh nl-ru nl-zh ru-zh de-ar fr-ar nl-ar ru-ar zh-ar fr-de nl-de ru-de zh-de nl-fr ru-fr zh-fr ru-nl zh-nl zh-ru
假设我们已经对zs的数据进行了bpe-encode,binarize(fairseq-preprocess)等操作,即,已经有zs数据的data-bin文件:
在这里插入图片描述
下面开始!

翻译到en

生成"伪"的、到英语的数据文件

我们首先使用上述的data-bin-zero-shot文件夹,对于每一个语言对(如ar-de),来生成一个"伪"的、到英语的数据文件(对应为ar-en)。

具体运行如下代码:

# general_scripts/opus100/create_pivot_data.py
import argparse
import os
import json
import shutil

def parse_opt():
    parser = argparse.ArgumentParser()
    parser.add_argument('--zero-shot-data-bin', type=str, default="data/opus-100-corpus/v1.0/data-bin-zero-shot")
    parser.add_argument('--save-path', type=str, default="data/opus-100-corpus/v1.0/fake-to-en-data-bin-zero-shot")
    parser.add_argument('--zero-shot-langs', type=str, default="ar,de,fr,nl,ru,zh")
    return parser.parse_known_args()[0]


def main():
    opts = parse_opt()
    zero_shot_data_bin = opts.zero_shot_data_bin
    zero_shot_langs = opts.zero_shot_langs.split(",")
    save_path = opts.save_path

    for src in zero_shot_langs:
        for tgt in zero_shot_langs:
            if src == tgt:
                continue
            st_src, st_tgt = sorted([src, tgt])
            lang_pair = f"{src}-{tgt}"
            lang_pair_dir = os.path.join(save_path, lang_pair)
            os.makedirs(lang_pair_dir, exist_ok = True)
            # dict
            old_path = os.path.join(zero_shot_data_bin, f"dict.{src}.txt")
            new_path = os.path.join(save_path, lang_pair, f"dict.{src}.txt")
            shutil.copyfile(old_path, new_path)
            shutil.copyfile(new_path, os.path.join(save_path, lang_pair, f"dict.en.txt")) # fake
            # bin
            old_path = os.path.join(zero_shot_data_bin, f"test.{st_src}-{st_tgt}.{src}.bin")
            new_path = os.path.join(save_path, lang_pair, f"test.{src}-en.{src}.bin")
            shutil.copyfile(old_path, new_path)
            shutil.copyfile(new_path, os.path.join(save_path, lang_pair, f"test.{src}-en.en.bin")) # fake
            # idx
            old_path = os.path.join(zero_shot_data_bin, f"test.{st_src}-{st_tgt}.{src}.idx")
            new_path = os.path.join(save_path, lang_pair, f"test.{src}-en.{src}.idx")
            shutil.copyfile(old_path, new_path)
            shutil.copyfile(new_path, os.path.join(save_path, lang_pair, f"test.{src}-en.en.idx")) # fake


if __name__ == "__main__":
    main()

还是以ar-de这个语言对为例,它对应、"伪"的、到英语的数据文件应有:dict.ar.txt, dict.en.txt, test.ar-en.ar.bin, test.ar-en.ar.idx, test.ar-en.en.bin, test.ar-en.en.idx,而从上述代码可以看到,里面的dict.ar.txt, test.ar-en.ar.bin, test.ar-en.ar.idx是从data-bin-zero-shot文件夹复制过来的真实的文件,关于en的文件则分别从ar的这三个文件直接copy过来,是伪数据。
后续我们使用fairseq-generate来生成en数据时,只会使用ar的数据dict.ar.txt, test.ar-en.ar.bin, test.ar-en.ar.idx来做实际的生成(我们需要),而en的伪数据dict.en.txttest.ar-en.en.bin, test.ar-en.en.idx被用于打分(我们并不需要)。

得到的结果如下:
在这里插入图片描述

把每一个zs语言对翻译到en

上一步得到的fake-to-en-data-bin-zero-shot被用于这一步的生成,具体的生成使用的是fairseq-generate。

具体代码如下:

# evaluate_commond/generate_pivot_to_en.sh
for lang_pair in ar-de ar-fr ar-nl ar-ru ar-zh de-fr de-nl de-ru de-zh fr-nl fr-ru fr-zh nl-ru nl-zh ru-zh de-ar fr-ar nl-ar ru-ar zh-ar fr-de nl-de ru-de zh-de nl-fr ru-fr zh-fr ru-nl zh-nl zh-ru; do
    src_tgt=($(echo $lang_pair | tr "-" "\n"))
    src=${src_tgt[0]}
    tgt=${src_tgt[1]}
    CUDA_VISIBLE_DEVICES=0 python3 evaluate_commond/evaluate.py --config evaluate_commond/evaluate_zero_shot.yml \
    --lang-pairs ${src}-en \
    --data-bin ../../data/opus-100-corpus/v1.0/fake-en-centrial-data-bin-zero-shot/${src}-${tgt} \
    --true-lang-pair ${src}-${tgt} \
    --pivot
done
# evaluate_commond/evaluate.py 略

上面关键的参数为:

  • lang-pairs:对于所有语言对,都是把这个语言对的src语言,翻译到en(实际的翻译方向)
  • true-lang-pair:这个只是用来创建结果文件夹,保存翻译的结果

得到的翻译结果如下:
在这里插入图片描述

从fairseq-generate生成的文件中,抽取纯en文件

以上述pivot_results/ar-de/generate_ar-en.log为例,里面的内容如下:
在这里插入图片描述
我们需要从中抽取D开头的纯en文本。具体使用的代码如下:

# general_scripts/opus100/extract_puretext_pivot.sh
#!/usr/bin/env bash
path="$1"
direction="$2"
for lang_pair in ar-de ar-fr ar-nl ar-ru ar-zh de-fr de-nl de-ru de-zh fr-nl fr-ru fr-zh nl-ru nl-zh ru-zh de-ar fr-ar nl-ar ru-ar zh-ar fr-de nl-de ru-de zh-de nl-fr ru-fr zh-fr ru-nl zh-nl zh-ru; do
    echo ${lang_pair}
    src_tgt=($(echo $lang_pair | tr "-" "\n"))
    tmp1=${src_tgt[0]}
    tmp2=${src_tgt[1]}
    lp1=${tmp1}-${tmp2}
    lp2=${tmp2}-${tmp1}
    outprefix=${path}/${lp1}
    genpath=${outprefix}/generate_${tmp1}-en.log
    hyppath=${outprefix}/en
    grep -P "^D" ${genpath} | LC_ALL=C sort -V | cut -f 3- > ${hyppath}
done

需要注意的是,fairseq-generate得到的generate_xxx-en.log文件中,结果是按照句子长度排序的,所以需要使用LC_ALL=C sort -V来按照D后面的sample-id来把它恢复到原来的顺序。如下文件:
在这里插入图片描述
在这里插入图片描述
至此,我们完成了第一步骤。

把en数据和所有zs语言对的tgt数据形成平行语料,然后做预处理

我们拿到了上面的pivot_results文件夹,该文件夹的下一级文件夹以zs语言对为命名,每一个zs语言对文件夹里面的en文件,为这个zs语言对的src数据,翻译过来的en纯文本数据。

对于每一个语言对,我们接下来需要把en纯文本数据和这个语言对的tgt端数据形成平行语料,然后做预处理。

形成en到tgt的平行语料

具体使用如下代码:

# data/opus-100-corpus/v1.0/create_en_to_pivot_data.py
import argparse
import os
import json
import shutil

def parse_opt():
    parser = argparse.ArgumentParser()
    parser.add_argument('--zero-shot-path', type=str, default="zero-shot")
    parser.add_argument('--generated-en-path', type=str, default="pivot_results")
    parser.add_argument('--save-path', type=str, default="en_to_pivot_data")
    parser.add_argument('--zero-shot-langs', type=str, default="ar,de,fr,nl,ru,zh")
    return parser.parse_known_args()[0]


def main():
    opts = parse_opt()
    zero_shot_path = opts.zero_shot_path
    generated_en_path = opts.generated_en_path
    zero_shot_langs = opts.zero_shot_langs.split(",")
    save_path = opts.save_path

    for src in zero_shot_langs:
        for tgt in zero_shot_langs:
            if src == tgt:
                continue
            st_src, st_tgt = sorted([src, tgt])
            lang_pair = f"{src}-{tgt}"
            lang_pair_dir = os.path.join(save_path, lang_pair)
            os.makedirs(lang_pair_dir, exist_ok = True)
            # en
            old_path = os.path.join(generated_en_path, lang_pair, "en")
            new_path = os.path.join(lang_pair_dir, f"opus.en-{tgt}-test.en")
            shutil.copyfile(old_path, new_path)
            # tgt
            old_path = os.path.join(zero_shot_path, f"{st_src}-{st_tgt}", f"opus.{st_src}-{st_tgt}-test.{tgt}")
            new_path = os.path.join(lang_pair_dir, f"opus.en-{tgt}-test.{tgt}")
            shutil.copyfile(old_path, new_path)


if __name__ == "__main__":
    main()

从而得到平行语料:
在这里插入图片描述

预处理

就是正常做bpe-encode和binarize,使用代码如下:

# data/opus-100-corpus/v1.0/encode-spm-pivot.sh
bpe=bpe-pivot
tmp=tmp
rm -r $bpe
mkdir -p $bpe

# apply bpe
for file_name in ar-de ar-fr ar-nl ar-ru ar-zh de-fr de-nl de-ru de-zh fr-nl fr-ru fr-zh nl-ru nl-zh ru-zh de-ar fr-ar nl-ar ru-ar zh-ar fr-de nl-de ru-de zh-de nl-fr ru-fr zh-fr ru-nl zh-nl zh-ru;do
    echo ${file_name}
    src_tgt=($(echo $file_name | tr "-" "\n"))
    src=${src_tgt[0]}
    tgt=${src_tgt[1]}
    mkdir ${bpe}/${file_name}
    python fairseq/scripts/spm_encode.py \
        --model ${tmp}/spm.bpe.model \
        --output_format=piece \
        --inputs en_to_pivot_data/${file_name}/opus.en-${tgt}-test.en en_to_pivot_data/${file_name}/opus.en-${tgt}-test.${tgt} \
        --outputs ${bpe}/${file_name}/test.en-${tgt}.bpe.en ${bpe}/${file_name}/test.en-${tgt}.bpe.${tgt}
done

# data/opus-100-corpus/v1.0/binarize-pivot.sh
#!/usr/bin/env bash
# create share dict
path=data-bin-pivot
rm -r $path
mkdir -p $path

#for lang in ar de es fa he it nl pl en; do
#  cp $path/dict.txt $path/dict.${lang}.txt
#done
#be nb km mt ur sv es lt rw gu pt tk or ml da mr eo sq id ro oc et uk fa br zu vi dz pl yi ig tt af yo lv hu sh el mk ga te ta de ky fy se bs fr kn hy nn pa as mg it zh fi mn li ne am ug uz ru ja bn ku eu hi sr my kk xh cy cs ka sk is hr ps az ko no tg he si gd an wa ha th sl ms ar ca bg gl nl; do

for lang_pair in ar-de ar-fr ar-nl ar-ru ar-zh de-fr de-nl de-ru de-zh fr-nl fr-ru fr-zh nl-ru nl-zh ru-zh de-ar fr-ar nl-ar ru-ar zh-ar fr-de nl-de ru-de zh-de nl-fr ru-fr zh-fr ru-nl zh-nl zh-ru; do
  echo ${lang_pair}
  mkdir $path/${lang_pair}
  src_tgt=($(echo $lang_pair | tr "-" "\n"))
  src=${src_tgt[0]}
  tgt=${src_tgt[1]}
  fairseq-preprocess \
      --source-lang en --target-lang $tgt \
      --testpref bpe-pivot/${lang_pair}/test.en-${tgt}.bpe \
      --destdir $path/${lang_pair} \
      --srcdict data-bin/dict.txt \
      --tgtdict data-bin/dict.txt
done

从而得到了第三步需要用的到,从en到tgt语言的data-bin文件夹:
在这里插入图片描述

在en到tgt语言的"伪"平行语料上评估pivot zs translation的性能

这一步和第一步的“ 把每一个zs语言对翻译到en”类似,我们使用如下代码:

# evaluate_commond/evaluate_pivot.sh
for lang_pair in ar-de ar-fr ar-nl ar-ru ar-zh de-fr de-nl de-ru de-zh fr-nl fr-ru fr-zh nl-ru nl-zh ru-zh de-ar fr-ar nl-ar ru-ar zh-ar fr-de nl-de ru-de zh-de nl-fr ru-fr zh-fr ru-nl zh-nl zh-ru; do
    src_tgt=($(echo $lang_pair | tr "-" "\n"))
    src=${src_tgt[0]}
    tgt=${src_tgt[1]}
    CUDA_VISIBLE_DEVICES=0 python3 evaluate_commond/evaluate.py --config evaluate_commond/evaluate_zero_shot.yml \
    --lang-pairs en-$tgt \
    --data-bin ../../data/opus-100-corpus/v1.0/fake-en-to-data-bin-zero-shot/${src}-${tgt} \
    --true-lang-pair ${src}-${tgt} \
    --pivot
done
# evaluate_commond/evaluate.py 略

至此,我们得到了pivot based zs translation的最终结果文件,如下图中的"generate_en-de.log":
在这里插入图片描述

direct zs translation VS pivot-based zs translation

最终,我们比较了用multilingual translation model来1. direct zs translation;2. pivot-based zs translation的结果对比:

  1. direct:BLEU:4.52 | LANG_ACC:28.85%
  2. pivot:BLEU:14.61| LANG_ACC:87.76%

可以看到,pivot-based zs translation是一个强baseline。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/23874.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IMC附录A

目录 A.1 恒等式与不等式 THEOREM A.1 (Binomial expansion theorem) PROPOSITION A.2 PROPOSITION A.3 PROPOSITION A.4 A.2 渐进符号 DEFINITION A.5 A.3 概率论基础 PROPOSITION A.7 (Union Bound) THEOREM A.8 (Bayes’ Theorem) PROPOSITION A.9 PROPOSITI…

图扑 Web SCADA 零代码组态水泥生产工艺流程 HMI

水泥是建筑工业三大基本材料之一,素有“建筑工业的粮食”之称。2022 年 1-9 月水泥产量为 15.63 亿吨,生产方法包括新型干法、立窑、湿窑、干法中空窑和立波尔窑等。 水泥生产线链条长、关键环节多的特性要求执行严密的流程监控。图扑软件大屏组态、UI 组…

国内家具行业数据浅析

大家好,这里是小安说网控。 家具是国民消费必需品之一,受疫情影响,近期销量数据不佳。2022年上半年,规模以上家具制造业企业营业收入3604亿元,同比下降4%;实现利润总额174.8亿元,同比增长2.6%。…

数据结构排序算法之冒泡排序

一 相关概念 稳定排序:如果原数据中a在b之前,而且ab,排序后a任然在b之前 不稳定排序:如果原数据中a在b之前,而且ab,排序后a在b之后 时间复杂度:对排序数据的总的操作次数,反映当n变…

安装Ruby和安装Rails详细步骤详解

rbenv安装Ruby rbenv可以管理多个版本的ruby。可以分为3种范围(或者说不同生效作用域)的版本: local版:本地,针对各项目范围(只在某个目录下有效) global版:全局,没有shell和local版时使用global版 shell版&#xf…

[MySQL]-删库后恢复

[MySQL]-删库后恢复 sen格 | 2022年11月 本文旨在记录个人在数据库的删库恢复演练过程中的一些总结,如有不足,欢迎指正。 一、恢复场景 1)假设生产实例MySQL端口为:3306 2)本地实例MySQL端口为:3307 在这…

pytorch快速入门

文章目录一、Tensorstensors的初始化(四种):tensors的属性和numpy的联系二、数据集的数据加载器加载数据集标号和可视化自己创建数据集用DataLoaders准备数据用于训练Transforms三、神经网络准备训练设备定义网络的类模型的layersnn.Flattennn.Linearnn.ReLUnn.Sequentialnn.So…

Python之基本扩展模块

一、datetime模块 1.1 主要的模块 datetime.date() #处理日期(年、月、日) datetime.time() #处理时间(时、分、秒和毫秒) datetime.datetime() #处理日期时间 datetime.timedelta() #处理时段(时间间隔…

基于Java+springboot+SSM的医疗报销系统的设计与实现

项目开发工具: IDEA, MYSQL, JDK1.8 项目使用技术: SpringBoot, SSM, H-UI, JSP, JQUERY, HTML 医疗报销系统【功能列表】 【前台用户】登录,注册,首页新闻轮播图,首页新闻按分类展示列表,栏目分类模块,报销流程模块,修改密码,个人信息展示,新增家庭成员, 家庭成品列表展示,…

Spring框架教程

Spring框架教程Spring框架教程1. 前言2. Spring框架概述2.1 什么是spring?2.2 Spring有哪些优点?2.3 Spring 有两个核心部分:IoC 和AOP2.4 Spring 特点2.5 Spring架构图,Spring由哪些模块组成?3. IOC容器3.1 IOC底层原理3.2 什么…

three.js初时基础

第一步:找到Three.js – JavaScript 3D Library (threejs.org) 第二步 第三步: 第四步: 安装依赖 第五步:新建一个项目文件,在文件中npm init 进行初始化出现一个package.json 第六步:配置安装🚀 快速开…

QtAV环境配置

本文章主要是使用MSVC编译器,因为QtAV是依赖FFmpeg的,所以需要下载QtAV源码和QtAV-depends-windows-x86x64; 官网地址:http://www.qtav.org/ Github 地址:https://github.com/wang-bin/QtAV 1,解压 将文件…

产品生命周期(PLM)发展历程及技术核心分析指导

产品生命周期管理(Product Lifecycle Management,简称PLM),是一种为企业产品全生命周期提供服务的软件解决方案,可以应用于在单一地点或分散在多个地点的企业内部,以及在产品研发领域,具有协作关系的企业之间&#xff…

windows 锁屏时执行某个程序

目录 前言 1 打开锁屏事件 2 创建任务计划程序 3 测试 前言 以windows10为例,这个功能的核心是使用windows自带的“任务计划程序”,可以帮助您实现触发器操作。 1 打开锁屏事件 默认情况下,锁屏事件并不会被系统记录,需要手动打…

vue3项目的创建、入口文件、全局方法、生命周期函数、setup中的生命周期函数使用、data的函数方式

文章目录1. 创建vue3项目1.1 基于webpack的工程创建1.2 通过vite来创建vue3项目vue3插件推荐1.3 通过npm init vue3创建项目2. vue3入口文件3. vue3中的全局方法修改4. vue3中封装全局方法5. vue3生命周期函数6. setup中生命周期使用7. data函数方式1. 创建vue3项目 1.1 基于w…

Spring Boot中消息是什么?同步异步消息是啥/都包含那些技术?Activate MQ消息怎么整合

写在前面: 继续记录自己的SpringBoot学习之旅,这次是SpringBoot应用相关知识学习记录。若看不懂则建议先看前几篇博客,详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用! 3.5.4 消息 3.5.4.1 简述 消息发送方:…

力扣(LeetCode)29. 两数相除(C++)

快速乘 题解只使用了 intintint 。 万恶的 INT_MININT\_MININT_MIN,怎么处理?打不过就加入——被除数和除数转为负数计算 。 xxx 除以 yyy ,等于从 xxx 中拿出若干个 yyy 。 从 xxx 中拿出 yyy 的数量,就是 xyx\div yxy 的商。 y…

Allegro差分自动添加回流地孔操作指导

Allegro差分自动添加回流地孔操作指导 Allegro自带给差分添加回流地孔的功能,具体操作如下 点击connect命令,任意拉一对差分 鼠标右击,选择Return Path。。。,选择settings 会弹出设置的对话框,Assign net name给孔分配一个网络,一般是GND, Return Path via 选择添加…

2019年1+X 证书 Web 前端开发中级理论考试题目原题+答案——第五套

📚文章目录 🎯关于1X标准 🎯关于中级考点 ⏩💻答案速查 理论题(满分100分),包括单选题、多选题、判断题。 📑一、单选题(每小题2分,共30小题,共60分) &…

Docker的基础命令

1.查找可用的镜像 docker search 镜像名 例:docker search nginxdocker search mysql2.拉取官方镜像(及下载镜像) docker pull 镜像名:标签例:docker pull nginx #表示现在最新版本的nginx镜像docker pull nginx:1.14…