Интуитивное пошаговое руководство

Вступление

Когда я начал свое путешествие по машинному обучению, было несколько концепций, которые меня очень увлекли, одной из таких вещей были рекомендательные системы. Это было одно из тех приложений машинного обучения, которые вы могли часто видеть в своей повседневной жизни. Делая покупки на Amazon, покупая одежду в Myntra, просматривая фильмы на Netflix, у нас были рекомендации повсюду, и, конечно же, знаменитый Конкурс Netflix Prize Competiton, где читали о конкурсе. , команды и их двухлетняя суета в борьбе с конкурентами - вот что меня очень взволновало в отношении рекомендательных систем (я предлагаю вам, ребята, посмотреть этот документальный фильм о команде-победителе). В этом блоге мы попытаемся дать интуитивно понятное пошаговое руководство по созданию очень простой рекомендательной системы с нуля.

Рекомендательная система

Перво-наперво, что такое рекомендательная система, вот как Википедия определяет рекомендательную систему.

Рекомендательная система - это система фильтрации информации, которая стремится предсказать «рейтинг» или «предпочтение», которое пользователь отдает элементу [1]

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

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

  • Совместная фильтрация (мы остановимся на этом в блоге)
  • Контентная фильтрация
  • Гибрид (смесь двух вышеперечисленных)

СОТРУДНИЧЕСТВО ПРОТИВ КОНТЕНТА

Совместная фильтрация использует прошлые взаимодействия пользователя с элементами для выработки новых рекомендаций, например, если человеку понравился фильм m1, а 5 другим людям понравился фильм m1 и в то же время понравился фильм m2, то фильм m2 может быть рекомендован этому пользователю (если быть точным, это пример совместной фильтрации пользователя и пользователя), тогда как фильтрация на основе содержимого требует дополнительной информации о пользователях (например, возраст, пол и т. д.) и элементах / фильмах (жанр , продолжительность фильма и т. д.) для создания прогноза преимущества совместного подхода заключаются в том, что они не требуют дополнительной информации о пользователе / ​​элементе, а извлекают полезные шаблоны из прошлого взаимодействия пользователя с элементом для создания собственных функций без необходимости в какой-либо дополнительной информации

ВИДЫ СОВМЕСТНОЙ ФИЛЬТРАЦИИ

Есть два типа подходов к совместной фильтрации.

  • На основе памяти
  • На основе моделей (в этом блоге мы будем создавать рекомендательную систему на основе моделей)

На основе памяти

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

  • Сходство пользователя и пользователя: сначала он находит пользователей, наиболее похожих на пользователя, заданного в нашем запросе, а затем прогнозирует предпочтение элемента на основе рейтинга наиболее похожих клиентов, например, если мы хотим предсказать, как клиент C будет присвоена оценка фильму m1, затем мы возьмем взвешенную сумму оценок, выставленных пользователями, похожими на этого пользователя, «Пользователи, которые похожи на вас, также понравились ...»
  • сходство элемент-элемент: методология аналогична подобию пользователь-пользователь, единственная разница заключается в том, что здесь вычисление сходства сосредоточено вокруг элемента, а не пользователя, допустим, мы хотим предсказывать фильмы для пользователя, тогда мы сначала найдет фильм с наивысшим рейтингом пользователя, найдет сходство этого фильма со всеми другими фильмами и предложит K лучших фильмов «Пользователи, которым понравился этот элемент, также понравились ...»

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

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

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

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

Теперь мы переходим к модельному подходу, но перед этим давайте немного поговорим о матричной факторизации.

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

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

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

КОД

Хватит теории, поговорим о коде! мы построим очень простую рекомендательную систему на основе моделей. Для решения задачи машинного обучения (под наблюдением) у нас всегда есть задача оптимизации, функция, которую мы пытаемся максимизировать / минимизировать, чтобы снизить стоимость без переобучения данных, и в процессе изучаем параметры нашей модели с помощью методов. как градиентный спуск. Итак, сначала давайте определимся с нашей задачей оптимизации

Где прогнозируемый рейтинг (r_hat) вычисляется следующим образом

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

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

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

