В 2018 году наша команда традиционно приняла участие в Вызов RecSys .
Это ежегодный конкурс рекомендательных систем, проводимый в рамках конференции RecSys. Оно не такое масштабное, как соревнования Kaggle, но считается одним из самых престижных соревнований по рекомендательным системам.
На этот раз задача была музыкальная — нужно было построить систему автоматического продолжения плейлистов.
В этом посте я подробно рассказываю о нашем решении.
Приглашаю вас под кат.
О конкурсе В этом году данные для конкурса предоставил Спотифай — сервис потоковой передачи музыки (который, к сожалению, официально не доступен в РФ).
Рекомендации являются одной из наиболее важных частей продукта Spotify и позволяют пользователям находить новую музыку, создавать плейлисты или слушать радио в соответствии со своими предпочтениями.
Участникам конкурса предстояло создать алгоритм автоматического продолжения плейлиста.
В качестве обучающих данных был представлен набор данных Million Playlist, название которого говорит само за себя.
Помимо информации о том, какие треки содержатся в плейлисте, также была предоставлена метаинформация о треках: исполнитель, название, продолжительность, название альбома.
Подробнее о конкурсе можно прочитать Здесь .
Цель конкурса Задача конкурса классическая для рекомендательных систем: сформировать топ-К рекомендаций для пользователя, зная историю его действий, но вместо обычных юзер-итемов здесь появляется плейлист-трек.
Говоря более формально, тестовые данные содержали части плейлистов (далее — сиды), и существовало несколько различных способов их генерации.
Для K = (5, 10, 25, 100) были семена с первыми K треками и K треками, выбранными случайным образом.
Еще были сиды с первым треком и только названием плейлиста.
Треки, которые не были включены в начальное число (несогласные), необходимо было спрогнозировать.
Для каждого плейлиста требовалось ровно 500 предсказаний.
Метрики Одной из особенностей конкурса было то, что метрика была не одна, как принято в большинстве соревнований, а несколько.
Ниже я расскажу о каждом из них.
R-Precision
Эта метрика показывает, какую долю релевантных треков мы угадали.
НДЦГ
Это классическая метрика качества ранжирования, о ней можно почитать, например, ЗдесьКлики
В Spotify есть механизм продолжения плейлиста (его можно увидеть на скриншоте в начале статьи): он предлагает несколько треков, с помощью которых вы можете расширить плейлист, а если ни один из них вас не устраивает, вы можете нажать кнопку обновления.и получите следующую порцию рекомендаций.
Количество таких обновлений до первого выбора — это показатель «Клики».
Проще говоря, позиция первой соответствующей рекомендации (в данном случае разделенная на 10).
Далее командам присваивается ранг по каждой из метрик.
Затем ранги суммируются с использованием схемы избирательной стратегии подсчета Борда.
Если
Если количество участников, то команда с 1 рангом получает
очков, команда, занявшая 2 место, получает
очки и так далее.
Решение
Схема проверки
Чтобы воспроизвести разделение поезд/тест, мы разделили исходный набор данных на три части: первая часть содержала 980 тысяч плейлистов, вторая и третья части содержали по 10 тысяч соответственно.Затем каждый плейлист из второй и третьей частей был разделен на затравочную и затравочную части, а размеры затравочных частей выбирались так же, как и в предоставленном тестовом наборе, а остальные треки уходили в задержку.
Отбор кандидатов
Рекомендательные системы часто используют двухэтапный подход: сначала используют более простую модель (например, матричная факторизация ) кандидаты выбираются из всего набора предметов, а затем кандидаты ранжируются по более сложной модели (например, повышение градиента ) с более широким набором функций.Отбор кандидатов необходим, прежде всего, из-за ограниченности вычислительных ресурсов: если мы будем использовать в качестве кандидатов весь набор доступных треков, то для одного плейлиста нам придется прогонять через модель около миллиона объектов.
Отбор кандидатов с использованием матричной факторизации
Матричная факторизация — один из наиболее распространенных подходов к построению рекомендательных систем.Основная идея этого метода — представить разреженную матрицу взаимодействий между пользователями и элементами как произведение двух матриц (U и I) меньшей размерности.
Тогда мы сможем получить рекомендации для пользователя, умножив вектор из матрицы U на матрицу I. Для факторизации матрицы мы использовали библиотеку ЛайтФМ с Потеря WARP (парный взвешенный приблизительный ранг) .
У нас также было две разные модели — одна для плейлистов с непустым начальным значением, другая для плейлистов с только заголовком (холодный старт).
Потеря деформации
Эта функция потерь лучше других справляется с задачами ранжирования.Он работает с тройками (пользователь, положительный_элемент, отрицательный_элемент) и имеет одну очень важную особенность – выбор отрицательных примеров происходит не случайно, а таким образом, что выбранные отрицательные примеры «ломают» текущий рейтинг модели, т.е.
были выше, чем положительный пример.
Таким образом, процедура обучения модели с использованием потерь WARP будет примерно следующей:
- Для пары
выберем случайный отрицательный пример среди всех остальных предметов (важно понимать, что делать это следует только в том случае, если вероятность выбора отрицательного примера, который на самом деле окажется положительным, достаточно мала).Давайте посчитаем прогноз модели попарно
И
и если нарушения порядка нет (то есть модель предсказала более высокий балл для положительного примера), то мы продолжаем выборку отрицательных примеров до тех пор, пока не произойдет нарушение. - Если мы получим нарушение с первой попытки, то мы можем сделать большой градиентный шаг, поскольку это означает, что на данный момент модель часто ставит отрицательные примеры выше положительных и ее веса необходимо существенно обновить.
Если нам пришлось долго искать подходящий отрицательный пример, то делаем небольшой шаг — модель уже достаточно хорошо обучена.
ЛайтФМ
Первая версия модели использовала только совместную информацию: наличие track_id в плейлисте playlist_id, представленном в виде двоичной разреженной матрицы.Строка матрицы соответствовала плейлисту, столбец — треку.
LightFM + текстовые функции
Эта модель использует встраивание слов из имени списка воспроизведения вместо playlist_id. Внедрение плейлиста представляет собой сумму вложений его слов.
,
,
Где
- это слова из названия плейлиста.
Таким образом мы решаем проблему холодного запуска — можем предоставлять более качественные рекомендации для плейлистов, у которых есть только имя.
Организаторы конкурса также предоставили информацию о том, сколько треков находится в скрытой части плейлиста.
Если в скрытой части был
треки, то мы выбираем
кандидаты.
Природа этих чисел — простая эвристика, придуманная по следующим причинам: мы хотим иметь достаточное количество кандидатов для небольших плейлистов (чтобы
), а также хотим, чтобы окончательный набор данных содержал примерно 10 миллионов строк из соображений производительности времени и памяти (поэтому k 15, а не к 50, например).
Ранжирование
После того, как мы выбрали кандидатов, мы можем рассматривать задачу рекомендации как задачу двоичной классификации: для каждого из треков в выбранных кандидатах мы учимся предсказывать, действительно ли этот трек был в списке воспроизведения.В нашем наборе обучающих данных каждая строка будет содержать атрибуты для пары (список воспроизведения, трек), а метка будет равна 1, если трек есть в списке воспроизведения, и 0, если его нет. В качестве признаков использовались несколько разных групп.
Функции на основе модели LightFM
Как уже описано выше, в модели LightFM мы получили векторыи скаляры
.
В качестве знаков мы будем использовать
, <
и рейтинг трека t среди всех кандидатов на плейлист p (ранг рассчитывался в соответствии с формулой ).
Эти четыре функции были взяты из моделей LightFM и LightFM Text.
Особенности, основанные на совместном появлении треков
Позволятьколичество плейлистов, содержащих треки
И
вместе, и
— количество плейлистов, содержащих трек
.
Эти значения были рассчитаны на фиксированном наборе плейлистов, состоящем из всех начальных частей.
Пусть плейлист
состоит из треков
.
Для трека
давайте посчитаем значения
и для них мы посчитаем различную статистику: минимальную, максимальную, среднюю и медиану.
Затем мы вычисляем ту же статистику для величин
.
В первом случае мы просто смотрим, как часто целевой трек встречался вместе с треками из плейлиста, а во втором случае еще и нормируем это на частоту появления других треков.
Нормализация помогает модели не перетренироваться на популярных треках и точнее извлекать информацию о том, насколько треки на самом деле похожи.
Другие знаки
Все характеристики рассчитаны для пары.
- Количество уникальных исполнителей в плейлисте
. - Количество уникальных альбомов в плейлисте
. - Количество и доля треков в плейлисте
с тем же альбомом/исполнителем, что и трек
. - Сколько раз встречался этот след?
во всех плейлистах. - Сколько раз встречались исполнитель/альбом трека?
во всех плейлистах. - Количество треков в начальной и контрольной частях плейлиста
.
Модель рекомендаций
Для построения окончательных рекомендаций мы использовали XGBoost .
Модель прошла обучение на
, гиперпараметры были выбраны на основе
по метрике РПЦ АУК .
Эта метрика была выбрана потому, что она является классической для задач классификации.
Не все функции одинаково полезны, поэтому будет интересно посмотреть на значения важности функций модели.
Особенность | Прирост |
нормализованное среднее значение совместной встречаемости | 1049 |
модель, скалярное произведение |
101 |
количество плейлистов | 100 |
нормализованное максимальное совпадение | 74 |
отслеживает количество удержаний | 63 |
медиана совместной встречаемости | 33 |
количество треков | 29 |
модель, скалярное произведение |
28 |
модель, рейтинг |
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 #математика #Алгоритмы #машинное обучение #рекомендующие системы
-
Blackberry Теряет Долю В Пользу Android
19 Oct, 24 -
Кодирование
19 Oct, 24