Загрузка урока...
Изучите коллаборативную фильтрацию — подход, основанный на поведении всех пользователей. Разберём user-user и item-item подходы, а также матричную факторизацию (SVD), которая лежит в основе Netflix Prize. Реализация на Python с использованием библиотеки surprise.
Введение
Коллаборативная фильтрация — это «социальный» подход к рекомендациям. Она не смотрит на свойства товаров, а анализирует поведение всех пользователей. Если пользователи А и Б купили одни и те же товары, то то, что понравилось А, вероятно, понравится и Б.
Этот подход принёс команде BellKor победу в конкурсе Netflix Prize с призовым фондом $1 000 000.
Два подхода к коллаборативной фильтрации
Подход 1. User-User коллаборативная фильтрация
Шаги:
Строим матрицу «пользователь → товар» с оценками
Находим K самых похожих пользователей к целевому
Берём товары, которые понравились похожим пользователям
Рекомендуем с учётом степени похожести
Реализация user-user:
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
# Данные: оценки пользователей (1-5)
ratings_data = pd.DataFrame([
# пользователь, товар, оценка
[1, 'джинсы', 5],
[1, 'футболка', 4],
[1, 'кеды', 3],
[2, 'джинсы', 4],
[2, 'футболка', 5],
[2, 'куртка', 4],
[3, 'кеды', 5],
[3, 'куртка', 4],
[3, 'футболка', 3],
[4, 'джинсы', 3],
[4, 'куртка', 5],
], columns=['user_id', 'item_id', 'rating'])
# Создаём матрицу user-item
user_item_matrix = ratings_data.pivot_table(
index='user_id',
columns='item_id',
values='rating',
fill_value=0
)
print("Матрица пользователь-товар:")
print(user_item_matrix)
# Вычисляем похожесть пользователей
user_similarity = cosine_similarity(user_item_matrix)
user_similarity_df = pd.DataFrame(
user_similarity,
index=user_item_matrix.index,
columns=user_item_matrix.index
)
print("\nПохожесть пользователей:")
print(user_similarity_df)
# Функция для user-user рекомендаций
def recommend_user_based(target_user_id, user_item_matrix, user_similarity_df, top_n=3):
# Товары, которые пользователь уже оценил
rated_items = user_item_matrix.loc[target_user_id]
rated_items = rated_items[rated_items > 0].index.tolist()
# Похожие пользователи (без самого себя)
similar_users = user_similarity_df[target_user_id].sort_values(ascending=False)
similar_users = similar_users[similar_users.index != target_user_id]
# Считаем предсказания для каждого товара
predictions = {}
for item in user_item_matrix.columns:
if item in rated_items:
continue # Не рекомендуем уже оценённые
# Взвешенная сумма оценок похожих пользователей
weighted_sum = 0
similarity_sum = 0
for other_user, similarity in similar_users.items():
rating = user_item_matrix.loc[other_user, item]
if rating > 0:
weighted_sum += similarity * rating
similarity_sum += similarity
if similarity_sum > 0:
predictions[item] = weighted_sum / similarity_sum
# Сортируем по предсказанной оценке
recommendations = sorted(predictions.items(), key=lambda x: x[1], reverse=True)
return recommendations[:top_n]
# Рекомендации для пользователя 1
recs = recommend_user_based(1, user_item_matrix, user_similarity_df, top_n=3)
print("\nРекомендации для пользователя 1 (user-user):")
for item, score in recs:
print(f" {item}: предсказанная оценка = {score:.2f}")Подход 2. Item-Item коллаборативная фильтрация
# Транспонируем матрицу для item-item
item_user_matrix = user_item_matrix.T
# Вычисляем похожесть товаров
item_similarity = cosine_similarity(item_user_matrix)
item_similarity_df = pd.DataFrame(
item_similarity,
index=item_user_matrix.index,
columns=item_user_matrix.index
)
print("\nПохожесть товаров (item-item):")
print(item_similarity_df)
# Функция для item-item рекомендаций
def recommend_item_based(target_user_id, user_item_matrix, item_similarity_df, top_n=3):
# Товары, которые пользователь оценил
user_ratings = user_item_matrix.loc[target_user_id]
rated_items = user_ratings[user_ratings > 0]
# Для каждого товара считаем похожие
recommendations = {}
for item, rating in rated_items.items():
similar_items = item_similarity_df[item].sort_values(ascending=False)
similar_items = similar_items[similar_items.index != item]
for sim_item, similarity in similar_items.items():
if sim_item not in recommendations:
recommendations[sim_item] = 0
recommendations[sim_item] += similarity * rating
# Убираем уже оценённые
for item in rated_items.index:
recommendations.pop(item, None)
# Сортируем и возвращаем
recommendations = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
return recommendations[:top_n]
# Рекомендации для пользователя 1 (item-item)
recs = recommend_item_based(1, user_item_matrix, item_similarity_df, top_n=3)
print("\nРекомендации для пользователя 1 (item-item):")
for item, score in recs:
print(f" {item}: взвешенная сумма = {score:.2f}")Подход 3. Матричная факторизация (SVD)
Этот метод стал прорывом в Netflix Prize. Идея: разложить матрицу пользователь-товар на две маленькие матрицы, которые представляют «скрытые факторы».
Как это работает:
Исходная матрица R (пользователи × товары) ≈ P × Q^T
Где:
- P — матрица пользователей в пространстве факторов
- Q — матрица товаров в пространстве факторов
- k — количество скрытых факторов (например, 10–100)Скрытые факторы для фильмов (пример):
Предсказание оценки: сумма произведений факторов.
Реализация SVD с библиотекой surprise:
# Установка: pip install scikit-surprise
from surprise import Dataset, Reader, SVD
from surprise.model_selection import train_test_split
import pandas as pd
# Подготовка данных
reader = Reader(rating_scale=(1, 5))
data = Dataset.load_from_df(ratings_data[['user_id', 'item_id', 'rating']], reader)
# Разделение на train и test
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)
# Создание и обучение SVD модели
model = SVD(n_factors=10, n_epochs=20, lr_all=0.005, reg_all=0.02)
model.fit(trainset)
# Предсказание для конкретного пользователя и товара
user_id = 1
item_id = 'куртка'
pred = model.predict(user_id, item_id)
print(f"\nПредсказание: пользователь {user_id} оценит '{item_id}' на {pred.est:.2f}")
# Рекомендации для пользователя (все товары)
def recommend_svd(user_id, model, items, rated_items, top_n=5):
predictions = []
for item in items:
if item in rated_items:
continue
pred = model.predict(user_id, item)
predictions.append((item, pred.est))
predictions.sort(key=lambda x: x[1], reverse=True)
return predictions[:top_n]
# Все товары и уже оценённые
all_items = user_item_matrix.columns.tolist()
rated_items = user_item_matrix.loc[1][user_item_matrix.loc[1] > 0].index.tolist()
recs = recommend_svd(1, model, all_items, rated_items, top_n=3)
print("\nРекомендации SVD для пользователя 1:")
for item, score in recs:
print(f" {item}: предсказанная оценка = {score:.2f}")Сравнение подходов
Проблема холодного старта для коллаборативной фильтрации
Гибридные системы (лучшее из двух миров)
# Простая гибридная модель: взвешенная сумма
def hybrid_recommend(user_id, item_id, model_svd, content_similarity, alpha=0.5):
# SVD предсказание (коллаборативное)
svd_pred = model_svd.predict(user_id, item_id).est
# Контентная близость (заглушка, нужно вычислять)
content_pred = content_similarity # значение от 1 до 5
# Взвешенная сумма
hybrid_pred = alpha * svd_pred + (1 - alpha) * content_pred
return hybrid_pred
print(f"Гибридное предсказание (alpha=0.5): {hybrid_recommend(1, 'куртка', model, 4.2, 0.5):.2f}")Реальные примеры внедрения
Резюме урока
Коллаборативная фильтрация и матричная факторизация — основа современных рекомендательных систем:
User-User — для небольших сообществ
Item-Item — для маркетплейсов с миллионами пользователей
SVD — для максимальной точности
Гибридные системы (коллаборативная + контентная) дают лучший результат.
Контрольные вопросы
Чем user-user отличается от item-item коллаборативной фильтрации?
Что такое скрытые факторы в SVD?
Какую проблему решает матричная факторизация?
Какая библиотека Python используется для SVD?
Что такое холодный старт и как его преодолеть?
В этом материале нет файлов для просмотра.