• 4.1 用级联词块划分器构建嵌套结构

    4.1 用级联词块划分器构建嵌套结构

    到目前为止,我们的词块结构一直是相对平的。已标注词符组成的树在如NP这样的词块节点下任意组合。然而,只需创建一个包含递归规则的多级的词块语法,就可以建立任意深度的词块结构。4.1是名词短语、介词短语、动词短语和句子的模式。这是一个四级词块语法器,可以用来创建深度最多为 4 的结构。

    1. grammar = r"""
    2. NP: {<DT|JJ|NN.*>+} # Chunk sequences of DT, JJ, NN
    3. PP: {<IN><NP>} # Chunk prepositions followed by NP
    4. VP: {<VB.*><NP|PP|CLAUSE>+$} # Chunk verbs and their arguments
    5. CLAUSE: {<NP><VP>} # Chunk NP, VP
    6. """
    7. cp = nltk.RegexpParser(grammar)
    8. sentence = [("Mary", "NN"), ("saw", "VBD"), ("the", "DT"), ("cat", "NN"),
    9. ("sit", "VB"), ("on", "IN"), ("the", "DT"), ("mat", "NN")]

    不幸的是,这一结果丢掉了 saw 为首的VP。它还有其他缺陷。当我们将此词块划分器应用到一个有更深嵌套的句子时,让我们看看会发生什么。请注意,它无法识别[1]开始的VP词块。

    1. >>> sentence = [("John", "NNP"), ("thinks", "VBZ"), ("Mary", "NN"),
    2. ... ("saw", "VBD"), ("the", "DT"), ("cat", "NN"), ("sit", "VB"),
    3. ... ("on", "IN"), ("the", "DT"), ("mat", "NN")]
    4. >>> print(cp.parse(sentence))
    5. (S
    6. (NP John/NNP)
    7. thinks/VBZ
    8. (NP Mary/NN)
    9. saw/VBD # [_saw-vbd]
    10. (CLAUSE
    11. (NP the/DT cat/NN)
    12. (VP sit/VB (PP on/IN (NP the/DT mat/NN)))))

    这些问题的解决方案是让词块划分器在它的模式中循环:尝试完所有模式之后,重复此过程。我们添加一个可选的第二个参数loop指定这套模式应该循环的次数:

    1. >>> cp = nltk.RegexpParser(grammar, loop=2)
    2. >>> print(cp.parse(sentence))
    3. (S
    4. (NP John/NNP)
    5. thinks/VBZ
    6. (CLAUSE
    7. (NP Mary/NN)
    8. (VP
    9. saw/VBD
    10. (CLAUSE
    11. (NP the/DT cat/NN)
    12. (VP sit/VB (PP on/IN (NP the/DT mat/NN)))))))

    注意

    这个级联过程使我们能创建深层结构。然而,创建和调试级联过程是困难的,关键点是它能更有效地做全面的分析(见第8.章)。另外,级联过程只能产生固定深度的树(不超过级联级数),完整的句法分析这是不够的。