Русский
Русский
English
Статистика
Реклама

Sibur Challenge 2020 или как мы фичи придумывали

Всем привет! В этом году компания Sibur Digital вновь проводила крупный (по сравнению с другими российскими) чемпионат по анализу данных. Мы с другом в нём участвовали и хотели бы поделиться с читателями Хабра своим решением и опытом, полученным от участия. Конечно вряд ли мы америку откроем этой статьей, но какой-нибудь новичок в соревнованиях по АД точно сможет почерпнуть для себя что-то полезное.

Кто мы такие?

Мы студенты которые очень сильно увлеклись темой DS и ML. Впервые мы узнали об этой сфере на конференции AI Journey, проходившей в нашем вузе. С того момента прошли не один, и не два, и не три курса (от Омского Государственного Технического университета до Andrew NG) и теперь постоянно участвуем в хакатонах и соревнованиях(в некоторых даже заняли призовые места), параллельно ищем стажировку.

О задаче

Мы взялись за вторую задачу соревнования - "сопоставление названий".

Суть следующая : Сибур работает с огромным количеством новых компаний, и для оптимизации рабочего процесса им было бы полезно понимать, что они работают с уже ранее знакомым холдингом. К примеру "Сибур Нефтехим" и "СИБУР ИТ" из одного холдинга, и при работе с одной из этих компаний было бы полезно использовать накопленную ранее информацию о холдинге СИБУР.

Перефразируем задачу на язык DS. Даны два названия, по ним мы должны определить - принадлежат ли компании одному холдингу или нет.

name_1

name_2

is_duplicate

Japan Synthetic Rubber Co

Jsr Bst Elastomer

1

JSR Corporation

BST ELASTOMERS CO.

0

Примерно так выглядел датасет.

Предобработка данных

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

from unidecode import unidecodeimport redef preprocess(text: str):    text = unidecode(text)    text = text.lower()    text = re.sub(r'[\.,]+', '', text)    text = re.sub(r"\(.*\)", ' ', text)    text = re.sub(r"[^\w\s]", ' ', text)    text = re.sub(r'\b\w\b', ' ', text)    text = ' '.join(text.split())    return text

После взялись за удаление ненужных слов. Первыми в список мусора полетели названия стран в названиях, для этого взяли модуль pycountry(который любезно подсказали организаторы в бейзлайн решении) и немного дополнили этот список стран их сокращениями, аббревиатурами которые сами нашли в выборке.

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

Поиск фичей

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

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

Первый прорыв нам дал признак "сколько букв сначала совпадает в двух словах подряд". Обучив логистическую регрессию в начале соревнования только на одном этом признаке мы получили результат чуть более 0.3 и перепрыгнули большинство в начале соревнования. В дальнейшем мы использовали не просто число совпадающих букв, а число совпадающих букв делим на суммарное количество букв обоих названий.

Вторым полезным признаком оказался коэффициент Жаккара взятый по словам из двух названий. Т.е мы разделили число пересекающихся слов в названиях на количество уникальных слов в двух названиях.

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

Остальные признаки, которые не оказались столь удачными, приведены в списке ниже:

  • количество совпадающих первых гласных, согласных

  • количество совпадающих первых буквы сокращения (аббревиатуры)

  • стандартные метрики: левенштейн, яро винклер, фузи вузи

  • tfidf - при подсчёте жаккара (или косинусного расстояния с нграммами)

  • сортировать уникальные слова в имени и считать наши метрики

  • процент пересекающихся ngram

  • количество совпадающих первых букв каждого слова (брать максимум)

  • количество букв первого, количество букв второго

  • количество слов первого, количество второго

Модель и блендинг решений

Как упоминалось выше, мы не собирались строить свое решение целиком и полностью на сильной модели, поэтому в качестве классификатора использовали XGBoost, который показал себя получше других простых моделей. И мы получили результат ~ 0.59 на лидерборде.

Далее мы понимали, что было бы неплохо обменяться с кем-то идеями и объединить решения. Мы познакомились с двумя другими участниками(Алехандро, Дмитрий, привет!), и заблендили наши решения, получив скор 0.69 на лидерборде. Так получилось, что все три наших решения имели разные подходы к задаче, поэтому их объединение и улучшило результат.

Выводы

В любой истории главное - выводы, поэтому, уверен, это будет самая интересная часть.

Начать стоит с того, что помогло нам достичь результата. В первую очередь это то, что мы не пошли простым путем fit_predict, а постарались посмотреть на задачу с разных сторон. Перепробовали огромное количество различных методов(начиная от метрики Левенштейна и подсчитывания косинусного расстояния и заканчивая сиамскими нейросетями). Провели анализ ошибок модели, который помог выстроить правильную предобработку и обновить словарь стоп-слов.

Что можно было доработать?

Можно было учитывать семантику слов или выдавать словам веса: если слово в двух названиях совпало и оно полезно (относится к названию компании) - имеет вес, мы автоматически считаем что оно настолько же вредно в "разнице" слов; использование как можно больше внешних данных с названием компаний и т. д. Также не забывать анализировать наблюдения, на которых ошибается модель (False Positive, False Negative), и на основе этого конструировать новые признаки.

P.S.

Весь код лежит здесь

Если хотите связаться с нами : matnik2001@gmail.com , domonion@list.ru

Источник: habr.com
К списку статей
Опубликовано: 21.12.2020 14:15:23
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Python

Data mining

Хакатоны

Машинное обучение

Natural language processing

Анализ данных

Хакатон

Nlp

Обработка естественного языка

Features

Feature selection

Фичи

Feature extraction

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru