Задача 2. Сопоставление названий
Sibur_Challenge_2020_Task_2.pdf
Видео: https://www.youtube.com/watch?t=46m16s&v=I35G535OeS8
docker build -t sibur .
docker run -it --rm -v {dirname fullpath}/output:/output sibur
result file: {dirname fullpath}/output/subm_final.csv
Альтернативный вариант - запуск тетрадки: Sibur_2020_Task2.ipynb
Научимся собирать названия в кластеры на основании информации о позитивных парах из трейна (name_1, name_2, is_duplicate=1).
Для этого токенизируем названия name -> tokens и просто как мешок слов представляем. При этом выкидываем legal entities и geo.
Итого получим граф:
- вершины - токенизированные названия
- ребра - связки
(name_1, name_2, is_duplicate=1)
Кластера - это компоненты связности.
Например:
положительные связки:
- ("Bridgestone (Huizhou)Synthetic Rubber Co. Ltd.", "Bridgestone India Pvt., Ltd.", 1)
- ("Bridgestone India Pvt., Ltd.", "Bridgestone India Automotive", 1)
токенизация:
"Bridgestone (Huizhou)Synthetic Rubber Co. Ltd." -> ("bridgestone", "synthetic", "rubber")
"Bridgestone India Pvt., Ltd." -> ("bridgestone")
"Bridgestone India Automotive" -> ("bridgestone", "automotive")
на выходе получим один кластер: {
("bridgestone"), ("bridgestone", "automotive"), ("bridgestone", "synthetic", "rubber")
}
Для фильтрации гео-токенов используем:
- spacy модель en_core_web_lg;
- пакеты geonamescache, pycountry;
Для фильтрации legal entities используем wiki-страницу:
Разбиваем трейн на три группы A, B, C. При этом разбиение строим так, чтобы каждый кластер из шага 1 целиком попадал в одну из трех групп (GroupKFold). Это важно.
Все фичи можно разделить на две группы:
- для name_1, name_2 разные варианты пересечения по токенам с учетом транслита и диакритики, наибольшие общие подпоследовательности по всем(первым N токенам), ...
- когда считаем фичи для группы А частотные словари насчитываем для B и C (чтобы не было лика - это важно)
Как строим частотные словари - для каждого токена считаем:
- сколько раз токен встречался в позитивных/негативных парах,
- сколько раз токен находился в симметрической разности токенов (name_1, name_2) в позитивных/негативных парах.
По сути получаем некоторое понимание того "насколько этот токен важный - в какой доле кейсов его можно или нельзя выкидывать".
В итоге для пары (name_1, name_2) -> ([token_1_1, tokens_1_2, token_1_3], [token_2_1, tokens_2_2, token_2_3]) можем насчитать статистики на основании частотных словарей.
Например, смотрим пересекающиеся токены - и считаем по ним min, max, mean значения из частотных словарей. То же самое считаем по симметрической разности.
Для нашего примера с кластером:
("bridgestone"), ("bridgestone", "automotive"), ("bridgestone", "synthetic", "rubber")
у слова "bridgestone" будет большой вес
- его из названий выкидывать нельзя, т.к. оно есть в каждом названии из кластера;
у слова "rubber" будет маленький вес
- его выкидывать из названий можно - т.к. не во всех названиях кластера это слово присутствует;
Когда будем насчитывать факторы для пар из другого кластера
например для пары ("Yokohama Rubber Co., Ltd. The", "Yokohama Tire Corporation"),
то для слова "rubber" поймем, что за него можно не очень большой штраф давать за то,
что в одном названии это слово есть, а в другом его нет.
Когда строим трейн мы частотные словари считаем три раза:
- для группы А на основании групп B,C
- для группы B на основании групп A,C
- для группы C на основании групп A,B
Для того чтобы подсчитать фичи "Группы 2" на тесте используем все три частотных словаря.
Для каждой фичи получим три значения - в качестве тестовой фичи будем использовать медиану. Так распределение отдельных фичей в тесте у нас НЕ поедет (будет такое же, как в трейне).
В качестве модели используем catboost (10 моделей, которые обучаются с разным сидом)
Параметры:
params = {
"iterations": 100,
"learning_rate": 0.03,
"depth": 6,
"l2_leaf_reg": 1.0,
"rsm": 0.9,
"border_count": 10,
"max_ctr_complexity": 2,
"random_strength": 1.0,
"bagging_temperature": 100.0,
"grow_policy": "SymmetricTree",
"min_data_in_leaf": 5,
"langevin": True,
"diffusion_temperature": 100000,
"auto_class_weights": 'SqrtBalanced'
}
Для получения итогового скора выбираем минимальный из прогнозов от всех моделей. Выбор усредненного прогноза показывал схожие, но чуть менее хорошие результаты на паблике.
На выход в качестве позитивных прогнозов отдаем топ-1600 по скору. Число 1600 выбрано на основании соотношения размера трейн/тест выборок и доли позитивных примеров в трейне.