Вашу задачу можно легко представить как задачу с графом, где нам нужно найти кратчайший путь между двумя узлами.
Чтобы преобразовать ваш синтаксический анализ зависимостей в граф, мы сначала должны иметь дело с тем фактом, что он представлен в виде строки. Вы хотите получить это:
'nsubj(are-5, Robots-1)\nxsubj(remind-8, Robots-1)\namod(culture-4, popular-3)\nprep_in(Robots-1, culture-4)\nroot(ROOT-0, are-5)\nadvmod(are-5, there-6)\naux(remind-8, to-7)\nxcomp(are-5, remind-8)\ndobj(remind-8, us-9)\ndet(awesomeness-12, the-11)\nprep_of(remind-8, awesomeness-12)\namod(agency-16, unbound-14)\namod(agency-16, human-15)\nprep_of(awesomeness-12, agency-16)'
выглядеть так:
[('are-5', 'Robots-1'), ('remind-8', 'Robots-1'), ('culture-4', 'popular-3'), ('Robots-1', 'culture-4'), ('ROOT-0', 'are-5'), ('are-5', 'there-6'), ('remind-8', 'to-7'), ('are-5', 'remind-8'), ('remind-8', 'us-9'), ('awesomeness-12', 'the-11'), ('remind-8', 'awesomeness-12'), ('agency-16', 'unbound-14'), ('agency-16', 'human-15'), ('awesomeness-12', 'agency-16')]
Таким образом, вы можете передать список кортежей в конструктор графа из модуля networkx, который проанализирует список и построить для вас график, а также дать вам аккуратный метод, который дает вам длину кратчайшего пути между двумя заданными узлами.
Необходимый импорт
import re
import networkx as nx
from practnlptools.tools import Annotator
Как получить строку в нужном формате списка кортежей
annotator = Annotator()
text = """Robots in popular culture are there to remind us of the awesomeness of unbound human agency."""
dep_parse = annotator.getAnnotations(text, dep_parse=True)['dep_parse']
dp_list = dep_parse.split('\n')
pattern = re.compile(r'.+?\((.+?), (.+?)\)')
edges = []
for dep in dp_list:
m = pattern.search(dep)
edges.append((m.group(1), m.group(2)))
Как построить график
graph = nx.Graph(edges) # Well that was easy
Как вычислить длину кратчайшего пути
print(nx.shortest_path_length(graph, source='Robots-1', target='awesomeness-12'))
Этот сценарий покажет, что кратчайший путь с учетом синтаксического анализа зависимости на самом деле имеет длину 2, поскольку вы можете перейти от Robots-1
к awesomeness-12
, пройдя через remind-8
1. xsubj(remind-8, Robots-1)
2. prep_of(remind-8, awesomeness-12)
Если вам не нравится этот результат, вы можете подумать о фильтрации некоторых зависимостей, в этом случае запретите добавление зависимости xsubj
на график.
person
HugoMailhot
schedule
01.10.2015