前言

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

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

  早在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)

  1. Going to play basketball this afternoon ?

  参考答案(Reference)

  1. 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.867*0.4889 = 0.4238

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

  1. #-*- coding:utf-8 -*-
  2. import sys
  3. import codecs
  4. import os
  5. import math
  6. import operator
  7. import json
  8.  
  9. # 如果是一份答案的话,务必在答案的后面加上.txt python Bleu.py Candidate ref.txt
  10. # 如果是多份答案的话,把多份答案放到一个文件夹中 python Bleu.py Candidate 文件夹
  11.  
  12. def fetch_data(cand, ref):
  13. """ Store each reference and candidate sentences as a list """
  14. references = []
  15. if '.txt' in ref:
  16. reference_file = codecs.open(ref, 'r', 'utf-8')
  17. references.append(reference_file.readlines())
  18. else:
  19. for root, dirs, files in os.walk(ref):
  20. for f in files:
  21. reference_file = codecs.open(os.path.join(root, f), 'r', 'utf-8')
  22. references.append(reference_file.readlines())
  23. candidate_file = codecs.open(cand, 'r', 'utf-8')
  24. candidate = candidate_file.readlines()
  25. return candidate, references
  26.  
  27. def count_ngram(candidate, references, n):
  28. clipped_count = 0
  29. count = 0
  30. r = 0
  31. c = 0
  32. for si in range(len(candidate)):
  33. # Calculate precision for each sentence
  34. #print si
  35. ref_counts = []
  36. ref_lengths = []
  37. #print references
  38. # Build dictionary of ngram counts
  39. for reference in references:
  40. #print 'reference' + reference
  41. ref_sentence = reference[si]
  42. ngram_d = {}
  43. words = ref_sentence.strip().split()
  44. ref_lengths.append(len(words))
  45. limits = len(words) - n + 1
  46. # loop through the sentance consider the ngram length
  47. for i in range(limits):
  48. ngram = ' '.join(words[i:i+n]).lower()
  49. if ngram in ngram_d.keys():
  50. ngram_d[ngram] += 1
  51. else:
  52. ngram_d[ngram] = 1
  53. ref_counts.append(ngram_d)
  54. # candidate
  55. cand_sentence = candidate[si]
  56. cand_dict = {}
  57. words = cand_sentence.strip().split()
  58. limits = len(words) - n + 1
  59. for i in range(0, limits):
  60. ngram = ' '.join(words[i:i + n]).lower()
  61. if ngram in cand_dict:
  62. cand_dict[ngram] += 1
  63. else:
  64. cand_dict[ngram] = 1
  65. clipped_count += clip_count(cand_dict, ref_counts)
  66. count += limits
  67. r += best_length_match(ref_lengths, len(words))
  68. c += len(words)
  69. if clipped_count == 0:
  70. pr = 0
  71. else:
  72. pr = float(clipped_count) / count
  73. bp = brevity_penalty(c, r)
  74. return pr, bp
  75.  
  76. def clip_count(cand_d, ref_ds):
  77. """Count the clip count for each ngram considering all references"""
  78. count = 0
  79. for m in cand_d.keys():
  80. m_w = cand_d[m]
  81. m_max = 0
  82. for ref in ref_ds:
  83. if m in ref:
  84. m_max = max(m_max, ref[m])
  85. m_w = min(m_w, m_max)
  86. count += m_w
  87. return count
  88.  
  89. def best_length_match(ref_l, cand_l):
  90. """Find the closest length of reference to that of candidate"""
  91. least_diff = abs(cand_l-ref_l[0])
  92. best = ref_l[0]
  93. for ref in ref_l:
  94. if abs(cand_l-ref) < least_diff:
  95. least_diff = abs(cand_l-ref)
  96. best = ref
  97. return best
  98.  
  99. def brevity_penalty(c, r):
  100. if c > r:
  101. bp = 1
  102. else:
  103. bp = math.exp(1-(float(r)/c))
  104.  
  105. return bp
  106.  
  107. def geometric_mean(precisions):
  108. return (reduce(operator.mul, precisions)) ** (1.0 / len(precisions))
  109.  
  110. def BLEU(candidate, references):
  111. precisions = []
  112. for i in range(4):
  113. pr, bp = count_ngram(candidate, references, i+1)
  114. precisions.append(pr)
  115. print 'P'+str(i), ' = ',round(pr, 2)
  116. print 'BP = ',round(bp, 2)
  117. bleu = geometric_mean(precisions) * bp
  118. return bleu
  119.  
  120. if __name__ == "__main__":
  121. candidate, references = fetch_data(sys.argv[1], sys.argv[2])
  122. bleu = BLEU(candidate, references)
  123. print 'BLEU = ',round(bleu, 4)
  124. out = open('bleu_out.txt', 'w')
  125. out.write(str(bleu))
  126. out.close()

Perplexity详解:http://blog.csdn.net/luo123n/article/details/48902815

Deep Learning基础--机器翻译BLEU与Perplexity详解的更多相关文章

  1. 基础 | batchnorm原理及代码详解

    https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...

  2. Docker 基础技术之 Linux cgroups 详解

    PS:欢迎大家关注我的公众号:aCloudDeveloper,专注技术分享,努力打造干货分享平台,二维码在文末可以扫,谢谢大家. 推荐大家到公众号阅读,那里阅读体验更好,也沉淀了很多篇干货. 前面两篇 ...

  3. Java工程师 基础+实战 完整路线图(详解版)

    Java工程师 基础+实战 完整路线图(详解版)   Java 基础 Java 是一门纯粹的面向对象的编程语言,所以除了基础语法之外,必须得弄懂它的 oop 特性:封装.继承.多态.此外还有泛型.反射 ...

  4. 《Java基础——break与continue用法详解》

    Java基础--break与continue用法详解       1. break语句: 规则: 1. 仅用于循环语句和switch语句当中,用于跳出循环. 2. 当只有一层循环时,则直接跳出循环,不 ...

  5. Deep Learning基础--理解LSTM/RNN中的Attention机制

    导读 目前采用编码器-解码器 (Encode-Decode) 结构的模型非常热门,是因为它在许多领域较其他的传统模型方法都取得了更好的结果.这种结构的模型通常将输入序列编码成一个固定长度的向量表示,对 ...

  6. Deep Learning基础--CNN的反向求导及练习

    前言: CNN作为DL中最成功的模型之一,有必要对其更进一步研究它.虽然在前面的博文Stacked CNN简单介绍中有大概介绍过CNN的使用,不过那是有个前提的:CNN中的参数必须已提前学习好.而本文 ...

  7. Deep Learning基础--理解LSTM网络

    循环神经网络(RNN) 人们的每次思考并不都是从零开始的.比如说你在阅读这篇文章时,你基于对前面的文字的理解来理解你目前阅读到的文字,而不是每读到一个文字时,都抛弃掉前面的思考,从头开始.你的记忆是有 ...

  8. Deep Learning基础--参数优化方法

    1. 深度学习流程简介 1)一次性设置(One time setup)          -激活函数(Activation functions) - 数据预处理(Data Preprocessing) ...

  9. PHP 基础篇 - PHP 错误级别详解

    一.前言 最近经常看到工作 2 年左右的童鞋写的代码也会出现以静态方法的形式调用非静态方法,这是个 Deprecated 级别的语法错误,代码里不应该出现的.对方很郁闷,说:为什么我的环境可以正常运行 ...

随机推荐

  1. bzoj4568-幸运数字

    题目 给出一棵树,每个节点上有权值\(a_i\),多次询问一条路径上选择一些点权值异或和最大值.\(n\le 2\times 10^4,q\le 2\times 10^5,0\le a_i\le 2\ ...

  2. BZOJ 2190 仪仗队(线性筛欧拉函数)

    简化题意可知,实际上题目求得是gcd(i,j)=1(i,j<=n)的数对数目. 线性筛出n大小的欧拉表,求和*2+1即可.需要特判1. # include <cstdio> # in ...

  3. java中的error该不该捕获

    写java程序时,通常会被提示捕获异常,而又有一些异常是不需要强制捕获的,这是一个被说烂了的话题.像我一样从其他语言转过来的人确实有点迷惑,那我以我的理解重新解释一遍吧. 异常的基类是Exceptio ...

  4. 【SPOJ】QTREE6(Link-Cut-Tree)

    [SPOJ]QTREE6(Link-Cut-Tree) 题面 Vjudge 题解 很神奇的一道题目 我们发现点有黑白两种,又是动态加边/删边 不难想到\(LCT\) 最爆力的做法,显然是每次修改单点颜 ...

  5. python基础----isinstance(obj,cls)和issubclass(sub,super)、反射、__setattr__,__delattr__,__getattr__、二次加工标准类型(包装)

    一.isinstance(obj,cls)和issubclass(sub,super)                                isinstance(obj,cls)检查是否ob ...

  6. 网络协议之DHCP与Route20170330

    由于要使用网络通讯,所以不可避免的要用到dhcp.理想的网络通讯方式是下面3种都要支持: 1,接入已有网络.这便要求可以作为dhcp客户端. 2,作为DHCP服务器,动态分配IP. 3,指定固定IP ...

  7. 洛谷P2398 GCD SUM (数学)

    洛谷P2398 GCD SUM 题目描述 for i=1 to n for j=1 to n sum+=gcd(i,j) 给出n求sum. gcd(x,y)表示x,y的最大公约数. 输入输出格式 输入 ...

  8. Codeforces Global Round 2 题解

    Codeforces Global Round 2 题目链接:https://codeforces.com/contest/1119 A. Ilya and a Colorful Walk 题意: 给 ...

  9. find~~~查找文件

    find . -name "klibc" 在当前文件内查找文件 klibc find . -name "*libc*" 在当前文件内查找文件 (模糊查询)

  10. scrapy 采集网页出现丢失url的问题

    url_list = ["http://www.icoat.cc/news/list_18_3.html", "http://www.icoat.cc/news/list ...