Как сделать дерево из вывода парсера зависимостей? - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь создать дерево (вложенный словарь) из вывода анализатора зависимостей. Предложение звучит так: «Я застрелил слона во сне». Я могу получить вывод, как описано по ссылке: Как мне выполнить анализ зависимостей в 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'), {})})})}

Чтобы найти путь от корня к листу, я использовал следующую ссылку: Возврат корня к конкретному листу из вложенного словарного дерева

[Создание дерева и поиск пути - это две разные вещи] Вторая цель - найти путь от узла к листу, как сделано Возврат корня к определенному листу из вложенного словарного дерева . Но я хочу получить от корня к листу (путь отношения зависимости) Так, например, когда я буду вызывать recurse_category (category, 'an'), где category - это структура вложенного дерева, а 'an' - слово в дереве, я должен получить ROOT-nsubj-dobj (отношение зависимости до корня) в качестве вывода.

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

Преобразует выходные данные во вложенную форму словаря. Я буду держать вас в курсе, если смогу найти путь. Может быть, это полезно.

list_of_tuples = [('ROOT','ROOT', 'shot'),('nsubj','shot', 'I'),('det','elephant', 'an'),('dobj','shot', 'elephant'),('case','sleep', 'in'),('nmod:poss','sleep', 'my'),('nmod','shot', 'sleep')]

nodes={}

for i in list_of_tuples:
    rel,parent,child=i
    nodes[child]={'Name':child,'Relationship':rel}

forest=[]

for i in list_of_tuples:
    rel,parent,child=i
    node=nodes[child]

    if parent=='ROOT':# this should be the Root Node
            forest.append(node)
    else:
        parent=nodes[parent]
        if not 'children' in parent:
            parent['children']=[]
        children=parent['children']
        children.append(node)

print forest

Вывод - вложенный словарь,

[{'Name': 'shot', 'Relationship': 'ROOT', 'children': [{'Name': 'I', 'Relationship': 'nsubj'}, {'Name': 'elephant', 'Relationship': 'dobj', 'children': [{'Name': 'an', 'Relationship': 'det'}]}, {'Name': 'sleep', 'Relationship': 'nmod', 'children': [{'Name': 'in', 'Relationship': 'case'}, {'Name': 'my', 'Relationship': 'nmod:poss'}]}]}]

Следующая функция может помочь вам найти путь от корня к листу:

def recurse_category(categories,to_find):
    for category in categories: 
        if category['Name'] == to_find:
            return True, [category['Relationship']]
        if 'children' in category:
            found, path = recurse_category(category['children'], to_find)
            if found:
                return True, [category['Relationship']] + path
    return False, []
0 голосов
/ 04 сентября 2018

Во-первых, если вы просто используете предварительно обученную модель для анализатора зависимостей Stanford CoreNLP, вам следует использовать CoreNLPDependencyParser из nltk.parse.corenlp и избегать использования старого интерфейса nltk.parse.stanford.

См. Stanford Parser и NLTK

После загрузки и запуска сервера 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   _   _
...