0

Улучшение извлечения имен людей с помощью NLTK [закрыто]

13

Проблема извлечения имен людей из текста

Я пытаюсь извлечь имена людей из текста. У кого-то есть рекомендованный метод для решения этой задачи?

Вот что я уже пробовал (код ниже): Я использую библиотеку nltk, чтобы найти все фрагменты, отмеченные как человек, а затем создаю список из всех имен, состоящих из заглавных существительных (NNP). Я пропускаю одиночные NNP, чтобы избежать захвата только фамилий.

Я получаю довольно хорошие результаты, но хотел бы узнать, существуют ли более эффективные способы решения этой проблемы.

Код:

import nltk
from nameparser.parser import HumanName

def get_human_names(text):
    tokens = nltk.tokenize.word_tokenize(text)
    pos = nltk.pos_tag(tokens)
    sentt = nltk.ne_chunk(pos, binary=False)
    person_list = []
    person = []
    name = ""
    for subtree in sentt.subtrees(filter=lambda t: t.node == 'PERSON'):
        for leaf in subtree.leaves():
            person.append(leaf[0])
        if len(person) > 1:  # избегаем захвата одиночных фамилий
            for part in person:
                name += part + ' '
            if name[:-1] not in person_list:
                person_list.append(name[:-1])
            name = ''
        person = []

    return person_list

text = """
Некоторые экономисты положительно отреагировали на Bitcoin, в том числе 
Франсуа Р. Вельде, старший экономист Федерального резервного банка в Чикаго, 
который описал его как "изящное решение проблемы создания цифровой валюты". 
В ноябре 2013 года Ричард Брэнсон объявил, что Virgin Galactic будет принимать 
Bitcoin в качестве оплаты, заявив, что он инвестировал в Bitcoin и нашел это 
"очень увлекательным, как целая новая глобальная валюта была создана", 
побуждая других также инвестировать в Bitcoin.
Другие экономисты, комментируя Bitcoin, были критичными. 
Экономист Пол Кругман предположил, что структура валюты 
поощряет накопление, и ее ценность проистекает из ожидания, что 
другие примут ее в качестве оплаты. Экономист Ларри Саммерс выразил 
позицию "ждать и смотреть" по поводу Bitcoin. Ник Колас, рыночный 
стратег группы ConvergEx, заметил влияние увеличивающегося 
использования Bitcoin и его ограниченного предложения, отметив: "Когда 
постепенное принятие встречается с относительно фиксированным предложением, 
не должно удивлять, что цены растут. И именно это сейчас происходит с ценами на BTC."
"""

names = get_human_names(text)
print("LAST, FIRST")
for name in names:
    last_first = HumanName(name).last + ', ' + HumanName(name).first
    print(last_first)

Вывод:

LAST, FIRST
Velde, Francois
Branson, Richard
Galactic, Virgin
Krugman, Paul
Summers, Larry
Colas, Nick

Помимо Virgin Galactic, все остальные результаты корректны. Конечно, сложно (возможно, невозможно) знать, что Virgin Galactic не является человеческим именем в контексте этой статьи.

Можете ли вы предложить лучшие методы для точной фильтрации имен людей в подобных текстах?

5 ответ(ов)

0

Для тех, кто ищет решение, я нашел эту статью довольно полезной: http://timmcnamara.co.nz/post/2650550090/extracting-names-with-6-lines-of-python-code

Вот пример кода на Python, который поможет вам извлечь имена из текста с использованием библиотеки NLTK:

>>> import nltk
>>> def extract_entities(text):
...     for sent in nltk.sent_tokenize(text):
...         for chunk in nltk.ne_chunk(nltk.pos_tag(nltk.word_tokenize(sent))):
...             if hasattr(chunk, 'node'):
...                 print(chunk.node, ' '.join(c[0] for c in chunk.leaves()))
...

Этот код последовательно обрабатывает текст, разбивает его на предложения, выполняет токенизацию и определяет части речи, а затем использует функцию ne_chunk для извлечения именованных сущностей. Убедитесь, что у вас установлена библиотека NLTK и загружены необходимые ресурсы, такие как модели для токенизации и тегирования частей речи.

0

