我一直在尝试使用spaCy获取依赖树,但我找不到如何获取树的任何信息,只能在如何浏览树方面找到一些内容。
如果有人想要轻松查看spacy生成的依赖树,一种解决方案是将其转换为nltk.tree.Tree
并使用nltk.tree.Tree.pretty_print
方法。以下是一个示例:
import spacy
from nltk import Tree
en_nlp = spacy.load('en')
doc = en_nlp("The quick brown fox jumps over the lazy dog.")
def to_nltk_tree(node):
if node.n_lefts + node.n_rights > 0:
return Tree(node.orth_, [to_nltk_tree(child) for child in node.children])
else:
return node.orth_
[to_nltk_tree(sent.root).pretty_print() for sent in doc.sents]
输出:
jumps
________________|____________
| | | | | over
| | | | | |
| | | | | dog
| | | | | ___|____
The quick brown fox . the lazy
编辑: 如果您要更改令牌表示形式,可以这样做:
def tok_format(tok):
return "_".join([tok.orth_, tok.tag_])
def to_nltk_tree(node):
if node.n_lefts + node.n_rights > 0:
return Tree(tok_format(node), [to_nltk_tree(child) for child in node.children])
else:
return tok_format(node)
导致结果如下:
jumps_VBZ
__________________________|___________________
| | | | | over_IN
| | | | | |
| | | | | dog_NN
| | | | | _______|_______
The_DT quick_JJ brown_JJ fox_NN ._. the_DT lazy_JJ
tok_format(tok)
。此外,你应该阅读文档。Spacy使用两种不同的词性表示方法 tok.pos_
和 tok.tag_
。https://spacy.io/docs/#token-postags - Christos Baziotistok.dep_
属性可与 tok.tag_
一起使用,表示句法依存关系。 - Shirish Kadam这棵树本身不是一个对象;你只能通过标记之间的关系来浏览它。这就是为什么文档中谈论如何导航树,而不是“获取”它。
首先,让我们解析一些文本以获取Doc
对象:
>>> import spacy
>>> nlp = spacy.load('en_core_web_sm')
>>> doc = nlp('First, I wrote some sentences. Then spaCy parsed them. Hooray!')
doc
是一个 Sequence
类型的 Token
对象集合:
>>> doc[0]
First
>>> doc[1]
,
>>> doc[2]
I
>>> doc[3]
wrote
但它没有一个根节点。我们解析了由三个句子组成的文本,因此有三个不同的树,每个树都有自己的根。如果我们想从每个句子的根开始解析,首先需要将句子作为不同的对象获取。幸运的是,doc
通过 .sents
属性向我们公开了这些对象:
>>> sentences = list(doc.sents)
>>> for sentence in sentences:
... print(sentence)
...
First, I wrote some sentences.
Then spaCy parsed them.
Hooray!
.root
属性指向其根标记的Span
。通常,根标记将是句子的主要动词(尽管对于不寻常的句子结构,如没有动词的句子,这可能不是真实的)。>>> for sentence in sentences:
... print(sentence.root)
...
wrote
parsed
Hooray
.children
属性向下遍历树。例如,让我们找到第一句话中动词的主语和宾语。每个子令牌的.dep_
属性描述其与父级的关系;例如,'nsubj'
的dep_
表示一个令牌是其父级的名义主语。>>> root_token = sentences[0].root
>>> for child in root_token.children:
... if child.dep_ == 'nsubj':
... subj = child
... if child.dep_ == 'dobj':
... obj = child
...
>>> subj
I
>>> obj
sentences
>>> list(obj.children)
[some]
你可以使用下面的库来查看你的依赖树,发现它非常有帮助!
import spacy
from spacy import displacy
nlp = spacy.load('en')
doc = nlp(u'This is a sentence.')
displacy.serve(doc, style='dep')
要生成SVG文件:
from pathlib import Path
output_path = Path("yourpath/.svg")
svg = displacy.render(doc, style='dep')
with output_path.open("w", encoding="utf-8") as fh:
fh.write(svg)
displacy.render(doc, style='dep')
)。 - prashanth/home/victoria/...
而不是~/...
)。 代码:from pathlib import Path; output_path = Path("/home/victoria/dependency_plot.svg"); svg = displacy.render(doc, style='dep', jupyter=False); output_path.open("w", encoding="utf-8").write(svg)
- Victoria Stuartserve
渲染时,它们会被打印出来。 - Suzanaimport spacy
nlp = spacy.load('en')
doc1 = nlp(u'This is the way the world ends. So you say.')
print(doc1.print_tree(light=True))
print_tree这个名称有点不准确,因为该方法本身并不打印任何内容,而是返回一个包含每个句子的字典列表。
import sys
def showTree(sent):
def __showTree(token):
sys.stdout.write("{")
[__showTree(t) for t in token.lefts]
sys.stdout.write("%s->%s(%s)" % (token,token.dep_,token.tag_))
[__showTree(t) for t in token.rights]
sys.stdout.write("}")
return __showTree(sent.root)
如果您想要终端的间距:
def showTree(sent):
def __showTree(token, level):
tab = "\t" * level
sys.stdout.write("\n%s{" % (tab))
[__showTree(t, level+1) for t in token.lefts]
sys.stdout.write("\n%s\t%s [%s] (%s)" % (tab,token,token.dep_,token.tag_))
[__showTree(t, level+1) for t in token.rights]
sys.stdout.write("\n%s}" % (tab))
return __showTree(sent.root, 1)
这段代码可以用来读取Spacy依存句法树;
import numpy as np
import spacy
rootNodeName = "ROOT"
class ParseNode:
def __init__(self, token, w):
self.word = token.text
self.w = w #or token.i
self.governor = None
self.dependentList = []
self.parseLabel = None
def generateSentenceParseNodeList(tokenizedSentence):
sentenceParseNodeList = []
for w, token in enumerate(tokenizedSentence):
print("add parseNode: w = ", w, ": text = ", token.text)
parseNode = ParseNode(token, w)
sentenceParseNodeList.append(parseNode)
return sentenceParseNodeList
def generateDependencyParseTree(tokenizedSentence, sentenceParseNodeList):
parseTreeHeadNode = None
for w, tokenDependent in enumerate(tokenizedSentence):
parseNodeDependent = sentenceParseNodeList[tokenDependent.i]
print("add dependency relation: tokenDependent w = ", w, ": text = ", tokenDependent.text, ", i = ", tokenDependent.i, ", tag_ = ", tokenDependent.tag_, ", head.text = ", tokenDependent.head.text, ", dep_ = ", tokenDependent.dep_)
if(tokenDependent.dep_ == rootNodeName):
parseTreeHeadNode = parseNodeDependent
else:
tokenGovernor = tokenDependent.head
parseNodeGovernor = sentenceParseNodeList[tokenGovernor.i]
parseNodeDependent.governor = parseNodeGovernor
parseNodeGovernor.dependentList.append(parseNodeDependent)
parseNodeDependent.parseLabel = tokenDependent.dep_
return parseTreeHeadNode
nlp = spacy.load('en_core_web_md')
text = "This is an example sentence."
tokenizedSentence = nlp(text)
sentenceParseNodeList = generateSentenceParseNodeList(tokenizedSentence)
parseTreeHeadNode = generateDependencyParseTree(tokenizedSentence, sentenceParseNodeList)
我还不太了解解析方面的知识。然而,我的文献研究结果表明,spaCy具有一种移位-规约依赖解析算法。这个算法解析问题/句子,产生一个解析树。为了可视化这个过程,你可以使用DisplaCy,这是一个CSS和Javascript的结合,可以与Python和Cython一起工作。此外,你可以使用SpaCy库进行解析,并导入自然语言工具包(NLTK)。希望这可以帮助到你。