多语种翻译实战:基于 unilm/edgelm 的 translation_multi_simple_epoch 框架(温度采样、语言标记与 mBART 微调)
【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm
本文以 edgelm/examples/multilingual/README.md 为骨架,结合仓库内 fairseq 源码与配套脚本,系统讲解如何在 unilm 仓库的 edgelm 分支下用多份双语平行语料训练多语种翻译模型:涵盖温度采样的数据配比控制、源/目标语言标记(langtok)的注入方式、从 mBART 预训练模型微调,以及推理生成与 sacrebleu 评测的完整链路。读者读完可掌握一整套可直接复现的多语种翻译训练、微调与评估方案。
框架能力概览
该框架面向"同时使用多份不同翻译方向的双语平行语料(bitext)训练一个统一的多语种翻译模型"这一场景,其核心任务实现在 edgelm/fairseq/tasks/translation_multi_simple_epoch.py 中,通过@register_task("translation_multi_simple_epoch")注册为 fairseq 任务。与单语对翻译任务不同,它要求所有语言共享同一份联合 BPE 词表,并围绕三个关键机制展开:
- 基于温度(temperature)的数据采样:对规模不均衡、方向各异的多个数据集进行配比采样,避免大语料淹没小语料。对应参数
--sampling-method(取值uniform/temperature/concat)与--sampling-temperature; - 可配置的语言标记(language token)注入:自动在源句/目标句上添加源语言或目标语言的标记 token,使模型感知"当前正在翻译哪种语言"。对应参数
--encoder-langtok(取值src/tgt/None)与--decoder-langtok(布尔开关); - 从预训练模型微调:支持加载 mBART 等多语种预训练模型继续训练,对应参数
--finetune-from-model。
温度采样:如何平衡不均衡的多语料数据
采样逻辑实现在 edgelm/fairseq/data/multilingual/sampling_method.py 中。该模块定义了三种采样函数:
uniform(dataset_sizes):对每个语对返回等权重1.0,即所有语对按相同概率被采样,完全不考虑语料规模差异;temperature_sampling(dataset_sizes, temp):对第 i 个语对,采样权重为(size_i / total_size) ** (1.0 / temp),其中size_i是该语对的样本数、total_size是所有语对样本总数。温度temp越大,权重越趋近均匀(削弱大语料优势);温度越小(趋近 0)则越偏向大语料;- 参数解析部分(
add_arguments)显示--sampling-method的实际可选值还包括RoundRobin(default="concat"),其中concat表示把全部数据集简单拼接后整体训练,RoundRobin则按语对轮转取数据——README 中列出的uniform/temperature/concat是三种最常用的配置。
--sampling-temperature的默认值为1.5,仅在--sampling-method "temperature"时生效。实践中的标准组合是--sampling-method "temperature" --sampling-temperature 1.5(见下文训练命令)。
语言标记(langtok):让模型知道在翻译哪种语言
多语种翻译模型需要在输入/输出中携带语言身份信息。README 给出的两种配置方式:
--encoder-langtok "src":在源句前添加源语言 token(也可设为tgt在源句前添加目标语言 token,或设为None不添加);--decoder-langtok:在目标句(即解码器输入)前添加目标语言 token,作为解码起始标记。
从源码看,语言标记的注入贯穿训练与推理两个阶段:
- 训练阶段,
MultilingualDatasetManager根据src_langtok_spec/tgt_langtok_spec对每个语对的数据集做变换(见 translation_multi_simple_epoch.py 中的build_dataset_for_inference); - 推理阶段,
inference_step会在prefix_tokens为空时,将目标语言 token 作为prefix_tokens塞给 generator(translation_multi_simple_epoch.py),等价于强制以目标语言 token 作为解码起点; - 生成结束后,
build_generator会把输出中用于解码的目标语言 token 通过symbols_to_strip_from_output剥掉(translation_multi_simple_epoch.py),保证最终译文不含语言标记;如需保留以便分析,可加--keep-inference-langtok。
从预训练模型微调
框架通过--finetune-from-model $pretrained_model指定预训练 checkpoint 路径(可以是 mBART 预训练模型,也可以是之前训练好的任意多语种模型),加载权重后继续训练,这是 mBART50 微调方案(many-to-one / one-to-many / many-to-many)的基础。
数据预处理:联合 BPE 词表与 binarize
多语种训练的前提是所有语言共享一个联合 BPE 词表,因此 README 要求按 mBART 的预处理流程复用其预训练的 sentencepiece 模型;你也可以在自己的数据集上训练联合 BPE 模型,再走翻译任务的多语种预处理链路。
仓库在 edgelm/examples/multilingual/data_scripts/ 目录下提供了完整的数据工具链:
- data_scripts/README.md 描述了从安装依赖(
pip install -r requirement.txt)、下载数据(设置WORKDIR_ROOT,数据会落在$WORKDIR_ROOT/ML50)到预处理(需安装 sentencepiece 并设置SPM_PATH)的流程; - 数据组织按流水线划分:
$WORKDIR_ROOT/ML50/raw(解压后的原始数据)→$WORKDIR_ROOT/ML50/dedup(去重数据)→$WORKDIR_ROOT/ML50/clean(从 dedup 数据中剔除与 valid/test 重叠的句子后的训练数据); - 下载脚本覆盖了常见多语数据集:download_ML50_v1.sh(ML50)、download_iwslt_and_extract.sh、download_ted_and_extract.py、download_wmt19_and_before.py、download_wmt20.sh、download_flores_data.sh、download_iitb.sh 等;
- 质量工具包括 dedup.py、fasttext_multi_filter.py(fastText 语种过滤)、strip_sgm.sh、check_valid_test_overlaps.py 等。
二进制化则使用 README 指定的 binarize.py:它依赖两个环境变量WORKDIR_ROOT与SPM_PATH,会自动下载 mBART50 的 sentencepiece 模型与 250k 词表,随后按语对用spm_encode.py把 train/test/valid 切分编码为 BPE piece,再调用 fairseq 的预处理命令生成各语对的 databin。注意:ML50 数据的各语言字典即为dict.{lang}.txt(见下文 mBART50 一节),需复制到数据目录中。
语言列表文件 ML50_langs.txt 每行一种语言代码(形如ar_AR、cs_CZ、de_DE、en_XX、fr_XX等,共 52 行,覆盖 ML50 全部语种),训练时通过--lang-dict传给任务,用于确定模型感知的有序语言集合。
训练:从零训练多语种翻译模型
README 给出的训练命令如下(假设数据已按上述流程 binarize 好,且各语对目录就绪):
lang_pairs=<language pairs to be trained, e.g. "en-cs,cs-en"> path_2_data=<set to data path> lang_list=<a file which contains a list of languages separated by new lines> fairseq-train $path_2_data \ --encoder-normalize-before --decoder-normalize-before \ --arch transformer --layernorm-embedding \ --task translation_multi_simple_epoch \ --sampling-method "temperature" \ --sampling-temperature 1.5 \ --encoder-langtok "src" \ --decoder-langtok \ --lang-dict "$lang_list" \ --lang-pairs "$lang_pairs" \ --criterion label_smoothed_cross_entropy --label-smoothing 0.2 \ --optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \ --lr-scheduler inverse_sqrt --lr 3e-05 --warmup-updates 2500 --max-update 40000 \ --dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \ --max-tokens 1024 --update-freq 2 \ --save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints \ --seed 222 --log-format simple --log-interval 2参数要点拆解:
| 参数 | 取值/示例 | 作用 |
|---|---|---|
--task translation_multi_simple_epoch | 固定 | 指定多语种翻译任务(对应 translation_multi_simple_epoch.py 中的注册任务) |
--lang-pairs | "en-cs,cs-en" | 逗号分隔、按训练顺序排列的语对列表;任务会将每个语对分别构建数据集 |
--lang-dict | $lang_list文件路径 | 每行一个语言的有序语言列表文件(可直接复用 ML50_langs.txt 或自建) |
--sampling-method | temperature | 语对采样方式,可选uniform/temperature/concat(源码还支持RoundRobin),默认concat |
--sampling-temperature | 1.5 | 温度系数,仅对temperature方式生效,越大越均匀 |
--encoder-langtok | src | 在源句前加源语言 token,可选src/tgt/None |
--decoder-langtok | 开启 | 在目标句前加目标语言 token 作为解码起始 |
--arch transformer --layernorm-embedding | 固定 | Transformer 结构 + embedding 层后 LayerNorm(与 mBART 结构对齐) |
--encoder-normalize-before --decoder-normalize-before | 固定 | Pre-LN 风格归一化 |
--criterion label_smoothed_cross_entropy --label-smoothing 0.2 | 固定 | 标签平滑 0.2 的交叉熵 |
--optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' | 固定 | Adam 优化器,与 mBART 一致的超参 |
--lr-scheduler inverse_sqrt --lr 3e-05 --warmup-updates 2500 --max-update 40000 | 固定 | 逆平方根学习率调度,2500 步预热,最多 4 万步更新 |
--dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 | 固定 | 正则化配置 |
--max-tokens 1024 --update-freq 2 | 固定 | 每 batch 最大 token 数与梯度累积步数(等效扩大 batch) |
--save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints | 固定 | 每 5000 步保存一次 checkpoint,保留最近 10 个,不按 epoch 存 |
--seed 222 --log-format simple --log-interval 2 | 固定 | 复现性种子与日志频率 |
仓库把上述命令封装成了脚本 train_multilingual_model.sh,按位置传三个参数即可运行:
bash train_multilingual_model.sh <path_2_data> <lang_list> <lang_pairs> # 例如:bash train_multilingual_model.sh ./data ./ML50_langs.txt "en-fr,en-cs,fr-en,cs-en"注意--lang-pairs与--lang-dict必须与数据目录中实际存在的语对一致。另外,TranslationMultiSimpleEpochTask.__init__中会对各源语言/目标语言的字典做一致性校验(check_dicts):所有源语言共享同一份字典、所有目标语言共享同一份字典,这正是"联合 BPE 词表 + 共享字典"设计在源码层面的体现。
微调:从 mBART 预训练模型继续训练
多语种模型同样可以从单语预训练模型(如 mBART)微调而来,只需在训练命令基础上增加--finetune-from-model指向预训练 checkpoint:
lang_pairs=<language pairs to be trained, e.g. "en-cs,cs-en"> path_2_data=<set to data path> lang_list=<a file which contains a list of languages separated by new lines> pretrained_model=<path to the pretrained model, e.g. mbart or another trained multilingual model> fairseq-train $path_2_data \ --finetune-from-model $pretrained_model \ --encoder-normalize-before --decoder-normalize-before \ --arch transformer --layernorm-embedding \ --task translation_multi_simple_epoch \ --sampling-method "temperature" \ --sampling-temperature 1.5 \ --encoder-langtok "src" \ --decoder-langtok \ --lang-dict "$lang_list" \ --lang-pairs "$lang_pairs" \ --criterion label_smoothed_cross_entropy --label-smoothing 0.2 \ --optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \ --lr-scheduler inverse_sqrt --lr 3e-05 --warmup-updates 2500 --max-update 40000 \ --dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \ --max-tokens 1024 --update-freq 2 \ --save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints \ --seed 222 --log-format simple --log-interval 2与从零训练相比,唯一的区别就是多了--finetune-from-model。配套脚本 finetune_multilingual_model.sh 将其封装为四个位置参数:
bash finetune_multilingual_model.sh <path_2_data> <lang_list> <lang_pairs> <pretrained_model>脚本注释明确说明pretrained_model"can be an mBART pretrained model as well"——即可以加载 mBART 预训练权重,也可以加载此前训练好的任意多语种模型作为起点。微调时建议保持与预训练一致的模型结构(transformer + layernorm-embedding + pre-norm)与较小的学习率,3e-05即为此类配置。
生成与评测:fairseq-generate + sacrebleu
标准生成流程
生成阶段同样使用多语种任务,且必须保证--lang-dict、--lang-pairs与训练时一致,模型才能正确解析语对与语言 token。生成时,源语言 token 会被加到源句前,目标语言 token 作为解码起始 token(即上文inference_step中prefix_tokens的注入逻辑):
model=<multilingual model> source_lang=<source language> target_lang=<target language> fairseq-generate $path_2_data \ --path $model \ --task translation_multi_simple_epoch \ --gen-subset test \ --source-lang $source_lang \ --target-lang $target_lang --sacrebleu --remove-bpe 'sentencepiece'\ --batch-size 32 \ --encoder-langtok "src" \ --decoder-langtok \ --lang-dict "$lang_list" \ --lang-pairs "$lang_pairs" > ${source_lang}_${target_lang}.txt--source-lang/--target-lang指定本次翻译方向(对应任务参数-s/-t);生成时任务内部会将lang_pairs固定为"{source_lang}-{target_lang}"这一条(见 translation_multi_simple_epoch.py);--sacrebleu让 fairseq 在输出末尾附带 sacreBLEU 分数;--remove-bpe 'sentencepiece'会按 sentencepiece 规则还原 BPE piece;- 输出重定向到
{source_lang}_{target_lang}.txt,其中逐句包含S(源句)、T(参考)、H(假设译文,即模型生成结果)三类行。
仓库同时提供了封装脚本 multilingual_fairseq_gen.sh:
bash multilingual_fairseq_gen.sh <path_2_data> <lang_list> <model>该脚本内置lang_pairs="en-fr,en-cs,fr-en,cs-en"、source_lang=cs、target_lang=en,可作为最简生成模板修改使用。
用自定义 tokenizer 复现文献指标
fairseq 内建的 sacrebleu 分数是基于sacrebleu的默认 tokenization 计算的。若要与其他文献对齐,可以换成自定义 tokenizer(例如针对目标语言的 Moses 风格 tokenizer)重新计算分数:
TOKENIZER=<path to a customized tokenizer for decoding evaluation> TOK_CMD=<"$TOKENIZER $target_lang" or cat for sacrebleu> cat {source_lang}_${target_lang}.txt | grep -P "^H" |sort -V |cut -f 3- |$TOK_CMD > ${source_lang}_${target_lang}.hyp cat {source_lang}_${target_lang}.txt | grep -P "^T" |sort -V |cut -f 2- |$TOK_CMD > ${source_lang}_${target_lang}.ref sacrebleu -tok 'none' -s 'none' ${source_lang}_${target_lang}.ref < ${source_lang}_${target_lang}.hyp这段流水线的含义是:
- 从生成文件中提取假设译文行(
^H)并按序号排序、cut -f 3-去掉行号与分数列,得到.hyp; - 提取参考译文行(
^T)、cut -f 2-去掉行号,得到.ref; - 用
sacrebleu -tok 'none' -s 'none'以"不分词、不采用句子级平滑"的方式计算 BLEU,从而与文献口径一致;若希望使用 sacrebleu 默认评测,则将TOK_CMD设为cat即可。
使用 mBART50 预训练模型
官方提供了四类 mBART50 checkpoint(均为可下载的 tar 包,本文不再列出外部地址,下载与解压方式见原文档):
- mMBART 50 pretrained:仅预训练、未做翻译微调的基础模型;
- mMBART 50 finetuned many-to-one:微调为"多种语言 → 英语";
- mMBART 50 finetuned one-to-many:微调为"英语 → 多种语言";
- mMBART 50 finetuned many-to-many:微调为"任意方向的多语言互译"。
每个 tar 包解压后包含四类文件:
| 文件 | 说明 |
|---|---|
model.pt | fairseq 模型 checkpoint |
ML50_langs.txt | 支持的语种列表(与仓库中的 ML50_langs.txt 同构) |
sentence.bpe.model | sentencepiece 模型 |
dict.{lang}.txt | 各语言的 fairseq 字典(lang替换为ML50_langs.txt中列出的语言代码) |
使用步骤分两步:
第一步,binarize 自己的数据:使用 binarize.py 工具,配合sentence.bpe.model与dict.{lang}.txt完成分词与二进制化,并把各语言字典复制到数据目录(--lang-dict指向ML50_langs.txt,模型需要据此构造字典)。
第二步,运行生成命令:
path_2_data=<path to your binarized data with fairseq dictionaries> model=<path_to_extracted_folder>/model.pt lang_list=<path_to_extracted_folder>/ML50_langs.txt source_lang=<source language> target_lang=<target language> fairseq-generate $path_2_data \ --path $model \ --task translation_multi_simple_epoch \ --gen-subset test \ --source-lang $source_lang \ --target-lang $target_lang --sacrebleu --remove-bpe 'sentencepiece'\ --batch-size 32 \ --encoder-langtok "src" \ --decoder-langtok \ --lang-dict "$lang_list"与自训练模型的生成命令相比,此处不再传--lang-pairs——因为预训练模型的语对集合已由 checkpoint 本身决定,--lang-dict提供的ML50_langs.txt足以让任务为指定的--source-lang/--target-lang构造正确的语言标记与字典。--encoder-langtok "src" --decoder-langtok则与训练/微调时的语言标记配置保持一致。
引用
如果论文复现或方法改进工作基于该框架,README 提供的规范引用如下:
@article{tang2020multilingual, title={Multilingual Translation with Extensible Multilingual Pretraining and Finetuning}, author={Yuqing Tang and Chau Tran and Xian Li and Peng-Jen Chen and Naman Goyal and Vishrav Chaudhary and Jiatao Gu and Angela Fan}, year={2020}, eprint={2008.00401}, archivePrefix={arXiv}, primaryClass={cs.CL} }小结
至此,一条从数据预处理(联合 BPE 词表 + binarize.py 二进制化)→ 温度采样多语训练(--sampling-method temperature --sampling-temperature 1.5)→ mBART 预训练模型微调(--finetune-from-model)→ 多语生成与 sacrebleu 评测的完整链路已经打通。核心要点可归纳为:共享联合词表是前提,--lang-dict/--lang-pairs的一致性贯穿训练与推理,--encoder-langtok/--decoder-langtok决定语言身份的注入方式。相关可复现脚本与源码均可在仓库 edgelm/examples/multilingual/ 与 edgelm/fairseq/tasks/translation_multi_simple_epoch.py 中直接查阅与运行。
【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考