BLEU:一种应用于机器翻译的Metric

学习笔记——BLEU:一种应用于机器翻译的Metric

在文本生成任务中,机器翻译的出的句子各种各样那如何去评价不同翻译结果的好坏呢?2002年IBM提出一个重要评价指标Bleu,该论文引用近万,发表于ACL。原文题目是“BLEU: a Method for Automatic Evaluation of Machine Translation”,是NLP从业者的必读文章之一。这篇笔记就从原理介绍,公式解析,再到代码实现来全面展示Bleu的实现。

1.简介

BLEU全称为Bilingual Evaluation Understudy,其意思是双语评估替补,所谓Understudy (替补),意思是代替人进行翻译结果的评估。一开始这项指标是为了翻译而发明的,但是后来它又被证明可以用来评估一组自然语言处理任务生成的文本。

  • 核心:BLEU的核心就是准确率precision,简单来说是通过判断机翻生成的句子中的n-gram在原文中出现的个数除以总的机翻生成的句子的n-gram,这样一来,BLEU的范围区间在【0,1】之间,越接近0说明翻译的句子质量越差,越接近1代表质量越好,从这里可以看出,决定一句话的翻译的质量好坏,参照的标准至关重要。
  • 为了下面介绍方便,我们现在明文规定,给出的标准译文(也就是专业的或者业余翻译员翻译的句子)的名称是reference,而神经网络生成的句子是prediction
  • BLEU还有许多变种。根据n-gram可以划分成多种评价指标,常见的指标有BLEU-1、BLEU-2、BLEU-3、BLEU-4四种,其中n-gram指的是连续的单词个数为n。
  • BLEU-1衡量的是单词级别的准确性,更高阶的BLEU可以衡量句子的流畅性。这一点也可以理解,假设现在取4-gram,我们就要看4个单词为一个词组的词组的出现比率,这比率越高,就代表连贯的翻译正确的词组越多,机器翻译的句子读起来就越是人读的句子。

论文地址:https://www.aclweb.org/anthology/P02-1040

2.公式详解

n-gram precision

我们首先来看一下n-gram, n-gram将一个句子中连续n个元素作为一个整体,长度为4的句子有4个1-gram,每个单词都是一个1-gram,有3个2-gram,有2个3-gram,1个4-gram,这个4-gram就是句子本身,我们看一下例子:

predictions = "My name is John"

