心得经验总结:机器翻译评测——BLEU算法详解(新增在线计算BLEU分值)

本文涉及的产品
语种识别,语种识别 100万字符
文档翻译,文档翻译 1千页
图片翻译,图片翻译 100张
简介: 心得经验总结:机器翻译评测——BLEU算法详解(新增在线计算BLEU分值)

◆版权声明:本文出自胖喵~的博客,转载必须注明出处。

转载请注明出处:

前言

  近年来,在自然语言研究领域中,评测问题越来越受到广泛的重视,可以说,评测是整个自然语言领域最核心和关键的部分。而机器翻译评价对于机器翻译的研究和发展具有重要意义:机器翻译系统的开发者可以通过评测得知系统存在的问题而不断改进,用户也可以根据评测报告选择满足自己需求的产品,而对于机器翻译的研究人员来说,评测能够给他们的技术发展方向提供最可靠的依据。

——摘自北京邮电大学信息工程系张剑博士在微软亚洲研究院访问期间完成的一篇论文中的一段话。  

  早在90年代初,美国国家自然基金委员会和欧盟就资助的国际语言工程标准(ISLE)计划就专门设立了EWG(Evaluation Working Group)机器翻译评测工作组。1992年至1994年之间,美国国防部高级研究计划署(DARPA)专门组织一批专家从翻译译文的忠实度、流利度和信息量三个角度对当时的法英、日英、西英的机器翻译系统进行了大规模的评测。目前比较流行的自动评测方法是是IBM提出的BLEU算法,BLEU(bilingual evaluation understudy),简单来说,BLEU算法的思想就是机器翻译的译文越接近人工翻译的结果,它的翻译质量就越高。所以评测算法就是如何定义机器翻译译文与参考译文之间的相似度。

  我们看下BLEU算法具体的细节吧:

N-gram

  BLEU 采用一种N-gram的匹配规则,原理比较简单,就是比较译文和参考译文之间n组词的相似的一个占比。

  例如:

    原文:今天天气不错

    机器译文:It is a nice day today

    人工译文:Today is a nice day

  如果用1-gram匹配的话:

  可以看到机器译文一共6个词,有5个词语都命中的了参考译文,那么它1-gram的匹配度为 5/6

  我们再以3-gram举例:

  可以看到机器译文一共可以分为四个3-gram的词组,其中有两个可以命中参考译文,那么它3-gram的匹配度为 2/4

  依次类推,我们可以很容易实现一个程序来遍历计算N-gram的一个匹配度。一般来说1-gram的结果代表了文中有多少个词被单独翻译出来了,因此它反映的是这篇译文的忠实度;而当我们计算2-gram以上时,更多时候结果反映的是译文的流畅度,值越高文章的可读性就越好。

召回率

  上面所说的方法比较好理解,也比较好实现,但是没有考虑到召回率,举一个非常简单的例子说明:

  原文:猫站在地上

  机器译文:the the the the

  人工译文:The cat is standing on the ground

  在计算1-gram的时候,the 都出现在译文中,因此匹配度为4/4 ,但是很明显 the 在人工译文中最多出现的次数只有2次,因此BLEU算法修正了这个值的算法,首先会计算该n-gram在译文中可能出现的最大次数:

  Count是N-gram在机器翻译译文中的出现次数,Max_Ref_Count是该N-gram在一个参考译文中最大的出现次数,最终统计结果取两者中的较小值。然后在把这个匹配结果除以机器翻译译文的N-gram个数。因此对于上面的例子来说,修正后的1-gram的统计结果就是2/4。

  我们将整个要处理的将机器翻译的句子表示为Ci,标准答案表示为 Si=si1,...sim(m表示有m个参考答案)  

  n-grams表示n个单词长度的词组集合,令Wk第k个n-gram

  比如这样的一句话,”I come from china”,第1个2-gram为:I come; 第2个2-gram为:come from; 第3个2-gram为:from china;

  Hk(Ci) 表示Wk翻译选译文Ci中出现的次数

  Hk(Sij) 表示Wk在标准答案Sij中出现的次数

  综上所述各阶N-gram的精度都可以按照下面这个公式计算:

  maxi∈mhk(sij)表示某n-gram在多条标准答案中出现最多的次数

  ∑i∑kmin(hk(ci),maxj∈mhk(sij))表示取n-gram在翻译译文和标准答案中出现的最小次数

