Как разобрать имена из необработанного текста

Мне было интересно, знает ли кто-нибудь о каких-либо хороших библиотеках или методах разбора имен из необработанного текста.

Например, скажем, у меня есть это в качестве примеров: (обратите внимание, что иногда это кортежи с заглавной буквы, а иногда нет)

James Vaynerchuck and the rest of the group will be meeting at 1PM. 
Sally Johnson, Jim White and brad burton. 
Mark angleman Happiness, Productivity & blocks. Mark & Evan at 4pm.

Моя первая мысль — загрузить какой-нибудь тегировщик частей речи (например, Python NLTK), пометить все слова. Затем удалите только существительные, затем сравните существительные с базой данных известных слов (т. е. с буквальным словарем), если их нет в словаре, предположим, что это имя.

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

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

Спасибо!


person Blakedallen    schedule 03.08.2014    source источник
comment
Это бы не сработало, потому что, в конце концов, что такое имя? Вы можете назвать ребенка как хотите, и поэтому в словаре может быть много имен. Некоторые люди могут быть даже названы в честь прилагательных.   -  person Kevin    schedule 03.08.2014
comment
Для получения дополнительной информации о том, что такое имя, см. falsehoods программисты верят в имена. И комментарии (например, как вы относитесь к Принцу, когда его имя было символом, которого даже не существовало в Юникоде?).   -  person abarnert    schedule 04.08.2014


Ответы (2)


Я не знаю, почему вы думаете, что вам нужен NLTK только для того, чтобы исключить словарные слова; простой словарь (который вы могли установить где-нибудь, например, /usr/share/dict/words, или вы можете скачать его из Интернета) — это все, что вам нужно:

with open('/usr/share/dict/words') as f:
    dictwords = {word.strip() for word in f}
with open(mypath) as f:
    names = [word for line in f for word in line.rstrip().split()
             if word.lower() not in dictwords]

Ваш список words может включать имена, но если это так, то он будет включать их с заглавной буквы, поэтому:

    dictwords = {word.strip() for word in f if word.islower()}

Или, если вы хотите внести в белый список имена собственные, а не в черный список словарных слов:

with open('/usr/share/dict/propernames') as f:
    namewords = {word.strip() for word in f}
with open(mypath) as f:
    names = [word for line in f for word in line.rstrip().split()
             if word.title() in namewords]

Но это действительно не сработает. Посмотрите на "Джима Уайта" из вашего примера. Его фамилия, очевидно, будет в любом словаре, а его имя будет во многих (как краткая версия «джимми», как обычная латинизация арабской буквы «джим» и т. д.). «Марк» также является распространенным словарным словом. И наоборот, «Воля» — очень распространенное имя, даже если вы хотите относиться к нему как к слову, а «Счастье» — необычное имя, но, по крайней мере, у нескольких людей оно есть.

Итак, чтобы хоть немного заставить эту работу работать, вы, вероятно, захотите объединить несколько эвристик. Во-первых, вместо того, чтобы слово всегда было именем или никогда не было именем, каждое слово имеет вероятность быть использованным в качестве имени в каком-либо соответствующем корпусе — Уайт может быть именем в 13,7% случаев, Марк — в 41,3%, Джим — в 99,1%. , Счастье 0,1% и т.д. Далее, если это не первое слово в предложении, а пишется с большой буквы, то гораздо вероятнее, что это имя (насколько больше? Не знаю, нужно тестировать и настраивать для вашего конкретного ввода), и если это строчные буквы, это вряд ли будет именем. Вы можете добавить больше контекста — например, у вас много полных имен, поэтому, если что-то является возможным именем и оно появляется рядом с чем-то, что является обычной фамилией, это, скорее всего, будет именем. Вы даже можете попытаться разобрать грамматику (это нормально, если вы откажетесь от некоторых предложений; они просто не получат никаких данных от правила грамматики), поэтому, если два соседних слова работают только как часть предложения, одно, если второе глагол, они, вероятно, не являются именем и фамилией, даже если то же самое второе слово может быть существительным (и именем) в других контекстах. И так далее.

person abarnert    schedule 03.08.2014
comment
Отличный подход, я не знал о файле слов в /usr/share/dict/. Я заметил, что он содержит такие слова, как Эбби и т. Д., Так что, возможно, простое занесение слов в черный список из словаря не будет полным решением, как описано выше. Мне нравится ваш эвристический подход, я отчитаюсь, когда попробую. - person Blakedallen; 04.08.2014
comment
@Blakedallen: В зависимости от вашей платформы (или загруженного вами стороннего диктофона) в вашем файле words все имена собственные могут быть написаны с заглавной буквы, а все имена нарицательные — в нижнем регистре, что означает, что if word.islower() позаботится об этой проблеме. Есть еще пределы того, насколько это полезно; большинство платформ используют словарь начала 20-го века (обычно Webster's 1934) из соображений авторского права, и, очевидно, он не будет охватывать многие новые слова, но вы можете загрузить более поздний или иным образом более подходящий корпус и извлечь слова для аналогичного эффекта. - person abarnert; 04.08.2014

Я нашел эту библиотеку весьма полезной для разбора имен: Python Name Parser

Он также может работать с именами в формате Фамилия, Имя.

person lakesh    schedule 03.08.2014