Построение рекомендательного механизма в Python при помощи библиотеки Scikit-learn

Раздел: Прикладные задачи -> 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))

Сложности: разреженность матрицы ведёт к неточным расстояниям; холодный старт не решается; большие объёмы данных требуют оптимизации (ball_tree, kd_tree).

Как объединить контентные и коллаборативные подходы (гибридная система)?

Можно скомбинировать предсказания SVD и TF-IDF через взвешенное суммирование или построить общую матрицу признаков.


# Допустим, уже есть предсказания из SVD (pf_svd) и из content (pf_content)
# Веса подбираются эмпирически
hybrid_pred = 0.7 * pf_svd + 0.3 * pf_content
# Далее рекомендации по наибольшим значениям
Ошибки: неверный выбор весов; перекос в сторону одного метода; сложность отладки.
- машинное обучение на данных python (машинное обучение на данных с помощью python)
- нейросеть с помощью python (нейросети на python)
- Ai script python (скрипты для искусственного интеллекта на python)

Расширенные примеры и дополнительные техники

Рассмотрим полный пайплайн рекомендательной системы на основе 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])

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

Разработка рекомендательной системы на Python - comments

En
рекомендательная система python (python)