Магия систем рекомендаций

Часто нас удивляет точность рекомендаций о том, что покупать на Amazon, смотреть на Netflix или слушать на Spotify. Мы чувствуем, что каким-то образом эти компании знают, как работает наш мозг, и монетизируют эту волшебную игру в угадывание. У них есть глубокая основа на поведенческих науках, и наша задача - воплотить все эти концепции в реальность таким образом, чтобы они были легкими для понимания и охватывали наиболее важные концепции.

Помните: люди чрезвычайно предсказуемы. Поведение указывает на личность. Личность определяет наше поведение, а наше поведение определяет наши решения.

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

Существует два основных типа систем рекомендаций:

  • Совместная фильтрация (CF)
  • Контентная фильтрация

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

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

Краеугольным камнем этого типа фильтрации являются петли обратной связи пользователя / элемента.

Эта обратная связь может быть оценкой пользователей, отметками "Нравится" или даже тем, насколько пользователь взаимодействует с определенным контентом.
У совместной фильтрации есть два смысла: узкое и более общее.

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

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

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

С точки зрения вычислений, совместная фильтрация в худшем случае составляет O (MN), где M - количество клиентов, а N - количество данных каталога продуктов. На практике, поскольку средний клиентский вектор очень тонкий, производительность обычно приближается к O (M + N).

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

У нас есть разные типы совместной фильтрации:

  • Пользователь-Пользователь
  • Пункт-Пункт
  • Пользовательский элемент

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

Item-Item: использует тот же подход, но меняет представление между пользователями и элементами. Это следует по логике «если тебе это нравится, то может и то». Другими словами, он рекомендует предметы, похожие на те, которые вам понравились ранее. Как и раньше, сходство между двумя элементами вычисляется с использованием общего числа пользователей в наборе данных. Этот алгоритм лучше, когда количество элементов намного меньше, чем количество пользователей. Примером может служить крупный интернет-магазин, когда ваши товары не меняются слишком часто. Главный недостаток состоит в том, что необходимо предварительно рассчитывать таблицы схожести элементов. Обновление этой таблицы при добавлении нового элемента стоит дорого.

User-Item: он сочетает в себе оба подхода для создания рекомендаций. Самые простые из них основаны на технике матричной декомпозиции. Цель состоит в том, чтобы создать векторы низкой размерности (встраивания) для всех пользователей и всех элементов, чтобы их умножение могло выявить, нравится ли элемент пользователю или нет.

Матрица «пользователь-элемент» является базовой основой традиционных методов совместной фильтрации и страдает от проблемы разреженности данных.

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

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

Алгоритмы User-Item имеют тот недостаток, что нет эффективного метода обновления вложений после добавления нового элемента или нового пользователя.

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

В следующей статье мы рассмотрим два основных типа систем совместной фильтрации:

  • На основе модели: использует различные методы, такие как интеллектуальный анализ данных и алгоритмы машинного обучения, для прогнозирования оценок пользователей безрейтинговых элементов. Обычно используются алгоритмы на основе кластеризации (k-ближайших соседей или KNN), методы матричной факторизации (SVD), вероятностная факторизация или глубокое обучение (нейронные сети).
  • На основе памяти: использует данные оценки пользователей для вычисления сходства. Обычно он находит сходство с помощью косинусов или корреляций Пирсона и принимает средневзвешенное значение оценок. Такой подход проще объяснить, но он плохо масштабируется.

На основе содержания

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

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

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

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

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

Примеры из практики

Для следующих тематических исследований мы будем использовать Python и общедоступный набор данных.

В частности, мы будем использовать набор данных MovieLens, собранный GroupLens Research. Файл, содержащий MovieLens 100k dataset, представляет собой стабильный эталонный набор данных, содержащий 100 000 оценок, выставленных 943 пользователями для 1682 фильмов, при этом каждый пользователь оценил не менее 20 фильмов.

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

  • u.item: список фильмов
  • u.data: список оценок пользователей.

Первые пять строк файла выглядят так:

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

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

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

Чтобы найти оценку R, которую пользователь U поставил бы элементу I, подход включает в себя:

  • Поиск пользователей, похожих на U, которые оценили элемент I
  • Расчет рейтинга R на основе оценок пользователей, найденных на предыдущем шаге.

Учитывая, что каждый пользователь является вектором, в scikit есть функция, которая вычисляет косинусное расстояние для каждого вектора.

>>> from scipy import spatial
>>> a = [1, 2]
>>> b = [2, 4]
>>> c = [2.5, 4]
>>> d = [4.5, 5]

>>> spatial.distance.cosine(c,a)
0.004504527406047898

>>> spatial.distance.cosine(c,b)
0.004504527406047898

>>> spatial.distance.cosine(c,d)
0.015137225946083022

>>> spatial.distance.cosine(a,b)
0.0

