2016-08-28 127 views
0
import nltk 
from nltk.parse.generate import generate,demo_grammar 
from nltk import CFG 
grammar = CFG.fromstring(""" 
ROOT -> S 
S -> NP VP 
NP -> NP PP 
NP -> DT NN 
DT -> 'The' 
NN -> 'work' 
PP -> IN NP 
IN -> 'of' 
NP -> DT NN 
DT -> 'the' 
NN -> 'painter' 
VP -> VBZ ADJP 
VBZ -> 'is' 
ADJP -> JJ 
JJ -> 'good' 
""")  
print(grammar) 
for sentence in generate(grammar, n=100): 
    print(' '.join(sentence)) 

给出了一个错误NLTK CFG递归深度误差

RuntimeError: maximum recursion depth exceeded while calling a Python object 

试图改变在functools.py隐蔽功能,还是同样的问题。

+0

查看https://github.com/nltk/nltk/issues/7 – alvas

+0

看过帖子。所以问题一直持续到日期,是吗? –

+0

这不是图书馆的问题。这是你如何定义语法的一个问题。你看到语法中出现无限循环的部分吗? – alvas

回答

3

函数generate作为其文档字符串状态“生成CFG中所有句子的迭代器”。显然,它通过按文件中列出的顺序选择替代扩展来实现。所以,第一次看到一个NP,它用规则NP -> NP PP扩展它。它现在有另一个NP扩大,它也扩大与相同的规则......等等无限期,或者直到超过python的限制。

要解决与您提供的语法问题,只需重新排序前两个NP规则,使递归规则不是第一个遇到的:

grammar = CFG.fromstring(""" 
ROOT -> S 
S -> NP VP 
NP -> DT NN 
NP -> NP PP 
DT -> 'The' 
... 
""") 

做这样的信号发生器将产生大量的完整的句子供你审查。请注意,正确的语法仍然是递归的,因此是无限的;如果您生成足够多的句子,您最终将达到相同的递归深度限制。

+0

感谢您的澄清。为什么不发生NP ... N ...获取编号,似乎也解决了这个问题 –

+0

你是什么意思,“编号”?任何立即避免无限递归的规则将“解决”这个问题,我展示了如何在不改变语法规则的情况下做到这一点。修正后的语法仍然会产生一个无限生成器;它只是首先返回有限长度的句子) – alexis

-1

我试图对NP NN DT等重复出现的次数进行编号。似乎解决了由于唯一标识(我假设)所导致的问题。令我感到奇怪的是,本来应该是这样的,即抛出的树木应该已经连续化了词类。

import nltk 
from nltk.parse.generate import generate,demo_grammar 
from nltk import CFG 
grammar = CFG.fromstring(""" 
ROOT -> S 
S -> NP VP 
NP -> NP1 PP 
NP1 -> DT1 NN1 
DT1 -> 'The' 
NN1 -> 'work' 
PP -> IN NP2 
IN -> 'of' 
NP2 -> DT2 NN2 
DT2 -> 'the' 
NN2 -> 'painter' 
VP -> VBZ ADJP 
VBZ -> 'is' 
ADJP -> JJ 
JJ -> 'good' 
""")  
print(grammar) 
for sentence in generate(grammar, n=100): 
    print(' '.join(sentence)) 
+0

在语言学上,你是过分指定规则,例如DT1和DT2似乎没有好动机,为什么不是'DT - >' '|'the''。当不确定合规规则起作用,它很优雅。如果需要过分规定,通常是“黑客”; P – alvas

+0

这不是必要的,也不正确。你的改变将递归语法变成了一个有限的语法:例如,你不能再在NP中拥有两个“PP”。花一些时间思考CFG表达什么,并用纸和铅笔玩耍。 – alexis

+0

@亚历克西斯我尊重你的观点。在进行换班解决方案之前,我需要深入研究CFG,在这种情况下,这对于递归原因是相反的。 –