Есть какой-нибудь хороший или лучший или прямой способ получить результат чанкинга от дерева nltk? - PullRequest
0 голосов
/ 31 августа 2018

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

import nltk 
height = 2
sentence = [("the", "DT"), ("little", "JJ"), ("yellow", "JJ"), ("dog", "NN"), ("barked","VBD"), ("at", "IN"), ("the", "DT"), ("cat", "NN")]

pattern = """NP: {<DT>?<JJ>*<NN>}
VBD: {<VBD>}
IN: {<IN>}"""
NPChunker = nltk.RegexpParser(pattern) 
result = NPChunker.parse(sentence)

In [29]: Tree.fromstring(str(result)).pretty_print()
                             S                                      
            _________________|_____________________________          
           NP                        VBD       IN          NP       
   ________|_________________         |        |      _____|____     
the/DT little/JJ yellow/JJ dog/NN barked/VBD at/IN the/DT     cat/NN

Мой подход - грубая сила, как показано ниже:

In [30]: [list(map(lambda x: x[0], _tree.leaves())) for _tree in result.subtrees(lambda x: x.height()==height)]
Out[30]: [['the', 'little', 'yellow', 'dog'], ['barked'], ['at'], ['the', 'cat']]

Я думал, что должен существовать какой-то прямой API или что-то, что я могу использовать для чанкинга. Любые предложения высоко ценятся.

1 Ответ

0 голосов
/ 31 августа 2018

Нет, в NLTK нет встроенной функции для возврата дерева определенной глубины.

Но вы можете использовать обход в глубину из Как пройти объект дерева NLTK?

Чтобы быть эффективным, вы можете выполнять итерацию в первую очередь по глубине и повторяться только в том случае, если глубина меньше необходимой, например

import nltk 
sentence = [("the", "DT"), ("little", "JJ"), ("yellow", "JJ"), ("dog", "NN"), ("barked","VBD"), ("at", "IN"), ("the", "DT"), ("cat", "NN")]

pattern = """NP: {<DT>?<JJ>*<NN>}
VBD: {<VBD>}
IN: {<IN>}"""
NPChunker = nltk.RegexpParser(pattern) 
result = NPChunker.parse(sentence)

def traverse_tree(tree, depth=float('inf')):
    """ 
    Traversing the Tree depth-first,
    yield leaves up to `depth` level.
    """
    for subtree in tree:
        if type(subtree) == nltk.tree.Tree:
            if subtree.height() <= depth:
                yield subtree.leaves()
                traverse_tree(subtree)


list(traverse_tree(result, 2))

[выход]:

[[('the', 'DT'), ('little', 'JJ'), ('yellow', 'JJ'), ('dog', 'NN')],
 [('barked', 'VBD')],
 [('at', 'IN')],
 [('the', 'DT'), ('cat', 'NN')]]

Другой пример:

x = """(S
  (NP the/DT 
      (AP little/JJ yellow/JJ)
       dog/NN)
  (VBD barked/VBD)
  (IN at/IN)
  (NP the/DT cat/NN))"""

list(traverse_tree(Tree.fromstring(x), 2))

[выход]:

[['barked/VBD'], ['at/IN'], ['the/DT', 'cat/NN']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...