- PVSM.RU - https://www.pvsm.ru -

1-го апреля завершился финал SNA Hackathon 2019 [1], участники которого соревновались в сортировке ленты социальной сети с использованием современных технологий машинного обучения, компьютерного зрения, обработки тестов и рекомендательных систем. Жесткий онлайн отбор и двое суток напряженной работы над 160 гигабайтами данных [2] не прошли даром :). Рассказываем о том, что помогло участникам прийти к успеху и о других интересных наблюдениях.
На конкурс были представлены данные механизмов подготовки ленты пользователей социальной сети OK [3], состоящие из трех частей:
Суммарный объем данных превышает 160 гигабайт, из них более 3-х приходится на логи, еще 3 на тексты и остальное на картинки. Большой объем данных не испугал участников: по статистике ML Bootcamp [4] в конкурсе приняло участие почти 200 человек, отправивших более 3000 сабмитов, а самые активные сумели пробить планку в 100 отправленных решений. Возможно, их мотивировал к этому и призовой фонд в 700 000 рублей + 3 видеокарты GTX 2080 Ti.

Участникам конкурса необходимо было решить задачу сортировки ленты: для каждого отдельного пользователя отсортировать показанные объекты таким образом, что те, которые получили отметку "Класс!", находились ближе к голове списка.
В качестве метрики оценки качества использовалась ROC-AUC [5]. При этом метрика считалась не по всем данным в целом, а отдельно для каждого пользователя и затем усреднялась. Этот вариант расчета примечателен тем, что алгоритмы, научившиеся выделять ставящих много классов пользователей, не получают преимущества. С другой стороны, такого варианта работы нет в стандартных пакетах Python, что вскрыло некоторые интересные моменты, о чем ниже.
Традиционно SNA Hackathon это не только алгоритмы, но и технологии — объем отгруженных данных превышает 160 гигабайт, что ставит участников перед интересными техническими задачами.

В академических исследования и на Kaggle доминирующим форматом данных является CSV [6], а также другие форматы с "открытым текстом". Однако в индустрии ситуация несколько иная – существенно большей компактности и скорости обработки можно добится используя "бинарные" форматы хранения.
В частности, в экосистеме построенной на базе Apache Spark [7], наибольшей популярностью пользуется Apache Parquet [8] — колоночный формат хранения данных с поддержкой многих важных для эксплуатации возможностей:
Но несмотря на наличие очевидных преимуществ, предоставление данных на конкурс в формате Apache Parquet встретило жесткую критику со стороны некоторых участников. Помимо консерватизма и нежелания тратить время на освоение чего-то нового было и несколько действительно неприятных моментов.
Во-первых поддержка формата в библиотеке Apache Arrow [9], основного средства для работы с Parquet из Python, пока далека от совершенства. Все структурные поля при подготовке данных пришлось развернуть до плоских, и все равно при чтении текстов многие участники столкнулись с багом и вынуждены были устанавливать старую версию библиотеки 0.11.1 вместо актуальной на тот момент 0.12. Во-вторых в Parquet-файл не заглянешь с помощью простых консольных утилит: cat, less и т.д. Однако, этот недостаток относительно легко компенсировать используя пакет parquet-tools [10].
Тем не менее те, кто изначально пытался конвертировать все данные в CSV, чтобы затем работать в привычной среде, в конце концов отказались от этой идеи – все-таки Parquet работает ощутимо быстрее.

На конференции SmartData в Санкт-Петербурге «широко известный в узких кругах» Алексей Натёкин сравнивал [11] производительность нескольких популярных инструментов для бустинга при работе на CPU/GPU и пришел к выводу что ощутимого выигрыша GPU не дает. Но уже тогда этот вывод привел к активной полемике, в первую очередь с разработчиками [12] отечественного инструмента CatBoost [13].
За прошедшие два года прогресс в развитии GPU и адаптации алгоритмов не стоял на месте и финал SNA Hackathon можно считать триумфом пары CatBoost+GPU — все победители использовали именно её и вытягивали метрику в первую очередь за счет возможности вырастить больше деревьев за единицу времени.
Свой вклад в высокий результат решений на базе CatBoost внес и интегрированный вариант [14] реализации mean target encoding [15], но количество и глубина деревьев давали более существенный прирост.
В похожем направлении движутся и другие инструменты бустинга, добавляя и совершенствуя поддержку GPU. Так что, grow more trees!