Counter({('My',): 1, ('name',): 1, ('is',): 1, ('John',): 1, ('My', 'name'): 1, ('name', 'is'): 1, ('is', 'John'): 1, ('My', 'name', 'is'): 1, ('name', 'is', 'John'): 1, ('My', 'name', 'is', 'John'): 1}

那么n-gram precision代表prediction中的n-gram在所有的reference translation中出现的概率

predictions = ['the cat is on mat']
reference1 = ‘there is the cat on the mat'
reference2 = 'a cat is on the mat'

我们以the举例,the在reference1中出现的概率为2次,在reference2中出现的概率为1次,那么这个the的频率就是2次

  • 我们发现,对于解析的一个特定的n-gram词,在众多的references句子中,其出现的频率并不一致,这时候我们就要去对比,取出出现频率最高的那个作为该n-gram出现的实际次数。

而最后的计算就是用prediction和reference dictionary中共同出现的n-gram个数除以prediction中总的n-gram个数,而这操作也是精确率的求法。

modified n-gram recision

上述算法中存在问题:同一个n-gram在不同的reference中重复出现,计算时次数累加,这样的算法显然是不合理的,如下例

prediction: the the the the the the the.

Reference 1: The cat is on the mat.
Reference 2: There is a cat on the mat.

prediction的1-gram precision是1,显然是不合理的。所以有了做了修正,其modified-gram precision为2/7,其中2=min(7,2)。即prediction和reference dictionary中共同出现的n-gram个数,从这一步修正开始,一个n-gram出现的频率不仅受references中出现频率的制约,也同时受prediction的制约,相当于取两者中的最低值作为min。

精确率

介绍完以上这些基础知识,下面我们正式来剖析一下公式:

p n = ∑ C ∈ P r e d i c t i o n ∑ n − g r a m ∈ C C o u n t c l i p ( n − g r a m ) ∑ C ′ ∈ P r e d i c t i o n ∑ n − g r a m ′ ∈ C ′ C o u n t ( n − g r a m ) p_n = \frac{\sum_{C\in{Prediction}}\sum_{n-gram\in C}Count_{clip}(n-gram)}{\sum_{C^{'}\in{Prediction}}\sum_{n-gram^{'}\in C^{'}}Count(n-gram)} pn=CPredictionngramCCount(ngram)CPredictionngramCCountclip(ngram)

  • 这里的 p n p_n pn其实代表的就是精确率,众所周知,精确率就是所有预测对的除以所有预测对的加上所有预测错的,那按照这样来推算,分子就是预测对的数目,分母就是所有预测的数目。

C o u n t c l i p Count_{clip} Countclip这是代表的n-gram既在prediction中出现又在references中出现,而且秉承着modified的原则,公式是:
C o u n t c l i p = m i n ( c o u n t , M a x _ R e f _ c o u n t ) Count_{clip} = min(count, Max \_ Ref \_ count) Countclip=min(count,Max_Ref_count)

  • 这个公式很有意思,因为它同时出现了一个min和一个max,也是我觉得整个bleu的精华所在。首先来说一下max
    • Max_Ref_count,从Ref中可以看出,是在众多的Ref中去比较,针对特定的n-gram提取出出现次数最高的那个作为频率。
    • 接下来是要把referencs和prediction作比较了,这里就得取最小,原因前文已经说了。
    • 这min-max的操作,就完成了对于 C o u n t c l i p Count_{clip} Countclip的计算。

最后计算

先放公式:
B L E U = B P ∗ e x p ( ∑ n = 1 N w n l o g P n ) BLEU = BP * exp(\sum_{n=1}^N w_n logP_n) BLEU=BPexp(n=1NwnlogPn)
我们一一来剖析这个公式的组成元素。

BP

我们假设一下,如果一个句子只翻译出一个the,而这个the在标准译文中又存在,那么其BLEU就会是1,但是这合理吗?不合理。而这种情况会让机器倾向于去翻译短句子,因为这样得分会更高,为了防范这种情况,就需要加入一个惩罚因子BP。其公式为:
B P = { 1 i f c > r exp ⁡ ( 1 − r / c ) i f c < = r BP = \begin{cases} 1 \quad if \quad c>r \\ \exp(1-r/c) \quad if \quad c <=r \end{cases} BP={1ifc>rexp(1r/c)ifc<=r
c为候选句子中的n-gram的个数,r代表的是答案译文中的与c最接近的译文单词的个数。

当c大于r时,不需要惩罚,但是当c小于r是,就要加一个小于1的系数作为惩罚因子。

w n w_n wn

这是权重系数,赋给不同n的gram的权重,比如说n取4,那么pn就有四个值代表1-gram,2-gram,3-gram,4-gram。

  • w1,w2,w3,w4加起来是1,如何分配可以自由分配。

最后就可以实现BLEU的计算。

3.代码实现

长度计算

首先我们来看一下r和c的计算过程

pred_len += len(prediction)

这边的pred_len就是c的总长度

references_len_list = [len(reference) for reference in references]
references_len_diff = [abs(len(prediction) - length) for length in references_len_list]
min_index = references_len_diff.index(min(references_len_diff))
references_len += references_len_list[min_index]

r的长度比较复杂,因为机翻和人翻的数目对比是1对多,多个答案译文我们计算长度时只能挑选,那么就使用references_len_diff这个变量去计算——,在众多reference中,其n-gram数目和对应的prediction最为接近的那个数目,我们将其纳入references_len中。

Counter

pred_counter: Counter = get_n_gram(prediction, n_gram)

使用counter来获取prediciton中所有的n-gram

reference_counter: Counter = Counter()
for reference in references:
    reference_counter |= get_n_gram(reference, n_gram)

这里就很有意思,references中有多句答案译文,参照上文,我们要挑选出数目最大的加入counter中,也就是min-max公式的max部分,那么使用counter 的 |= 来实现这一目的。

counter_clip = pred_counter & reference_counter

这一步就是实现min-max 的min的过程。

BLEU计算

for counter in counter_clip:
    precision_matches[len(counter) - 1] += counter_clip[counter]
for counter in pred_counter:
    precision_total[len(counter) - 1] += pred_counter[counter]

这一步就是将每一次计算到的counter_clipcounter保存下来

precision_score = precision_matches / precision_total
precision_score = tensor(ngram_weights) * torch.log(precision_score)
brevity_penalty = _get_brevity_penalty(pred_len, references_len)
bleu = brevity_penalty * torch.exp(torch.sum(precision_score))

最终完成BLEU的计算。

你可能感兴趣的:(机器翻译,深度学习,自然语言处理)