python - 如何从依赖解析器的输出中生成树?
问题描述
我正在尝试从依赖解析器的输出中创建一棵树(嵌套字典)。这句话是“我在睡梦中射杀了一头大象”。我能够获得链接中描述的输出: 如何在 NLTK 中进行依赖解析?
nsubj(shot-2, I-1)
det(elephant-4, an-3)
dobj(shot-2, elephant-4)
prep(shot-2, in-5)
poss(sleep-7, my-6)
pobj(in-5, sleep-7)
要将这个元组列表转换为嵌套字典,我使用了以下链接: 如何将元组的 python 列表转换为树?
def build_tree(list_of_tuples):
all_nodes = {n[2]:((n[0], n[1]),{}) for n in list_of_tuples}
root = {}
print all_nodes
for item in list_of_tuples:
rel, gov,dep = item
if gov is not 'ROOT':
all_nodes[gov][1][dep] = all_nodes[dep]
else:
root[dep] = all_nodes[dep]
return root
这给出了如下输出:
{'shot': (('ROOT', 'ROOT'),
{'I': (('nsubj', 'shot'), {}),
'elephant': (('dobj', 'shot'), {'an': (('det', 'elephant'), {})}),
'sleep': (('nmod', 'shot'),
{'in': (('case', 'sleep'), {}), 'my': (('nmod:poss', 'sleep'), {})})})}
为了找到根到叶路径,我使用了以下链接:从嵌套字典树返回根到特定叶
[制作树和查找路径是两件独立的事情]第二个目标是找到根到叶子节点的路径,就像 done从嵌套字典树中返回根到特定叶子。但我想获得根到叶(依赖关系路径)所以,例如,当我调用 recurse_category(categories, 'an') 时,其中 categories 是嵌套的树结构,'an' 是树中的单词,我应该得到ROOT-nsubj-dobj
(直到根的依赖关系)作为输出。
解决方案
首先,如果你只是使用斯坦福 CoreNLP 依赖解析器的预训练模型,你应该使用CoreNLPDependencyParser
fromnltk.parse.corenlp
并避免使用旧nltk.parse.stanford
接口。
在终端中下载并运行 Java 服务器后,在 Python 中:
>>> from nltk.parse.corenlp import CoreNLPDependencyParser
>>> dep_parser = CoreNLPDependencyParser(url='http://localhost:9000')
>>> sent = "I shot an elephant with a banana .".split()
>>> parses = list(dep_parser.parse(sent))
>>> type(parses[0])
<class 'nltk.parse.dependencygraph.DependencyGraph'>
现在我们看到解析的类型DependencyGraph
来自nltk.parse.dependencygraph
https://github.com/nltk/nltk/blob/develop/nltk/parse/dependencygraph.py#L36
只需执行以下操作即可将 转换DependencyGraph
为对象:nltk.tree.Tree
DependencyGraph.tree()
>>> parses[0].tree()
Tree('shot', ['I', Tree('elephant', ['an']), Tree('banana', ['with', 'a']), '.'])
>>> parses[0].tree().pretty_print()
shot
_________|____________
| | elephant banana
| | | _____|_____
I . an with a
要将其转换为括号中的解析格式:
>>> print(parses[0].tree())
(shot I (elephant an) (banana with a) .)
如果您正在寻找依赖三元组:
>>> [(governor, dep, dependent) for governor, dep, dependent in parses[0].triples()]
[(('shot', 'VBD'), 'nsubj', ('I', 'PRP')), (('shot', 'VBD'), 'dobj', ('elephant', 'NN')), (('elephant', 'NN'), 'det', ('an', 'DT')), (('shot', 'VBD'), 'nmod', ('banana', 'NN')), (('banana', 'NN'), 'case', ('with', 'IN')), (('banana', 'NN'), 'det', ('a', 'DT')), (('shot', 'VBD'), 'punct', ('.', '.'))]
>>> for governor, dep, dependent in parses[0].triples():
... print(governor, dep, dependent)
...
('shot', 'VBD') nsubj ('I', 'PRP')
('shot', 'VBD') dobj ('elephant', 'NN')
('elephant', 'NN') det ('an', 'DT')
('shot', 'VBD') nmod ('banana', 'NN')
('banana', 'NN') case ('with', 'IN')
('banana', 'NN') det ('a', 'DT')
('shot', 'VBD') punct ('.', '.')
CONLL 格式:
>>> print(parses[0].to_conll(style=10))
1 I I PRP PRP _ 2 nsubj _ _
2 shot shoot VBD VBD _ 0 ROOT _ _
3 an a DT DT _ 4 det _ _
4 elephant elephant NN NN _ 2 dobj _ _
5 with with IN IN _ 7 case _ _
6 a a DT DT _ 7 det _ _
7 banana banana NN NN _ 2 nmod _ _
8 . . . . _ 2 punct _ _
推荐阅读
- elasticsearch - 字段_source有什么区别?弹性搜索
- vba - VBA 不捕获 SAP 列表的行
- django - 在解耦的 wagtail 项目中创建页面/子页面时,我们如何处理“实时查看”?
- html - 为什么我导入外部字体的样式不起作用
- nginx - nginx 在使用 try_files 和 proxy_pass 时返回 405 Not Allowed
- java - java - 如果重复,则读取用户输入并打印行
- flutter - 徽章上的三元运算符仅在有新消息时显示徽章
- python - 代码在某些条件下需要永远执行。需要跑得更快
- sql - 填充函数给出(空值被聚合或其他 SET 操作消除)错误
- excel - 如何通过excel宏向图表添加文本?