Обязательно

Матричные разложения

Раскладываем матрицу user-item на латентные факторы — база всех современных подходов

Время изучения: 20 мин

Идея матричных разложений

Коллаборативная фильтрация на основе kNN работает, но масштабируется плохо. Матричные разложения — элегантная альтернатива: вместо поиска соседей мы раскладываем матрицу оценок R на произведение двух маленьких матриц. Каждому пользователю и товару соответствует вектор «латентных факторов» — скрытых характеристик.

RPQR \approx P \cdot Q^\top

R — матрица оценок (m×n), P — матрица пользователей (m×k), Q — матрица товаров (n×k)

Что такое латентные факторы? Для фильмов это могут быть «комедия vs драма», «новый vs классический», «экшн vs спокойный». Мы не задаём их явно — модель находит сама. Предсказание оценки — скалярное произведение векторов пользователя и товара.

r^ui=puqi=f=1kpufqif\hat{r}_{ui} = p_u \cdot q_i = \sum_{f=1}^{k} p_{uf} \cdot q_{if}

Предсказание: скалярное произведение латентных векторов

SVD — Singular Value Decomposition

Классическое SVD из линейной алгебры раскладывает любую матрицу:

R=UΣVR = U \Sigma V^\top

U — ортогональная (m×m), Σ — диагональная (m×n), V — ортогональная (n×n)

Проблема: классическое SVD требует полностью заполненную матрицу. А в рекомендациях 99% ячеек пустые — пользователь оценил только малую часть каталога. Поэтому напрямую SVD не применимо, и нам нужны модификации.

Funk SVD — оптимизация через SGD

Simon Funk предложил простое решение на Netflix Prize (2006): не раскладывать всю матрицу, а минимизировать ошибку только на известных оценках. Оптимизируем через стохастический градиентный спуск (SGD):

minP,Q(u,i)K(ruipuqi)2+λ(pu2+qi2)\min_{P, Q} \sum_{(u,i) \in \mathcal{K}} (r_{ui} - p_u \cdot q_i)^2 + \lambda(\|p_u\|^2 + \|q_i\|^2)

K — множество известных оценок, λ — регуляризация

  • Суммируем ошибку только по известным парам (u, i) — пропуски игнорируем
  • Добавляем L2-регуляризацию, чтобы не переобучиться
  • SGD обновляет p_u и q_i после каждой оценки — быстро сходится
  • Часто добавляют bias-ы: r̂_ui = μ + b_u + b_i + p_u·q_i (глобальное среднее + bias пользователя + bias товара)

ALS — Alternating Least Squares

Альтернативный подход к оптимизации: вместо SGD чередуем два шага. Фиксируем Q — находим оптимальное P (обычный метод наименьших квадратов). Затем фиксируем P — находим оптимальное Q. Повторяем до сходимости.

  • Каждый шаг — решение линейной системы уравнений, а не градиентный спуск
  • Каждый подшаг — выпуклая задача → гарантированно находим оптимум
  • Легко параллелится: обновления p_u для разных пользователей независимы
  • Идеально подходит для распределённых систем (Apache Spark MLlib)

ALS vs SGD — когда что?

SGD — быстрее на одной машине, легко реализовать, хорошо работает с explicit feedback. ALS — лучше параллелится (стандарт в Spark), естественнее работает с implicit feedback, стабильнее сходится. Для production-систем с миллионами пользователей ALS + Spark — типичный выбор.

Implicit Feedback

В реальности явных оценок (1-5 звёзд) мало. Чаще есть только implicit feedback: клики, просмотры, покупки, время на странице. Hu, Koren & Volinsky (2008) предложили модификацию матричных разложений для этого случая.

Ключевая идея: вводим два понятия. Preference — нравится или нет (бинарная). Confidence — насколько мы уверены в этом.

pui={1,rui>00,rui=0,cui=1+αruip_{ui} = \begin{cases} 1, & r_{ui} > 0 \\ 0, & r_{ui} = 0 \end{cases}, \quad c_{ui} = 1 + \alpha \cdot r_{ui}

p — preference (бинарная), c — confidence (растёт с количеством взаимодействий)

Если пользователь купил товар 5 раз — мы более уверены, что он нравится, чем если купил 1 раз. А отсутствие взаимодействия не означает «не нравится» — может, пользователь просто не видел товар.

NMF — Non-negative Matrix Factorization

NMF — разложение с ограничением: все элементы P и Q должны быть ≥ 0. Это даёт интерпретируемость: латентные факторы можно читать как «степень принадлежности» к теме.

  • Фактор = тема/жанр, значение = «насколько этот фильм — комедия»
  • Нет отрицательных значений → легче объяснить бизнесу
  • Используется не только в RecSys: тематическое моделирование, анализ изображений
  • Обычно чуть хуже по качеству, чем SVD/ALS, но выигрывает в интерпретируемости

Регуляризация в матричных разложениях

Без регуляризации матричное разложение легко переобучается — особенно при разреженных данных. Стандартные приёмы:

  • L2-регуляризация весов (λ·(||P||² + ||Q||²)) — основной метод, всегда используется
  • Bias-ы пользователей и товаров — вынесение систематических отклонений отдельно
  • Число латентных факторов k — чем больше k, тем больше параметров и риск переобучения. Типичные значения: 20-200
  • Ранняя остановка по валидационной метрике (RMSE на отложенных оценках)

Библиотека Surprise

Surprise — Python-библиотека для экспериментов с рекомендациями. Из коробки: SVD, SVD++, NMF, kNN-based CF, кросс-валидация.

from surprise import SVD, Dataset, accuracy
from surprise.model_selection import cross_validate

# Загружаем встроенный датасет MovieLens 100K
data = Dataset.load_builtin('ml-100k')

# SVD с 50 латентными факторами
algo = SVD(n_factors=50, n_epochs=20, lr_all=0.005, reg_all=0.02)

# 5-fold кросс-валидация
results = cross_validate(algo, data, measures=['RMSE', 'MAE'], cv=5, verbose=True)
print(f"Mean RMSE: {results['test_rmse'].mean():.4f}")

Итого

  • Матричные разложения: R ≈ P·Qᵀ — находим латентные факторы пользователей и товаров
  • Классическое SVD не работает с пропусками → используем Funk SVD (SGD) или ALS
  • ALS — стандарт для больших систем (Spark), SGD — быстрее на одной машине
  • Implicit feedback: вводим confidence weights — чем больше взаимодействий, тем увереннее
  • NMF — интерпретируемое разложение (все значения ≥ 0)
  • Регуляризация обязательна: L2, bias-ы, выбор числа факторов k
  • Surprise — отличная библиотека для старта экспериментов