Меньший угол между векторами C и A дает меньшее значение косинусного расстояния.

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

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

Вот как будет выглядеть эта нормализация:

  • Для пользователя A вектор рейтинга [1, 2] имеет среднее значение 1.5. Вычитание 1.5 из каждого рейтинга даст вам вектор [-0.5, 0.5].
  • Для пользователя B вектор рейтинга [2, 4] имеет среднее значение 3. Вычитание 3 из каждого рейтинга даст вам вектор [-1, 1].

Проделав то же самое для пользователей C и D, мы видим, что теперь оценки скорректированы так, чтобы получить средний балл 0 для всех пользователей, что приводит их всех к одинаковому уровню. и снимает их предвзятость.

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

Хорошим выбором для заполнения пропущенных значений может быть средний рейтинг каждого пользователя, но исходные средние значения для пользователя A и B равны 1.5 и 3 соответственно, и заполняются все пустые значения A с 1.5 и B с 3 сделают их разными пользователями. Эта проблема решена с помощью нашей нормализации, поскольку центрированное среднее значение обоих пользователей равно 0, что дает представление о том, что все отсутствующие значения равны 0.

После того, как мы определили список пользователей, похожих на пользователя U, мы можем вычислить R, которое U даст определенному элементу Я. Мы можем сделать это разными способами.

Мы можем предсказать, что оценка пользователя R для элемента I будет близка к средней оценке, присвоенной I пятью или 10 первых пользователей, наиболее похожих на U. Математическая формула средней оценки, присвоенной n пользователями, будет выглядеть так:

Эта формула показывает, что средняя оценка, присвоенная n похожими пользователями, равна сумме выставленных ими оценок, деленной на количество похожих пользователей, то есть n.

Бывают ситуации, когда найденные вами n похожих пользователей не одинаково похожи на целевого пользователя U. Три верхних из них могут быть очень похожи, а остальные могут быть не так похожи на U, как верхние 3. В этом случае вы можете рассмотреть подход, при котором рейтинг наиболее похожего пользователя имеет значение. больше, чем второй по популярности пользователь и так далее. Средневзвешенное значение может помочь нам в этом.

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

Фактор подобия, который будет действовать как вес, должен быть обратным расстоянию, описанному выше, потому что меньшее расстояние означает большее сходство. Например, вы можете вычесть косинусное расстояние из 1, чтобы получить косинусное подобие.

С коэффициентом сходства S для каждого пользователя, аналогичного целевому пользователю U, мы можем рассчитать средневзвешенное значение по следующей формуле:

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

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

Этот метод является примером CF. Если мы используем рейтинговую матрицу для поиска похожих предметов на основе оценок, присвоенных им пользователями, то подход будет выглядеть так: Item-Item CF.

Тем не менее, подход «элемент-элемент» плохо работает для наборов данных с элементами просмотра или развлечениями, такими как MovieLens. Такие наборы данных получают лучшие результаты при использовании методов матричной факторизации, которые мы увидим в разделе CF на основе моделей.

CF на основе модели

В матрице пользовательских элементов есть два измерения:

  1. Количество пользователей
  2. Количество предметов

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

Факторизацию матрицы можно рассматривать как разбиение большой матрицы на произведение более мелких. Это похоже на факторизацию целых чисел, где 12 можно записать как 6 x 2 или 4 x 3. В случае матриц матрица A с размерами m x n может быть уменьшена до произведения двух матриц X и Y с размерами m x p и p x n. соответственно.

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

Сокращенные матрицы фактически представляют пользователей и элементы по отдельности. Строки m в первой матрице представляют пользователей m, а столбцы p рассказывают вам об особенностях или характеристиках пользователей. То же самое и с матрицей элементов с n элементами и характеристиками p. Вот пример того, как выглядит матричная факторизация:

На изображении выше матрица уменьшена на две матрицы. Слева - матрица пользователей с m пользователями, а сверху - матрица элементов с n элементами. Рейтинг 4 уменьшается или делится на:

  1. Пользовательский вектор (2, -1)
  2. Вектор предмета (2.5, 1)

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

  • Предположим, что в векторе пользователя (u, v), u представляет, насколько пользователю нравится жанр ужасов, а v представляет, насколько ему нравится жанр романс.
  • Таким образом, вектор пользователя (2, -1) представляет пользователя, которому нравятся фильмы ужасов и который оценивает их положительно, и не любит фильмы, в которых есть романтика, и оценивает их отрицательно.
  • Предположим, что в векторе элементов (i, j), i представляет, насколько фильм относится к жанру ужасов, а j представляет, насколько этот фильм относится к жанру романса.
  • У фильма (2.5, 1) рейтинг ужасов 2.5 и рейтинг романтики 1. Умножение его на пользовательский вектор с использованием правил умножения матриц дает (2 * 2.5) + (-1 * 1) = 4.
  • Итак, фильм относился к жанру ужасов, и пользователь мог бы оценить его 5, но небольшое включение романа привело к падению окончательной оценки до 4.

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

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

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

