我生成这种NLTK语法的方式有问题吗?

时间:2017-03-30 02:49:42

标签: python python-3.x nlp nltk

我用NLTK写了这个简单的程序,它应该打印出语法树。但是,即使正在创建RecursiveDescentParser,它也不打印任何内容。我的问题是什么?我是否错误地定义了语法?我尝试迭代解析器的方式有问题吗?提前谢谢。

import nltk

'''The price of peace is rising.'''

grammar = nltk.CFG.fromstring("""
  S -> NP VP
  VP -> V NP | V NP PP
  PP -> P NP
  V -> "is" | "rising"
  NP -> Det N | Det N PP
  Det -> "the" | "of"
  N -> "price" | "peace"
  P -> "in" | "on" | "by" | "with"
  """)

sentence = "the price of peace is rising"
wordArray = sentence.split()

print(wordArray)

parser = nltk.RecursiveDescentParser(grammar)

for tree in parser.parse(wordArray):
    print(tree)

1 个答案:

答案 0 :(得分:0)

首先,始终以一口大小开始编写语法。

让我们从简单的句子Peace is rising开始。

我们想要结构S -> NP VP,其中:

  • VP是一个不及物动词短语,在这种特殊情况下,is rising附带辅助is,而rise附带-ing渐进变形。< / p>

  • NP只是一个名词。

[代码]:

import nltk

your_grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> AUX V 
V -> "rising"
AUX -> "is"
NP -> N
N -> "peace"
""")

parser = nltk.RecursiveDescentParser(your_grammar)
sentence = "peace is rising".split()

for tree in parser.parse(sentence):
    print (list(tree))

[OUT]:

[Tree('NP', [Tree('N', ['peace'])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]

现在使用NP -> DT NP | N

将限定符添加到NP中
import nltk

your_grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> AUX V 
V -> "rising"
AUX -> "is"
NP -> N | DT NP  
N -> "peace" | "price" 
DT -> "the"
""")

parser = nltk.RecursiveDescentParser(your_grammar)
sentence = "the price is rising".split()

for tree in parser.parse(sentence):
    print (list(tree))

[OUT]:

[Tree('NP', [Tree('DT', ['the']), Tree('NP', [Tree('N', ['price'])])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]

最后,我们可以在NP中添加PP构造,NP -> NP PPPP -> P NP

import nltk

your_grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> AUX V 
V -> "rising"
AUX -> "is"
NP -> N | DT NP | NP PP  
N -> "peace" | "price" 
DT -> "the"
PP -> P NP
P -> "of"
""")

parser = nltk.RecursiveDescentParser(your_grammar)
sentence = "the price of peace is rising".split()

for tree in parser.parse(sentence):
    print (list(tree))

在最佳结果中为我们提供了最佳解析。

[OUT]:

[Tree('NP', [Tree('DT', ['the']), Tree('NP', [Tree('NP', [Tree('N', ['price'])]), Tree('PP', [Tree('P', ['of']), Tree('NP', [Tree('N', ['peace'])])])])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]

但它也带有一些讨厌的递归循环错误,看起来像这样:

  File "/usr/local/lib/python3.5/site-packages/nltk/tree.py", line 158, in __getitem__
    return self[index[0]][index[1:]]
  File "/usr/local/lib/python3.5/site-packages/nltk/tree.py", line 156, in __getitem__
    return self[index[0]]
  File "/usr/local/lib/python3.5/site-packages/nltk/tree.py", line 150, in __getitem__
    if isinstance(index, (int, slice)):
RecursionError: maximum recursion depth exceeded in __instancecheck__

这是因为nltk.RecursiveDescentParser尝试递归地查找解析,因为NP -> NP PPPP -> P NP规则可以无限重复。如果您想知道原因,请尝试将其作为StackOverflow上的单独问题; P

一个简单的解决方案是使用try-except

try:
    for tree in parser.parse(sentence):
        print (list(tree))
except RecursionError:
    exit()

但那太丑了!相反,您可以使用ChartParser

import nltk

your_grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> AUX V 
V -> "rising"
AUX -> "is"
NP -> N | DT NP | NP PP  
N -> "peace" | "price" 
DT -> "the"
PP -> P NP
P -> "of"
""")

parser = nltk.ChartParser(your_grammar)
sentence = "the price of peace is rising".split()

for tree in parser.parse(sentence):
    print (list(tree))

[OUT]:

[Tree('NP', [Tree('NP', [Tree('DT', ['the']), Tree('NP', [Tree('N', ['price'])])]), Tree('PP', [Tree('P', ['of']), Tree('NP', [Tree('N', ['peace'])])])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]
[Tree('NP', [Tree('DT', ['the']), Tree('NP', [Tree('NP', [Tree('N', ['price'])]), Tree('PP', [Tree('P', ['of']), Tree('NP', [Tree('N', ['peace'])])])])]), Tree('VP', [Tree('AUX', ['is']), Tree('V', ['rising'])])]