惩罚因子

  上面的算法已经足够可以有效的翻译评估了,然而N-gram的匹配度可能会随着句子长度的变短而变好,因此会存在这样一个问题:一个翻译引擎只翻译出了句子中部分句子且翻译的比较准确,那么它的匹配度依然会很高。为了避免这种评分的偏向性,BLEU在最后的评分结果中引入了长度惩罚因子(Brevity Penalty)。

  BP的计算公式如上。lc代表表示机器翻译译文的长度,ls表示参考答案的有效长度,当存在多个参考译文时,选取和翻译译文最接近的长度。当翻译译文长度大于参考译文的长度时,惩罚系数为1,意味着不惩罚,只有机器翻译译文长度小于参考答案才会计算惩罚因子。

BLEU 

  由于各N-gram统计量的精度随着阶数的升高而呈指数形式递减,所以为了平衡各阶统计量的作用,对其采用几何平均形式求平均值然后加权,再乘以长度惩罚因子,得到最后的评价公式:

  BLEU的原型系统采用的是均匀加权,即Wn=1/N 。N的上限取值为4,即最多只统计4-gram的精度。

实例

  译文(Candidate)

Going to play basketball this afternoon ?

  参考答案(Reference)

Going to play basketball in the afternoon ?

  译文gram长度:7  参考答案gram长度:8

  先看1-gram,除了this这个单词没有命中,其他都命中了,因此:

    P1 = 6/7 = 0.85714...

  其他gram以此类推:

    P2 = 4/6 = 0.6666..

    P3 = 2/5 = 0.4

    P4 = 1/4 = 0.25

  再计算logPn,这里用python自带的:

  ∑logPn和为-2.8622 ;再乘以Wn,也就是除以4为 0.7156

  BP = e^(1-8/7) 约等于 0.867

  BLEU = 0.867 e^((P1 + P2 + P3 + P4)/4) = 0.8670.4889 = 0.4238

  本来打算自己实现一个python的代码,结果发现已经有国外小哥做了,拿下来稍微修改了点内容,这里供大家参考

#-- coding:utf-8 --

import sys

import codecs

import os

import math

import operator

import json

# 如果是一份答案的话,务必在答案的后面加上.txt python Bleu.py Candidate ref.txt

# 如果是多份答案的话,把多份答案放到一个文件夹中 python Bleu.py Candidate 文件夹

def fetch_data(cand, ref):

""" Store each reference and candidate sentences as a list """

references = 【】

if '.txt' in ref:

reference_file = codecs.open(ref, 'r', 'utf-8')

references.append(reference_file.readlines())

else:

for root, dirs, files in os.walk(ref):

for f in files:

reference_file = codecs.open(os.path.join(root, f), 'r', 'utf-8')

references.append(reference_file.readlines())

candidate_file = codecs.open(cand, 'r', 'utf-8')

candidate = candidate_file.readlines()

return candidate, references

def count_ngram(candidate, references, n):

clipped_count = 0

count = 0

r = 0

c = 0

for si in range(len(candidate)):

# Calculate precision for each sentence

#print si

ref_counts = 【】

ref_lengths = 【】

#print references

# Build dictionary of ngram counts

for reference in references:

#print 'reference' + reference

ref_sentence = reference【si】

ngram_d = {}

words = ref_sentence.strip().split()

ref_lengths.append(len(words))

limits = len(words) - n + 1

# loop through the sentance consider the ngram length

for i in range(limits):

ngram = ' '.join(words【i:i+n】).lower()

if ngram in ngram_d.keys():

ngram_d【ngram】 += 1

else:

ngram_d【ngram】 = 1

ref_counts.append(ngram_d)

# candidate

cand_sentence = candidate【si】

cand_dict = {}

words = cand_sentence.strip().split()

limits = len(words) - n + 1

for i in range(0, limits):

ngram = ' '.join(words【i:i + n】).lower()

if ngram in cand_dict:

cand_dict【ngram】 += 1

else:

cand_dict【ngram】 = 1

clipped_count += clip_count(cand_dict, ref_counts)

count += limits

r += best_length_match(ref_lengths, len(words))

c += len(words)

if clipped_count == 0:

pr = 0

else:

pr = float(clipped_count) / count

bp = brevity_penalty(c, r)

return pr, bp

def clip_count(cand_d, ref_ds):

"""Count the clip count for each ngram considering all references"""

count = 0

for m in cand_d.keys():

m_w = cand_d【m】

m_max = 0

for ref in ref_ds:

if m in ref:

m_max = max(m_max, ref【m】)

m_w = min(m_w, m_max)

count += m_w

return count

def best_length_match(ref_l, cand_l):

"""Find the closest length of reference to that of candidate"""

least_diff = abs(cand_l-ref_l【0】)

best = ref_l【0】

for ref in ref_l:

