Нахождение или нет, слово находится на пути зависимости двух объектов с spaCy
Я работаю над проблемой nlp, учитывая предложение с двумя сущностями, мне нужно сгенерировать логическое указание для каждого слова, если оно стоит на пути зависимости между этими сущностями.
Например:
"Туманный
гребень e1 > восстает из всплеска e2 >"
Я хочу перебрать каждое слово и сказать, находится ли он на пути зависимости между e1 и e2
Два важных замечания:
-Если вы пытаетесь мне помочь (во-первых, спасибо), не беспокойтесь о разметке xml с помощью
- Поскольку я не являюсь экспертом по nlp, меня немного смущает значение "на пути зависимости", и я извиняюсь, если он недостаточно ясен (эти слова используются моим преподавателем)
заранее спасибо
2 ответа
Таким образом, мое решение было найдено с помощью этого поста
Есть ответ, посвященный spaCy
Моя реализация для нахождения пути зависимости между двумя словами в данном предложении:
import networkx as nx
import spacy
enter code here
doc = nlp("Ships carrying equipment for US troops are already waiting off the Turkish coast")
def shortest_dependency_path(doc, e1=None, e2=None):
edges = []
for token in doc:
for child in token.children:
edges.append(('{0}'.format(token),
'{0}'.format(child)))
graph = nx.Graph(edges)
try:
shortest_path = nx.shortest_path(graph, source=e1, target=e2)
except nx.NetworkXNoPath:
shortest_path = []
return shortest_path
print(shortest_dependency_path(doc,'Ships','troops'))
Выход:
['Ships', 'carrying', 'for', 'troops']
На самом деле он сначала строит неориентированный граф для предложения, где слова - это узлы, а зависимости между словами - это ребра, а затем находит кратчайший путь между двумя узлами.
Для своих нужд я просто проверяю каждое слово на сгенерированный путь зависимости (кратчайший путь)
Путь зависимости - это способ описания того, как предложения строятся в предложении. У SpaCy есть действительно хороший пример в их документах с предложением Apple is looking at buying U.K. startup for $1 billion.
Прошу прощения, что у меня нет хорошей визуализации, но поработайте над своим примером:
A misty ridge uprises from the surge.
В spaCy мы следуем их примеру, чтобы получить зависимости:
import spacy
nlp = spacy.load('en_core_web_lg')
doc = nlp("A misty ridge uprises from the surge.")
for chunk in doc.noun_chunks:
print(chunk.text, chunk.root.text, chunk.root.dep_, chunk.root.head.text)
Это получит "пункты", которые составляют ваше предложение. Ваш вывод будет выглядеть так:
Text | root.text| root.dep_ | root.head.text
A misty ridge uprises uprises ROOT uprises
the surge surge pobj from
chunk.text
текст, который составляет ваше предложение о зависимости (обратите внимание, что в зависимости от структуры предложения возможны совпадения). root.text
дает корень (или голову) дерева зависимостей. head
из дерева это спа token
объект, и имеет дочерние элементы, которые вы можете перебрать, чтобы проверить, есть ли другой токен в дереве зависимостей.
def find_dependencies(doc, word_to_check=None, dep_choice=None):
"""
word_to_check is the word you'd like to see on the dependency tree
example, word_to_check="misty"
dep_choice is the text of the item you'd like the dependency check
to be against. Example, dep_choice='ridge'
"""
tokens, texts = [], []
for tok in doc:
tokens.append(tok)
texts.append(tok.text)
# grabs the index/indices of the token that you are interested in
indices = [i for i,text in enumerate(texts) if text==dep_choice]
words_in_path = []
for i in indices:
reference = tokens[i]
child_elements = [t.text for t in reference.get_children()]
if word_to_check in child_elements:
words_in_path.append((word_to_check, reference))
return words_in_path
Код не самый красивый, но таким образом вы можете получить список кортежей, содержащих слово, которое вы хотите проверить, и соответствующий родительский токен. Надеюсь, это полезно
РЕДАКТИРОВАТЬ:
В целях более точной адаптации к вашему варианту использования (и огромного упрощения того, как выглядит мой первоначальный ответ):
# This will give you 'word':<spaCy doc object> key value lookup capability
tokens_lookup = {tok.text:tok for tok in doc}
if "misty" in tokens_lookup.get("ridge").children:
# Extra logic here