# load_data.py

import pandas as pd
from surprise import Dataset
from surprise import Reader

# This is the same data that was plotted for similarity earlier
# with one new user "E" who has rated only movie 1
ratings_dict = {
    "item": [1, 2, 1, 2, 1, 2, 1, 2, 1],
    "user": ['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D', 'E'],
    "rating": [1, 2, 2, 4, 2.5, 4, 4.5, 5, 3],
}

df = pd.DataFrame(ratings_dict)
reader = Reader(rating_scale=(1, 5))

# Loads Pandas dataframe
data = Dataset.load_from_df(df[["user", "item", "rating"]], reader)
# Loads the builtin Movielens-100k data
movielens = Dataset.load_builtin('ml-100k')

K-ближайшие соседи (k-NN) и матричная факторизация.

В библиотеке Surprise есть много алгоритмов, которые мы можем очень легко использовать, k-NN.

# recommender.py

from surprise import KNNWithMeans

# To use item-based cosine similarity
sim_options = {
    "name": "cosine",
    "user_based": False,  # Compute  similarities between items
}
algo = KNNWithMeans(sim_options=sim_options)

Это мы можем обучать и предсказывать с помощью k-NN.

>>> from load_data import data
>>> from recommender import algo

>>> trainingSet = data.build_full_trainset()

>>> algo.fit(trainingSet)
Computing the cosine similarity matrix...
Done computing similarity matrix.
<surprise.prediction_algorithms.knns.KNNWithMeans object at 0x7f04fec56898>

>>> prediction = algo.predict('E', 2)
>>> prediction.est
4.15

И, наконец, мы можем точно настроить наши гиперпараметры и среднеквадратичную ошибку.

from surprise import KNNWithMeans
from surprise import Dataset
from surprise.model_selection import GridSearchCV

data = Dataset.load_builtin("ml-100k")
sim_options = {
    "name": ["msd", "cosine"],
    "min_support": [3, 4, 5],
    "user_based": [False, True],
}

param_grid = {"sim_options": sim_options}

gs = GridSearchCV(KNNWithMeans, param_grid, measures=["rmse", "mae"], cv=3)
gs.fit(data)

print(gs.best_score["rmse"])
print(gs.best_params["rmse"])

Советчик СВД

Как вариант, мы можем запустить рекомендательный алгоритм, используя SVD вместо k-NN.

from surprise import SVD
from surprise import Dataset
from surprise.model_selection import GridSearchCV

data = Dataset.load_builtin("ml-100k")

param_grid = {
    "n_epochs": [5, 10],
    "lr_all": [0.002, 0.005],
    "reg_all": [0.4, 0.6]
}
gs = GridSearchCV(SVD, param_grid, measures=["rmse", "mae"], cv=3)

gs.fit(data)

print(gs.best_score["rmse"])
print(gs.best_params["rmse"])

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

0.9642278631521038
{'n_epochs': 10, 'lr_all': 0.005, 'reg_all': 0.4}

использованная литература

Суреш Чандра Сатапати, Викрант Бхатеджа, Амит Джоши. « Труды международной конференции по информационным технологиям и коммуникационным технологиям ». 2016 г.



Тервин, Лорен; Хилл, Уилл (2001). За пределами рекомендательных систем: помогать людям помогать друг другу. Эддисон-Уэсли. п. 6.

Бадрул Сарвар, Джордж Карипис, Джозеф Констан и Джон Ридл (2001). « Рекомендательные алгоритмы совместной фильтрации на основе элементов ». GroupLens Research Group / Армейский исследовательский центр HPC. Первая статья, опубликованная по рекомендациям на основе заданий.

Дэвид А. Голдберг, Дэвид А. Николс, Дуглас Б. Терри. « Использование коллаборативной фильтрации для создания информационного полотна ». Коммуникации ACM. 1991. Первое использование термина коллаборативная фильтрация.

Библиотека LightFM : гибридный рекомендательный алгоритм на Python.

Библиотека Python-recsys: библиотека Python для реализации рекомендательной системы.

Библиотека Surprise: scikit Python, создающий и анализирующий рекомендательные системы, которые имеют дело с явными рейтинговыми данными.

Аггарвал, Чару С. (2016). «Рекомендательные системы: Учебник». Springer.

Петр Брусиловский (2007). «Адаптивный Интернет». п. 325.

Адитья, П. и Буди, Индра и Мунаджат, Кориб. (2016). «Сравнительный анализ совместной фильтрации на основе памяти и на основе моделей при внедрении рекомендательной системы для электронной коммерции в Индонезии: тематическое исследование PT X». п. 303–308

InCubeGroup. Рекомендательные системы для Private Banking. Ссылка 18.03.2020.