if abs(cand_l-ref) [span style="color: rgba(0, 0, 0, 1)"> least_diff:

least_diff = abs(cand_l-ref)

best = ref

return best

def brevity_penalty(c, r):

if c > r:

bp = 1

else:

bp = math.exp(1-(float(r)/c))

return bp

def geometric_mean(precisions):

return (reduce(operator.mul, precisions)) * (1.0 / len(precisions))

def BLEU(candidate, references):

precisions = 【】

for i in range(4):

pr, bp = count_ngram(candidate, references, i+1)

precisions.append(pr)

print 'P'+str(i+1), ' = ',round(pr, 2)

print 'BP = ',round(bp, 2)

bleu = geometric_mean(precisions) bp

return bleu

if name == "main":

candidate, references = fetch_//代码效果参考:http://www.zidongmutanji.com/bxxx/473742.html

data(sys.argv【1】, sys.argv【2】)

bleu = BLEU(candidate, references)

print 'BLEU = ',round(bleu, 4)

out = open('bleu_out.txt', 'w')

out.write(str(bleu))

out.close()

在线计算

  因为很多人(非计算机专业)的同学留言问我BLEU相关的计算,为了更加方便,我提供了一个在线BLEU计算的页面,供大家使用。

  地址:

  只需按照提示,上传译文,点击计算即可。

  另外针对中文计算BLEU的“分词”功能,我也提供了出来。

  地址:

  昨天熬夜写到凌晨2点多,终于搞定。

  各位觉得还有用的话,欢迎多多推广。

相关文章
|
1月前
|
算法 Java
算法:Java计算二叉树从根节点到叶子结点的最大路径和
算法:Java计算二叉树从根节点到叶子结点的最大路径和
|
1月前
|
机器学习/深度学习 算法
递归算法题练习(数的计算、带备忘录的递归、计算函数值)
递归算法题练习(数的计算、带备忘录的递归、计算函数值)
|
2天前
|
机器学习/深度学习 算法
**反向传播算法**在多层神经网络训练中至关重要,它包括**前向传播**、**计算损失**、**反向传播误差**和**权重更新**。
【6月更文挑战第28天】**反向传播算法**在多层神经网络训练中至关重要,它包括**前向传播**、**计算损失**、**反向传播误差**和**权重更新**。数据从输入层流经隐藏层到输出层,计算预测值。接着,比较预测与真实值计算损失。然后,从输出层开始,利用链式法则反向计算误差和梯度,更新权重以减小损失。此过程迭代进行,直到损失收敛或达到训练次数,优化模型性能。反向传播实现了自动微分,使模型能适应训练数据并泛化到新数据。
8 2
|
15天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
15天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
22天前
|
算法
m基于PSO粒子群优化的LDPC码NMS译码算法最优归一化参数计算和误码率matlab仿真
MATLAB2022a仿真实现了基于遗传优化的NMS LDPC译码算法,优化归一化参数以提升纠错性能。NMS算法通过迭代处理低密度校验码,而PSO算法用于寻找最佳归一化因子。程序包含粒子群优化的迭代过程,根据误码率评估性能并更新解码参数。最终,展示了迭代次数与优化过程的关系,并绘制了SNR与误码率曲线。
21 2
|
23天前
|
存储 算法 测试技术
数据结构学习记录——树习题-Complete Binary Search Tree(题目描述、输入输出示例、数据结构的选择、核心算法、计算左子树的规模)
数据结构学习记录——树习题-Complete Binary Search Tree(题目描述、输入输出示例、数据结构的选择、核心算法、计算左子树的规模)
19 1
|
23天前
|
算法
数据结构和算法学习记录——时间复杂度的计算(嵌套循环、大O的渐进表示法、双重循环、常数循环、strchr、冒泡排序、二分查找、斐波那契数列递归)
数据结构和算法学习记录——时间复杂度的计算(嵌套循环、大O的渐进表示法、双重循环、常数循环、strchr、冒泡排序、二分查找、斐波那契数列递归)
32 1
|
1月前
|
算法 调度 UED
作业调度算法(含详细计算过程)和进程调度算法浅析
作业调度算法(含详细计算过程)和进程调度算法浅析
234 1
作业调度算法(含详细计算过程)和进程调度算法浅析
|
1月前
|
算法
说说你对算法中时间复杂度,空间复杂度的理解?如何计算?
该文介绍了算法的基本概念,强调了时间和空间复杂度在衡量算法效率中的重要性。时间复杂度表示算法执行时间与输入规模的增长关系,常用大O符号表示,如O(1), O(log n), O(n), O(nlogn), O(n^2)等。文章指出,最坏情况下的时间复杂度是评估算法性能的上限,并且在实际应用中需要在时间与空间之间找到平衡。