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

本文介绍利用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。

你可能感兴趣的:(翻译)