Поиск главы существительного в NLTK и stanford parse в соответствии с правилами поиска главы NP
Обычно голова nounfrase является существительным, которое является самым правым из NP, как показано ниже. Дерево - это головка родительского NP. Так
ROOT
|
S
___|________________________
NP |
___|_____________ |
| PP VP
| ____|____ ____|___
NP | NP | PRT
___|_______ | | | |
DT JJ NN NN IN NNP VBD RP
| | | | | | | |
The old oak tree from India fell down
Out [40]: Дерево ('S', [Дерево ('NP', [Дерево ('NP', [Дерево ('DT', ['The']), Дерево ('JJ', [' old ']), Tree (' NN ', [' oak ']), Tree (' NN ', [' tree '])]), Tree (' PP ', [Tree (' IN ', [' from ' ]), Tree ('NP', [Tree ('NNP', ['India'])])])]), Tree ('VP', [Tree ('VBD', ['fall']), Tree ('PRT', [Tree ('RP', ['down'])])])])
Следующий код на основе java-реализации использует упрощенное правило для поиска главы NP, но мне нужно основываться на rules:
parsestr='(ROOT (S (NP (NP (DT The) (JJ old) (NN oak) (NN tree)) (PP (IN from) (NP (NNP India)))) (VP (VBD fell) (PRT (RP down)))))'
def traverse(t):
try:
t.label()
except AttributeError:
return
else:
if t.label()=='NP':
print 'NP:'+str(t.leaves())
print 'NPhead:'+str(t.leaves()[-1])
for child in t:
traverse(child)
else:
for child in t:
traverse(child)
tree=Tree.fromstring(parsestr)
traverse(tree)
Приведенный выше код дает результат:
NP: ['', 'old', 'oak', 'tree', 'from', 'India']
NPhead: Индия
NP: ['', 'старый', 'дуб', 'дерево']
NPhead: дерево
NP: [ 'Индия']
NPhead: Индия
Хотя теперь он дает правильный результат для данного предложения, но мне нужно включить условие, которое только самое большее существительное извлекается как голова, в настоящее время он не проверяет, было ли оно существительным (NN)
print 'NPhead:'+str(t.leaves()[-1])
Итак, что-то вроде следующего в состоянии np head в приведенном выше коде:
t.leaves().getrightmostnoun()
Майкл Коллинз (Приложение A) содержит правила поиска главы для Penn Treebank, и, следовательно, нет необходимости, чтобы только самые правые существительное - это голова. Следовательно, вышеуказанные условия должны включать такой сценарий.
В следующем примере, приведенном в одном из ответов:
(NP (NP человек), который дал (NP разговор)) пошел домой
Главным существительным предмета является человек, но последний отпуск node NP - это тот, кто дал разговор.
Ответы
Ответ 1
Есть встроенная строка для объекта Tree
в NLTK (http://www.nltk.org/_modules/nltk/tree.html), см. https://github.com/nltk/nltk/blob/develop/nltk/tree.py#L541.
>>> from nltk.tree import Tree
>>> parsestr='(ROOT (S (NP (NP (DT The) (JJ old) (NN oak) (NN tree)) (PP (IN from) (NP (NNP India)))) (VP (VBD fell) (PRT (RP down)))))'
>>> for i in Tree.fromstring(parsestr).subtrees():
... if i.label() == 'NP':
... print i
...
(NP
(NP (DT The) (JJ old) (NN oak) (NN tree))
(PP (IN from) (NP (NNP India))))
(NP (DT The) (JJ old) (NN oak) (NN tree))
(NP (NNP India))
>>> for i in Tree.fromstring(parsestr).subtrees():
... if i.label() == 'NP':
... print i.leaves()
...
['The', 'old', 'oak', 'tree', 'from', 'India']
['The', 'old', 'oak', 'tree']
['India']
Обратите внимание: это не всегда так, что правое большинство существительное является головным существительным NP, например.
>>> s = '(ROOT (S (NP (NN Carnac) (DT the) (NN Magnificent)) (VP (VBD gave) (NP ((DT a) (NN talk))))))'
>>> Tree.fromstring(s)
Tree('ROOT', [Tree('S', [Tree('NP', [Tree('NN', ['Carnac']), Tree('DT', ['the']), Tree('NN', ['Magnificent'])]), Tree('VP', [Tree('VBD', ['gave']), Tree('NP', [Tree('', [Tree('DT', ['a']), Tree('NN', ['talk'])])])])])])
>>> for i in Tree.fromstring(s).subtrees():
... if i.label() == 'NP':
... print i.leaves()[-1]
...
Magnificent
talk
Возможно, Magnificent
может быть главным существительным. Другим примером является то, что NP содержит относительное предложение:
(NP (NP человек), который дал (NP разговор)) пошел домой
Голова существительное субъекта person
, но последний отпуск node NP the person that gave the talk
равен talk
.
Ответ 2
Я искал python script, используя NLTK, который выполняет эту задачу и наткнулся на эту запись. Вот решение, которое я придумал. Это немного шумно и произвольно, и определенно не всегда выбирает правильный ответ (например, для составных существительных). Но я хотел опубликовать его, если бы было полезно, чтобы у других было решение, которое в основном работает.
#!/usr/bin/env python
from nltk.tree import Tree
examples = [
'(ROOT (S (NP (NP (DT The) (JJ old) (NN oak) (NN tree)) (PP (IN from) (NP (NNP India)))) (VP (VBD fell) (PRT (RP down)))))',
"(ROOT\n (S\n (NP\n (NP (DT the) (NN person))\n (SBAR\n (WHNP (WDT that))\n (S\n (VP (VBD gave)\n (NP (DT the) (NN talk))))))\n (VP (VBD went)\n (NP (NN home)))))",
'(ROOT (S (NP (NN Carnac) (DT the) (NN Magnificent)) (VP (VBD gave) (NP ((DT a) (NN talk))))))'
]
def find_noun_phrases(tree):
return [subtree for subtree in tree.subtrees(lambda t: t.label()=='NP')]
def find_head_of_np(np):
noun_tags = ['NN', 'NNS', 'NNP', 'NNPS']
top_level_trees = [np[i] for i in range(len(np)) if type(np[i]) is Tree]
## search for a top-level noun
top_level_nouns = [t for t in top_level_trees if t.label() in noun_tags]
if len(top_level_nouns) > 0:
## if you find some, pick the rightmost one, just 'cause
return top_level_nouns[-1][0]
else:
## search for a top-level np
top_level_nps = [t for t in top_level_trees if t.label()=='NP']
if len(top_level_nps) > 0:
## if you find some, pick the head of the rightmost one, just 'cause
return find_head_of_np(top_level_nps[-1])
else:
## search for any noun
nouns = [p[0] for p in np.pos() if p[1] in noun_tags]
if len(nouns) > 0:
## if you find some, pick the rightmost one, just 'cause
return nouns[-1]
else:
## return the rightmost word, just 'cause
return np.leaves()[-1]
for example in examples:
tree = Tree.fromstring(example)
for np in find_noun_phrases(tree):
print "noun phrase:",
print " ".join(np.leaves())
head = find_head_of_np(np)
print "head:",
print head
Для примеров, обсуждаемых в вопросе и в других ответах, это вывод:
noun phrase: The old oak tree from India
head: tree
noun phrase: The old oak tree
head: tree
noun phrase: India
head: India
noun phrase: the person that gave the talk
head: person
noun phrase: the person
head: person
noun phrase: the talk
head: talk
noun phrase: home
head: home
noun phrase: Carnac the Magnificent
head: Magnificent
noun phrase: a talk
head: talk