2011-10-21 16 views
7

To jest follow-up of my question. Używam nltk do analizowania osób, organizacji i ich relacji. Korzystając z this example, udało mi się stworzyć fragmenty osób i organizacji; Jestem jednak otrzymuję błąd w poleceniu nltk.sem.extract_rel:Wyodrębnij relacje za pomocą NLTK

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

Oto kompletny kod:

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) 

Przykład ten jest bardzo podobny do tego given in the book, ale przykład zastosowania przygotowałem "parsowane dokumenty", które pojawiają się znikąd i nie wiem, gdzie znaleźć typ obiektu. Przeszukałem także biblioteki git. Każda pomoc jest doceniana.

Moim ostatecznym celem jest pozyskanie osób, organizacji, tytułów (dat) dla niektórych firm; następnie twórz sieciowe mapy osób i organizacji.

+0

czy kiedykolwiek tego dowiedzieć? mogę zobaczyć, co wymyśliłeś, ponieważ otrzymuję dokładnie ten sam problem. – user3314418

Odpowiedz

4

Wygląda na to, że jest to "Sparsowany dokument". Obiekt musi mieć element headline i element text, z których oba są listami tokenów, w których niektóre tokeny są oznaczane jako drzewa. Na przykład ten (hacky) przykład działa:

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) 

Kiedy uruchomić ten zapewnia wyjście:

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

Oczywiście nie byłoby faktycznie w nim kodu tak, ale zapewnia, że ​​działający przykład z danymi Format oczekiwany przez extract_rels, wystarczy określić sposób wykonywania kroków wstępnego przetwarzania, aby uzyskać masowe przesyłanie danych do tego formatu.

+0

dzięki, bdk. Próbuję teraz przekonwertować drzewa uzyskane w chunked_sentences na format analizowanego dokumentu. Brak błędów przy użyciu Twojej metody, ale nie daje też żadnych wyników. Możliwe, że wzór regex nie pasuje. – karlos

+0

hmm, nie jestem pewien, dlaczego nie uzyskujesz rezultatów z powyższym skryptem, po prostu próbowałem wkleić go do pliku (aby upewnić się, że nie zepsułem pasty) i uruchomiłem go i dało oczekiwane wyniki tutaj. – bdk

+0

Nie, miałem na myśli, twój skrypt działa dobrze, ale kiedy zmodyfikuję go do mojego celu (używając mojego tekstu/drzew), to nie zwraca związków. Podejrzewam, że musi coś zrobić z moim wzorem regex lub moimi drzewami. dzięki za pomoc. – karlos

4

Oto kod źródłowy funkcji 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) 
""" 
.... 

Więc jeśli przechodzą parametr corpus jako ieer funkcja nltk.sem.extract_rels oczekuje parametr doc być przedmiotem IEERDocument. Powinieneś przekazać korpus jako as lub po prostu go nie zaliczać (domyślnie jest to as). W tym przypadku oczekuje listy porcji drzew (to jest to, czego chciałeś). I zmodyfikowany kod jak poniżej:

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

i daje wynik:

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

Nic nie dostałem, gdy skopiowałem i wkleiłem ten przykładowy kod, czy regex ma rację? ... Kiedy go uruchomię, nie daje mi danych wyjściowych. –

+1

Uruchomiłem to ponownie i przyniosłem taki sam wynik. Myślę, że regularna ekspresja jest właściwa. Naprawdę nie wiem, jaki może być problem. – cuneytyvz

+1

Jedyna myśl, którą zrobiłem, to usunąć '.decode()', ponieważ jestem w python3, myślisz, że jest to związane z tym problemem? ... –

0

jest to wersja NLTK problem. Twój kod powinien działać w NLTK 2.x ale NLTK 3 należy kodować jak ten

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

Powiązane problemy