Как да анализирате имена от необработен текст

Чудех се дали някой знае за добри библиотеки или методи за анализиране на имена от необработен текст.

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

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.

Първата ми мисъл е да заредя някакъв вид маркер за част от речта (като Pythons NLTK), да маркирам всички думи. След това изтрийте само съществителните, след това сравнете съществителните с база данни с известни думи (т.е. буквален речник), ако не са в речника, приемете, че са име.

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

Всякакви мисли, предложения или библиотеки, към които можете да ме насочите, биха били много полезни.

Благодаря!


person Blakedallen    schedule 03.08.2014    source източник
comment
Това наистина няма да работи, защото в крайна сметка какво е име? Можете да наименувате дете както искате и като такива много имена може да има в речника. Някои хора може дори да бъдат кръстени на прилагателни.   -  person Kevin    schedule 03.08.2014
comment
За повече информация относно това какво е име, вижте неистини програмистите вярват за имената. И коментарите (напр. как се справяте с Принс, когато името му беше символ, който дори не съществуваше в Unicode?).   -  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/. Забелязвам, че съдържа думи като Abby и т.н., така че може би просто поставянето на думи в черен списък от dict няма да бъде пълно решение, както е описано по-горе. Харесва ми вашия евристичен подход, ще докладвам, когато го пробвам. - person Blakedallen; 04.08.2014
comment
@Blakedallen: В зависимост от вашата платформа (или dict на трета страна, който сте изтеглили), вашият words файл може да има всички собствени съществителни с главни букви и всички общи съществителни с малки букви, което означава, че if word.islower() ще се погрижи за този проблем. Все още има ограничения за това колко полезно е; повечето платформи използват речник от началото на 20-ти век (обикновено Webster's 1934) поради съображения за авторско право и очевидно това няма да покрие много по-нови думи, но можете да изтеглите по-късен или по друг начин по-подходящ корпус и да извлечете думите за подобен ефект. - person abarnert; 04.08.2014

Намерих тази библиотека за доста полезна за анализиране на имена: Python Nameparser

Може да работи и с имена, които са форматирани Фамилия, Име.

person lakesh    schedule 03.08.2014