机器翻译评价指标 — BLEU

一. 简介

Bilingual Evaluation Understudy: BLEU。在自然语言处理中的机器翻译任务中, BLEU非常常见, 它是用于评估模型生成的句子(candidate)实际句子(reference)的差异的指标. 它的取值范围在0.0到1.0之间, 如果两个句子完美匹配(perfect match), 那么BLEU是1.0, 反之, 如果两个句子完美不匹配(perfect mismatch), 那么BLEU为0.0. 虽然这个指标不够完美, 但是它有5个非常引人注目的好处(compelling benefits):

    • 计算代价小,速度快
    • 容易理解
    • 与语言无关(这意味着你可以使用全世界任意的语言来测试)
    • 与人类评价结果高度相关
    • 被学术界和工业界广泛采用

二.计算

  • 最早的BLEU算法

最早的𝐵𝐿𝐸𝑈算法是直接统计candidate中的单词有多少个出现在𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒中,具体的式子是:
𝐵𝐿𝐸𝑈=(出现在𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒中的candidate的单词的个数) / (candidate 中单词的总数)

以下面例子为例:
candidate: the the the the the the the
𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒: the cat is on the mat
candidate中所有的单词都在𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒中出现过,因此:𝐵𝐿𝐸𝑈=7/7=1
对上面的结果显然是不合理的,而且主要是分子的统计不合理,因此对上面式子中的分子进行了改进

  • 改进的BLEU算法 — 分子截断计数

𝐶𝑜𝑢𝑛𝑡_𝑤𝑖 表示单词𝑤𝑖𝑐andidate中出现的次数,𝑅𝑒𝑓_𝐶𝑜𝑢𝑛𝑡_𝑤𝑖 表示单词𝑤𝑖𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒中出现的次数;
仍然以上面的例子为例,在𝑐andidate中只有一个单词𝑡𝑒,因此只要计算一个𝐶𝑜𝑢𝑛𝑡^𝑐𝑙𝑖𝑝𝑡𝑒𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒中只出现了两次,因此:𝐵𝐿𝐸𝑈=2/7

  • 引入𝑛𝑔𝑟𝑎𝑚

在上面我们一直谈的都是对于单个单词进行计算,单个单词可以看作时1𝑔𝑟𝑎𝑚1𝑔𝑟𝑎𝑚可以描述翻译的充分性,即逐字翻译的能力,但不能关注翻译的流畅性,因此引入了𝑛𝑔𝑟𝑎𝑚,在这里一般𝑛不大于4。引入𝑛𝑔𝑟𝑎𝑚后的表达式如下:

𝑝𝑛 中的𝑛表示𝑛𝑔𝑟𝑎𝑚𝑝𝑛表示𝑛-𝑔𝑟𝑎𝑚的精度,即1𝑔𝑟𝑎𝑚时,𝑛=1。很多时候在评价一个系统时会用多条𝑐andidate来评价,因此上面式子中引入了一个候选集合𝑐andidates

接下来简单的理解下上面的式子,首先来看分子:
1)第一个 描述的是各个𝑐andidate的总和;(可能会有多个candidates)
2)第二个 描述的是一条𝑐andidate中所有的𝑛𝑔𝑟𝑎𝑚的总和;
3)𝐶𝑜𝑢𝑛𝑡𝑐𝑙𝑖𝑝(𝑛𝑔𝑟𝑎𝑚) 表示某一个𝑛𝑔𝑟𝑎𝑚词的截断计数;
再来看分母,前两个和分子中的含义一样,𝐶𝑜𝑢𝑛𝑡(𝑛𝑔𝑟𝑎𝑚)表示𝑛𝑔𝑟𝑎𝑚𝑐andidate中的计数。
再进一步来看,实际上分母就是𝑐andidate𝑛𝑔𝑟𝑎𝑚的个数分子是出现在𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒中的𝑐andidate𝑛𝑔𝑟𝑎𝑚的个数

举一个例子来看看实际的计算:
𝑐andidate: the cat sat on the mat
𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒: the cat is on the mat
计算𝑛𝑔𝑟𝑎𝑚的精度:
𝑝1=56=0.83333,𝑝2=35=0.6,𝑝3=14=0.25,𝑝4=03=0

添加对句子长度的乘法因子:
在翻译时,若出现译文很短的句子时往往会有较高的𝐵𝐿𝐸𝑈值,因此引入对句子长度的乘法因子,其表达式如下:

在这里𝑐表示𝑐𝑎𝑑𝑖𝑛𝑎𝑡𝑒的长度,𝑟表示𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒的长度。

得到最终的表达式:

三.NLTK实现

  • 句子的BLEU值
>>> from nltk.translate.bleu_score import sentence_bleu
>>> reference = [['this', 'is', 'a', 'test'], ['this', 'is' 'test']]
>>> candidate = ['this', 'is', 'a', 'test']
>>> score = sentence_bleu(reference, candidate)
>>> print(score)
1.0

这个例子的结果为1.0, 因为candidate与reference的第1个句子perfect match了。(多个references而不是多个candidates)

  • Corpus(语料库)的BLEU值

它用于来对多个句子比如一个段落甚至一篇文章进行得分评价.

# two references for one document
>>> from nltk.translate.bleu_score import corpus_bleu
>>> references = [[['this', 'is', 'a', 'test'], ['this', 'is' 'test']]]
>>> candidates = [['this', 'is', 'a', 'test']]
>>> score = corpus_bleu(references, candidates)
>>> print(score)

1.0

四.参考

0