Инструменты и кейс на MovieLens

Финальный урок: обзор библиотек рекомендаций и сквозной мини-кейс рекомендателя фильмов в духе датасета MovieLens — целиком на stdlib.

MovieLens — классический открытый датасет оценок фильмов, на котором традиционно учат и сравнивают рекомендательные алгоритмы.

Обзор инструментов

В реальных проектах алгоритмы из курса не пишут с нуля — берут проверенные библиотеки. Важно понимать, какая для чего.

БиблиотекаСильна вКогда брать
SurpriseЯвный фидбэк, SVD/KNN, оценка метрикУчебные и небольшие проекты на оценках
implicitНеявный фидбэк, ALS, BPR, быстроКлики/покупки, продакшн средних масштабов
LightFMГибрид: CF + контентные признакиХолодный старт, нужны фичи товаров
RecBoleДесятки моделей, включая deep/sequentialИсследования, сравнение подходов

Также в экосистеме: FAISS/HNSWlib и векторные БД для ANN-этапа, XGBoost/LightGBM/CatBoost для ранжирования, PyTorch для two-tower и трансформеров. Эти инструменты требуют сторонних пакетов, поэтому код ниже — не на них, а сквозная демонстрация идей на stdlib.

Кейс: рекомендатель фильмов

Соберём всё в один маленький конвейер на оценках в духе MovieLens: item-based похожесть фильмов → персональный прогноз для пользователя → отбор top-N. Данные крошечные, но логика — настоящая.

import math
from collections import defaultdict

# оценки пользователь -> {фильм: оценка}
ratings = {
    "Аня":   {"Матрица": 5, "Дюна": 4, "Титаник": 2, "Аватар": 4},
    "Борис": {"Матрица": 5, "Дюна": 5, "Аватар": 4},
    "Вера":  {"Титаник": 5, "Дневник": 5, "Матрица": 1},
    "Глеб":  {"Матрица": 4, "Дюна": 4, "Аватар": 5, "Дневник": 1},
}

# вектор оценок по фильму (item -> {user: rating})
item_vec = defaultdict(dict)
for u, rs in ratings.items():
    for film, r in rs.items():
        item_vec[film][u] = r

def cosine(a, b):
    common = set(a) & set(b)
    if not common:
        return 0.0
    num = sum(a[u] * b[u] for u in common)
    na = math.sqrt(sum(v*v for v in a.values()))
    nb = math.sqrt(sum(v*v for v in b.values()))
    return num / (na * nb) if na and nb else 0.0

def recommend(user, n=2):
    seen = ratings[user]
    scores = {}
    for film in item_vec:
        if film in seen:
            continue
        num = den = 0.0
        for liked, r in seen.items():
            s = cosine(item_vec[film], item_vec[liked])
            num += s * r
            den += s
        if den > 0:
            scores[film] = num / den
    return sorted(scores.items(), key=lambda x: -x[1])[:n]

for film, score in recommend("Борис"):
    print(f"Борису: {film} (прогноз {round(score, 2)})")

Вывод:

Борису: Титаник (прогноз 4.73)
Борису: Дневник (прогноз 4.71)

Борис любит фантастику (Матрица, Дюна, Аватар). Из невиденного «Титаник» получает чуть более высокий прогноз, чем «Дневник». Прогнозы близки и завышены — это честная иллюстрация ограничений крошечных данных: фильмы пересекаются почти по одним и тем же пользователям, поэтому их item-item похожести высоки и слабо различают вкусы. На реальном MovieLens с тысячами оценок такие различия становятся куда выразительнее, а нормировка похожестей и вычитание средних делают прогнозы аккуратнее.

Как работает под капотом и куда расти

Этот кейс — компактная item-based CF: тот же приём, что у Amazon, только на оценках вместо кликов. В настоящем MovieLens-пайплайне дальше идёт всё, что мы изучили: разложение матрицы для борьбы с разреженностью, контентные признаки фильмов для холодного старта, two-tower и ANN для масштаба, бустинг для ранжирования, метрики precision@k/NDCG и A/B-тест для проверки. Начав с такого ядра и постепенно подключая библиотеки, вы пройдёте путь от учебного примера до промышленной системы.

Частые ошибки

  • Сразу хвататься за deep learning. На малых данных простая item-based CF или MF часто не уступает; усложняйте по необходимости.
  • Брать библиотеку не под тип фидбэка. Surprise — про оценки, implicit — про клики; перепутать значит мучиться.
  • Оценивать кейс только глазами. Даже маленький рекомендатель надо мерить метриками на отложенной выборке.

Итоги

  • Surprise — для оценок, implicit — для неявного, LightFM — гибрид, RecBole — исследования.
  • Реальный кейс собирает весь курс: похожесть, разложение, контент, масштаб, метрики.
  • Item-based CF на оценках MovieLens — рабочее ядро, с которого удобно начинать.
  • Усложнять модель стоит по мере роста данных, а качество всегда подтверждать метриками и A/B.
Проверьте себя
1. Какую библиотеку логичнее взять для рекомендаций на неявном фидбэке (клики, покупки)?
ASurprise
Bimplicit
CЛюбую — разницы нет
DНикакую, только ручной код
2. Чем по сути является собранный кейс-рекомендатель фильмов на MovieLens?
AГлубокой нейросетью-трансформером
BItem-based коллаборативной фильтрацией: похожесть фильмов плюс взвешенный прогноз
CЧистой популярностью без персонализации
DКонтентной моделью на TF-IDF