使用the NLTK book中定义的方法,我想创建一个已经被POS标记的句子的解析树。根据我从上面链接的章节中理解的内容,您希望能够识别的任何单词都需要在语法中。这看起来很荒谬,因为有一个内置的POS标签,可以手工编写每个单词的词性完全冗余。我是否遗漏了允许这种解析方法的一些功能?
答案 0 :(得分:3)
使用stanford解析器,不需要POS标记来获取树的解析,因为它已内置到模型中。 StanfordParser
和模型无法开箱即用,需要下载。
大多数人在尝试使用NLTK中的StanfordParser
>>> from nltk.parse import stanford
>>> sp = stanford.StanfordParser()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/user/anaconda3/lib/python3.5/site-packages/nltk/parse/stanford.py", line 51, in __init__
key=lambda model_name: re.match(self._JAR, model_name)
File "/home/user/anaconda3/lib/python3.5/site-packages/nltk/internals.py", line 714, in find_jar_iter
raise LookupError('\n\n%s\n%s\n%s' % (div, msg, div))
LookupError:
===========================================================================
NLTK was unable to find stanford-parser\.jar! Set the CLASSPATH
environment variable.
For more information, on stanford-parser\.jar, see:
<http://nlp.stanford.edu/software/lex-parser.shtml>
===========================================================================
要解决此问题,请将Stanford Parser下载到目录并解压缩内容。让我们在* nix系统/usr/local/lib/stanfordparser
上使用示例目录。文件stanford-parser.jar
必须与其他文件一起位于那里。
当所有文件都存在时,设置解析器和模型位置的环境变量。
>>> import os
>>> os.environ['STANFORD_PARSER'] = '/usr/local/lib/stanfordparser'
>>> os.environ['STANFORD_MODELS'] = '/usr/local/lib/stanfordparser'
现在,您可以使用解析器导出您所拥有的句子的可能解析,例如:
>>> sp = stanford.StanfordParser()
>>> sp.parse("this is a sentence".split())
<list_iterator object at 0x7f53b93a2dd8>
>>> trees = [tree for tree in sp.parse("this is a sentence".split())]
>>> trees[0] # example parsed sentence
Tree('ROOT', [Tree('S', [Tree('NP', [Tree('DT', ['this'])]), Tree('VP', [Tree('VBZ', ['is']), Tree('NP', [Tree('DT', ['a']), Tree('NN', ['sentence'])])])])])
返回iterator
对象,因为给定句子可以有多个解析器。
答案 1 :(得分:1)
这是涉及两种不同的技术。您链接的章节是关于手写的无上下文语法,它通常有几十个规则,可以处理一小部分英语(或您覆盖的任何其他语言)。虽然可以在大量此类规则(以及其他技术)上创建大覆盖系统,但NLTK中的CFG实现仅用于教学或演示目的 - 换句话说,它是一个玩具。不要考虑将它用于通用解析。
对于解析真实文本,有像Stanford解析器这样的概率解析器(nltk在nltk.parse.stanford
中有一个接口)。这些解析器通常在大型树库上进行训练,它们可以处理未知单词,正如您所期望的那样,它们可以将POS标记文本作为输入,或者进行自己的POS标记。
所有这一切都说,如果你有理由这样做,就不必调整NLTK的CFG机器来处理未知单词:在POS标签而不是单词上写下语法(例如,你和#39; d写NP => "DT" "NN"
,以便POS标签是终端);然后从你的标记句子中提取POS标签,在它们上面构建一个解析树,并将这些单词重新放入。(如果你的CFG包含混合终端和非终端的规则,这就不够了,例如{{1 }}。)