[机器翻译]—BLEU值的计算

前言

最近还卡在复现工作的结果这一环节上。具体来说,我使用那篇工作提供的脚本,使用的是fairseq-generate来完成的结果的评估。然后我发现我得到的结果和论文中的结果完全不一致。
首先,在预处理阶段,如记一次多语言机器翻译模型的训练所示,我是用moses的tokenizer完成的tokenize,然后又使用moses的lowercase完成的小写化,最后用subword-nmt bpelearn和apply的子词。当然,一方面,小写化不利于模型性能的比较(来自师兄);另一方面,可以使用sentencepiece这一工具来直接学bpe,而不需要做额外的tokenize,但本文暂不考虑。

别人是怎么做的?

这部分内容主要参考:Computing and reporting BLEU scores

考虑以下情况:机器翻译的训练和测试数据,都经过tokenize和truecased的预处理,以及bpe的分词。而在后处理阶段,在保证正确答案(ref)和模型输出(hyp)经过相同的后处理操作的情况下,不同的操作带来的BLEU值是很不同的。如下图所示:
[机器翻译]—BLEU值的计算_第1张图片
主要有以下发现:

  1. 【行1vs行2】在bpe级别计算的BLEU值偏高。解释:行1没有采取任何后处理,也就是说,hyp和ref都是tokenized、truecased的bpe子词。此时,由于粒度更细,原本word级别是错误的输出,分成更细粒度的子词,可能就产生“正确”的结果了。
  2. 【行3vs行4】如果不使用sacreBLEU提供的standard tokenization,结果BLEU值偏高。解释:行3没有做detokenize,同时,把sacreBLEU中的standard tokenization也ban掉了;而行4先做了detokenize(行4中的tokenization要理解为detokenize),然后使用了sacreBLEU中的standard tokenization(默认应该是13a tokenizier)。一般来说,行3被称为tokenized BLEU(wrong),行4被称为detokenized BLEU(right)。但是我不知道这两个为什么差别这么大。
  3. 【行5】如果不考虑大小写,也就是完全小写,BLEU值偏高。
  4. 【行6】这一类应该也算是tokenized BLEU,也就是说,它先做了detokenize,只不过在计算BLEU时,又要进行tokenize的时候,使用的是其它第三方的tokenizer而不是sacreBLEU中的tokenizer,这种做法对最终的结果也有影响。

总结:

  • 用SacreBLEU!
  • 在计算BLEU之前,要做好完全的post-preprocess(undo BPE\truecase\detokenize等等)!

我的错误

经过上一部分,可以看到,我的预处理步骤的问题并不大(虽然小写会导致结果偏高),我的问题主要出在,在运行fairseq-generate时,我没有提供bpe\bpe-codes\tokenizer\scoring\post-process参数,也就是说,我没有做任何的post-process。其中,各参数的功能如下:

  • bpe:通过bpe.decode(x)语句来做undo bpe。以bpe=subword_nmt为例,做的就是:(x + " ").replace(self.bpe_symbol, "").rstrip(),其中self.bpe_symbol=@@
  • tokenizer:通过tokenizer.decode(x)语句来做detokenize。以tokenzier=moses为例,做的就是:MosesDetokenizer.detokenize(inp.split())
  • scoring:通过scorer = scoring.build_scorer(cfg.scoring, tgt_dict)语句来建立计算BLEU的对象。如果scoring=‘bleu’(默认),则具体计算的语句为scorer.add(target_tokens, hypo_tokens),其中,target\hypo_tokens是经过一些预处理(可能经过了undo bpe和detokenize,也有可能什么也没做:只是用" "这个分隔符把sentence中所有的tokenized bpe子词连成了一串字符串),得到target\hypo_str之后,再做fairseq提供的简单的tokenize(fairseq/fairseq/tokenizer.py),然后计算BLEU值。而如果scoring=‘sacrebleu’,则具体计算的语句为scorer.add_string(target_str, detok_hypo_str),在这种情况下,如果我们做好了应该做的post-process,target_str就是纯纯的原文本,detok_hypo_str也如此。而在计算BLEU值时,我们又是用的sacrebleu的standard tokenization,可比性会高很多。
  • post-process:这个参数和bpe参数重复

(可能)正确做法

CUDA_VISIBLE_DEVICES=5 fairseq-generate ../../data/iwslt14/data-bin   --path checkpoints/iwslt14/baseline/evaluate_bleu/checkpoint_best.pt   --task translation_multi_simple_epoch   --source-lang ar   --target-lang en   --encoder-langtok "src"   --decoder-langtok   --bpe subword_nmt   --tokenizer moses   --scoring sacrebleu   --bpe-codes /home/syxu/data/iwslt14/code   --lang-pairs "ar-en,de-en,en-ar,en-de,en-es,en-fa,en-he,en-it,en-nl,en-pl,es-en,fa-en,he-en,it-en,nl-en,pl-en" --quiet

主要就是提供了bpe\bpe-codes\tokenizer\scoring,这四个参数。结果如下。

TBC

另外,也可以不看fairseq-generate提供的BLEU结果,而是利用它生成的hyp.txt和ref.txt文件,然后用sacrebleu工具来计算分数。

TBC

尚存疑问

  • 为什么tokenized\detokenized BLEU差别那么大?----> 师兄说,可能有一些语种,如拉丁字母构成的,这种情况下,tokenized BLEU意味着,使用拉丁字母特有的分词器来进行分词,可能会把文本全部分成字符。
  • fairseq-generate的–sacrebleu有什么用?---->好像没屌用。

参考资料

TBC

你可能感兴趣的:(机器翻译,机器翻译,人工智能,自然语言处理)