Как стать автором
Обновить
73.83
Онлайн-кинотеатр Иви
Мы открываем для людей многообразие мира кино

Как мы рекомендуем новинки каталога в онлайн-кинотеатре ivi (+ код на Python)

Время на прочтение4 мин
Количество просмотров5K
В блоге онлайн-кинотеатра ivi накопилось достаточно статей про архитектуру рекомендательной системы Hydra. Однако рекомендации — это не только внешний API, но и алгоритмы, которые живут «под капотом» и реализуют достаточно сложную бизнес-логику.

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


Статья будет содержать воспроизводимый пример кода на языке Python с использованием Keras.

Холодный старт контента: постановка проблемы


Как работают рекомендации? Примерно следующим образом:


Мы используем для рекомендаций следующий пайплайн:

  • загружаем статистику просмотров контента в виде матрицы user-content
  • применяем волшебную коробку машинного обучения
  • на выходе из коробки у каждой единицы каталога появляются фичи
  • фичи контента используем для рекомендаций

Все этапы пайплайна обучения модели холодного старта можно найти в этом репозитории github.com/ivi-ru/hydra
Фичи контента мы получаем с помощью библиотеки implicit следующим образом

train_model.py
import implicit
import numpy as np
from scipy.sparse import load_npz

# загружаем матриц user-item
user_item_views_coo = load_npz('/srv/data/user_item_interactions.npz')

als_params = { 'factors': 40, 'regularization': 0.1, 'num_threads': 3, 'iterations': 5}

print('Начинаем обучение ALS-модели')
als_model = implicit.als.AlternatingLeastSquares(**als_params)
als_model.fit(user_item_views_coo.T)
als_factors = als_model.item_factors
print('ALS-модель обучена, факторы контента ', als_factors.shape)

als_factors_filename = '/srv/data/fair_als_factors.npy'
np.save(als_factors_filename, als_factors,allow_pickle=True)
print('Сохранили факторы контента в', als_factors_filename)


Как рекомендовать контент, который вышел на сервисе совсем недавно? У такого контента будут отсутствовать просмотры (или просмотров будет очень мало) — это значит, что в выхлопе волшебной коробки машинного обучения не будет фичей по такому контенту и он не будет появляться в рекомендациях у пользователей. Фичи, которые мы получаем на основе взаимодействий пользователь-контент, кстати, называются коллаборативными.

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

Другой вариант — построить модель, которая умеет предсказывать фичи «холодного» контента.

Мы решили пойти по второму пути и вот куда пришли

Cold Start 1.0


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

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

Редакторские тэги — это краткое описание контента в виде конечного (обычно несколько сотен) набора характеристик. Ниже приведён набор тэгов контента «Бобры-зомби»


В первом приближении мы решали задачу холодного старта следующим образом:

  • для каждого «холодного» контента натйти максимально похожий на него по тэгам
  • взять коллаборативные фичи похожего контента
  • коллаборативные фичи холодного контента — это среднее по фичам его «горячих» соседей


На python это выглядит как-то так
for row in new_items_neighbors:
    neighbors_als_indices = row.neighbors_ids[:self.cold_start_neighbors_count]
    neighbors_average_factors = item_factors[neighbors_als_indices].mean(axis=0)
    # сохраняем результат усреднения в матрицу фичей ALS
    item_factors[row.new_item_als_index] = neighbors_average_factors



Данный метод как-то работал, но у него было два недостатка:

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


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

Рефакторинг модели холодного старта



Вместо того, чтобы вычислять ALS-фичи контента с помощью эвристик (вроде усреднения), мы можем натренировать нейросеть, которая будет предсказывать коллаборативные фичи контента — например, по редакторским тэгам. Похожая модель уже мелькала на Хабре вот тут, а до Яндекса о подобной модели рассказывал музыкальный сервис Spotify


Код прототипа модели доступен в репозитории ivi, нейросеть для холодного старта выглядит следующим образом:

cold_start_model.py
def _get_model(self, dims: List[int]) -> Sequential:
    model = Sequential()
    model.add(
        Dense(
            units=dims[1], activation='linear', input_dim=dims[0],
            kernel_initializer=WeightInitializer.custom_normal,
            bias_initializer='zeros'
        )
    )
    model.compile(
        loss=lambda y_true, y_pred: K.sum(K.square(y_pred - y_true), axis=-1),
        optimizer=optimizers.Adam(lr=self.learning_rate, decay=self.decay)
    )
    return model


С какими сложностями столкнулись при реализации этого эксперимента?

  • обучать сеть оказалось довольно тяжело: фичи закодированы one-hot, и сеть плохо обучается из-за большой размерности входного слоя. Пришлось проводить тщательный отбор фичей, в итоге используем только категории, жанры, а из редакторских тэгов выбираем самые «важные» с помощью tf-idf
  • беда с установкой Keras с помощью менеджера пакетов pipenv: python окружение не собиралось, пришлось допиливать сторонний пакет maxvolpy, с которым не подружился Keras

Результаты эксперимента



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

  • 60 чч на чтение статей и разработку прототипа
  • 30 чч на интеграцию прототипа в кодовую базу проекта
  • 10 чч на деплой новой модели — затащить Keras в python окружение оказалось не так просто из-за наших специфических зависимостей (вроде maxvolpy)

Мы получили простор для дальнейших экспериментов — использование нейронных сетей позволяет обучаться не только на редакторских тэгах, но и на других фичах: картинках, сценариях, пользовательских комментариях, видеоряде и т.д.
Теги:
Хабы:
Всего голосов 8: ↑7 и ↓1+6
Комментарии6

Публикации

Информация

Сайт
www.ivi.ru
Дата регистрации
Дата основания
Численность
501–1 000 человек