Вы пытались извлечь только имена людей из текста и проверяли каждое полученное имя с использованием WordNet - большой лексической базы данных английского языка. Код, который вы представили, выполняет задачу распознавания имен, но все же присутствует пара нюансов, которые можно улучшить.

Проблема

Ваш код корректно извлекает имена, но имя "Larry Summers" оказалось в списке имен, поскольку "Summers" является распространённым словом, входящим в WordNet. Это объясняет, почему было выбрано только одно имя с недействительным результатом.

Решение

Чтобы избежать этого, хорошей практикой будет проверять не только наличие слова в WordNet, но и то, является ли это слово фамилией или распространённым существительным. Можно дополнительно фильтровать имена, чтобы учитывать контекст. Вы можете, например, использовать POS-теги, чтобы удостовериться, что распознанное слово действительно является частью имени.

Код с исправлениями

Вот обновлённый блок кода с учётом данной проблемы:

import nltk
from nameparser.parser import HumanName
from nltk.corpus import wordnet

person_list = []
def get_human_names(text):
    tokens = nltk.tokenize.word_tokenize(text)
    pos = nltk.pos_tag(tokens)
    sentt = nltk.ne_chunk(pos, binary=False)

    person = []
    for subtree in sentt.subtrees(filter=lambda t: t.label() == 'PERSON'):
        full_name = ' '.join(leaf[0] for leaf in subtree.leaves())
        person_list.append(full_name)

text = """
... ваш текст ...
"""

get_human_names(text)

# Фильтрация имен на основе наличия слов в WordNet
valid_person_names = [] 
for person in person_list:
    person_split = person.split(" ")
    if all(not wordnet.synsets(name) for name in person_split[1:]):  # Проверяем все, кроме первого слова
        valid_person_names.append(person)

print(valid_person_names)

Объяснение

  1. Мы фильтруем каждое имя из person_list, проверяя, есть ли в WordNet синонимы для всех частей имени, кроме первого слова (предполагая, что первое слово является именем, а остальные могут быть фамилиями или отдельными словами).
  2. Если ни одно из оставшихся имен не найдено в WordNet, то оно добавляется в valid_person_names.

Вывод

Теперь ваши результаты будут корректнее, и имя "Larry Summers" будет исключено из списка, если оно не является корректной комбинацией имени и фамилии.

0

Вы можете попробовать сделать разрешение найденных имен и проверить, можете ли вы найти их в базе данных, такой как freebase.com. Скачайте данные локально и выполняйте запросы (они в формате RDF), или воспользуйтесь API Google: https://developers.google.com/freebase/v1/getting-started. Большинство крупных компаний, географических мест и т.д. (которые могут быть захвачены вашим сниппетом) можно будет отфильтровать на основе данных Freebase.

0

Я хотел бы поделиться довольно жадным решением, чтобы решить проблему, поднятую @Enthusiast: получить полное имя человека, если это возможно.

Критерием для распознавания сущностей типа PERSON в библиотеке Spacy является использование заглавной буквы в начале каждого имени. Например, 'jim hoffman' не будет распознано как именованная сущность, тогда как 'Jim Hoffman' будет.

Таким образом, если наша задача заключается просто в извлечении имен из текста, мы можем сначала сделать первую букву каждого слова заглавной, а затем передать этот текст в Spacy.

Вот пример кода:

import spacy

def capitalizeWords(text):
    newText = ''

    for sentence in text.split('.'):
        newSentence = ''
        for word in sentence.split():
            newSentence += word.capitalize() + ' '  # делаем первую букву заглавной
        newText += newSentence.strip() + '\n'  # удаляем лишние пробелы

    return newText

nlp = spacy.load('en_core_web_md')

doc = nlp(capitalizeWords(rawText))

#......

Обратите внимание, что этот подход позволяет охватить полные имена, но за счет увеличения числа ложных положительных срабатываний.

0

Это сработало довольно хорошо для меня. Мне нужно было изменить всего одну строку, чтобы всё заработало:

    for subtree in sentt.subtrees(filter=lambda t: t.node == 'PERSON'):

нужно заменить на:

    for subtree in sentt.subtrees(filter=lambda t: t.label() == 'PERSON'):

В выводе были небольшие недостатки (например, он определял "Money Laundering" как человека), но с моими данными база имен может оказаться ненадежной.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь