在CTB上训练一个Berkeley Parser

 

1. 简介

   Berkeley Parser 是加州大学伯克利分校 NLP 实验室开发的一种基于概率上下文无关文法(PCFG)的成分句法分析器,支持英语,汉语,德语等多个语种,它具有较高的句法分析性能,准确率较高,可选参数较多,运行速度快递优点,在 ACL,NAACL 等主流国际会议的论文中得到广泛使用。

  想了解 Berkeley Parser 可以参考这篇论文”Learning Accurate, Compact, and Interpretable Tree Annotation“,这篇论文是句法分析领域的一篇经典之作。

2. 使用

  (1)从 http://code.google.com/p/berkeleyparser/ 下载最新版 Berkeley Parser 的 JRE1.7 对应的jar包并解压,将源代码添加到 eclipse 中,选择 JRE 1.7 作为开发环境,同时将可以用的堆内存调大一些,例如 -Xmx2048m。

  (2)采用 Penn Chinese Treebank 5.1 作为树库

  在使用 CTB 5.1 训练时,需要注意几个地方:

  edu.berkeley.nlp.PCFGLA.Corpus.java 的 loadChinese 方法中,对中文训练语料集文件的分隔需要注意,程序里面按照文件 ID 使用固定分割。

  Train: 1-270,400-1151;Dev: 301-325;Test: 271-300

  CTB 5.1 训练集,开发集,测试集分别包含18103/352/348个句子。

  我们可以根据自己需要可以把对应的文件进行替换,但是记住每个分段都至少要有一个文件。比如1-25必须至少有一个文件。

  edu.berkeley.nlp.treebank.PennTreebanReader.java 按 PTB 的格式从文件中读取树,因此,需要整理中文树库文件,即将新闻编号,句子编号等 SGML 格式的多余内容删除,使得文件中只保留bracketed 格式的数据。写个 Python 脚本就可以处理了。

  由于 Berkeley Parser 是按照英文 WSJ 树库来解析语料,而中文树库文件的后缀是 fid,因此会导致树库加载失败。一种修改方案是将中文树库文件的后缀改为 mrg,并将所有树库文件放置在一个设定好的目录内,例如 CTBData,另一种方案比较方便就是直接修改源程序 edu.berkeley.nlp.treebank.PennTreebanReader.java 的 TreeCollection 函数,将默认文件后缀 mrg 改成与 CTB 一致的 fid,不过这样就只能解析 CTB,但是会一劳永逸。

  (4)树库文件的问题:

  问题1:CHTB_672.FID(CTB 5.0)

    ID=6887

    该句子以 (IP 开头,因而没有根节点,导致 split 失败。

    方案:在该句子前后分别加入 "("和")",暂时只发现一个文件出现这个问题

  问题2:CHTB_1031.FID(CTB 5.0,5.1)

    ID=12409

    ……….

    (NP (NN 政府

    )))

    ……….

    方案:应该修改为 “(NP (NN 政府)))”

  问题3:文件CHTB_1117.FID(CTB 5.0,5.1)

    ID=16046

    ……….

    (NP-PN (NR Ken Madsen)))

    ……….

    方案:可以改成 “(NR Ken_Madsen)“

  另外,用训练得到的 model 分析测试句子的时候会出现大量零输出的现象,给 slav 发邮件,他说在测试的时候加上参数 -accurate,我至今没有明白这个参数起什么作用,可能是在 pruning 过程中发挥作用了吧。

  如果使用1-270+400-999作为训练集,271-300作为测试集。在分析第339句的时候会出现零输出,不知为何。

  (5)训练模型

  java -cp berkeleyParser.jar edu.berkeley.nlp.PCFGLA.GrammarTrainer -path /data/train -out chn.gr -treebank CHINESE

  也可以使用单文件的训练语料进行训练,这样方便选取不同规模的训练语料,不过此时需要将树库文件转为 UTF-8 格式,否则可能会导致错误。这时可以使用如下命令

  java -cp berkeleyParser.jar edu.berkeley.nlp.PCFGLA.GrammarTrainer -path /data/train.txt -out chn.gr -treebank SINGLEFILE

  (6)测试

  测试语料需要经过分词,如果没有分词请加入 -tokenize 选项。

  java -jar BerkeleyParser.jar -gr chn.gr -inputFile ../data/test/test.in -outputFile ../data/test/test.out

  分析语料的时候有可能出现如下错误

  java.lang.StringIndexOutOfBoundsException: String index out of range: 0

  经过 debug 后发现是因为语料中存在连续的2个空格所致,后处理一下语料就可以了

3. 实验结果

  使用系统提供的训练好的Model

  在 Slav Petrov and Dan Klein 的文章 Improved inference for unlexicalized parsing(NAACL2007)中,采用常用的数据集切分方案:

  Train=1-270+400-1151;Dev=301-325;Test=271-300

  论文报告的结果:

  ALL:LP/LR/F1=84.8/81.9/83.32;

  <=40:LP/LR/F1=86.9/85.7/86.30

  我们的测试:

  java -cp berkeleyParser.jar edu.berkeley.nlp.PCFGLA.GrammarTester -path /data/train -in chn.gr -treebank CHINESE -section final -maxL 1000

  我们跑的结果:

  ALL :     LP/LR/F1= 85.64/82.87/84.23

  <=40:LP/LR/F1= 87.92/85.4/86.64

  其中我们设置的训练次数设置为5,即 -SMcycles = 5,实验结果比论文的结果还是有一点差距,我猜测一方面是 slav 的实验过程中还涉及一些 trick 或者细节处理,而我的实验比较初级,基本采用了 Bekeley Parser 默认设置,另一方面,我们采用的是 CTB 5.1,而我无法确定论文中采用的 CTB 的版本。因此这个差距也是说得通的,如果哪位朋友在 CTB 5.1 上的实验结果接近论文的结果,还麻烦你告诉我一下,谢谢喽。

  如果加上 -accurate 选项,结果能略微高点,结果如下:

  ALL :     LP/LR/F1= 85.79/82.97/84.36

  <=40:LP/LR/F1= 88.1/85.56/86.81

  可以发现,加上 -accurate 参数后,所有指标都会相应提高一点,感兴趣的朋友也可以试试其他参数,比如 uni 规则的惩罚设置等。

  另外,也可以发现,我们的实验结果比 slav 论文报告的要高不少,可能是数据处理方式不同,也可能是这几年 berkeley parser 的代码也调整优化了,也可能是我的实验中有什么纰漏。
  
  在这里也必须要指出的是,不同的数据处理方式也会导致不同的结果,如果跟我的结果不一样,不一定表示错了,可能是语料的差异。

4. 参考:

  http://ldd2000.blogspot.com/2008/11/berkeley-parser.html

  http://japaneseenglishchinesetools.blogspot.com/2011/11/zz-berkeley-parser.html

 

在CTB上训练一个Berkeley Parser》上有3条评论

  1. 您好, 您对Berkeley分析器的详解对我的帮助很大,我想问您一个问题,
    CoNLL 格式的词性标记 是什么样子的, 我测试的时候,试了很多个添加词性的格式,一直没通过,您若有空 能给个例句吗?

    谢谢您!

    • 就是 VV 这样的,可以参考 CoNLL 评测的文档,我平时也不用词性的,berkeley parser会自动做POS

  2. 我对CTB非常有兴趣,不知道那里可以下载中文树库。能将你的中文树库分享一下吗

发表评论

电子邮件地址不会被公开。 必填项已用*标注