Item-based collaborative filtering
Фильмы похожи, если их оценивали одни и те же люди (косинус по столбцам матрицы взаимодействий). Никаких жанров — только поведение.
score — внутренний ранжировочный балл (сумма похожестей соседей, взвешенная твоими оценками). Это не рейтинг 1–5, не вероятность и не «качество» фильма; сравнивать его можно только внутри одного пользователя и одной модели.
Жанры на карточках показаны только для интерпретации в интерфейсе — модель их не использует (item-CF смотрит лишь на поведение).
Матрица сходства: топ-15 популярных фильмов
Ярче клетка — сильнее «совместная» похожесть (часто оцениваются вместе). Диагональ приглушена (сходство фильма с самим собой = 1). Наведи на клетку — покажет точное значение.
Осторожно с интуицией. У популярных фильмов сходство часто завышено: их смотрит широкая аудитория, поэтому у них много общих зрителей — но это не всегда настоящая вкусовая близость, а popularity bias. Именно поэтому нужны shrinkage (мы уже применяем, λ=20), centering и осторожная интерпретация cosine.
Теория простым языком
Коллаборативная фильтрация рекомендует на основе поведения людей, а не описаний. Главная мысль: «кто смотрел этот фильм, часто смотрел и вот этот» — значит, эти два фильма похожи, даже если у них разные жанры.
Чем это отличается от content-based
Content-based смотрел внутрь фильма (жанры, теги). Здесь мы про содержание фильма не знаем ничего — смотрим только на то, кто что оценил. Этот подход так и называется:
Бывает двух видов: смотреть на похожих пользователей («такие же люди, как ты, любят…») или на похожие айтемы («к этому фильму обычно идёт вот этот»). Мы реализовали второй — item-based, и точно не потому, что айтемов «меньше»: у нас как раз наоборот, 610 пользователей и 9724 фильма.
Выбор здесь не универсальный, а из сравнения двух вещей. Первая — что быстрее устаревает: на каталоге фильмов похожесть двух картин почти не двигается от одного нового просмотра, а профиль человека двигается сразу; в новостной ленте всё наоборот — там айтемы живут часы. Вторая — что больше: матрица похожестей квадратична по своей стороне, и при 10⁸ пользователей user-user просто не соберётся, а при 10⁴ айтемов item-item соберётся легко. Предрассчитать можно обе; вопрос в том, как часто пересчитывать и влезает ли результат. На MovieLens обе стороны маленькие, так что item-based здесь — выбор учебный, а не вынужденный.
▸Как CF вырос из корреляции
Когда два фильма считаются похожими
Вернёмся к матрице «пользователи × фильмы» с оценками. Каждый фильм — это столбец: список того, кто и как его оценил. Похожесть двух фильмов — это похожесть их столбцов.
Как получаются рекомендации
1. Берём фильмы, которые ты хорошо оценил (rating ≥ 4) — только лайки; низкие оценки в профиль не идут, чтобы нелюбимое не тянуло рекомендации вверх.
2. Для каждого находим самые похожие на него (по столбцам матрицы).
3. Складываем эти «голоса»: фильм, похожий сразу на несколько твоих любимых, получает высокий балл. Верхние по баллу и показываем (убрав уже виденные).
Если у пользователя нет оценок ≥ 4, откатываемся на всю его историю (иначе рекомендовать было бы не от чего). Первично здесь смысл: низкая оценка — не слабый лайк. Выигрыш в точности при этом есть, но маленький, и интервал его не отделяет от нуля:
# офлайн: считаем похожести между всеми парами фильмов один раз
нормируем каждый столбец-фильм матрицы оценок
sim[i][j] = cosine(столбец i, столбец j)
recommend(пользователь u, K):
score = {}
для каждого фильма j, который u оценил ≥ 4 (лайки):
для каждого соседа i из топ-похожих на j:
score[i] += sim[i][j] * r[u][j]
# если лайков нет — берём всю историю u (fallback)
убрать из score уже виденные u фильмы
вернуть K фильмов с наибольшим score▸Формула: похожесть и итоговый балл
Похожесть фильмов и — косинус их столбцов оценок и :
Балл фильма для пользователя — сумма похожестей на то, что лайкнул (оценка ≥ 4), взвешенная этими оценками:
Так фильмы с низкой оценкой не дают вклада вовсе. Альтернативы: взять все оценки как вес (тогда 2★ даёт малый положительный вклад — методологически спорно) или центрировать (ниже среднего → минус). Мы берём positive-only из смысловых соображений; замер обоих вариантов — выше.
На практике сумму берут не по всем , а только по k ближайшим соседям фильма — отсюда «kNN». Сколько именно соседей оставлено у нас, написано в контракте обучения внизу страницы.
Сколько стоит усадка похожестей
Усадка тянет к нулю похожести, посчитанные по двум-трём общим зрителям. Звучит разумно — но «звучит разумно» не значит «работает»:
Главные сложности
Хочется сказать: «зато item-CF обыгрывает popularity, вот он, выигрыш персонализации». Точечно так и есть — но стоит посчитать парный интервал, и уверенность исчезает:
Нижняя граница чуть ниже нуля, то есть на MovieLens в этом протоколе преимущество персонализации над «просто популярным» не доказано. Это не приговор методу: 363 оцениваемых пользователя — очень мало, и интервал такой ширины ожидаем. Но разница в третьем знаке между двумя моделями на такой выборке — ещё не результат, и подавать её как результат нельзя.
Сильные стороны
- Реальная персонализация: учитывает твою историю.
- Не нужны описания айтемов — достаточно поведения (но его надо корректно логировать: логи грязные, смещённые, без impressions — см. B1).
- Похожести можно предрассчитать offline; если каталог меняется медленнее вкусов, пересчитывать их приходится реже, чем user-user.
Слабые стороны
- Холодный старт: бесполезна для новых пользователей и айтемов.
- Разреженность данных бьёт по качеству.
- Память и вычисления растут с числом айтемов (похожести между всеми парами).
⚠️ Что может пойти не так
- Разреженность: у двух фильмов может быть всего пара общих зрителей — косинус по такой выборке случаен. Помогает усадка (shrinkage): чем меньше общих оценок n_ij, тем сильнее похожесть тянут к нулю множителем n_ij/(n_ij+λ). Здесь это уже применено, λ = 20 — замер обоих вариантов чуть выше.
- Косинус по сырым оценкам смещён: щедрый зритель, который всем ставит 5, раздувает похожести. Часто оценки сначала центрируют (вычитают среднее пользователя).
- Холодный старт: новый фильм не с чем сравнить, новому пользователю — нечего складывать.
- Популярные фильмы лезут в соседи ко всему подряд (их многие смотрели), поэтому без поправок item-CF тоже подвержен popularity bias.
🧠 Проверь себя: Каталог меняется медленно, а люди заходят каждый день и всё время что-то смотрят. Что это говорит о выборе между item-based и user-based?
Как подобраны ручки — и почему не по тесту
Конфигурация обучения
Всё, что нужно, чтобы повторить числа на этой странице. Значения читаются из самих обученных моделей, а не набраны в вёрстке, — разойтись с кодом они не могут.
Что дальше
Опирается на этот модуль — здесь он нужен как предпосылка
Можно читать параллельно — тот же блок, порядок между ними не важен
До финальной сборки не хватает ещё 11 модулей по этому пути.
Порядок здесь — рекомендация из карты курса, ничего не блокируется. Отметка «прочитано» хранится только в этом браузере.
Источники
- Item-Based Collaborative Filtering Recommendation AlgorithmsB. Sarwar, G. Karypis, J. Konstan, J. Riedl · 2001 · статьясхема «похожесть айтемов + взвешенная сумма оценок», реализованная в модуле
- Matrix Factorization Techniques for Recommender SystemsY. Koren, R. Bell, C. Volinsky · 2009 · статьяразбор слабостей соседских методов, из-за которых появилась факторизация