2011-10-21 13 views
7

Questo è un follow-up of my question. Sto usando nltk per analizzare le persone, le organizzazioni e le loro relazioni. Usando this example, sono stato in grado di creare blocchi di persone e organizzazioni; tuttavia, sto ottenendo un errore nel comando nltk.sem.extract_rel:estrae le relazioni utilizzando NLTK

AttributeError: 'Tree' object has no attribute 'text' 

Ecco il codice completo:

import nltk 
import re 
#billgatesbio from http://www.reuters.com/finance/stocks/officerProfile?symbol=MSFT.O&officerId=28066 
with open('billgatesbio.txt', 'r') as f: 
    sample = f.read() 

sentences = nltk.sent_tokenize(sample) 
tokenized_sentences = [nltk.word_tokenize(sentence) for sentence in sentences] 
tagged_sentences = [nltk.pos_tag(sentence) for sentence in tokenized_sentences] 
chunked_sentences = nltk.batch_ne_chunk(tagged_sentences) 

# tried plain ne_chunk instead of batch_ne_chunk as given in the book 
#chunked_sentences = [nltk.ne_chunk(sentence) for sentence in tagged_sentences] 

# pattern to find <person> served as <title> in <org> 
IN = re.compile(r'.+\s+as\s+') 
for doc in chunked_sentences: 
    for rel in nltk.sem.extract_rels('ORG', 'PERSON', doc,corpus='ieer', pattern=IN): 
     print nltk.sem.show_raw_rtuple(rel) 

Questo esempio è molto simile a quella given in the book, ma gli usi di esempio preparato 'documenti analizzati', che appare da nessuna parte e non so dove trovare il suo tipo di oggetto. Ho perlustrato anche le librerie git. Qualsiasi aiuto è apprezzato.

Il mio obiettivo finale è estrarre persone, organizzazioni, titoli (date) per alcune aziende; quindi creare mappe di rete di persone e organizzazioni.

+0

hai mai capire questo? posso vedere cosa ti è venuto in mente perché sto ottenendo esattamente lo stesso problema. – user3314418

risposta

4

Sembra essere un "Documento analizzato" un oggetto deve avere un membro headline e un membro text entrambi i quali sono elenchi di token, in cui alcuni token sono contrassegnati come alberi. Per esempio questo (hacky) esempio funziona:

import nltk 
import re 

IN = re.compile (r'.*\bin\b(?!\b.+ing)') 

class doc(): 
    pass 

doc.headline=['foo'] 
doc.text=[nltk.Tree('ORGANIZATION', ['WHYY']), 'in', nltk.Tree('LOCATION',['Philadelphia']), '.', 'Ms.', nltk.Tree('PERSON', ['Gross']), ','] 

for rel in nltk.sem.extract_rels('ORG','LOC',doc,corpus='ieer',pattern=IN): 
    print nltk.sem.relextract.show_raw_rtuple(rel) 

Quando viene eseguito questo fornisce l'uscita:

[ORG: 'WHYY'] 'in' [LOC: 'Philadelphia'] 

Ovviamente non sarebbe in realtà il codice in questo modo, ma fornisce un esempio di lavoro dei dati formato previsto da extract_rels, è sufficiente determinare come eseguire i passaggi di pre-elaborazione per ottenere il massaggio dei dati in tale formato.

+0

grazie, bdk. Sto provando ora a convertire gli alberi ottenuti in chunked_sentences nel formato del documento analizzato. Nessun errore nell'usare il tuo metodo, ma non mi sta dando alcun risultato. È possibile che il pattern regex non sia una corrispondenza. – karlos

+0

hmm, non sono sicuro del motivo per cui non si ottengono risultati con lo script sopra, ho appena provato ad incollarlo in un file (per assicurarmi che non avessi fatto il pasticcio della pasta) e averlo eseguito e ha dato i risultati attesi qui. – bdk

+0

no, volevo dire, il tuo script sta funzionando bene, ma quando lo modifico per il mio scopo (usando il mio testo/alberi), non restituisce le relazioni. Sospetto che debba fare qualcosa con il mio schema regex o con i miei alberi. Grazie per l'aiuto. – karlos

4

Ecco il codice sorgente della funzione nltk.sem.extract_rels:

def extract_rels(subjclass, objclass, doc, corpus='ace', pattern=None, window=10): 
""" 
Filter the output of ``semi_rel2reldict`` according to specified NE classes and a filler pattern. 

The parameters ``subjclass`` and ``objclass`` can be used to restrict the 
Named Entities to particular types (any of 'LOCATION', 'ORGANIZATION', 
'PERSON', 'DURATION', 'DATE', 'CARDINAL', 'PERCENT', 'MONEY', 'MEASURE'). 

:param subjclass: the class of the subject Named Entity. 
:type subjclass: str 
:param objclass: the class of the object Named Entity. 
:type objclass: str 
:param doc: input document 
:type doc: ieer document or a list of chunk trees 
:param corpus: name of the corpus to take as input; possible values are 
    'ieer' and 'conll2002' 
:type corpus: str 
:param pattern: a regular expression for filtering the fillers of 
    retrieved triples. 
:type pattern: SRE_Pattern 
:param window: filters out fillers which exceed this threshold 
:type window: int 
:return: see ``mk_reldicts`` 
:rtype: list(defaultdict) 
""" 
.... 

Quindi, se si passa il parametro corpus come IEER, la funzione nltk.sem.extract_rels si aspetta che il parametro doc di essere un oggetto IEERDocument. Dovresti superare il corpus come asso o semplicemente non passarlo (il default è asso). In questo caso si aspetta un elenco di alberi di blocchi (è quello che volevi). Ho modificato il codice, come di seguito:

import nltk 
import re 
from nltk.sem import extract_rels,rtuple 

#billgatesbio from http://www.reuters.com/finance/stocks/officerProfile?symbol=MSFT.O&officerId=28066 
with open('billgatesbio.txt', 'r') as f: 
    sample = f.read().decode('utf-8') 

sentences = nltk.sent_tokenize(sample) 
tokenized_sentences = [nltk.word_tokenize(sentence) for sentence in sentences] 
tagged_sentences = [nltk.pos_tag(sentence) for sentence in tokenized_sentences] 

# here i changed reg ex and below i exchanged subj and obj classes' places 
OF = re.compile(r'.*\bof\b.*') 

for i, sent in enumerate(tagged_sentences): 
    sent = nltk.ne_chunk(sent) # ne_chunk method expects one tagged sentence 
    rels = extract_rels('PER', 'ORG', sent, corpus='ace', pattern=OF, window=7) # extract_rels method expects one chunked sentence 
    for rel in rels: 
     print('{0:<5}{1}'.format(i, rtuple(rel))) 

e dà il risultato:

[PER: u'Chairman/NNP'] u'and/CC Chief/NNP Executive/NNP Officer/NNP of/IN the/DT' [ORG: u'Company/NNP'] 
+1

Non ho ottenuto nulla quando ho copiato e incollato questo codice di esempio, la regex è corretta? ... Quando lo eseguo non mi dà l'output. –

+1

L'ho eseguito di nuovo e ho preso lo stesso risultato. Penso che l'espressione regolare sia giusta. Non so davvero quale potrebbe essere il problema. – cuneytyvz

+1

L'unico pensiero che ho fatto è stato rimuovere il '.decode()', dal momento che sono in python3, pensi che questo sia collegato a questo problema? .... –

0

questo è NLTK problema di versione. il codice dovrebbe funzionare in 2.x NLTK ma per NLTK 3 si dovrebbe codice come questo

IN = re.compile(r'.*\bin\b(?!\b.+ing)') 
for doc in nltk.corpus.ieer.parsed_docs('NYT_19980315'): 
    for rel in nltk.sem.relextract.extract_rels('ORG', 'LOC', doc,corpus='ieer', pattern = IN): 
     print (nltk.sem.relextract.rtuple(rel)) 

NLTK Example for Relation Extraction Does not work

Problemi correlati