Skip to content

text parser for organisation name recognition and definition of their similarity

Notifications You must be signed in to change notification settings

dikar8/org_name_similarity

Repository files navigation

org_name_similarity

Структура проекта и описание задачи

Модуль org_name_similarity - это текстовый парсер, распознающий названия компаний в англоязычном тексте и определяющий их схожесть. Программа принимает на вход текст и возвращает JSON-файл cо словарем, в котором ключи - это названия компаний, а их значения - это списки, состоящие из списков индексов (индекс первой буквы, индекс последней буквы).

Форматеры и линтеры

Для форматирования были выбраны isort и black. К flake8 добавлены следующие плагины:

flake8-builtins==2.0.1

flake8-warnings==0.3.0

flake8-simplify==0.19.3

flake8-return==1.2.0

flake8-comprehensions==3.10.1

С результатами первичного запуска линтеров можно ознакомиться в linting.md.

Инструкция:

Способ №1. Установка через pip

  1. Создайте виртуальную среду, активируйте её и установите модуль через pip
python3 -m venv venv

source ./venv/bin/activate

python3 -m pip install -i https://test.pypi.org/simple/ org-name-similarity==0.0.1

Описание проекта - https://test.pypi.org/project/org-name-similarity/0.0.1/

Способ №2. Установка через git

  1. Создайте виртуальную среду, активируйте её и скачайте проект
python3 -m venv venv

source ./venv/bin/activate

git clone https://github.com/dpkaranov/org_name_similarity.git
  1. Перейдите в директорию проекта и установите зависимости
cd ./org_name_similarity

для пользователей

pip3 install -r requirements.txt

для разработчиков

pip3 install -r dev_requirements.txt
  1. Скачайте модель и распакуйте её в папке ./org_name_similarity/models

  2. Положите текстовый файл в папку ./org_name_similarity/texts

  3. Запустите скрипт

python name_sim.py --path <путь/до/файла>

или

python3 name_sim.py --path <путь/до/файла>
  1. JSON-файл с результатом парсинга появится в папке out

Возможен и другой вариант использования:

Если есть необходимость определить схожесть каких-либо названий через терминал, можно использовать следующую команду:

python3 name_sim.py --check <первое название> <второе название>

В этом случае программа возвратит булево значение True / False

Кроме описанных примеров, возможно импортирование класса NamSim в Ваш скрипт.

Убедитесь, что папка с модулем находится в директории Вашего проекта. Импортируйте класс.

from org_name_similarity.name_sim import NamSim

namsim = NamSim()

print(namsim.check_similarity('Saudi Aramco', 'Rosneft'))

Структура проекта:

├── __init__.py
├── name_sim.py
├── data
      └── data.csv
├── images
├── metrics
      └── comp_with_128.csv
      └── first_metrics.csv
      └── hard_comp_with_128.csv
├── models
├── notebooks
      └── 1_created_multilang_dataset.ipynb
      └── 2_upload_transformers_for_exps.ipynb
      └── 3_train_transformer.ipynb
      └── 4_compare_models.ipynb
      └── 5_prepare_new_dataset.ipynb
      └── 6_train_new_model.ipynb
      └── 7_train_model_128.ipynb
├── texts
├── out

Метод решения и его обоснование

Для решения задачи определения схожести названий проведено дообучение (fine-tuning) модели-трансформер с помощью фреймворка sentence-transformes. Трансформеры буквально "захватили" NLP, демонстрируя высокие показатели по сравнению с RNN, LSTM и др. технологиями машинного обучения. Их привлекательность для обработки естественного языка заключается в применении механизма внутреннего внимания, устанавливающего свзязи между отдельными словами.

alt text

В качестве альтернативы рассматривались tensorflow, torch, spacy, но в итоге выбор был сделан в пользу sentence-transformes. Преимущества ST: высокопроизводительные модели, автоматизированная настройка гиперпараметров и простота использования. Технология достаточно проста: списки строк (сначала первые названия компаний, потом вторые) отправляются в модель, которая возвращает эмбеддинги. Полученные эмбеддинги сравниваются с помощью измерения косинусного расстояния между ними. Если косинусное расстояние близко к 1, то названия организаций схожи, если к 0, то нет. Помимо этого для поиска имен в тексте (задача NER) используется Spacy.

Набор данных (датасет)

Для обучения модели использовался датасет, состоящий из 497814 строк и 4 столбцов - номер пары (pair_id), первое название (name_1), второе название (name_2) и отметка схожести (is_duplicated). При этом 99 % пары были отмечены как непохожие (0), и менее 1 % - похожие (1). К тому же, названия компаний включали в себя разный шум (символы, лишние буквы из других алфавитов и т.д.). Соответственно, необходимо было тщательно подготовить датасет перед обучением.

Этапы решения задачи

  1. Подготовка данных к обучению модели;

  2. Обучение моделей и сравнение их показателей;

  3. Тестирование модели и выбор лучшей;

  4. Создание скрипта;

Эксперименты

