機器翻譯評測——BLEU改進后的NIST算法


  ◆版權聲明:本文出自胖喵~的博客,轉載必須注明出處。

  轉載請注明出處:http://www.cnblogs.com/by-dream/p/7765345.html 

 

 

  上一節介紹了BLEU算的缺陷。NIST(National Institute of standards and Technology)方法是在BLEU方法上的一種改進。最主要的是引入了每個n-gram的信息量(information)的概念。BLEU算法只是單純的將n-gram的數目加起來,而nist是在得到信息量累加起來再除以整個譯文的n-gram片段數目。這樣相當於對於一些出現少的重點的詞權重就給的大了。

  信息量的計算公式是:

  解釋一下:分母是n元詞在參考譯文中出現的次數,分子是對應的n-1元詞在參考譯文中的出現次數。對於一元詞匯,分子的取值就是整個參考譯文的長度。這里之所以這樣算,應該是考慮到出現次數少的就是重點詞這樣的一個思路。

  計算信息量之后,就可以對每一個共現n元詞乘以它的信息量權重,再進行加權求平均得出最后的評分結果:  

  這里注意幾個地方:

  1、N一般取5

  2、β是一個常數,在Lsys/Lref=2/3 時,β使得長度罰分率為0.5,它是個經驗值,大概的曲線是:

  3、Lref 是參考答案的平均長度(注意L的上方有一個平均符號)

  4、Lsys是譯文的長度

 

  下面是我費勁千辛萬苦找到了計算nist值的工具:

  首先進入nist組織的官網:https://www.nist.gov/itl/iad/mig/tools

  下載第三個,然后我們直接運行,發現因為找不到依賴的庫,會出現報錯:

  Can't locate XML/Twig.pm in @INC (you may need to install the XML::Twig module)

 

   之前也不會perl,這個也折騰了好久。下載XML-Twig 。進入:http://search.cpan.org/~mirod/XML-Twig-3.48/Twig.pm

  下載成功后,需要三步:

  1、perl Makefile.PL -y :這一步在下載下來的readme中有說明,參數還可以指定 -n。

  2、make

 

  3、make install:這一步需要root權限,否則會報錯

  沒給root權限,報的錯

  我們再運行一下,沒有再報錯了

  我們用nist提供的example試試,發現算法可以使用:

 我們看下其他的用法:

BLEU-4(mteval-v13a,官方OpenMT12評估指標)
  調用行: perl mteval-v13a.pl -r REFERENCE_FILE -s SOURCE_FILE -t CANDIDATE_FILE -c -b
  選項-c:區分大小寫的得分
  選項-b:僅BLEU得分
IBM BLEU(bleu-1.04a)
  調用行: perl bleu-1.04.pl -r REFERENCE_FILE -t CANDIDATE_FILE
  默認情況下,評分是區分大小寫的
NIST(mteval-v13a)
  調用行: perl mteval-v13a.pl -r REFERENCE_FILE -s SOURCE_FILE -t CANDIDATE_FILE -c -n
  選項-c:區分大小寫的得分
  選項-n:僅NIST評分
TER(tercom-0.7.25)
  調用行: java -jar tercom.7.25.jar -r REFERENCE_FILE -h CANDIDATE_FILE -N -s
  選項-N:啟用歸一化
  選項-s:區分大小寫的得分
METEOR(氣象0.7)
  調用行: perl meteor.pl -s SYSTEM_ID -r REFERENCE_FILE -t CANDIDATE_FILE --modules "exact porter_stem wn_stem wn_synonymy"
  選項--modules "exact porter_stem wn_stem wn_synonymy":按照順序使用所有四個METEOR匹配模塊

 

  這里我們可以看到除了提供nist算法外,還提供BLEU,於是我們用BLEU那篇文章中舉例的那句話,我們看看值是否相等。

  src.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mteval SYSTEM "ftp://jaguar.ncsl.nist.gov/mt/resources/mteval-xml-v1.3.dtd">
<mteval>
    <srcset setid="example_set" srclang="Arabic">
        <doc docid="doc1" genre="nw">
            <p>
                <seg id="1">下午去打籃球不?"</seg>
            </p>
        </doc>
    </srcset>
</mteval>

  tst.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mteval SYSTEM "ftp://jaguar.ncsl.nist.gov/mt/resources/mteval-xml-v1.3.dtd">
<mteval>
    <tstset setid="example_set" srclang="Arabic" trglang="English" sysid="sample_system">
        <doc docid="doc1" genre="nw">
            <p>
                <seg id="1">Going to play basketball this afternoon ?</seg>
            </p>
        </doc>
    </tstset>
</mteval>

  ref.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mteval SYSTEM "ftp://jaguar.ncsl.nist.gov/mt/resources/mteval-xml-v1.3.dtd">
<mteval>
    <refset setid="example_set" srclang="Arabic" trglang="English" refid="ref1">
        <doc docid="doc1" genre="nw">
            <p>
                <seg id="1">Going to play basketball in the afternoon ?</seg>
            </p>
        </doc>
    </refset>
</mteval>

  運行命令:

  得到的bleu值和我們之前計算的bleu值是一致的。成功~

  然后我在后續計算的過程中,發現了nist腳本中的BLEU計算的時候,會把xml中的符號例如“左括號”他會轉移為&#40; 進行計算。而&#40;就是左括號的標准轉義字符,只不過這里計算的時候剛好給相反了,有點讓人想不通。。

  最后附上轉換xml的腳本,因為之前BLEU計算的時候,不需要xml格式的,因此寫了一個批量轉化的腳本:

#!/usr/bin/python
#coding=utf8

import sys
import re
import codecs
import os
from xml.etree.ElementTree import ElementTree as etree
from xml.etree.ElementTree import Element, SubElement, ElementTree

reload(sys)
sys.setdefaultencoding( "utf-8" )


# 傳入至少5個參數
# 生成譯文的xml
# param 1: 要處理的是什么文件,只允許傳入 "src","tst","ref"
# param 2:評測集名稱
# param 3:源語言
# param 4:目標語言
# param 5..:要處理的文件

# 例如
# 生成原文 
# python genXML.py src tmq30 English Chinese tmq30.txt
# 生成譯文
# python genXML.py tst tmq English Chinese baidu.txt Google.txt
# 生成ref 
# python genXML.py ref tmq English Chinese ref.txt ref2.txt 


'''
@ 生成ref的xml
@ param 1: 多份ref的list,list中每一個元素為一個ref的list
@ param 2:評測集名稱
@ param 3:源語言
@ param 3:目標語言
'''
def genrefxml(reflists, setid, srclang, trglang):
    mteval = Element('mteval')
    for reflist in reflists:
        sysid = reflist[0]
        set = SubElement(mteval, "refset")
        set.attrib = {"setid":setid, "srclang":srclang, "trglang":trglang, "refid":sysid}
        doc = SubElement(set, "doc")
        doc.attrib = {"docid":"doc1"}
    
        i = 0
        for sentence in reflist:
            # 第一位存儲具體是哪個引擎
            if i != 0:

                p = SubElement(doc, "p")
                seg = SubElement(p, "seg")
                seg.attrib = {"id":str(i)}
                seg.text = sentence
            i = i+1
    tree = ElementTree(mteval)
    tree.write(setid+'_ref.xml', encoding = 'utf-8')


'''
@ 生成譯文的xml
@ param 1: 多份譯文的list,list中每一個元素為一個譯文的list
@ param 2:評測集名稱
@ param 3:源語言
@ param 3:目標語言
'''
def gentstxml(tstlists, setid, srclang, trglang):
    mteval = Element('mteval')
    for tstlist in tstlists:
        sysid = tstlist[0]
        set = SubElement(mteval, "tstset")
        set.attrib = {"setid":setid, "srclang":srclang, "trglang":trglang, "sysid":sysid}
        doc = SubElement(set, "doc")
        doc.attrib = {"docid":"doc1"}
    
        i = 0
        for sentence in tstlist:
            # 第一位存儲具體是哪個引擎
            if i != 0:

                p = SubElement(doc, "p")
                seg = SubElement(p, "seg")
                seg.attrib = {"id":str(i)}
                seg.text = sentence
            i = i+1
    tree = ElementTree(mteval)
    tree.write(setid+'_tst.xml', encoding = 'utf-8')


'''
@ 生成原文的xml
@ param 1: 原文內容的list
@ param 2:評測集名稱
@ param 3:源語言
'''
def gensrcxml(senlist, setid, srclang):
    mteval = Element('mteval')
    set = SubElement(mteval, "srcset")
    set.attrib = {"setid":setid, "srclang":srclang}
    doc = SubElement(set, "doc")
    doc.attrib = {"docid":"doc1"}
    
    i = 1
    for sentence in senlist:
        p = SubElement(doc, "p")
        seg = SubElement(p, "seg")
        seg.attrib = {"id":str(i)}
        seg.text = sentence
        i = i+1
    tree = ElementTree(mteval)
    tree.write(setid+'_src.xml', encoding = 'utf-8')


# 調用具體的生成xml
def genxmltree(filetype, setid, srclang, trglang, files):
    if filetype not in ["src","tst","ref"]:
        print "filetype is error"
        return
    
    # 處理原文
    if filetype == "src":
        srclist = []
        for line in open(files[0]):
            line = line.strip()
            if line:
                srclist.append(line)
        gensrcxml(srclist, setid, srclang)

    # 處理譯文
    if filetype == "tst":
        tstslist = []
        for tstfile in files:
            tstlist =[]
            tstlist.append(str(tstfile).strip('.txt'))
            for line in open(tstfile):
                line = line.strip()
                if line:
                    tstlist.append(line)
            tstslist.append(tstlist)
        gentstxml(tstslist, setid, srclang, trglang)

    # 處理ref
    if filetype == "ref":
        reflists = []
        for reffile in files:
            reflist =[]
            reflist.append(str(reffile).strip('.txt'))
            for line in open(reffile):
                line = line.strip()
                if line:
                    reflist.append(line)
            reflists.append(reflist)
        genrefxml(reflists, setid, srclang, trglang)


argv_len = len(sys.argv)
#print argv_len
if argv_len < 6:
    print "param error! src/ref tmq English Chinese 1.txt " 
    sys.exit()

filetype = sys.argv[1]
setid = sys.argv[2]
srclang = sys.argv[3]
trglang = sys.argv[4]
files = []
for i in range(5, len(sys.argv)):
    files.append(sys.argv[i])

genxmltree(filetype, setid, srclang, trglang, files)

 

 

文中nist算法參考論文《Automatic Evaluation of Machine Translation Quality Using N-gram Co-Occurrence Statistics 》

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM