Как Мы Решили Проблему Продолжения Плейлистов На Recsys Challenge И Заняли 3 Место

В 2018 году наша команда традиционно приняла участие в Вызов RecSys .

Это ежегодный конкурс рекомендательных систем, проводимый в рамках конференции RecSys. Оно не такое масштабное, как соревнования Kaggle, но считается одним из самых престижных соревнований по рекомендательным системам.

На этот раз задача была музыкальная — нужно было построить систему автоматического продолжения плейлистов.

В этом посте я подробно рассказываю о нашем решении.

Приглашаю вас под кат.

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

О конкурсе В этом году данные для конкурса предоставил Спотифай — сервис потоковой передачи музыки (который, к сожалению, официально не доступен в РФ).

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

Участникам конкурса предстояло создать алгоритм автоматического продолжения плейлиста.

В качестве обучающих данных был представлен набор данных Million Playlist, название которого говорит само за себя.

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

Подробнее о конкурсе можно прочитать Здесь .



Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

Цель конкурса Задача конкурса классическая для рекомендательных систем: сформировать топ-К рекомендаций для пользователя, зная историю его действий, но вместо обычных юзер-итемов здесь появляется плейлист-трек.

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

Для K = (5, 10, 25, 100) были семена с первыми K треками и K треками, выбранными случайным образом.

Еще были сиды с первым треком и только названием плейлиста.

Треки, которые не были включены в начальное число (несогласные), необходимо было спрогнозировать.

Для каждого плейлиста требовалось ровно 500 предсказаний.

Метрики Одной из особенностей конкурса было то, что метрика была не одна, как принято в большинстве соревнований, а несколько.

Ниже я расскажу о каждом из них.



R-Precision

Эта метрика показывает, какую долю релевантных треков мы угадали.



Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место



НДЦГ

Это классическая метрика качества ранжирования, о ней можно почитать, например, Здесь

Клики

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

и получите следующую порцию рекомендаций.

Количество таких обновлений до первого выбора — это показатель «Клики».

Проще говоря, позиция первой соответствующей рекомендации (в данном случае разделенная на 10).

Далее командам присваивается ранг по каждой из метрик.

Затем ранги суммируются с использованием схемы избирательной стратегии подсчета Борда.

Если

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

Если количество участников, то команда с 1 рангом получает

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

очков, команда, занявшая 2 место, получает

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

очки и так далее.



Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

Решение

Схема проверки

Чтобы воспроизвести разделение поезд/тест, мы разделили исходный набор данных на три части: первая часть содержала 980 тысяч плейлистов, вторая и третья части содержали по 10 тысяч соответственно.

Затем каждый плейлист из второй и третьей частей был разделен на затравочную и затравочную части, а размеры затравочных частей выбирались так же, как и в предоставленном тестовом наборе, а остальные треки уходили в задержку.



Отбор кандидатов

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

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



Отбор кандидатов с использованием матричной факторизации

Матричная факторизация — один из наиболее распространенных подходов к построению рекомендательных систем.

Основная идея этого метода — представить разреженную матрицу взаимодействий между пользователями и элементами как произведение двух матриц (U и I) меньшей размерности.

Тогда мы сможем получить рекомендации для пользователя, умножив вектор из матрицы U на матрицу I. Для факторизации матрицы мы использовали библиотеку ЛайтФМ с Потеря WARP (парный взвешенный приблизительный ранг) .

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



Потеря деформации

Эта функция потерь лучше других справляется с задачами ранжирования.

Он работает с тройками (пользователь, положительный_элемент, отрицательный_элемент) и имеет одну очень важную особенность – выбор отрицательных примеров происходит не случайно, а таким образом, что выбранные отрицательные примеры «ломают» текущий рейтинг модели, т.е.

были выше, чем положительный пример.

Таким образом, процедура обучения модели с использованием потерь WARP будет примерно следующей:

  1. Для пары

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

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

    Давайте посчитаем прогноз модели попарно

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

    И

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

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

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

    Если нам пришлось долго искать подходящий отрицательный пример, то делаем небольшой шаг — модель уже достаточно хорошо обучена.

Более формальное описание потерь WARP можно прочитать в оригинальной статье или в этом посте .



ЛайтФМ

Первая версия модели использовала только совместную информацию: наличие track_id в плейлисте playlist_id, представленном в виде двоичной разреженной матрицы.

Строка матрицы соответствовала плейлисту, столбец — треку.



Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место



LightFM + текстовые функции

Эта модель использует встраивание слов из имени списка воспроизведения вместо playlist_id. Внедрение плейлиста представляет собой сумму вложений его слов.



Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место



Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

,

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

, Где

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

- это слова из названия плейлиста.

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

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

Если в скрытой части был

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

треки, то мы выбираем

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

кандидаты.

Природа этих чисел — простая эвристика, придуманная по следующим причинам: мы хотим иметь достаточное количество кандидатов для небольших плейлистов (чтобы

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

), а также хотим, чтобы окончательный набор данных содержал примерно 10 миллионов строк из соображений производительности времени и памяти (поэтому k 15, а не к 50, например).



Ранжирование

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

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



Функции на основе модели LightFM

Как уже описано выше, в модели LightFM мы получили векторы

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

и скаляры

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

.

В качестве знаков мы будем использовать

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

, <

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

и рейтинг трека t среди всех кандидатов на плейлист p (ранг рассчитывался в соответствии с формулой ).

