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

Как эффективно и точно построить систему рекомендаций на основе сеансов?

В CBC мы используем рекуррентную нейронную сеть (RNN), основанную на работе в этих документах. Наша модель реализована в TensorFlow, фреймворке, который мы все любим ненавидеть (и ненавидеть любить).

Но прежде чем мы углубимся в детали, я начну с подготовки сцены. Как активный браузер, я всегда ищу новые способы поиска контента, будь то в социальных сетях, поиске или из уст в уста. Я человек простых вкусов - я люблю спиртные напитки местного производства и жалуюсь на Комиссию по транзиту Торонто (TTC), несмотря на то, что редко ее употребляю.

Я надеюсь, что смогу найти новости, которые меня легко заинтересуют, например, когда енот пытался поймать метро Торонто или когда моя родная провинция выиграла большой приз на World Gin Awards. Для такого создателя контента, как CBC, нам нужно найти новые способы донести нужный контент до нужного пользователя. Эта практика уже применяется и практикуется такими компаниями, как Netflix, Spotify и Youtube.

Так входит в систему рекомендаций топ-N, класс алгоритмов, которые позволяют нам отображать персонализированный контент на основе поведения пользователя. Учитывая историю чтения пользователя, мы хотим предоставить N наиболее вероятных статей (например, на изображении выше для N установлено значение 5), которые они хотели бы прочитать следующей. Потребуется время, чтобы рассмотреть различные решения этой проблемы, но я расскажу о том, как наша команда CBC решает эту проблему с помощью машинного обучения.

Модель

Для тех, кто не знаком, RNN выполняет моделирование и классификацию последовательности, учитывая достаточно большой набор данных для обучения. Чтобы смягчить обучающую нестабильность, обнаруженную в ванильной RNN, используется RNN Gated Recurrent Unit (GRU).

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

Учитывая набор A из n статей, пользовательская последовательность U для пользователя j и GRU, который дает оценку вероятности для пары последовательность-статья, позволяют получить лучшую статью, просто принимая argmax:

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

Потеря

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

В нашей системе используется реализация одной такой потери, определенной здесь, которая называется TOP1-max. Это написано следующим образом:

Рассмотрим набор A всех статей. Возьмем набор n отрицательных примеров из A, т. Е. Статей, которые пользователь не прочтите и назовите его N. ГРУ присваивает каждой статье j в N оценку, назовем ее r_j . Это позволяет нам рассчитать оценки softmax s_j для всех отрицательных примеров в N, следующим образом:

Расчет убытка L с учетом оценки r_t для целевой (правильной) статьи происходит следующим образом:

Оптимизируя ГРУ за счет минимизации этой потери, мы наблюдаем значительный прирост производительности, что подводит нас к вопросу - как мы измеряем производительность?

Тренировка

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

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

«Но, Джон, глупый утенок», - скажете вы, - «может это привнесет в модель предвзятость новизны?» Действительный балл! Может быть! Рассмотрение только последнего элемента в сеансе может привести к тому, что модель узнает более свежую динамику пользователя. Наша гипотеза заключается в том, что это сохраняет актуальность рекомендаций.

Популярные показатели оценки для подобных моделей рекомендаций включают отзыв @ k (% случаев, когда правильный ярлык находится в верхних k прогнозах), MRR @ k (M ean R eciprocal R ank) и catalog-охват @ k ( % возможного содержания, которое вы рекомендуете при показе прогнозов k).

Для обучения мы используем пакетный стохастический градиентный спуск. Все вышеперечисленные показатели отслеживаются нашим дружелюбным соседом TensorBoard.

В качестве проверки работоспособности мы сравниваем все показатели после обучения с простой базовой линией - прогнозированием самых популярных статей. Если мы не можем справиться с этим, значит, у нас проблемы.

Мы обучаем новую подобную модель каждый час, используя службу Google CloudML, и обслуживаем ее через Flask API, через Google AppEngine. Такая настройка позволяет нам обрабатывать сотни запросов в секунду, что важно при резких скачках трафика во время последних новостей. Чтобы ускорить весь процесс, мы используем небольшой ГРУ, сокращая время обучения до 5–10 минут на модель.

Insights

Внимательные читатели могли заметить, что охват нашего каталога для k = 5 составляет только ~ 20% во время обучения, что звучит очень мало (и это так!). Некоторый исследовательский анализ может пролить некоторый свет.

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

Приведенный выше сюжет довольно плотный, поэтому я уточню. Выберите час дня, скажем, 12:00. (бледно-зеленый). Найдите 20,0 на логарифмической шкале x линейной диаграммы и поднимитесь вертикально, пока не дойдете до бледно-зеленой линии. Здесь значение y, ~ 70%, показывает, сколько истории просмотров покрывают 20% самых популярных статей в обеденное время. Это много!

ГРУ добивается приличного отзыва @ 5 (~ 35%), но предвзятость в данных показывает его слабое место: разнообразие. Работа над этим вопросом ведется. Не дает уснуть по ночам.

Наш набег на рекомендательные системы в CBC до сих пор был забавным, и сейчас проводятся A / B-тесты для их проверки. В следующий раз, когда вы будете проверять новости, обратите внимание на собственные рекомендации! А пока вы можете найти его на MyCBC.

Кроме того, мы нанимаем!