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

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

Системы совместной фильтрации генерируют рекомендации, основанные на сходстве между пользовательскими оценками элементов, а не на сходстве пользователей ИЛИ элементов. Чтобы понять это, введем понятие матрицы полезности.

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

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

Разложение матрицы

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

  1. Дана матрица полезности M с n строками и m столбцами (n пользователей и m элементов),
  2. Найдите матрицу U с n строками и d столбцами,
  3. Найдите матрицу V с d строками и m столбцами,
  4. Таким образом, UV приближается к M, где рейтинги (элементы M) известны (не пустые).

Этот процесс называется UV-разложение.
Мерой близости UV к M обычно является среднеквадратическая ошибка или RMSE, где мы:

  1. Просуммируйте по всем известным элементам M квадрат разности между этими элементами и соответствующими элементами UV
  2. Вычислите среднее значение этих квадратов
  3. Вычислить квадратный корень из среднего

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

Инкрементальный расчет оптимума

Чтобы аппроксимировать M, мы начинаем с произвольных U и V, затем итеративно корректируем каждую, чтобы минимизировать RMSE. Предположим, что P=UV, тогда:

Где pij — элемент P в строке i и столбце j.

является элементом P в строке i и столбце j.

Квадрат ошибки оценки может быть выражен как:

Затем мы можем обновить U и V следующим образом:

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

В идеале должна быть точка, где RMSE = 0. На практике мы итерируем несколько раз, пока RMSE не станет приемлемо малым или процесс не сойдется к локальному минимальному значению, поскольку у нас нет гарантии найти глобальное значение в приемлемое время.
Для очень больших матриц M у нас может не хватить памяти или вычислительной мощности для вычисления каждого элемента на каждой итерации, поэтому мы выбираем случайное подмножество — разновидность процесса, известного как стохастический градиентный спуск.

Нейросетевой подход

Нейронные сети обучаются аппроксимировать целевую функцию путем минимизации ошибки оценки с помощью алгоритма градиентного спуска. Мы можем использовать присущие им возможности оптимизации для матричной факторизации.
Для этого мы проецируем пользователей и элементы в скрытое пространство размерности d, используя встраивающие слои. Встраивающие слои учатся сопоставлять многомерный разреженный набор дискретных функций с плотным массивом действительных чисел в непрерывном пространстве, что эквивалентно проецированию наших n пользователей и m элементов в d-мерные векторы.
Затем сеть выполняет скалярное произведение между вложениями для оценки оценок.

Мы обучаем такую ​​сеть методом стохастического градиентного спуска (или аналогичным), используя RMSE (или MSE, поскольку он доступен в большинстве библиотек) в качестве функции ошибки.

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

Рекомендации по глубокой нейронной сети

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

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

Мы экспериментировали с набором данных goodbooks-10k, который содержит около 1 млн оценок 10 000 книг от более чем 50 000 пользователей. Сеть матричной факторизации на рис. 1, обученная всего за 12 итераций, достигла потери при проверке (то есть ошибки на тестовом наборе) 0,93. Рекомендатель глубокой нейронной сети на рис. 3, обученный на том же наборе данных для того же количества итераций, получил потерю проверки 0,76.

Таким образом, подход глубокой сети является весьма многообещающим.

Проблема с холодным запуском

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

  • рекомендовать товары, которые выбрали похожие пользователи
  • порекомендуйте похожие товары

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

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

В нашем эксперименте с набором данных goodbooks-10k мы добавили информацию о названии в качестве метаданных элемента, предполагая, что в отсутствие другой информации люди будут судить о книге по ее названию. Обратите внимание, что перед внедрением текстовую информацию необходимо преобразовать в числовое представление. Для этого мы использовали токенизатор Keras. Затем мы провели обучение для тех же 12 итераций, что и раньше, и достигли потери при проверке 0,72.

Это заметное улучшение, но, возможно, не такое большое, как можно было бы ожидать интуитивно (возможно, вместо этого нам следовало попробовать использовать обложки).

Автоэнкодеры для рекомендаций

Автоэнкодеры — это нейронные сети, обученные восстанавливать входные данные. В неполном автоэнкодере, таком как тот, что показан на рис. 5, самый внутренний скрытый слой содержит меньше нейронов, чем входной или выходной слои. Когда мы обучаем такую ​​сеть, скрытый слой изучает представление ввода, которое затем используется для его реконструкции в выходном слое.

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

Для этого мы загружаем в автоэнкодер строки нашей матрицы полезности M. Этот подход связан с двумя проблемами:

  1. Матрица полезности может быть достаточно большой. В нашем случае, например, у него более 50 000 пользователей и 10 000 книг. Наш автоэнкодер будет иметь столько входных узлов, сколько элементов, следовательно, 10 000.
  2. Матрица полезности разрежена, а недоступные рейтинги представлены нулем.

Обучение сети восстановлению нулей в матрице лишает цели и тратит время вычислений. Мы хотим, чтобы он прогнозировал рейтинг, отличный от нуля.

Для этого нам нужно минимизировать функцию потерь только на тех точках данных, которые известны, т.е. на тех рейтингах, которые у нас есть. Увы, библиотека Keras, обычно используемая для задач DNN, не имеет простого способа выполнить градиентный спуск только для одних входных значений, но не для других. Нам придется реализовать автоэнкодер в Tensorflow или Pytorch.

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

Простой автоэнкодер на рис. 5, реализованный в Tensorflow для оптимизации только доступных рейтингов и обученный в течение 100 эпох, достигает потери при проверке 0,66. Автоэнкодер может превзойти предыдущие методы, но для сходимости требуется больше итераций. Поэтому он полезен, если и когда он может фиксировать сложное поведение клиентов, которое нельзя было бы рассматривать иначе. Экспериментирование является ключевым.

Преимущество подхода с использованием глубоких нейронных сетей

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

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

Вот несколько ресурсов в Azure, которые могут быть полезны для разработки рекомендательной системы.

Дальнейшая работа: оценочные метрики

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

Для этой цели был разработан набор показателей, два из которых часто цитируются:

  • Precision@k — из первых k рекомендуемых элементов, сколько на самом деле понравилось пользователю U? Под «нравится» мы обычно подразумеваем, что пользователь оценил элемент выше заданного порога (например, 3/5).
  • Recall@k — доля всех товаров, которые понравились пользователю U и которые действительно были ему рекомендованы.

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