基于统计机器翻译的文白对译

本文介绍利用NiuTrans工具进行文白对译的步骤,默认用户已经安装NiuTrans,安装目录为NiuTrans/,以下相对路径基于此目录。

文白对译模型训练步骤分为语料预处理、对齐、翻译模型训练、语言模型训练、参数调整四个阶段。

一、语料预处理

我们拿到的原始数据格式比较杂乱,需要做预处理,最终形成规则的平行语料数据。

语 料预处理包括统一标点符号,删除无关符号,删除段前段后,句前句后空格,分词等阶段。最终形成两个平行文件,暂称为src.txt和tgt.txt两个文 件(若是文白翻译src为文,tgt为白,反之src为白,tgt为文),这两个文件每行一句话(自然句),每句话已经分好词,词语以空格分割开,两个文 件中每行一一对应,因此行数相等。

考虑到文白词语的异意性,句句对齐后的句子分词策略为:白话文为平常的中文分词,文言文为一元分词。

二、对齐

NiuTrans采用第三方工具giza++进行词汇对齐,由于giza++只能进行单向对齐,为了保证对齐结果的准确性,NiuTrans合并了两个方向上的对齐结果,生成了最终的对齐结果供后续步骤使用。

具 体来说,若src==》tgt对齐,giza++会生成一个名为src2tgt.A3.final的结果文件;若tgt==》src对齐,giza++会 生成一个名为tgt2src.A3.final的结果文件;NiuTrans对这两个方向的A3文件进行合并,生成最终的对齐文件 alignment.txt。

以上的对齐步骤可参看脚本代码scripts/NiuTrans-running-GIZA++.pl。

需要特别注意的是,giza++ 进行单向对齐时,如果源/目标句对的长度(分词后词汇个数)相差太大,giza++会对长的一方进行剪切,而在另一个方向目标/源对齐时,并不一定进行剪 切。这样就造成了在两个对齐结果文件src2tgt.A3.final和tgt2src.A3.final的不一致。这个不一致将会造成NiuTrans 在合并生成alignment.txt时发生错误直接退出。这种错误只跟源/目标的长度比有关,与具体哪种语言无关。因此本文题目虽然是《文白对译步骤》,其实是所有语言通用的步骤。因此,直接运行脚本scripts/NiuTrans-running-GIZA++.pl,在第八步之后会出现错误退出,导致训练失败。

解决方法为:在第七步之后,第八步之前,遍历src2tgt.A3.final和tgt2src.A3.final两个文件,将不一致的句对从两个A3文件中剔除,同时也从两个平行语料文件中剔除。

遍历算法很简单,首先看下A3文件的格式:

# Sentence pair (20) source length 11 target length 13 alignment score : 1.14927e-38
智果 便 向 太史 请求 脱离 智族 姓氏 , 另 立 为辅 氏
NULL ({ 2 }) 智 ({ }) 果 ({ 1 5 6 7 8 }) 别 ({ 10 }) 族 ({ }) 于 ({ 3 }) 太 ({ 4 }) 史 ({ }) , ({ 9 }) 为 ({ }) 辅 ({ 11 12 }) 氏 ({ 13 })

上面摘录的是一个句子对的对齐结果。第一行为句对描述,第二行为目标句子内容,第三行为对齐结果。【Sentence pair (20)】表示为第20个句对,source length 11表示源句长度为11,target length 13表示目标句子长度为13。遍历两个A3文件中的每个pair(三行),检查若第一个文件中的source length与第二个文件中的target length相等,且第一个文件中的target length和第二个文件中的source length 相等,说明该句对是一致的,否则不一致,把该句对从两个A3文件和平行文件中剔除。

处理代码粘贴如下:

check.py
# -*- coding: utf-8 -*-
'''
Created on 2014年8月25日
@author: wuseguang
'''
import sys
import re
print "脚本名:", sys.argv[0]
if(len(sys.argv)!=5):
    print "参数不对"
    sys.exit()
src=sys.argv[1]
tgt=sys.argv[2]
srcs=sys.argv[3]
tgts=sys.argv[4]
errPairs=[]
with open(src,'r') as srcFile,open(tgt,'r')as tgtFile,open(src+'.check','w')as srcw,open(tgt+'.check','w')as tgtw:
    index=-1
    pair=0
    flag=True
    while True:
        index+=1
        print index
        srcLine=srcFile.readline()
        tgtLine=tgtFile.readline()
        if not srcLine or not tgtLine:
            break
         
        if index%3!=0 or not srcLine.startswith("# Sentence pair"):
            if flag:
                srcw.write(srcLine)
                tgtw.write(tgtLine)
            continue
        srcData=re.split('\D+',srcLine)
        tgtData=re.split('\D+',tgtLine)
        #print srcData
        #print tgtData
        if srcData[2]!=tgtData[3] or srcData[3]!=tgtData[2]:
            errPairs.append(index/3+1)
            flag=False
            continue
        pair+=1
        flag=True
        oldtitle="# Sentence pair ("+srcData[1]+")"
        newtitle='# Sentence pair ('+str(pair)+')'
        print oldtitle
        print newtitle
        srcw.write(srcLine.replace(oldtitle,newtitle))
        tgtw.write(tgtLine.replace(oldtitle,newtitle))
         
