Совместная фильтрация обычно используется для создания рекомендательных систем (например, рекомендаций для шоу / фильмов Netflix). Современные модели совместной фильтрации на самом деле используют довольно простой метод, который, как оказалось, работает довольно хорошо. В этом посте я дам обзор этих современных моделей, которые используют поверхностное обучение, а затем представлю новый метод (на мой взгляд, многообещающий!), Который использует глубокое обучение. В этом посте я буду использовать в качестве примера Набор данных MovieLens, который содержит оценки фильмов пользователями. Я также демонстрирую, как использовать мелкую и глубокую совместную фильтрацию в скрипте, представленном в моем Github, поэтому, если вы хотите использовать эти модели, посмотрите мой Github! Этот скрипт использует отличную библиотеку глубокого обучения fastai (написанную поверх PyTorch) и PyTorch.

Поверхностное обучение

Самые популярные в настоящее время модели совместной фильтрации используют так называемые матрицы внедрения. Матрицы вложения содержат многомерную информацию. Например, допустим, у нас есть матрица вложения для фильмов с тремя факторами. Может случиться так, что эти три фактора соответствуют тому, как фильм заключается в действии, насколько романтичен фильм и похож ли фильм на документальный фильм или нет. Конечно, эти факторы могут соответствовать чему угодно (и их не обязательно легко интерпретировать), и матрицы встраивания часто содержат множество факторов. Именно эти матрицы обновляются при обучении модели совместной фильтрации. Используя пример набора данных MovieLens, с нашей стандартной техникой совместной фильтрации у нас будет матрица встраивания для пользователей и фильмов (см. Рисунок ниже). Размер матрицы - это количество пользователей или фильмов по количеству факторов, которые мы выбираем. Что касается выбора количества факторов в матрицах вложения, это требует некоторых проб и ошибок. В примере сценария на моем Github количество факторов внедрения было установлено равным 50. Перед началом обучения значения в этих матрицах внедрения инициализируются случайным образом. Во время обучения эти значения обновляются, чтобы уменьшить потери (т.е. сделать прогнозируемые рейтинги более похожими на фактические). Во время каждой итерации обучения для каждой оценки фильма пользователем берется скалярное произведение соответствующих векторов. Этот точечный продукт представляет собой прогнозируемый рейтинг. Скалярное произведение используется для оценки каждого отдельного пользователя каждого фильма с оценкой (Примечание: фильмы, которые не были оценены пользователем, имеют значение 0), а прогнозируемые оценки сравниваются с фактическими оценками. Затем стохастический градиентный спуск (или близкие варианты стохастического градиентного спуска) используется для обновления значений в матрицах внедрения с целью уменьшения функции потерь. В дополнение к встраиваемым матрицам, современные модели совместной фильтрации содержат термин смещения, который, по сути, предназначен для учета определенных пользователей, которые всегда дают более высокие или низкие оценки, или фильмов, которые в целом получают более высокие или низкие оценки (т.е. хорошие или плохие фильмы). Эти условия смещения добавляются к скалярному произведению.

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

Глубокое обучение

Итак, мы рассмотрели текущую современную модель совместной фильтрации, которая работает достаточно хорошо и использует поверхностное обучение, но что дальше в этой области? Что ж, многообещающим направлением может быть совместная фильтрация с глубоким обучением, потому что (1) глубокое обучение оказалось чрезвычайно успешным в других направлениях работы (например, компьютерное зрение) и (2) оно позволяет создавать более подробные спецификации модели, что на первый взгляд действительно раздражает, но может позволить специалистам по машинному обучению создавать модели, адаптированные к их наборам данных. Насколько мне известно, идея совместной фильтрации с глубоким обучением была впервые представлена ​​в рамках fastai MOOC, и я думаю, что это очень интересное направление для этой области! Прежде чем вдаваться в подробности совместной фильтрации с глубоким обучением, я должен признать, что, используя пример набора данных MovieLens, модель поверхностного обучения превзошла модель глубокого обучения. Однако я думаю, что при достаточном изменении архитектуры модели и с правильным набором данных (возможно, более крупными наборами данных - я использовал только часть набора данных MovieLens), совместная фильтрация с глубоким обучением может превзойти модели поверхностного обучения.

Здесь я собираюсь рассмотреть модель только с одним скрытым слоем, но эти модели можно настроить так, как вы хотите! Примечание. Я попытался добавить больше слоев, и с этим набором данных модель одного скрытого слоя показала наилучшие результаты.

Как и раньше, мы начинаем с создания матрицы встраивания для фильмов и пользователей со случайно инициализированными весами (размер - это количество пользователей или фильмов по заданному количеству факторов). Затем для каждого пользователя и соответствующих векторов факторов встраивания фильма мы объединяем эти векторы (см. Рисунок ниже). В примере сценария на этом этапе есть небольшой выпад (0,05), чтобы предотвратить переобучение. Затем мы умножаем вектор конкатенированных факторов внедрения на другую матрицу с размером факторов внедрения * 2 (в этом примере это должно быть так, поскольку это количество столбцов в векторе конкатенированного внедрения) на другое число (в пример у меня 10). Затем матричный продукт пропускается через функцию активации выпрямленных линейных единиц (ReLU; это причудливый способ сказать, что отрицательные значения были изменены на 0); это очень часто встречается в глубоком обучении и делает функцию нелинейной. Опять же, чтобы предотвратить переобучение, мы применяем больше отсева. После этого мы берем матричное произведение (которое прошло через ReLU и выпали) и умножаем его на матрицу, которая имеет другое количество строк (опять же, в этом примере 10) и один столбец. Следовательно, результатом умножения матриц будет одно число, а это именно то, что нам нужно, поскольку мы пытаемся предсказать один рейтинг. Этот прогнозируемый рейтинг затем проходит через сигмовидную функцию (умножается на [(Максимальный рейтинг - Минимальный рейтинг) + Минимальный рейтинг]), чтобы приблизить прогнозируемое значение к фактическим прогнозам в наборе данных. Это повторяется для всего, что касается одного пользователя и рейтинга, и, как и раньше, прогнозируемые значения сравниваются с фактическими значениями, а значения в нашей модели обновляются со стохастическим градиентным спуском с обратным распространением (как и с любой проблемой глубокого обучения).

Здесь следует отметить, что я ничего не упомянул о смещении, потому что линейные слои в PyTorch уже учитывают смещение, поэтому нам не о чем беспокоиться.

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