ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

unilm/EdgeLM 无监督机器翻译质量估计:基于 MC-Dropout 的翻译不确定性估计完整复现指南

unilm/EdgeLM 无监督机器翻译质量估计:基于 MC-Dropout 的翻译不确定性估计完整复现指南 unilm/EdgeLM 无监督机器翻译质量估计基于 MC-Dropout 的翻译不确定性估计完整复现指南【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm本篇指南基于 unilm 仓库edgelmEdgeLM分支下的 无监督质量估计示例文档讲解如何在神经机器翻译NMT场景中复现 Fomicheva 等人 2020 年论文Unsupervised Quality Estimation for Neural Machine Translation的核心方法通过在推理时保留 dropoutMC-Dropout 思想进行多次随机前向/解码利用「评分方差」与「多假设译文相似度」两类不确定性信号在无参考、无标注的条件下估计每条机器翻译的质量。读完本文你将掌握从数据预处理、fairseq 二值化、GPU 批量翻译到 dropout 评分聚合与 Meteor 相似度计算的完整命令流程并能从 FairseqDropout 等源码理解--retain-dropout的底层生效机制。1. 方法背景为什么推理时的随机性能反映翻译质量该示例对应 Fomicheva 等人 2020 年发表的无监督质量估计方法。其基本假设是当源句对模型而言「容易」时推理中保留的随机扰动dropout不会显著改变模型行为——无论是对给定译文的打分还是重新生成译文而当源句困难、模型不确定时多次随机前向会给出差异较大的分数或互不相同的译文。仓库中该示例提供了两条可互相印证的估计路径Scoring 路径把同一条源句和同一句机器译文重复 N 次输入模型打分--retain-dropout使每次前向的 dropout 掩码不同N 个分数的聚合统计默认均值可换标准差等即不确定性估计Generation 路径对每条源句在 dropout 开启下解码出 N 个候选译文用 Meteor 计算这些候选两两之间的平均相似度相似度越低说明翻译越不确定。两条路径都不需要参考译文因此可以部署在生产环境中对 NMT 输出做逐句质量打分、筛选可疑译文。2. 环境依赖与准备工作2.1 外部依赖根据 README 的 Requirements 一节复现需要安装以下外部工具mosesdecoder提供分词脚本tokenizer.perl与detokenizer.perlsubword-nmt提供apply_bpe.py用于应用 BPE 子词切分flores评测语言对数据MLQE dataset repository翻译模型.ptcheckpoint与测试数据的官方下载地址FLORES-101 上的训练/测试模型与数据均从该仓库获取。另外 Generation 路径的 Meteor 计算需要本机安装 Java脚本内部通过java -Xmx2G -jar调用 Meteor jar见第 5.3 节。2.2 关键变量约定原文档为整个流程定义了一组环境变量复现前需先设置好变量含义SRC_LANG/TGT_LANG源语言 / 目标语言INPUT输入前缀$INPUT.$SRC_LANG是源句文件$INPUT.$TGT_LANG是参考译文文件OUTPUT_DIR存放最终结果的路径MOSES_DECODERmosesdecoder 安装路径BPE_ROOTsubword-nmt 安装路径BPEBPE 模型bpe.codes之类路径MODEL_DIR包含 NMT.pt模型及源/目标词典dict.$LANG.txt的目录TMP中间临时文件目录GPUGPU 推理时使用的 GPU idDROPOUT_N随机前向或重复解码次数 N关于 N 的取值原文档给出明确经验论文实验使用DROPOUT_N30但作者观察到超过 10 次之后提升已不显著——因此实际部署时可根据算力预算把 N 降到 10 左右性价比更高。3. 第一步标准解码产出机器译文质量估计的对象是「模型自己产出的译文」因此先按标准流程翻译一次测试集。3.1 预处理分词 BPEfor LANG in $SRC_LANG $TGT_LANG; do perl $MOSES_DECODER/scripts/tokenizer/tokenizer.perl -threads 80 -a -l $LANG $INPUT.$LANG $TMP/preprocessed.tok.$LANG python $BPE_ROOT/apply_bpe.py -c ${BPE} $TMP/preprocessed.tok.$LANG $TMP/preprocessed.tok.bpe.$LANG done注意-a参数表示按空格对齐分词后续detokenizer.perl依赖这种对齐来还原原文空格preprocessed.tok.bpe.$SRC_LANG这份 BPE 源句文件在第 4 节还会被重复使用不要清理。3.2 二值化加速fairseq-preprocess --srcdict $MODEL_DIR/dict.$SRC_LANG.txt --tgtdict $MODEL_DIR/dict.$TGT_LANG.txt \ --source-lang ${SRC_LANG} --target-lang ${TGT_LANG} --testpref $TMP/preprocessed.tok.bpe --destdir $TMP/bin --workers 43.3 fairseq-generate 翻译并整理输出CUDA_VISIBLE_DEVICES$GPU fairseq-generate $TMP/bin --path ${MODEL_DIR}/${SRC_LANG}-${TGT_LANG}.pt --beam 5 \ --source-lang $SRC_LANG --target-lang $TGT_LANG --no-progress-bar --unkpen 5 $TMP/fairseq.out grep ^H $TMP/fairseq.out | cut -d- -f2- | sort -n | cut -f3- $TMP/mt.outfairseq-generate的标准输出格式为Hypo N 译文N 为句子序号这里用grep ^Hsort -n保证多 worker 并行时句子顺序不乱cut -f3-取出译文。3.4 后处理合并 BPE 标记 反分词sed -r s/( )| ( ?$)//g $TMP/mt.out | perl $MOSES_DECODER/scripts/tokenizer/detokenizer.perl \ -l $TGT_LANG $OUTPUT_DIR/mt.outsed去掉 subword-nmt 的子词连接符detokenizer.perl依据 3.1 中的空格对齐恢复标点与空格最终得到可读的机器译文mt.out作为 Scoring 路径的打分对象。4. 第二步产生不确定性估计4.1 Scoring 路径MC-Dropout 打分(1) 将源句与译文各重复 N 次python ${SCRIPTS}/scripts/uncertainty/repeat_lines.py -i $TMP/preprocessed.tok.bpe.$SRC_LANG -n $DROPOUT_N \ -o $TMP/repeated.$SRC_LANG python ${SCRIPTS}/scripts/uncertainty/repeat_lines.py -i $TMP/mt.out -n $DROPOUT_N -o $TMP/repeated.$TGT_LANG其中repeat_lines.py即仓库中的 repeat_lines.py它把输入文件逐行重复 N 次写出重复前会先做空格归一化。(2) 对重复后的「源句-译文」对重新二值化fairseq-preprocess --srcdict ${MODEL_DIR}/dict.${SRC_LANG}.txt --tgtdict ${MODEL_DIR}/dict.${TGT_LANG}.txt \ --source-lang ${SRC_LANG} --target-lang ${TGT_LANG} --testpref ${TMP}/repeated --destdir ${TMP}/bin-repeated复现提示原文档该行写的是$TGT_DIC是变量名笔误执行时应统一为--tgtdict ${MODEL_DIR}/dict.${TGT_LANG}.txt打分模型路径原文档写作${LP}.pt语言对缩写与前面${SRC_LANG}-${TGT_LANG}.pt指向同一 checkpoint请保持命名一致。(3) 带 dropout 的推理打分CUDA_VISIBLE_DEVICES${GPU} fairseq-generate ${TMP}/bin-repeated --path ${MODEL_DIR}/${LP}.pt --beam 5 \ --source-lang $SRC_LANG --target-lang $TGT_LANG --no-progress-bar --unkpen 5 --score-reference --retain-dropout \ --retain-dropout-modules [TransformerModel,TransformerEncoder,TransformerDecoder,TransformerEncoderLayer,TransformerDecoderLayer] \ --seed 46 $TMP/dropout.scoring.out grep ^H $TMP/dropout.scoring.out | cut -d- -f2- | sort -n | cut -f2 $TMP/dropout.scores这条命令的三个要点--score-reference不再生成新译文而是计算模型对「源句 参考译文此处即机器译文」的对数似然分--retain-dropout推理阶段保留 dropout使 N 次前向的分数呈现随机波动--retain-dropout-modules指定哪些模块启用推理期 dropout。原文档说明若不指定dropout 会在与训练时相同的位置生效示例中显式列出了TransformerModel、TransformerEncoder、TransformerDecoder、TransformerEncoderLayer、TransformerDecoderLayer五类模块命令行里写成 JSON 数组字符串。--seed 46固定随机种子保证实验可复现。最后cut -f2取出每条记录的分数Hypo N score格式的第二字段得到 N×句数的分数流dropout.scores——同一句子的 N 个分数在文件中是连续排列的。(4) 聚合分数python $SCRIPTS/scripts/uncertainty/aggregate_scores.py -i $TMP/dropout.scores -o $OUTPUT_DIR/dropout.scores.mean \ -n $DROPOUT_Naggregate_scores.py 按每 N 行一组做聚合。源码内置了六种可选聚合函数-f参数std、var、median、mean、min、max默认mean。需要强调的是作为不确定性指标通常应选std分数波动越大越不确定mean更像是对单次打分的去噪平滑。这正是该脚本支持多种聚合函数的价值所在。4.2 Generation 路径多假设解码 Meteor 相似度(1) 带 dropout 解码出 N 个假设CUDA_VISIBLE_DEVICES${GPU} fairseq-generate ${TMP}/bin-repeated --path ${MODEL_DIR}/${LP}.pt \ --beam 5 --source-lang $SRC_LANG --target-lang $TGT_LANG --no-progress-bar --retain-dropout \ --unkpen 5 --retain-dropout-modules TransformerModel TransformerEncoder TransformerDecoder \ TransformerEncoderLayer TransformerDecoderLayer --seed 46 $TMP/dropout.generation.out grep ^H $TMP/dropout.generation.out | cut -d- -f2- | sort -n | cut -f3- $TMP/dropout.hypotheses_ sed -r s/( )| ( ?$)//g $TMP/dropout.hypotheses_ | perl $MOSES_DECODER/scripts/tokenizer/detokenizer.perl \ -l $TGT_LANG $TMP/dropout.hypotheses注意与 Scoring 命令的差异这里没有--score-reference因此是对每条重复的源句做 beam5 解码得到 N 个受 dropout 扰动的译文假设--retain-dropout-modules以空格分隔的形式传入五个模块名而非 JSON 字符串。(2) 计算 N 个假设之间的 Meteor 平均相似度python meteor.py -i $TMP/dropout.hypotheses -m path_to_meteor_installation -n $DROPOUT_N \ -o $OUTPUT_DIR/dropout.gen.sim.meteormeteor.py 的输出dropup.gen.sim.meteor即每个源句对应的生成一致性得分同一句子的 N 个假设互相越像分数越高翻译越确定。5. 源码纵深--retain-dropout在 EdgeLM 中的实现5.1 配置项定义GenerationConfigretain_dropout与retain_dropout_modules是 fairseq 生成配置的正式字段定义在 GenerationConfigretain_dropout: bool field( defaultFalse, metadata{help: Use dropout at inference time}, ) # temporarily set to Any until https://github.com/facebookresearch/hydra/issues/1117 is fixed retain_dropout_modules: Any field( defaultNone, metadata{ help: if set, only retain dropout for the specified modules; if not set, then dropout will be retained for all modules }, )两点实现细节值得注意retain_dropout_modules被临时声明为Any类型注释说明是等待 hydra 的一个 issue 修复因此命令行既可以传 JSON 数组字符串[TransformerModel,...]也可以像 Generation 命令那样传空格分隔的裸模块名两种写法在本仓库都能被接受字段帮助文本明确设置为 None 时所有模块都保留 dropout这正对应原文档「By default, dropout is applied in the same places as for training」的说法。5.2 生效链路从模型到 Dropout 模块在 fairseq_model.py 中生成流程构建解码器参数时会读取上述配置if getattr(cfg.generation, retain_dropout, False): kwargs[retain_dropout] cfg.generation.retain_dropout kwargs[retain_dropout_modules] cfg.generation.retain_dropout_modules这些参数最终经make_generation_fast_(retain_dropout..., retain_dropout_modules...)分发到每个 dropout 模块。核心实现在 FairseqDropoutclass FairseqDropout(nn.Module): def __init__(self, p, module_nameNone): super().__init__() self.p p self.module_name module_name self.apply_during_inference False def forward(self, x, inplace: bool False): if self.p 0 and (self.training or self.apply_during_inference): return F.dropout(x, pself.p, trainingTrue, inplaceinplace) else: return x从源码结构看其工作机制是每个FairseqDropout实例携带module_name所属模块名如TransformerEncoderLayermake_generation_fast_被调用时若retain_dropoutTrue且未指定模块白名单或自身module_name命中白名单则把apply_during_inference置为 True之后forward中self.training or self.apply_during_inference为真即使模型处于eval()模式也会以trainingTrue的方式执行 dropout——这正是「推理时保留随机性」的实现关键N 次前向共享同一 eval 模型但 dropout 掩码逐次重新采样。如果某个 dropout 实例的module_name为 None 而又指定了白名单源码会打印 warning 提示「无法为该模块启用推理期 dropout」。仓库中的测试 tests/test_inference_dropout.py 专门验证了这一机制对同一输入重复前向开启retain_dropout后输出分数应发生变化可用于回归验证你本地版本的--retain-dropout是否生效。5.3 三个辅助脚本的实现细节repeat_lines.py逐行读入、每行重复 N 次写出写入前用 .join(line.split())归一化空格-o缺省时输出到 stdout。它保证 Scoring 阶段「源句与译文第 i 份严格对齐」是后续按连续 N 行聚合的前提。aggregate_scores.py滑动窗口式聚合——累计repeat_times个分数后立即输出聚合值并清窗因此要求输入文件中同一句子的 N 个分数必须连续由 4.1 的sort -n步骤保证。std/var等聚合基于 numpy一行一个输出值。meteor.py这是三个脚本中最复杂的一个值得细看read_translations按连续 N 行切分把 N 个假设归到同一个句段 id 下generate_input对每个句段取combinations(range(N), 2)生成C(N,2)个两两配对第 i 份做系统输出、第 j 份做参考写入临时文件——因此 Meteor 比较的不是「假设 vs 参考译文」而是「假设 vs 假设」run_meteor以java -Xmx2G -jar meteor_jar调用参数为-p 0.5 0.2 0.6 0.75 -norm -l lang。注释特别指出这是 Meteor 默认参数仅把 alpha 从默认值改为 0.75使精确率与召回率在评分中获得等权重read_output只解析以Segment开头的行每攒满 C(N,2) 个原始分段得分就取平均输出一个句段级相似度。也就是说对 N 个假设共有 C(N,2) 次配对比较最终每个源句得到一个均值。6. 结果解读与适用边界两条路径的输出文件对应关系输出文件含义不确定性方向$OUTPUT_DIR/dropout.scores.meanN 次 dropout 打分的聚合值默认均值可换std用-f std时越大越不确定$OUTPUT_DIR/dropout.gen.sim.meteorN 个 dropout 假设两两 Meteor 相似度的均值越小越不确定实践注意事项均来自原文档与源码事实N 的取值论文用 30作者实测超过 10 无显著提升资源受限时 N10 即可随机种子示例固定--seed 46更换种子会改变结果跨实验对比时务必保持一致模块白名单Scoring 与 Generation 两条命令的--retain-dropout-modules传参格式不同JSON 数组 vs 空格分隔两者在 GenerationConfig 的Any类型下均可解析适用前提模型 checkpoint、词典、BPE 与 moses 分词流程必须来自同一 MLQE 训练配置且fairseq-generate使用--beam 5 --unkpen 5与示例保持一致才能对齐论文中的复现口径语言相关meteor.py默认-l en评测非英语目标语时应显式指定目标语言。综上该示例目录README 三个脚本构成了一套自包含的 NMT 无监督质量估计流水线标准解码产出译文MC-Dropout 打分与多假设 Meteor 相似度分别从「置信度」和「一致性」两个角度给出逐句质量信号配合 FairseqDropout 的推理期 dropout 机制即可在完全无参考、无标注的数据上部署翻译质量监控。【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表