Эксперимент №1 Обучение модели на мультиязычном датасете

Гипотеза: перевод всех схожих пар названий организаций и такого же количества непохожих пар на разные языки позволит увеличить датасет в несколько раз, а классы будут представлены в нем в одинаковых пропорциях.

alt text

Перевод названий организаций осуществлен с помощью библиотеки transliterate. В качестве модели выбрана MiniLM-L12-v2.

Реализация этого эксперимента представлена в папке notebooks, в файлах 1 - 4.

В 4 ноутбуке проведено сравнение обученной модели с необученными.

Сравнение по метрикам обученной модели MiniLM-L12-v2 с её необученным аналогом и остальными трансформерами

alt text

alt text

alt text

alt text

alt text

alt text

Таблица №1 Сводная таблица

alt text

Вывод: несмотря на перевод слов на разные языки и мультиязычную базу самой модели, модель переобучилась. Это не столько очевидно по результатам тестов на тестовом наборе данных, выделенном из общего датасета, сколько по "ручной проверке". Так, например, модель не смогла отличить Газпром от Роснефти, а с этим примером может справиться даже расстояние Левенштейна. Тем не менее, этот эксперимент позволил отбросить одну из гипотез, а сравнение разных моделей показало, что гораздо больше смысла в обучении distiluse-base-multilingual-cased-v2 (на базе BERT), которая даже без обучения показала очень высокие показатели.

Эксперимент №2 Создание нового датасета и обучение distiluse-base-multilingual-cased-v2

Гипотеза: правильная подготовка нового датасета, в котором классы были бы представлены пропорционально, и fine-tuning на нем distiluse-base-multilingual-cased-v2 позволят избежать переобучение и повысят результативность модели.

В этом эксперименте использовался иной принцип подготовки данных:

  1. Найдены все уникальные значения (порядка 17 тыс. на оба столбца);

  2. Удалены лишние символы (т.е. все буквы не относящиеся к латинскому алфавиту), пустые и короткие строки;

  3. Все длинные названия разделены по пробелу, вторые слова перемешаны и добавленны к первым. Эти слова образовали список name_1. Для формирования name_2 к каждому слову из name_1 в случайном порядке прибавлены часто встречающиеся слова, заканчивающие названия англоязычных организаций.

Часто встречающиеся слова

alt text

  1. Таким образом, получились списки name1 и name2, которые вместе представляют собой массив пар схожих названий (label - 1.0). Для формирования массива непохожих названий name1 сдвинут на один вправо, а name2 повернут. Также удалено последнее значение обоих списков.

На тестовых данных distiluse-base-multilingual-cased-v2 показала невероятные 1.0 по всем метрикам. Проверка модели на сложных примерах может показать её реальное качество. Почему сложные? Потому что часть примеров модель никогда не видела (например, на кириллице или российских наименований с сокращенным указанием формы собственности в начале строки "ООО", "ОАО" и т.д. ). Примеров немного, но даже на них модель distiluse-base-multilingual-cased-v2 продемонстрировала хорошие результаты, отличив Bridge от Бриджит Бардо, Зенит от Спартака и т.д. Модель не справилась с Роскачеством и Россетями, что показаывает о необходимости подготовки русскоязычной модели отдельно.

Проверка модели на сложных примерах

alt text

Подробнее с ходом эксперимента можно ознакомиться в блокнотах №6 и №7.

Вывод: модель distiluse-base-multilingual-cased-v2 продемонстрировала практически невероятный результат. Если бы она не показывала хороший результат на новых данных можно было бы подумать, что она переобучилась. Возможно, эту модель изначально тренировали для установления схожести между словами.

Эксперимент №3 Уменьшение размерности output-слоя при сохранении точности

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

В блокноте №7 представлен эксперимент по созданию модели с уменьшенной размерностью последнего слоя (с 512 до 128). Может возникнуть вопрос почему сразу, еще до обучения модели не внести коррективы? В таком случае мы могли потерять важные фичи, кроме того, этот эксперимент предполагает изучение возможности снижения размера исходящего эмбеддинга для уже обученных моделей.

alt text

Вывод: как видно из представленных данных, модель не отстает по точности от своего аналога. По всей видимости можно уменьшить размер выходящего из модели эмбеддинга без потери качества, но веса для последнего слоя сформированы на тестовом датасете, что не дает возможности корректно оценить работу такой модели.

Оценка производительности

Модели показали разную производительность. Как видно из представленных данных, модель с выходящим слоем 128 (128_size_bert_v2) обрабатывает запросы в 3 раза быстрее.

Оборудование:

RAM - не менее 4 Gb

GPU - не менее 1 Gb

Модель 128_size_bert_v2

Скорость инференса на GPU: 3334 слов в секунду. Скорость инференса на CPU: 128 слов в секунду.

Модель 1.0_db-multilingual-cased-v2

Скорость инференса на GPU: 1667 слов в секунду. Скорость инференса на CPU: 128 слов в секунду.

About

text parser for organisation name recognition and definition of their similarity

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages