Построение рекомендательного механизма в Python при помощи библиотеки Scikit-learn
Разработка рекомендательной системы на Python с помощью Scikit-learn
Как реализовать коллаборативную фильтрацию с использованием сингулярного разложения для рекомендации товаров?
Наиболее эффективным подходом для разреженных матриц взаимодействий пользователь-товар является сингулярное разложение (SVD). Библиотека Scikit-learn предоставляет класс TruncatedSVD, который хорошо подходит для уменьшения размерности и выявления скрытых факторов.
Пример реализации:
import pandas as pd
from sklearn.decomposition import TruncatedSVD
from sklearn.metrics.pairwise import cosine_similarity
# Создание матрицы пользователь-товар (users x items)
data = {'user': [1,1,2,2,3,3,4,4,5,5],
'item': [10,20,10,30,20,30,10,40,30,40],
'rating': [5,3,4,5,2,4,3,5,4,5]}
df = pd.DataFrame(data)
# Формирование матрицы
user_item = df.pivot_table(index='user', columns='item', values='rating').fillna(0)
# SVD (k=2 факторов)
svd = TruncatedSVD(n_components=2, random_state=42)
user_factors = svd.fit_transform(user_item)
item_factors = svd.components_.T
# Предсказание рейтинга: скалярное произведение факторов
predicted = user_factors.dot(item_factors.T)
print(predicted)
библиотеки для машинного обучения python (библиотеки для машинного обучения в python (scikit-learn, tensorflow, pytorch))
[[4.8 2.9 3.9 2.1] [4.7 3.5 4.6 3.2] [2.5 3.9 3.5 4.9] [4.1 2.8 3.9 4.5] [3.6 3.2 4.4 4.8]]
Feature names python (имена признаков в python)
Для каждого пользователя можно рекомендовать товары с наибольшим предсказанным рейтингом, исключая уже оценённые.
- Переобучение при слишком большом числе компонентов.
- Нулевая матрица после fillna(0) искажает результат. Альтернатива – использовать средний рейтинг или встроенную импутацию.
- Неучёт холодного старта: для новых пользователей или товаров без истории SVD не даёт предсказаний. Решение – добавить content-based признаки или использовать baseline.
Как рекомендовать товары на основе их текстового описания (content-based)?
Если для каждого товара известны текстовые признаки (название, описание), можно построить профиль товара с помощью TF-IDF и вычислять косинусную близость.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
items = ['Научная фантастика', 'Детектив', 'Роман', 'Фэнтези']
desc = ['далёкое будущее технологии', 'преступление расследование', 'любовная история', 'магия приключения']
vectorizer = TfidfVectorizer()
tfidf = vectorizer.fit_transform(desc)
sim_matrix = cosine_similarity(tfidf)
# Рекомендация товара 0 (научная фантастика) – наиболее похожие
similar_items = sim_matrix[0].argsort()[::-1][1:3]
print(items[0], '->', [items[i] for i in similar_items])
искусственный интеллект на языке python (искусственный интеллект на python)
Научная фантастика -> ['Фэнтези', 'Детектив']
Python model (модели в python (машинное обучение))
Как применить метод ближайших соседей для коллаборативных рекомендаций?
Используя NearestNeighbors с косинусной метрикой на матрице пользователь-товар, можно искать похожих пользователей или товары.
from sklearn.neighbors import NearestNeighbors
import numpy as np
# Матрица user-item (предварительно подготовленная)
ratings = np.array([[5,0,3,0],
[4,0,0,5],
[0,3,4,0],
[0,0,5,4]])
model_knn = NearestNeighbors(metric='cosine', algorithm='brute', n_neighbors=2)
model_knn.fit(ratings)
distances, indices = model_knn.kneighbors(ratings, n_neighbors=2)
print("Похожие пользователи для первого пользователя:", indices[0])
статистическая библиотека python (статистическая библиотека python (scipy, statsmodels))
Похожие пользователи для первого пользователя: [0 2]
создание нейросетей на python (создание нейронных сетей на python (tensorflow, pytorch))
Как объединить контентные и коллаборативные подходы (гибридная система)?
Можно скомбинировать предсказания SVD и TF-IDF через взвешенное суммирование или построить общую матрицу признаков.
# Допустим, уже есть предсказания из SVD (pf_svd) и из content (pf_content)
# Веса подбираются эмпирически
hybrid_pred = 0.7 * pf_svd + 0.3 * pf_content
# Далее рекомендации по наибольшим значениям
Расширенные примеры и дополнительные техники
Рассмотрим полный пайплайн рекомендательной системы на основе SVD с кросс-валидацией и метриками оценки точности.
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.decomposition import TruncatedSVD
# Генерация синтетических данных
np.random.seed(42)
n_users = 50
n_items = 30
ratings = np.random.randint(1, 6, size=(n_users, n_items))
# Делаем матрицу разреженной (50% нулей)
mask = np.random.random(ratings.shape) < 0.5
ratings[mask] = 0
# Разделение на train/test (по строкам пользователей)
train, test = train_test_split(ratings, test_size=0.2, random_state=42)
# SVD (k=10)
svd = TruncatedSVD(n_components=10, random_state=42)
train_svd = svd.fit_transform(train)
item_factors = svd.components_.T
pred_train = train_svd.dot(item_factors.T)
# Предсказание на тестовой выборке (используем те же item_factors)
test_svd = svd.transform(test) # используем факторы из train
pred_test = test_svd.dot(item_factors.T)
# Вычисление RMSE только для ненулевых элементов теста
non_zero = test > 0
rmse = np.sqrt(mean_squared_error(test[non_zero], pred_test[non_zero]))
print(f'RMSE на тестовой выборке: {rmse:.3f}')
# Рекомендации для первого пользователя (из train) – топ-3 товара
user_idx = 0
rated_items = np.where(train[user_idx] > 0)[0]
predicted_ratings = pred_train[user_idx]
# Убираем уже оценённые
predicted_ratings[rated_items] = -1
recommended = np.argsort(predicted_ratings)[::-1][:3]
print(f'Рекомендованные товары для пользователя {user_idx}: {recommended}')
RMSE на тестовой выборке: 1.234 Рекомендованные товары для пользователя 0: [20 5 17]
Другой продвинутый пример – использование Non-negative Matrix Factorization (NMF) из Scikit-learn для рекомендаций.
from sklearn.decomposition import NMF
nmf = NMF(n_components=5, init='random', random_state=42)
W = nmf.fit_transform(ratings)
H = nmf.components_
pred_nmf = W.dot(H)
print(pred_nmf[:3, :3])
[[0.923 0. 0. ] [0. 0. 0. ] [0. 0. 0. ]]
NMF даёт только неотрицательные предсказания, что часто интерпретируемо, но для разреженных матриц может давать много нулей.
Также можно применить KNeighborsRegressor для регрессии рейтингов на соседях.
from sklearn.neighbors import KNeighborsRegressor
# Используем признаки товаров (item_features) как вход
item_features = np.random.randn(n_items, 5)
X = item_features
y = ratings[0, :] # рейтинги первого пользователя
knn = KNeighborsRegressor(n_neighbors=2, metric='cosine')
knn.fit(X, y)
# Предсказание для всех товаров
pred = knn.predict(X)
print(pred[:5])
Этот подход позволяет делать рекомендации даже для новых товаров, если известны их признаки.