Разнообразие, новизна и покрытие

Урок объясняет, почему высокая точность ещё не значит хорошие рекомендации, и вводит метрики разнообразия, новизны и покрытия.

Beyond-accuracy метрики оценивают рекомендации не по попаданию в релевантное, а по разнообразию, новизне и широте охвата каталога — свойствам, которые точность игнорирует.

Почему точность обманчива

Представьте систему, которая каждому пользователю рекомендует один и тот же топ-10 бестселлеров. У неё может быть приличная precision@k — бестселлеры и правда многим нравятся. Но такая система бесполезна: она не персонализирует, не открывает нового и хоронит весь длинный хвост. Точность измеряет «угадали ли мы», но не «полезна ли выдача в целом». Поэтому её дополняют другими метриками.

Разнообразие (diversity)

Разнообразие — насколько непохожи между собой рекомендованные объекты. Список из десяти почти одинаковых боевиков менее ценен, чем боевик, комедия и драма. Считают как среднюю непохожесть пар в выдаче.

import math

def cosine(a, b):
    num = sum(x * y for x, y in zip(a, b))
    na = math.sqrt(sum(x*x for x in a)); nb = math.sqrt(sum(y*y for y in b))
    return num / (na * nb) if na and nb else 0.0

# вектора признаков рекомендованных товаров
rec = {
    "боевик_1": [1, 0, 0],
    "боевик_2": [0.9, 0.1, 0],
    "драма_1":  [0, 1, 0],
}
names = list(rec)
pairs, total = 0, 0.0
for i in range(len(names)):
    for j in range(i + 1, len(names)):
        total += 1 - cosine(rec[names[i]], rec[names[j]])
        pairs += 1
print("Разнообразие выдачи:", round(total / pairs, 3))

Вывод:

Разнообразие выдачи: 0.632

Новизна и покрытие

  • Новизна (novelty). Насколько неожиданны и непопулярны рекомендованные объекты. Постоянно советовать очевидные хиты — низкая новизна; открывать пользователю редкое и подходящее — высокая.
  • Покрытие (coverage). Какая доля всего каталога вообще попадает в чьи-либо рекомендации. Если система советует только 5% товаров, остальные 95% невидимы — плохо и для пользователей, и для бизнеса (длинный хвост простаивает).
  • Serendipity (приятная неожиданность). Рекомендации, которые пользователь не ожидал, но оценил. Самое ценное и самое трудное для измерения.
# покрытие каталога
catalog = {f"item{i}" for i in range(100)}
recommended_to_anyone = {f"item{i}" for i in range(0, 100, 4)}  # каждый 4-й
coverage = len(recommended_to_anyone) / len(catalog)
print("Покрытие каталога:", f"{coverage:.0%}")

Вывод:

Покрытие каталога: 25%

Как работает под капотом

На практике точность и разнообразие конфликтуют: самые «безопасные» (точные) рекомендации часто однообразны. Поэтому в ранжирование добавляют переранжирование на разнообразие — например, MMR (maximal marginal relevance), который выбирает объекты, балансируя релевантность и непохожесть на уже выбранные. Цель — не максимум одной метрики, а здоровый баланс, который удерживает пользователя и не схлопывает каталог.

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

  • Оптимизировать только точность. Получите однообразную ленту хитов без персонализации и охвата.
  • Игнорировать покрытие. Узкая выдача убивает длинный хвост и обедняет каталог.
  • Путать новизну с шумом. Новизна должна оставаться релевантной, а не быть случайным товаром.

Итоги

  • Высокая точность не гарантирует полезную выдачу: топ хитов «точен», но бесполезен.
  • Разнообразие меряет непохожесть объектов в списке.
  • Новизна и покрытие отвечают за неожиданность и охват каталога.
  • Хорошая система балансирует точность с разнообразием (например, через MMR).
Проверьте себя
1. Почему рекомендатель с хорошей precision@k всё равно может быть плохим?
AТочность всегда означает хорошие рекомендации
BОн может всем показывать одни и те же хиты — точно, но без персонализации, разнообразия и охвата хвоста
CВысокая точность невозможна
DPrecision@k нельзя посчитать
2. Что измеряет метрика покрытия (coverage)?
AСкорость ответа системы
BКакую долю всего каталога система вообще кому-нибудь рекомендует
CСреднюю оценку товаров
DЧисло пользователей