В 2020 году команда машинного обучения в Hootsuite объединилась с командой Amplify для создания функции публикации рекомендаций: системы, которая рекомендует публиковать публикации в социальных сетях на основе того, каким контентом пользователь поделился в прошлом. Цель заключалась в том, чтобы увеличить количество контента, которым делятся через Amplify, и упростить поиск интересного контента для наших пользователей. В этом посте описываются используемые методы и системная архитектура для этой функции. Также будет обсуждаться производительность в продакшене. Ниже на рис. 1 приведен снимок экрана с изображением лицевой стороны раздела с рекомендациями.

Фон

Amplify - это продукт, созданный Hootsuite, который позволяет компаниям расширять охват своего контента в социальных сетях, делясь им через учетные записи своих сотрудников в социальных сетях. Сотрудники имеют доступ к панели управления контентом компании и могут поделиться им в своих сетях. Одна из текущих проблем, которую пытается решить группа усиления, заключается в том, что некоторые компании создают много контента, который может соответствовать вкусам каждого пользователя, а может и не соответствовать. Вы не захотите публиковать сообщения в своей сети, например, об биржевой информации, если ваша личная сеть ожидает, что вы всегда будете публиковать статьи об потрясающих рок-группах, таких как Led Zeppelin или Foo Fighters.

Совместная фильтрация

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

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

Давайте немного погрузимся в принцип работы СВД. SVD по своей сути полагается на рейтинги, которые пользователи выставляют для элементов, чтобы делать прогнозы о том, как пользователь оценит новый элемент. Сделать рекомендацию на основе этого так же просто, как спрогнозировать, как пользователь будет оценивать все элементы, с которыми он не взаимодействовал (в данном случае - общие), и отсортировать этот список, чтобы вернуть его пользователю. Чтобы сделать этот прогноз, сначала мы создаем матрицу, в которой каждая строка представляет пользователя, а каждый столбец представляет элемент. Элементами этой матрицы являются рейтинги, присваиваемые пользователям. На диаграмме на рисунке 2 ниже показана матрица рейтингов в левой части уравнения.

С помощью некоторой линейной алгебры эту матрицу можно разложить на матрицу пользовательского вложения и матрицу поствложения. Если вы хотите узнать подробнее о том, как это работает, обратитесь к этой отличной статье. Однако важно понимать, что это разложение может иметь место, даже если в матрице оценок отсутствуют значения. Это означает, что, используя матрицу внедрения пользователя и матрицу поствложения, полученную в результате разложения, прогнозируемые рейтинги для каждой пары элементов пользователя могут быть получены путем умножения соответствующей строки пользователя и столбца сообщения из этих двух матриц. Таким образом, матрица рейтингов может быть заполнена пропущенными значениями. Все, что остается, - это отфильтровать матрицу для сообщений, которыми уже поделились, и представить пользователю сообщения с наивысшим прогнозируемым рейтингом в качестве рекомендаций. Так работает базовая система рекомендаций!

Неявный рейтинг

В настоящее время продукт Amplify не позволяет пользователям оценивать контент, которым они делятся. Это представляет проблему, поскольку для того, чтобы разложить матрицу оценок на пользовательскую матрицу и пост-матрицу, вам необходимо заполнить некоторые начальные значения (аналогично обучающим данным в контролируемых задачах). Фактически, чем больше у вас изначально есть, тем лучше вы должны ожидать от системы (однако вы не можете заполнить их все, иначе системе нечего будет предсказать). Однако эту проблему можно преодолеть. используя неявные оценки вместо явных.

Так что же такое неявный и явный рейтинг? Явные оценки, такие как 5-звездочная оценка товарам на Amazon, предоставляются пользователями и преднамеренно. Неявные рейтинги выводятся на основе действий пользователей. Например, на Netflix, смотрели ли они фильм и как долго они его смотрели.

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

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

Надеюсь, наша система рекомендаций побудит пользователей прочитать сообщения, прежде чем делиться ими!

Архитектура системы

Системная архитектура нашего механизма рекомендаций показана на рисунке 4.

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

