如何用NLTK RegexpParser解析多Chunk?VN块未匹配问题排查
关于NLTK RegexpParser多Chunk解析的问题解答
核心问题解答
- 单个
nltk.RegexpParser完全支持解析多个不同类型的Chunk,不存在技术限制。 - 语法规则中可以同时定义多种Chunk类型(比如你示例里的NP和VN),这是官方支持的功能。
为什么你的VN块没被识别?
你的VN规则{<VB.?><DT>?<NN>}没匹配到内容,核心原因是NLTK的RegexpParser默认采用「非重叠Chunk」策略——一旦某个Token被归入一个Chunk(比如你的测试句里c++/NN被匹配成NP),就不会再被其他Chunk包含。结合你的测试场景:
- 测试句里的
need/VBP后面紧跟的a/DT project/NN manager/NN被优先匹配成了NP,所以need无法和这些已被Chunk的Token组成VN; knows/VBZ后面的c++/NN同样被匹配成了NP,导致knows和c++无法组成VN。
解决方法
1. 换用不重叠的测试句
找一个符合VN规则且不会和NP规则冲突的句子,比如"I eat an apple",同时可以调整语法规则的定义顺序(先定义的规则会优先匹配):
import nltk def parser(s): grammar = """ VN: {<VB.?><DT>?<NN>} NP: {<DT>?<JJ>*<NN>+} """ words = nltk.word_tokenize(s) tagged_words = nltk.pos_tag(words) cp = nltk.RegexpParser(grammar) chunked = cp.parse(tagged_words) print(chunked) for item in chunked: if isinstance(item, nltk.tree.Tree): if item.label() == 'NP': print(item.leaves(), 'Noun Phrase') if item.label() == 'VN': print(item.leaves(), 'Verbed Noun Phrase') parser("I eat an apple")
运行后会输出:
(S i/NN (VN eat/VBP an/DT apple/NN)) [('eat', 'VBP'), ('an', 'DT'), ('apple', 'NN')] Verbed Noun Phrase
2. 调整规则避免重叠
如果要在原测试句中识别VN,可以修改规则,比如让VN匹配动词加未被NP覆盖的结构,或者缩小NP规则的匹配范围。例如把NP规则改成{<DT><JJ>*<NN>+}(去掉?,要求必须有DT),这样c++/NN就不会被匹配成NP,knows c++就能被VN规则匹配。
3. 支持重叠Chunk(进阶)
如果需要允许同一个Token被多个Chunk包含,就需要自定义ChunkParser,利用NLTK的ChunkParserI接口实现,或者通过tree2conlltags和conlltags2tree手动处理标记。
内容的提问来源于stack exchange,提问作者konto
相关产品推荐
相关产品推荐