Инструмент Apache Spark [7] прочно занимает лидирующие позиции в индустриальном Data Science, в том числе и благодаря наличию API для Python. Тем не менее, использование Python сопряжено с дополнительными накладными расходами на интеграцию между разными средами выполнения и работу интерпретатора.
Само по себе это не является проблемой, если пользователь отдает себе отчет в том, к какому объему дополнительных расходов приводит то или иное действие. Однако, оказалось, что очень многие не осознают масштабов проблемы — несмотря на то, что участники не использовали Apache Spark, дискуссии на тему Python vs. Scala возникали в чате хакатона регулярно, что привело к появлению соответствующего поста с разбором [16].
Если кратко, то замедление от использования Spark через Python по сравнению с использованием Spark через Scala/Java можно разбить на следующие уровни:
Отчасти негативный эффект можно компенсировать используя PyPy [17] (JIT для Python) и векторизированные UDF [18], однако и в этих случаях разница производительности кратная, а сложность реализации и развертывания идет дополнительным "бонусом".
Но самое интересное на Data Science-хакатонах это, конечно, не технологии, а новые модные и старые проверенные алгоритмы. В этом году на SNA Hackathon тотально доминировал CatBoost, но было и несколько альтернативных подходов. О них и поговорим :).

Одна из первых публикаций [19] решений по итогам отборочного тура была посвещана отнють не деревьям, а дифференцируемым графам (так же именуемым искуственными нейронными сетями). Автор является сотрудником ОК, поэтому может позволить себе не гнаться за призами, а получать удовольствие строя перспективное решение на базе цельного математического фундамента.
Основная идея предложенного решения заключалась в том, чтобы построить единый вычислительный дифференцируемый граф, переводящий имеющиеся признаки в прогноз, учитывающий различные аспекты входных данных:
Эта модель очень хорошо показала себя на онлайн-отборе в решении задачи рекомендации текстового контента, поэтому сразу несколько команд попытались воспроизвести её на финале, однако, к успеху не пришли. Отчасти это было связано с тем, что для этого нужны время и опыт, а отчасти от того, что количество признаков в финале было значительно больше и методы на базе деревьев получили за счет них существенное преимущество.

Конечно при организации конкурса мы знали о том, что в логах есть достаточно сильный сигнал, ведь собранные там признаки отражают существенную часть проделанной в ОК работы по ранжированию ленты. Тем не менее до самого конца надеялись, что у участников получится справится с "проклятием третьего знака" — ситуации когда огромные человеческие и машинные ресурсы вкладываемые в разработку модели извлечения признаков из контента (текстов и фото) выливаются в крайне скромные приросты качества по сравнению с уже подготовленными, преимущественно коллаборативными, признаками.
Зная об этой проблеме мы изначально разбили задачу на три трека в отборочном туре и сформировали объединенный набор данных только на финале, но в формате хакатона с фиксированной метрикой команды, инвестировавшие в развитие контентных моделей, оказались в заведомо проигрышной ситуации в сравнении с командами, развивашими коллаборативную часть.
Компенсировать эту несправедливость помог приз жюри...

Который практически единогласно был присужден за работу по воспроизведению и апробации алгоритма Deep Cluster [22] от facebook. Простой и не требующий изначальной разметки метод построения кластеров и эмбедингов картинок подкупал новизной идеи и многообещающими результатами.
Суть метода предельно проста:
С минимумом усилий удалось получить качественную кластеризацию картинок ОК, хорошие эмбединги и прирост метрики в третьем знаке.

В любых данных можно найти "лазейки", позволяющие улучшить прогноз. Само по себе это не так плохо, гораздо хуже если "лазейки" находятся сами и долгое время проявляются только в виде непонятных расхождений между результатами валидации на исторических данных и А/Б тестами.
Одна из самых распространенных "лазеек" такого рода — использование информации из будущего. Подобная информация часто является очень сильным сигналом и алгоритм машинного обучения, если ему это позволить, начнет её с уверенностью использовать. Когда делаешь модель для своего продукта, то всячески стараешься избежать просачивания информации из будущего, но на хакатоне это хороший шанс поднять метрику, чем и воспользовались участники.
Самая очевидная лазейка заключалась в наличии в данных полей со счетчиками реакций на объекте на момент показа — numLikes и numDislikes. Сравнив два ближайших по времени события, связанные с одним и тем же объектом, можно было с высокой точностью установить какова была реакция на объект в первом из них. Подобных счетчиков в данных было несколько, и их использование давало заметное преимущество. Естественно, в реальной эксплуатации подобная информация будет недоступна.
В жизни на подобную проблему можно наткнутся и не осознавая этого, как правило с негативными результатами. Например, посчитав статистику по количеству отметок "Класс!" для объекта по всем данным и взяв как отдельный признак. Или, как сделали в одной из участвовавших команд, добавив в модель идентификатор объекта как категориальный признак. На тренировочном множестве модель с таким признаком работает хорошо, но на тестовое множество обобщиться не может.

Все материалы конкурса, включая данные и презентации решений участников доступны в Облаке Mail.ru [2]. Данные доступны для использования исследовательских проектах без ограничений, кроме наличия ссылки. Для истории, оставим здесь финальную таблицу с метриками команд-финалистов:
SNA Hackathon 2019, как и предыдущие мероприятия серии, удался во всех смыслах. Нам удалось собрать под одной крышей классных специалистов в разных областях и плодотворно провести время, за что огромное спасибо и самим участникам, и всем тем кто помогал с организацией.
Можно было что-то сделать еще лучше? Конечно да! Каждый проведенный конкурс обогащает нас новым опытом, который мы учитываем при подготовке следующего и не собираемся останавливаться на достигнутом. Так что, до скорых встреч на мероприятиях серии SNA Hackathon!
Автор: dmitrybugaychenko
Источник [26]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/data-mining/314849
Ссылки в тексте:
[1] SNA Hackathon 2019: https://snahackathon.org
[2] 160 гигабайтами данных: https://cloud.mail.ru/public/A9cF/bVSWJCJgt
[3] OK: https://ok.ru
[4] ML Bootcamp: https://mlbootcamp.ru/main/
[5] ROC-AUC: https://ru.wikipedia.org/wiki/ROC-%D0%BA%D1%80%D0%B8%D0%B2%D0%B0%D1%8F
[6] CSV: https://ru.wikipedia.org/wiki/CSV
[7] Apache Spark: http://spark.apache.org
[8] Apache Parquet: https://parquet.apache.org
[9] Apache Arrow: https://arrow.apache.org
[10] parquet-tools: https://github.com/apache/parquet-mr/tree/master/parquet-tools
[11] сравнивал: https://www.youtube.com/watch?v=u8az6sLEGpA&feature=youtu.be
[12] разработчиками: https://www.youtube.com/watch?v=UYDwhuyWYSo&feature=youtu.be
[13] CatBoost: https://github.com/catboost/catboost
[14] вариант: https://catboost.ai/docs/concepts/algorithm-main-stages_cat-to-numberic.html#algorithm-main-stages_cat-to-numberic
[15] mean target encoding: https://medium.com/datadriveninvestor/improve-your-classification-models-using-mean-target-encoding-a3d573df31e8
[16] поста с разбором: https://habr.com/ru/company/odnoklassniki/blog/443324/
[17] PyPy: https://pypy.org
[18] векторизированные UDF: https://spark.apache.org/docs/latest/sql-pyspark-pandas-with-arrow.html
[19] публикаций: https://habr.com/ru/company/odnoklassniki/blog/445348
[20] MLP: https://en.wikipedia.org/wiki/Multilayer_perceptron
[21] query-key-value attention: https://arxiv.org/pdf/1706.03762.pdf
[22] Deep Cluster: https://github.com/facebookresearch/deepcluster
[23] здесь: https://habr.com/ru/post/447376/
[24] здесь: https://github.com/BraginIvan/sna2019open
[25] здесь: https://github.com/seshaln/sna2019/blob/master/collab50-final.ipynb
[26] Источник: https://habr.com/ru/post/448140/?utm_source=habrahabr&utm_medium=rss&utm_campaign=448140
Нажмите здесь для печати.