Мы можем разбить прогнозируемый рейтинг на четыре части.

  • Глобальное среднее (mu): глобальное среднее - это средний рейтинг всех оценок в нашем наборе обучающих данных, этот термин можно рассматривать как наш базовый прогнозный рейтинг, и модель учится насколько это нужно изменить, чтобы получить верный прогноз.
  • Предвзятость пользователя: предвзятость пользователя можно рассматривать как термин, фиксирующий поведение пользователя, например, некоторые пользователи слишком критичны по сравнению с другими, поэтому они, как правило, дают немного меньше рейтинги.
  • Пристрастие к фильму. Пристрастие к фильму можно рассматривать как термин, фиксирующий популярность фильма. Например, есть некоторые культовые классические фильмы, такие как «Аватар», «Искупление Шоушенка», которые обычно имеют высокие рейтинги, поэтому они фильмы, как правило, получают более высокий рейтинг за рекомендацию.
  • Взаимодействие пользователя и фильма: наконец, у нас есть термин, который рассчитывается на основе взаимодействия между конкретным пользователем и фильмом путем вычисления латентных векторов подобия ч / б пользователя и фильма (объяснено в разделе выше).

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

НАБОР ДАННЫХ

Мы взяли очень популярный набор данных под названием MovieLens 100k [2], этот набор данных содержит 100 тыс. Оценок в диапазоне от 1 до 5, от 943 пользователей на 1682 фильмах, и сделали разбиение по времени на поезд-тест 80–20 т. Е. использовали первые 80% рейтингов для обучения и оставшиеся 20% для тестирования.

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

for each epoch:
   for each pair of (user, movie):
   b_i =  b_i - learning_rate * dL/db_i
   c_j =  c_j - learning_rate * dL/dc_j

Для простоты мы сохраняем user_bias и смещение фильма только в качестве обучаемых параметров, мы вычисляем векторы User и Movie с использованием SVD (вы можете думать о SVD как о методе матричной факторизации. ).

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

ее dl / db_i относится к производной от предвзятости пользователя, а dl / dc_j относится к производной от предвзятости фильма.

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

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

def fit_recommender(total_epochs,learning_rate,train_sparse_matrix,train_df,test_df,svd_components = 5):
    '''learns parameters for the recommednder'''
    total_train_mse = []
    total_test_mse = []
    U1, Sigma, V1 = randomized_svd(train_sparse_matrix,      n_components=svd_components,n_iter=2, random_state=24)
    total_train_mse = []
    total_test_mse = []
    for epoch in range(total_epochs):
        for user,movie,rate in train_df[['user','movie','rating']].values:
            b_i[user] = b_i[user] - learning_rate *  derivative_db(user,movie,rate,U1,V1,mu,alpha) 
            c_j[movie] = c_j[movie] - learning_rate *  derivative_dc(user,movie,rate,U1,V1,mu,alpha)
        train_error = get_prediction(train_df,b_i,c_j,mu)
        test_error = get_prediction(test_df,b_i,c_j,mu)
        total_train_mse.append(train_error)
        total_test_mse.append(test_error)
        print("After Epoch {}------Train rmse:{}  Test rmse:{}".format(epoch,train_error,test_error))
     print("=======================================================")

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

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

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

Нам нужно построить набор данных немного по-другому, чтобы сюрприз сработал.

from surprise import Reader, Dataset
reader = Reader(rating_scale=(1,5))
# create the traindata from the dataframe...
train_data = Dataset.load_from_df(train_df[['user', 'movie', 'rating']], reader)
# build the trainset from traindata.., It is of dataset format from surprise library..
trainset = train_data.build_full_trainset() # we have to convert testset into list tuples of user,movie,rating
testset = list(zip(test_df.user.values, test_df.movie.values, test_df.rating.values))

Из класса набора данных мы вызываем функцию load_from_df, которая строит набор поездов в требуемом формате, теперь давайте создадим нашу рекомендательную систему

def run_surpise(surprise_algo,trainset):
    svd.fit(trainset)
    train_preds = svd.test(trainset.build_testset())
    train_actual_ratings, train_pred_ratings = get_ratings(train_preds)
    train_rmse = get_errors(train_preds) 
    test_preds = svd.test(testset)
    test_actual_ratings, test_pred_ratings = get_ratings(test_preds)
    test_rmse = get_errors(test_preds)    
    print("Train RMSE : {}  Test RMSE : {}".format(train_rmse,test_rmse))

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

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

ПРОБЛЕМА ХОЛОДНОГО СТАРТА

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

ЗАКЛЮЧЕНИЕ

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

Ссылка на репозиторий: https://github.com/ravi207/RecommenderSystem/blob/main/recommender_system.ipynb

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

ССЫЛКИ

[1] https://en.wikipedia.org/wiki/Recommender_system

[2] Ф. Максвелл Харпер и Джозеф А. Констан. 2015. Наборы данных MovieLens: история и контекст. Транзакции ACM в интерактивных интеллектуальных системах (TiiS) 5, 4: 19: 1–19: 19. Https://doi.org/10.1145/2827872