2015-09-18 7 views
11

in generale Una testa di un sostantivo è un nome che è più a destra del NP come mostrato sotto l'albero è la testa del padre NP . CosìTrovare la testa di una frase nominale in NLTK e stanford parse secondo le regole di trovare la testa di un 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]: Albero ('S', [Albero ('NP', [Albero ('NP', [Albero ('DT', [ 'La']), Albero (' JJ ', [' old ']), Tree (' NN ', [' oak ']), Tree (' NN ', [' tree '])]), Tree (' PP ', [Tree (' IN ' , ['da']), Albero ('NP', [Albero ('NNP', ['India'])])])]), Albero ('VP', [Albero ('VBD', ['fell ']), Albero (' PRT ', [Albero (' RP ', [' basso '])])])])

Il seguente codice based on a java implementation utilizza una regola semplicistica per trovare la testa del NP, ma ho bisogno di essere basata sul 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) 

Th e sopra il codice dà uscita:

NP: [ 'The', 'vecchio', 'quercia', 'albero', 'da', 'India'] NPhead: India NP: [ 'The', ' vecchio', 'quercia', 'albero'] NPhead: albero NP: [ 'India'] NPhead: India

Anche se ora il suo dando uscita corretta per la sentenza data, ma ho bisogno di incorporare una condizione che solo la maggior parte dei sostantivi viene estratta come testa, attualmente non controlla se si tratta di un sostantivo (NN)

print 'NPhead:'+str(t.leaves()[-1]) 

Quindi, qualcosa come seguire nella condizione testa np nel codice di cui sopra:

t.leaves().getrightmostnoun() 

Michael Collins dissertation (Appendix A) include regole di testa di accertamento per la Penn Treebank, e, quindi, non è necessario che solo il sostantivo più a destra è la testa. Quindi le condizioni di cui sopra dovrebbero incorporare tale scenario.

Per il seguente esempio, come indicato in una delle risposte:

(NP (NP la persona) che ha dato (NP il discorso)) è andato a casa

Il sostantivo capo della il soggetto è la persona, ma l'ultimo nodo di uscita del NP è la persona che ha dato il discorso.

+0

Qual è la tua domanda? – barny

+0

@barny come trovare la testa e NP – stackit

+2

Si prega di leggere la pagina di aiuto http://stackoverflow.com/help/mcve. In questo caso, mostra l'output che * do * get: "non funziona" non è sufficiente per StackOverflow. Inoltre, prova ad aggiungere ulteriori dichiarazioni di stampa al tuo codice (come ad esempio prima di attraversare (figlio) e un altro in entrata per attraversare). Pubblica l'output di quella traccia di esecuzione, a condizione che non mostri immediatamente * te * il problema. – Prune

risposta

8

C'è una stringa incorporata nell'oggetto Tree in NLTK (http://www.nltk.org/_modules/nltk/tree.html), vedere https://github.com/nltk/nltk/blob/develop/nltk/tree.py#L541.

Si noti che non è sempre il caso che la maggior parte del sostantivo è il nome della testa di un NP, ad es.

>>> 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 

Probabilmente, Magnificent può essere ancora il sostantivo testa.Un altro esempio è quando il NP comprende una clausola relativa:

(NP (NP la persona) che ha dato (NP il discorso)) è andato a casa

Il sostantivo testa del soggetto è person ma il ultimo nodo di uscita di NP the person that gave the talk è talk.

+0

lo ho fatto finalmente come mostrato nel codice, ma ho solo bisogno di aggiungere una condizione per verificare se il più a destra è un NN – stackit

+0

controllare la mia domanda aggiornata – stackit

+0

Quindi qualcosa come seguire nella condizione di testa np nel codice di cui sopra: t.leaves () .getrightmostnoun() – stackit

1

Stavo cercando uno script python utilizzando NLTK che esegue questa attività e incappato in questo post. Ecco la soluzione che ho trovato. È un po 'rumoroso e arbitrario, e sicuramente non sempre sceglie la risposta giusta (ad esempio per i nomi composti). Ma Volevo pubblicarlo nel caso in cui fosse utile per gli altri avere una soluzione che funziona per lo più.

#!/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 

Per gli esempi discussi nella domanda e nelle altre risposte, questo è l'output:

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 
Problemi correlati