Введение в коллаборативную фильтрацию

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

Понимание коллаборативной фильтрации

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

Пользовательская и товарная коллаборативная фильтрация

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

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

В нашем примере мы сосредоточимся на пользовательской коллаборативной фильтрации.

Создание матрицы «пользователь-объект»

Сердцем коллаборативной фильтрации является матрица «пользователь-объект». Это большая таблица, где пользователи перечислены с одной стороны, а фильмы — с другой. Каждая ячейка в матрице указывает, взаимодействовал ли пользователь с определённым фильмом.

graph TD A("User 1") -->|Liked|B(Movie A) B("User 1") -->|Liked|C(Movie B) C("User 1") -->|Not Liked|D(Movie C) D("User 2") -->|Liked|B(Movie A) E("User 2") -->|Liked|D(Movie C) F("User 3") -->|Liked|C(Movie B) G("User 3") -->|Not Liked| H("Movie C")

Пошаговое руководство по созданию системы рекомендаций

Шаг 1: Подготовка данных

Для начала вам нужен набор данных о взаимодействии пользователей с фильмами. Популярный набор данных для этой цели — MovieLens, который содержит оценки пользователей для различных фильмов.

Python

import pandas as pd

# Загрузка набора данных MovieLens
ratings_df = pd.read_csv('u.data', sep='\t', header=None, names=['userId', 'movieId', 'rating', 'timestamp'])
movies_df = pd.read_csv('u.item', sep='|', header=None, names=['movieId', 'title', 'release_date', 'video_release_date', 'IMDB_URL', 'unknown', 'Action', 'Adventure', 'Animation', 'Children', 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'IMAX', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War', 'Western'])

Шаг 2: Создание матрицы «пользователь-объект»

Далее вам нужно создать матрицу «пользователь-объект» из данных оценок.

Python

# Создание матрицы «пользователь-объект»
user_item_matrix = ratings_df.pivot(index='userId', columns='movieId', values='rating')

Шаг 3: Реализация коллаборативной фильтрации

Мы будем использовать алгоритм K-ближайших соседей (KNN) для поиска похожих пользователей.

Python

from sklearn.neighbors import NearestNeighbors

# Функция для поиска похожих пользователей
def find_similar_users(user_id, n_neighbors=10):
    # Создаём модель KNN
    knn = NearestNeighbors(n_neighbors=n_neighbors, algorithm='brute', metric='cosine')
    knn.fit(user_item_matrix)

    # Находим похожих пользователей
    distances, indices = knn.kneighbors(user_item_matrix.loc[user_id].values.reshape(1, -1))
    similar_users = user_item_matrix.index[indices.flatten()]
    return similar_users

# Функция для генерации рекомендаций
def generate_recommendations(user_id, n_recs=10):
    similar_users = find_similar_users(user_id)
    recommended_movies = []

    for user in similar_users:
        movies_liked_by_user = user_item_matrix.loc[user][user_item_matrix.loc[user] > 0].index
        recommended_movies.extend(movies_liked_by_user)

    # Удаляем фильмы, уже понравившиеся целевому пользователю
    recommended_movies = [movie for movie in recommended_movies if user_item_matrix.loc[user_id, movie] == 0]

    # Возвращаем топ N рекомендаций
    return recommended_movies[:n_recs]

# Пример использования
user_id = 1
recommended_movies = generate_recommendations(user_id)
print("Рекомендованные фильмы для пользователя", user_id, ":", recommended_movies)

Шаг 4: Работа с проблемой холодного старта и предвзятостью популярности

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

  • Проблема холодного старта: она возникает, когда новые пользователи или фильмы добавляются в систему, и недостаточно данных для точных рекомендаций. Один из способов решения — использование гибридных моделей, сочетающих коллаборативную и контентную фильтрацию.
  • Предвзятость популярности: происходит, когда популярные товары рекомендуются чаще, затмевая менее известные, но потенциально интересные. Методы, такие как матричная факторизация, помогают смягчить эту проблему, уменьшая размерность матрицы «пользователь-объект» и фокусируясь на скрытых факторах, а не на необработанных оценках.

Продвинутые техники: матричная факторизация

Матричная факторизация — более продвинутая техника, которая уменьшает размерность матрицы «пользователь-объект», представляя пользователей и фильмы как низкоразмерные векторы (вложения). Этот подход можно реализовать с помощью нейронных сетей.

Python

from keras import layers, models

# Определение архитектуры модели
class RecommenderNet(models.Model):
    def __init__(self, num_users, num_movies, embedding_size):
        super(RecommenderNet, self).__init__()
        self.user_embedding = layers.Embedding(num_users, embedding_size, input_length=1)
        self.movie_embedding = layers.Embedding(num_movies, embedding_size, input_length=1)
        self.dot_product = layers.Dot(axes=-1)
        self.bias_user = layers.Embedding(num_users, 1, input_length=1)
        self.bias_movie = layers.Embedding(num_movies, 1, input_length=1)
        self.sigmoid = layers.Activation('sigmoid')

    def call(self, inputs):
        user_id, movie_id = inputs
        user_embedding = self.user_embedding(user_id)
        movie_embedding = self.movie_embedding(movie_id)
        dot_product = self.dot_product([user_embedding, movie_embedding])
        user_bias = self.bias_user(user_id)
        movie_bias = self.bias_movie(movie_id)
        x = dot_product + user_bias + movie_bias
        return self.sigmoid(x)

# Компиляция модели
model = RecommenderNet(num_users, num_movies, embedding_size)
model.compile(loss='binary_crossentropy', optimizer='adam')

# Обучение модели
model.fit(x_train, y_train, epochs=5, batch_size=64, validation_data=(x_val, y_val))

Заключение

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

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

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