Процесс выглядит следующим образом: пользователь поделится или прочитает статью на Amplify. Это генерирует событие в нашем потоке Kafka, которое загружается службой приема в S3. Данные обрабатываются и дополняются с помощью задания Spark, которое вызывает вечный идентификатор для добавления необходимой информации, а затем возвращается в S3 как обработанные данные. Затем мы используем AWS Sagemaker для выполнения учебного задания, которое будет использовать эти обработанные данные и создавать модель. Затем эту модель можно развернуть в сервисе Kubernetes на основе Flask, из которого интерфейсная часть будет запрашивать прогнозы!

Фильтрация

Поскольку Hootsuite - международная компания, не все наши пользователи публикуют сообщения на одном языке. Фактически, некоторые компании, являющиеся нашими клиентами, имеют сообщения на нескольких языках. При этом мы не хотим, чтобы наша система рекомендаций давала рекомендации пользователям, не знающим их языка. Таким образом, мы используем библиотеку определения языка в Python (в настоящее время langdetect, но в процессе перехода на fastText, как следует из названия, быстро) для создания карт идентификаторов сообщений и их языков. Затем мы предлагаем только те сообщения, которые написаны на том же языке, что и те, которыми пользователь делился или читал в прошлом.

Метрики

Этот раздел немного утомителен, но он важен при создании механизма рекомендаций. Измерение производительности рекомендательной системы с помощью точности - это своего рода антипаттерн. Если вы используете точность, вы предполагаете, что лучшая система - это та, которая будет рекомендовать сообщения, которыми пользователь определенно поделится. Более желательно рекомендовать посты, о которых пользователь не подумал бы, но которые они все же действительно ценят. Таким образом, наша команда рассмотрела несколько различных показателей для использования.

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

Охват - отражает степень, в которой сгенерированные рекомендации охватывают каталог доступных товаров, более широкий охват повышает удовлетворенность пользователей. Покрытие определяется не на уровне отдельного пользователя, а скорее на уровне системы [1].

Высокое разнообразие! = Высокий охват, например: если разным пользователям рекомендуется один и тот же разнообразный набор элементов, среднее разнообразие системы будет высоким, но охват останется низким. Разнообразие измеряется в соответствии с рекомендациями пользователя, а охват - измерением на системном уровне.

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

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

Мы попробовали два метода для повышения совокупной оценки охвата. Первый метод принудительно создает случайный пост для каждого участника. Такая случайность контролируется начальным значением случайности и порогом точности (насколько уверена модель в своих прогнозах). Поиск с гиперпараметрами предполагает, что использование порога = 0,5 и коэффициента случайности 42 дает совокупный показатель охвата около 0,77, что кажется разумным для использования в производственной среде.

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

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

Системный мониторинг и обнаружение сбоев

Чтобы определить, когда производительность падает или когда наша служба вывода не возвращает прогнозы, мы построили информационные панели, используя Grafana. Это позволяет нам определять, когда система возвращает значения слишком медленно или возвращает ошибки. Затем мы можем получить уведомление через Slack, чтобы мы могли быстро принять меры.

Переподготовка

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

Производственные показатели

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

В среднем сообщениями делятся примерно 28% времени, чему наша команда вполне довольна. Чтобы улучшить результаты, мы стремимся использовать байесовскую оптимизацию для параметров модели и включать различные элементы в наш расчет неявного рейтинга для каждого пользователя. Мы также рассмотрели возможность проведения A / B-тестов, в которых мы представляем разное количество предложений для каждого варианта. В настоящее время система примет решение о том, сколько представить, на основе своего уровня достоверности; однако мы можем видеть, используя Mixpanel для детализации наших результатов, что пользователи, которым представлены 3 рекомендации, имеют более высокий уровень успеха. Это говорит о том, что эксперимент, в котором случайной подвыборке пользователей предоставляется фиксированное количество рекомендаций, является правильным. Результаты этого анализа Mixpanel показаны в таблице 1.

Заключение

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

С учетом сказанного у меня есть список людей, которым я хотел бы поблагодарить своих товарищей по команде из группы машинного обучения за усердную работу по реализации проекта «Рекомендуемая публикация» (Аман Бхатиа, Имтиаз Джадавджи , Селин Лю, Энтони Донохо, Майкл Сиан и Ана Рамдас), а также команду Amplify.

Если у вас есть какие-либо вопросы по этому проекту, не стесняйтесь обращаться ко мне в LinkedIn.