5.2 验证 Toolbox 词汇

Toolbox 格式的许多词汇不符合任何特定的模式。有些条目可能包括额外的字段,或以一种新的方式排序现有字段。手动检查成千上万的词汇条目是不可行的。我们可以在Counter的帮助下很容易地找出频率异常的字段序列:

  1. >>> from collections import Counter
  2. >>> field_sequences = Counter(':'.join(field.tag for field in entry) for entry in lexicon)
  3. >>> field_sequences.most_common()
  4. [('lx:ps:pt:ge:tkp:dt:ex:xp:xe', 41), ('lx:rt:ps:pt:ge:tkp:dt:ex:xp:xe', 37),
  5. ('lx:rt:ps:pt:ge:tkp:dt:ex:xp:xe:ex:xp:xe', 27), ('lx:ps:pt:ge:tkp:nt:dt:ex:xp:xe', 20), ...]

检查完高频字段序列后,我们可以设计一个词汇条目的上下文无关语法。在5.2中的语法使用我们在8.看到的 CFG 格式。这样的语法模型隐含 Toolbox 条目的嵌套结构,建立一个树状结构,树的叶子是单独的字段名。最后,我们遍历条目并报告它们与语法的一致性,如5.2所示。那些被语法接受的在前面加一个'+' [1],那些被语法拒绝的在前面加一个'-' [2]。在开发这样一个文法的过程中,它可以帮助过滤掉一些标签[3]

  1. grammar = nltk.CFG.fromstring('''
  2. S -> Head PS Glosses Comment Date Sem_Field Examples
  3. Head -> Lexeme Root
  4. Lexeme -> "lx"
  5. Root -> "rt" |
  6. PS -> "ps"
  7. Glosses -> Gloss Glosses |
  8. Gloss -> "ge" | "tkp" | "eng"
  9. Date -> "dt"
  10. Sem_Field -> "sf"
  11. Examples -> Example Ex_Pidgin Ex_English Examples |
  12. Example -> "ex"
  13. Ex_Pidgin -> "xp"
  14. Ex_English -> "xe"
  15. Comment -> "cmt" | "nt" |
  16. ''')
  17. def validate_lexicon(grammar, lexicon, ignored_tags):
  18. rd_parser = nltk.RecursiveDescentParser(grammar)
  19. for entry in lexicon:
  20. marker_list = [field.tag for field in entry if field.tag not in ignored_tags]
  21. if list(rd_parser.parse(marker_list)):
  22. print("+", ':'.join(marker_list)) ![[1]](/projects/nlp-py-2e-zh/Images/346344c2e5a627acfdddf948fb69cb1d.jpg)
  23. else:
  24. print("-", ':'.join(marker_list)) ![[2]](/projects/nlp-py-2e-zh/Images/f9e1ba3246770e3ecb24f813f33f2075.jpg)

另一种方法是用一个词块分析器(7.),因为它能识别局部结构并报告已确定的局部结构,会更加有效。在5.3中我们为词汇条目建立一个词块语法,然后解析每个条目。这个程序的输出的一个示例如5.4所示。

  1. grammar = r"""
  2. lexfunc: {<lf>(<lv><ln|le>*)*}
  3. example: {<rf|xv><xn|xe>*}
  4. sense: {<sn><ps><pn|gv|dv|gn|gp|dn|rn|ge|de|re>*<example>*<lexfunc>*}
  5. record: {<lx><hm><sense>+<dt>}
  6. """

Images/iu-mien.png

图 5.4:一个词条的 XML 表示,对 Toolbox 记录的词块分析的结果