学海无涯

在每天的学习中不断成长

常用链接

统计

最新评论

测试集语料的合并

      这是久久没有写c++程序之后,写的第一个相对比较久的程序。目的就是将nist03,04,05这三个单独的测试集进行合并,以进行bleu值的测算。三个测试集中分别包含源文,参考译文,还有4个机器译文。而最后的结果就是要分别将三个测试集的源文,参考译文,以及机器译文进行合并。
方法的思想其实很简单,其中源文和参考译文的合并只要将三个单独的文档合并成一个文档,并稍微改一下格式就可以完成了。而难点就在于机器译文的合并。因为每篇源文中对应了四个机器译文。
      单独用文字不容易说明这个问题,我们将其形象化。比如nist03的源文是A,04的源文是B,05的源文是C。而A对应的对应的机器译文是abcd,B对应的机器译文是efgh,C对应的机器译文是ijkl。
      这里解释一下什么是A对应abcd,即比如A是一整篇文档,而a,b,c,d分别是机器给出的这篇文档的4个翻译,所以机器译文的文档就是将a,b,c,d这4个译文顺序排列,并用指定的标识符来与源文进行对应。
      而如果我们将源文进行合并了之后,那么源文就变成了ABC,所以机器译文也要相应做出改变,而不能单纯地将机器译文的三个文档简单合并。ABC对应的第一个机器译文是aei,第二个机器译文是bfj,第三个机器译文是cgk,第四个机器译文是dhl,所以我们将机器译文合并后的排列顺序就应该调整为aeibfjcgkdhl。
由于对于c++我是初学者,所以我实现的方法可能比较粗暴简单。对于每个机器译文,在最开始都有一个<DOC docid= 的标识符来标识指定的翻译,而末尾都有</DOC>来进行结束。因此我们只要根据这两个标识符就可以区分出所有的机器翻译,然后再对其进行重新组合。
以其中一个代码为例: 
 1 string PartOne(string s)
 2 {
 3      size_t x=0,y=1,z=0;
 4      string tmp;
 5      x=s.find("<DOC docid=\"AFC20030102.0015\" sysid=\"E01\">");
 6      y=s.rfind("sysid=\"E01\"");
 7       z=s.find("</DOC>",y);
 8      tmp.append(s,x,z-x+6);
 9       return tmp;
10 }
      这个代码是分割出nist03中的第一个机器译文,我们可以看出<DOC docid=\"AFC20030102.0015\" sysid=\"E01\">" 是这个译文的标识符,E01表示的是第一个译文,同理E02,E03,E04表示的就是第二,第三,第四个译文。
      而由于nist03,04,05的机器译文格式不完全一样,因此为了最后计算bleu值时能够被识别,必须将所有机器译文的格式进行统一(我一开始就是没有将格式进行统一,以至于合并了之后也无法计算bleu值)。 
 1 string PartTwo(string s)
 2 {
 3     size_t x=0,y=1,z=0;
 4     string tmp;
 5     x=s.find("<DOC docid=\"PD20040202.001\" sysid=\"cha\">");
 6     y=s.rfind("sysid=\"cha\"");
 7     z=s.find("</DOC>",y);
 8     tmp.append(s,x,z-x+6);
 9     int pos=0;
10     while(1)
11     {
12         pos=tmp.find("sysid=\"cha\"",pos+5);
13         if (-1 == pos)
14             break;
15         else
16         tmp = tmp.substr(0,pos)+"sysid=\"E01\""+tmp.substr(pos+11);
17 
18     }
19     return tmp;
20 }
       以这个例子来说明,这是分割出nist04的第一个机器译文,而由于nist04的机器译文中,第一个译文是用 sysid="cha"来进行识别,因此第11行到第18行就是进行格式的统一,将cha替换成E01(我们这里默认都使用跟nist03一样的格式)。后面的机器译文也是使用类似的方法进行处理。
      这样将所有译文都分割出来并统一格式之后,再将他们合并之后就完成了整个代码的编写。
      这里再给出将所有代译文合并的过程: 
out<<"<refset setid=\"mt05_chinese_eval\" srclang=\"zh\" trglang=\"en\">";
2     out<<PartOne(n3)<<endl<<PartTwo(n4)<<endl<<PartThree(n5)<<endl
3         <<PartOneS(n3)<<endl<<PartTwoS(n4)<<endl<<PartThreeS(n5)<<endl
4         <<PartOneT(n3)<<endl<<PartTwoT(n4)<<endl<<PartThreeT(n5)<<endl
5         <<PartOneF(n3)<<endl<<PartTwoF(n4)<<endl<<PartThreeF(n5)<<endl;
6     out<<"</refset>";
      头尾的两个out是输出特定的首尾格式。out是将其输出到事先指定好的文档中。
      最后对这个编写代码的过程进行思考总结。首先可能由于我对c++的编写不是太熟练,很多方法也不会用,因此将这个看去其实很简单的代码也写了好久,并不断修正各种小错误。其中遇到最大的困难还是不知道要如何更便捷的修改格式,因此采用了最粗暴的方式,这样可能会导致算法的复杂度更高,需要消耗的时间更久,在以后的学习过程中希望能够学会使用更简便的方法。 




posted on 2012-08-06 12:11 nlp 阅读(189) 评论(0)  编辑 收藏 引用 所属分类: 原创


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理