Распознавание именованных сущностей NLTK в списке Python

Я использовал НЛТК ne_chunk извлечь именованные объекты из текста:

my_sent = "WASHINGTON -- In the wake of a string of abuses by New York police officers in the 1990s, Loretta E. Lynch, the top federal prosecutor in Brooklyn, spoke forcefully about the pain of a broken trust that African-Americans felt and said the responsibility for repairing generations of miscommunication and mistrust fell to law enforcement."


nltk.ne_chunk(my_sent, binary=True)

Но я не могу понять, как сохранить эти объекты в списке? Например -

print Entity_list
('WASHINGTON', 'New York', 'Loretta', 'Brooklyn', 'African')

Благодарю.

6 ответов

Решение

nltk.ne_chunk возвращает вложенный nltk.tree.Tree объект, так что вам придется пройти через Tree объект, чтобы добраться до NE.

Взгляните на распознавание именованных сущностей с помощью регулярного выражения: NLTK

>>> from nltk import ne_chunk, pos_tag, word_tokenize
>>> from nltk.tree import Tree
>>> 
>>> def get_continuous_chunks(text):
...     chunked = ne_chunk(pos_tag(word_tokenize(text)))
...     continuous_chunk = []
...     current_chunk = []
...     for i in chunked:
...             if type(i) == Tree:
...                     current_chunk.append(" ".join([token for token, pos in i.leaves()]))
...             elif current_chunk:
...                     named_entity = " ".join(current_chunk)
...                     if named_entity not in continuous_chunk:
...                             continuous_chunk.append(named_entity)
...                             current_chunk = []
...             else:
...                     continue
...     return continuous_chunk
... 
>>> my_sent = "WASHINGTON -- In the wake of a string of abuses by New York police officers in the 1990s, Loretta E. Lynch, the top federal prosecutor in Brooklyn, spoke forcefully about the pain of a broken trust that African-Americans felt and said the responsibility for repairing generations of miscommunication and mistrust fell to law enforcement."
>>> get_continuous_chunks(my_sent)
['WASHINGTON', 'New York', 'Loretta E. Lynch', 'Brooklyn']

Вы также можете извлечь label каждого имени объекта в тексте, используя этот код:

import nltk
for sent in nltk.sent_tokenize(sentence):
   for chunk in nltk.ne_chunk(nltk.pos_tag(nltk.word_tokenize(sent))):
      if hasattr(chunk, 'label'):
         print(chunk.label(), ' '.join(c[0] for c in chunk))

Выход:

GPE WASHINGTON
GPE New York
PERSON Loretta E. Lynch
GPE Brooklyn

Ты можешь видеть Washington, New York а также Brooklyn являются GPE означает геополитические образования

а также Loretta E. Lynch это PERSON

Как вы получаете tree в качестве возвращаемого значения, я думаю, вы хотите выбрать те поддеревья, которые помечены NE

Вот простой пример, чтобы собрать всех тех, кто в списке:

import nltk

my_sent = "WASHINGTON -- In the wake of a string of abuses by New York police officers in the 1990s, Loretta E. Lynch, the top federal prosecutor in Brooklyn, spoke forcefully about the pain of a broken trust that African-Americans felt and said the responsibility for repairing generations of miscommunication and mistrust fell to law enforcement."

parse_tree = nltk.ne_chunk(nltk.tag.pos_tag(my_sent.split()), binary=True)  # POS tagging before chunking!

named_entities = []

for t in parse_tree.subtrees():
    if t.label() == 'NE':
        named_entities.append(t)
        # named_entities.append(list(t))  # if you want to save a list of tagged words instead of a tree

print named_entities

Это дает:

[Tree('NE', [('WASHINGTON', 'NNP')]), Tree('NE', [('New', 'NNP'), ('York', 'NNP')])]

или в виде списка списков:

[[('WASHINGTON', 'NNP')], [('New', 'NNP'), ('York', 'NNP')]]

Также смотрите: Как перемещаться по nltk.tree.Tree?

Используйте tree2conlltags из nltk.chunk. Также ne_chunk нуждается в pos-тегах, которые помечают токены слов (таким образом, нужен word_tokenize).

from nltk import word_tokenize, pos_tag, ne_chunk
from nltk.chunk import tree2conlltags

sentence = "Mark and John are working at Google."
print(tree2conlltags(ne_chunk(pos_tag(word_tokenize(sentence))
"""[('Mark', 'NNP', 'B-PERSON'), 
    ('and', 'CC', 'O'), ('John', 'NNP', 'B-PERSON'), 
    ('are', 'VBP', 'O'), ('working', 'VBG', 'O'), 
    ('at', 'IN', 'O'), ('Google', 'NNP', 'B-ORGANIZATION'), 
    ('.', '.', 'O')] """

Это даст вам список кортежей: [(token, pos_tag, name_entity_tag)] Если этот список не совсем то, что вы хотите, конечно, легче разобрать список, который вы хотите, из этого списка, чем дерево nltk.

Код и детали по этой ссылке; проверить это для получения дополнительной информации

Редактировать Добавлен вывод строки документа

Вы также можете рассмотреть возможность использования Spacy:

import spacy
nlp = spacy.load('en')

doc = nlp('WASHINGTON -- In the wake of a string of abuses by New York police officers in the 1990s, Loretta E. Lynch, the top federal prosecutor in Brooklyn, spoke forcefully about the pain of a broken trust that African-Americans felt and said the responsibility for repairing generations of miscommunication and mistrust fell to law enforcement.')

print([ent for ent in doc.ents])

>>> [WASHINGTON, New York, the 1990s, Loretta E. Lynch, Brooklyn, African-Americans]

Tree это список. Куски - это поддеревья, непоследовательные слова - это обычные строки. Итак, давайте спустимся по списку, извлечем слова из каждого куска и присоединимся к ним.

>>> chunked = nltk.ne_chunk(my_sent)
>>>
>>>  [ " ".join(w for w, t in elt) for elt in chunked if isinstance(elt, nltk.Tree) ]
['WASHINGTON', 'New York', 'Loretta E. Lynch', 'Brooklyn']

Nltk .ne_chunk возвращает вложенный объект nltk.tree.Tree, поэтому вам нужно будет пройти через объект Tree, чтобы добраться до сетевых элементов. Вы можете использовать понимание списка, чтобы сделать то же самое.

import nltk   
my_sent = "WASHINGTON -- In the wake of a string of abuses by New York police officers in the 1990s, Loretta E. Lynch, the top federal prosecutor in Brooklyn, spoke forcefully about the pain of a broken trust that African-Americans felt and said the responsibility for repairing generations of miscommunication and mistrust fell to law enforcement."

word = nltk.word_tokenize(my_sent)   
pos_tag = nltk.pos_tag(word)   
chunk = nltk.ne_chunk(pos_tag)   
NE = [ " ".join(w for w, t in ele) for ele in chunk if isinstance(ele, nltk.Tree)]   
print (NE)
Другие вопросы по тегам