Ich habe versucht, zu finden, wie man den Abhängigkeitsbaum mit SpaCy bekommt, aber ich kann nichts finden, wie man den Baum erhält, nur auf how to navigate the tree.Wie bekomme ich den Abhängigkeitsbaum mit SpaCy?
Antwort
Es stellt sich heraus, dass der Baum through the tokens in einem Dokument verfügbar ist.
Würden Sie die Wurzel des Baumes finden möchten, können Sie jedoch das Dokument gehen Sie einfach:
def find_root(docu):
for token in docu:
if token.head is token:
return token
Um dann den Baum zu navigieren, die Token-API erhalten haben through the children
ich auch gebraucht tun sie so unter vollständigen Code:
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)
Und wenn Sie möchten, für das Terminal Abstand:
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)
Ich habe gerade Modul zum Drucken sowie übereinstimmenden Baum (oder Knoten zu finden) auf Regex wie Muster hinzugefügt. Wenn Sie interessiert sind, hier ist der Link: https://github.com/krzysiekfonal/grammaregex Es ist noch nicht installierbar bereit, aber diese Woche sollte erfüllt werden und über Pip verfügbar sein. – Krzysiek
Für den Fall, dass jemand den von spacy erzeugten Abhängigkeitsbaum leicht anzeigen möchte, wäre eine Lösung, ihn in nltk.tree.Tree
umzuwandeln und die Methode nltk.tree.Tree.pretty_print
zu verwenden. Hier ein Beispiel:
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]
Ausgang:
jumps
________________|____________
| | | | | over
| | | | | |
| | | | | dog
| | | | | ___|____
The quick brown fox . the lazy
Edit: Für die Token-Darstellung Ändern Sie dies tun können:
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)
was dazu führt:
jumps_VBZ
__________________________|___________________
| | | | | over_IN
| | | | | |
| | | | | dog_NN
| | | | | _______|_______
The_DT quick_JJ brown_JJ fox_NN ._. the_DT lazy_JJ
Aber meiner Meinung nach ist es wichtig, die Abhängigkeiten sowie die Postages von Spacy zu behalten. – Krzysiek
Gute Arbeit! Gibt es eine einfache Möglichkeit, das Abhängigkeitstag zwischen zwei Knoten hinzuzufügen? –
@DavidBatista sehe meine Bearbeitung. Wenn Sie der Baumstruktur 'tok_format (tok)' 'ein paar andere Sachen hinzufügen wollen. Außerdem sollten Sie die Dokumentation lesen. Spacy verwendet 2 verschiedene POS-Darstellungen 'tok.pos_' und' tok.tag_'. https://spacy.io/docs/#token-postags –
Der Baum ist kein Objekt an sich; Sie navigieren nur über die Beziehungen zwischen Token. Deshalb sprechen die Doktoren über das Navigieren durch den Baum, aber nicht darum, es "zu bekommen".
Lassen Sie uns zunächst einen Text analysieren ein Doc
Objekt zu erhalten:
>>> import spacy
>>> nlp = spacy.load('en')
>>> doc = nlp('First, I wrote some sentences. Then spaCy parsed them. Hooray!')
doc
ist ein Sequence
von Token
Objekte:
>>> doc[0]
First
>>> doc[1]
,
>>> doc[2]
I
>>> doc[3]
wrote
Aber es hat keinen einzigen Wurzel Token. Wir haben einen Text analysiert, der aus drei Sätzen besteht, also gibt es drei verschiedene Bäume, jeder mit einer eigenen Wurzel. Wenn wir unser Parsing von der Wurzel jedes Satzes aus beginnen wollen, wird es helfen, zuerst die Sätze als unterschiedliche Objekte zu erhalten. Glücklicherweise macht doc
uns diese über die .sents
Eigenschaft:
>>> sentences = list(doc.sents)
>>> for sentence in sentences:
... print(sentence)
...
First, I wrote some sentences.
Then spaCy parsed them.
Hooray!
Jeder dieser Sätze ein Span
mit seiner Wurzel-Token zeigt .root
Eigenschaft ist.Üblicherweise wird die Wurzel Token die Hauptverb des Satzes sein (obwohl dies nicht für ungewöhnliche Satzstrukturen wahr sein kann, wie Sätze ohne Verb):
>>> for sentence in sentences:
... print(sentence.root)
...
wrote
parsed
Hooray
mit dem Root-Token gefunden haben, können wir nach unten navigieren der Baum über die .children
Eigenschaft jedes Token. Suchen wir zum Beispiel das Subjekt und das Objekt des Verbs im ersten Satz. Die .dep_
Eigenschaft jedes Kind Tokens describes its relationship with its parent; zum Beispiel bedeutet ein dep_
von 'nsubj'
, dass ein Token der Nominalsubjekt seines Elternteils ist.
>>> 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
Wir ebenfalls durch den Baum hinunter halten kann eine dieser Token Kinder viewing:
>>> list(obj.children)
[some]
So mit den Eigenschaften oben können Sie den gesamten Baum navigieren. Wenn Sie einige Abhängigkeitsstrukturen für Beispielsätze visualisieren möchten, um die Struktur zu verstehen, empfehle ich, mit displaCy zu spielen.
Ich habe noch nicht genug Wissen über das Parsing. Das Ergebnis meiner Literaturstudie hat jedoch ergeben, dass spaCy einen Shift-Reduction-Parsing-Algorithmus hat. Dies analysiert die Frage/den Satz, was zu einem Parsingbaum führt. Um dies zu visualisieren, können Sie die DisplaCy, eine Kombination aus CSS und Javascript, mit Python und Cython verwenden. Darüber hinaus können Sie mit der SpaCy-Bibliothek analysieren und das Natural Language Toolkit (NLTK) importieren. Hoffe, das hilft
Ein Dokument wird 1 Wurzel pro Satz haben –
Es gibt keine Notwendigkeit, über die Token zu iterieren, um den Stamm zu finden; Sie können einfach auf die '.root'-Eigenschaft eines Satzes zugreifen. Ich werde meine eigene Antwort veröffentlichen, die das zeigt. –