Я хотел бы добавить несколько примеров к превосходному принятому ответу.Протестировано в Python 2.7.
Синтаксический анализ
Давайте использовать это нечетное имя в качестве примера.
name = "THE | big,- Pharma: LLC" # example of a company name
Мы можем начать с удаления терминов правового контроля (здесь LLC).Для этого есть потрясающая cleanco библиотека Python, которая делает именно это:
from cleanco import cleanco
name = cleanco(name).clean_name() # 'THE | big,- Pharma'
Удаляет все знаки пунктуации:
name = name.translate(None, string.punctuation) # 'THE big Pharma'
(для строк Unicode,вместо этого работает следующий код ( source , regex ):
import regex
name = regex.sub(ur"[[:punct:]]+", "", name) # u'THE big Pharma'
Разделить имя на токены, используя NLTK :
import nltk
tokens = nltk.word_tokenize(name) # ['THE', 'big', 'Pharma']
Строчные все токены:
tokens = [t.lower() for t in tokens] # ['the', 'big', 'pharma']
Удалите стоп-слова. Обратите внимание, что это может привести к проблемам с такими компаниями, как On Mars
будет некорректно соответствовать Mars
, потому что On
- стоп-слово.
from nltk.corpus import stopwords
tokens = [t for t in tokens if t not in stopwords.words('english')] # ['big', 'pharma']
Я не рассматриваю здесь акцентированные и специальные символы (улучшения приветствуются).
Соответствует
Теперь, когда мы сопоставили все названия компаний с токенами,мы хотим найти совпадающие пары. Возможно, сходство Жакара (или Яро-Винклера) лучше, чем Левенштейна, для этой задачи, но все еще недостаточно хорошо. Причина в том, что он не учитывает важность слов в названии.(как это делает TF-IDF). Такие распространенные слова, как «Компания«влияют на оценку так же, как слова, которые могут однозначно идентифицировать название компании.
Чтобы улучшить это, вы можете использовать трюк подобия имени, предложенный в этой потрясающей серии сообщений (не мое).Вот пример кода из него:
# token2frequency is just a word counter of all words in all names
# in the dataset
def sequence_uniqueness(seq, token2frequency):
return sum(1/token2frequency(t)**0.5 for t in seq)
def name_similarity(a, b, token2frequency):
a_tokens = set(a.split())
b_tokens = set(b.split())
a_uniq = sequence_uniqueness(a_tokens)
b_uniq = sequence_uniqueness(b_tokens)
return sequence_uniqueness(a.intersection(b))/(a_uniq * b_uniq) ** 0.5
Используя это, вы можете сопоставить имена с сходством, превышающим определенный порог.В качестве более сложного подхода вы также можете взять несколько баллов (скажем, этот балл уникальности, Джакарда и Яро-Винклера) и обучить двоичную модель классификации, используя некоторые помеченные данные, которые при заданном количестве баллов будут выводить, если пара кандидатовэто совпадение или нет.Подробнее об этом можно узнать из того же сообщения в блоге.