with open(srcs,'r') as srcsfile,open(tgts,'r') as tgtsfile,open(srcs+'.check','w')as srcw,open(tgts+'.check','w')as tgtw:
    pair=0
    errSet=set(errPairs)
    #print srcs+'\n'
    #print tgts+'\n'
    while True:
        pair+=1
        #print 'pair:',pair
        srcline=srcsfile.readline()
        tgtline=tgtsfile.readline()
        if not srcline or not tgtline:
            break
        if pair in errSet:
            continue
        srcw.write(srcline)
        tgtw.write(tgtline)
print errPairs
print len(errPairs)

 

请将该文件放置于scripts目录下。后续脚本会自助调用。

然后,注释掉scripts/NiuTrans-running-GIZA++.pl脚本中的第八步的代码。在调用scripts/NiuTrans-running-GIZA++.pl脚本之后,调用check.py进行一致性检查,最后调用NiuTrans的合并对齐命令../bin/NiuTrans.SymAlignment。

三、翻译模型训练

在上一步对齐的结果alignment.txt上,进行翻译模型的训练,训练命令为:

perl NiuTrans-phrase-train-model.pl -tmdir $workDir/model.phrase/ -s $srcFile -t $tgtFile -a $aligFile

-s指向源平行语料文件,-t指向目标平行语料文件,-a指向alignment.txt文件。

 

四、语言模型训练

语言模型检查目标语言的合法度,因此训练语料只需用目标语言语料即可,格式跟平行语料格式一样,即每行一句,没句以空格分词。训练命令如下:

perl NiuTrans-training-ngram-LM.pl -corpus $lmodelFile -ngram 3 -vocab $workDir/lm/lm.vocab -lmbin $workDir/lm/lm.trie.data
lmodelFile即为训练语料文件,惯例以lm.txt命名。

 

五、参数调整

参数调整阶段,对上面训练的两个模型(翻译模型和语言模型)进行权重的调整,其实质是把这两个模型作为两个feature,然后套如特征模型。

训练命令如下:

perl NiuTrans-phrase-generate-mert-config.pl -tmdir $workDir/model.phrase/ -lmdir $workDir/lm/ -ngram 3 -o $workDir/NiuTrans.phrase.user.config

 

六、总流程小结

为了操作方便,以上的所有流程我写成到了一个总脚本中,名为train.sh放置在script目录下。内容如下:

 1 #!/bin/sh
 2 scriptDir=$(realpath $PWD)
 3 workDir=$(realpath $1)
 4 srcFile=${workDir}/preprocessing/$2
 5 tgtFile=${workDir}/preprocessing/$3
 6 lmodelFile=${workDir}/preprocessing/$4
 7 aligFile=$workDir/wordalignment/alignment.txt
 8 src2tgtA3File=$workDir/wordalignment/src2tgt.A3.final
 9 tgt2srcA3File=$workDir/wordalignment/tgt2src.A3.final
10 echo "script_dir is ${scriptDir}"
11 echo "work_dir is $workDir"
12 echo "src_file is ${srcFile}"
13 echo "tgt_file is ${tgtFile}"
14 echo "alignFile is $aligFile"
15 #exit
16 mkdir $workDir/wordalignment -p
17 mkdir $workDir/lm -p
18 mkdir $workDir/model.phrase -p
19 #exit
20 cd $scriptDir
21 perl NiuTrans-running-GIZA++.pl -src $srcFile -tgt $tgtFile -out $aligFile -tmpdir $workDir/wordalignment/
22 cd $scriptDir
23 python $scriptDir/check.py $src2tgtA3File $tgt2srcA3File $srcFile $tgtFile
24 src2tgtA3File=${src2tgtA3File}.check
25 tgt2srcA3File=${tgt2srcA3File}.check
26 srcFile=${srcFile}.check
27 tgtFile=${tgtFile}.check
28 cd $scriptDir
29 ../bin/NiuTrans.SymAlignment  $tgt2srcA3File $src2tgtA3File $aligFile
30 cd $scriptDir
31 perl NiuTrans-phrase-train-model.pl -tmdir $workDir/model.phrase/ -s $srcFile -t $tgtFile -a $aligFile
32 cd $scriptDir
33 perl NiuTrans-training-ngram-LM.pl -corpus $lmodelFile -ngram 3 -vocab $workDir/lm/lm.vocab -lmbin $workDir/lm/lm.trie.data
34 cd $scriptDir
35 perl NiuTrans-phrase-generate-mert-config.pl -tmdir $workDir/model.phrase/ -lmdir $workDir/lm/ -ngram 3 -o $workDir/NiuTrans.phrase.user.config

脚本的内容已经非常清晰,不再详述。

运行此脚本的前提为:1、NiuTrans-running-GIZA++.pl脚本中第八步已经被注释;2、check.py已经放置在scripts文件夹下。

运行示例:(wenyan.txt baihua.txt位于../work/preprocessing/目录)

./train.sh ../work/ wenyan.txt baihua.txt lm2.txt

七、测试

在模型训练完毕后,即可进行测试。首先需要具备测试文件test.txt,测试文件格式与平行文件格式一样,与训练语料保持无交集即可。测试命令如下:

perl NiuTrans-phrase-decoder-model.pl -test $workDir/test/test.txt -c $workDir/NiuTrans.phrase.user.config -output $workDir/test/Xbest.out

-test指明测试文件位置,-c指明上一步训练的模型配置文件位置,-output 指明翻译结果文件位置。

注意,若需要指明多个翻译结果,需要修改脚本NiuTrans-phrase-decoder-model.pl第56行的-nbest参数,默认为1。

posted @ 2014-11-20 20:29  五色光  阅读(1343)  评论(0编辑  收藏  举报