Эти четыре функции были взяты из моделей LightFM и LightFM Text.

Особенности, основанные на совместном появлении треков

Позволять

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

количество плейлистов, содержащих треки

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

И

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

вместе, и

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

— количество плейлистов, содержащих трек

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

.

Эти значения были рассчитаны на фиксированном наборе плейлистов, состоящем из всех начальных частей.

Пусть плейлист

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

состоит из треков

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

.

Для трека

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

давайте посчитаем значения

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

и для них мы посчитаем различную статистику: минимальную, максимальную, среднюю и медиану.

Затем мы вычисляем ту же статистику для величин

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

.

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

Нормализация помогает модели не перетренироваться на популярных треках и точнее извлекать информацию о том, насколько треки на самом деле похожи.



Другие знаки

Все характеристики рассчитаны для пары

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

.

  • Количество уникальных исполнителей в плейлисте

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

    .

  • Количество уникальных альбомов в плейлисте

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

    .

  • Количество и доля треков в плейлисте

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

    с тем же альбомом/исполнителем, что и трек

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

    .

  • Сколько раз встречался этот след?

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

    во всех плейлистах.

  • Сколько раз встречались исполнитель/альбом трека?

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

    во всех плейлистах.

  • Количество треков в начальной и контрольной частях плейлиста

    Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

    .



Модель рекомендаций

Для построения окончательных рекомендаций мы использовали XGBoost .

Модель прошла обучение на

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

, гиперпараметры были выбраны на основе

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

по метрике РПЦ АУК .

Эта метрика была выбрана потому, что она является классической для задач классификации.

Не все функции одинаково полезны, поэтому будет интересно посмотреть на значения важности функций модели.

Особенность Прирост
нормализованное среднее значение совместной встречаемости 1049


Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

модель, скалярное произведение

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

101
количество плейлистов 100
нормализованное максимальное совпадение 74
отслеживает количество удержаний 63
медиана совместной встречаемости 33
количество треков 29


Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

модель, скалярное произведение

Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

28


Как мы решили проблему продолжения плейлистов на RecSys Challenge и заняли 3 место

модель, рейтинг
26
среднее совпадение 20
Видно, что нормализованное среднее значение совместного встречаемости значительно выделяется среди других.

Это означает, что информация о совпадении треков дает очень сильный сигнал, что, в общем-то, неудивительно.

Также эту функцию можно было использовать в качестве выбора кандидатов вместо модели LightFM, и это дало не худшие результаты.

Другой

Железо

Все модели обучались на сервере с процессором Intel Xeon E5-2679 v3 (28 ядер, 56 потоков), 256 ГБ оперативной памяти.

Обучение итогового конвейера занимало около 100 часов и потребляло в пике 200Гб памяти, при этом значительная (около 90%) часть времени уходила на обучение модели выбора кандидатов.

Модель ранжирования обучалась довольно быстро — около двух часов (не считая подбора гиперпараметров).



Не удалось

Были и неудачи.

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

Отправив заявку, мы узнали, что это был не предпоследний день, а последний.

И скорость новой подачи оказалась намного ниже нашей лучшей подачи.

Разбираться, почему так произошло, не было времени, поэтому мы представили лучшую работу, которая осталась на третьем месте.

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

В один из дней соревнований значение метрики R-Precision резко возросло у всех команд в таблице лидеров.

Мы не придали этому значения, но по итогам соревнований узнали, что организаторы добавили в метрику еще одну составляющую – соответствие исполнителя трека.

Это также можно добавить к метрике проверки и, возможно, повысить скорость.

Код Наше решение разработаны как блокноты Jupyter и могут быть воспроизведены (!), запуская их последовательно.

Только для этого вам понадобится машина с 200Гб+ ОЗУ и пара дней времени.

Решения других участников Команда, занявшая первое место, также регулярно участвует в RecSys Challenge и занимает высокие места.

Их решение похоже на наше, но реализовано на Java .

У вторых финалистов довольно интересный подход – они использовали Шумоподавление автоэнкодера для восстановления плейлистов из их частей .

Заключение Если вы посмотрите на итоговую таблицу лидеров, наша команда занимает шестое и четвертое места по рейтинговым метрикам (R-Precision и NDCG) и первое место по показателю «Клики».

Как это произошло? А получилось так из-за удачного решения проблемы холодного запуска с использованием модели LightFM Text. Метрика «Клики» жёстче штрафует в тех случаях, когда мы не угадываем ни одного трека из плейлиста.

Использование модели LightFM Text улучшило средний показатель кликов с 2,2 до 1,78. Подход отбора кандидатов с использованием более простой модели и последующего ранжирования их с помощью более сложной модели по-прежнему остается одним из наиболее успешных в классических задачах построения топ-К рекомендаций.

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

Эта схема вполне подходит и для производственных систем — вы можете начать строить свою рекомендательную систему на основе матричной факторизации, а затем улучшать ее, добавляя второй этап.

Если у вас есть вопросы по статье, смело задавайте их в комментариях :) P.S. Более подробную статью об этом мы написали для мастер-класса на конференции RecSys. Доступ к ее материалам на сайте ограничен, поэтому если вам интересно узнать чуть больше подробностей о нашем решении, напишите мне в личное сообщение.

Теги: #Машинное обучение #python #математика #Алгоритмы #машинное обучение #рекомендующие системы

Вместе с данным постом часто просматривают: