Как посчитать diversity в recsys в SQL

Закрепи формулу recsys diversity в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать recsys diversity в Telegram

Зачем diversity

Если recsys рекомендует юзеру 10 похожих товаров (все детские книги о динозаврах), это «filter bubble». Diversity = разнообразие внутри одной рекомендации. Балансируется с relevance: чистое diversity = random recommendations. Чистое relevance = bubble. Reality — что-то посередине.

Intra-list distance

Average distance между парами товаров в рекомендации. Дистанция — обычно 1 − cosine_similarity(item_a, item_b).

ILD = average over pairs (i, j) in top-k of (1 - sim(i, j))

Range: [0, 1]. 0 — все одинаковые. 1 — все максимально разные.

Доля категорий в рекомендации

Простой proxy: сколько уникальных категорий среди рекомендованных:

category_diversity = unique_categories_in_top_k / top_k_size

При k=10: если 5 категорий, diversity = 0.5.

Diversity в SQL

WITH user_recs AS (
    SELECT
        user_id,
        product_id,
        rank,
        category_id
    FROM recsys_recommendations
    WHERE rec_date = CURRENT_DATE
      AND rank <= 10
),
per_user_diversity AS (
    SELECT
        user_id,
        COUNT(DISTINCT category_id)::NUMERIC / COUNT(*) AS category_diversity,
        COUNT(*) AS k
    FROM user_recs
    GROUP BY user_id
)
SELECT
    AVG(category_diversity) AS avg_diversity,
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY category_diversity) AS median_diversity,
    COUNT(*) AS users
FROM per_user_diversity;

avg 0.6 для k=10 — средне. 0.3 — много дубликатов. 0.9 — почти максимум.

Закрепи формулу recsys diversity в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать recsys diversity в Telegram

Diversity vs relevance

WITH user_recs AS (
    SELECT
        user_id,
        AVG(predicted_relevance) AS avg_relevance,
        COUNT(DISTINCT category_id)::NUMERIC / COUNT(*) AS diversity
    FROM recsys_recommendations
    WHERE rec_date = CURRENT_DATE
      AND rank <= 10
    GROUP BY user_id
)
SELECT
    CORR(avg_relevance, diversity) AS relevance_diversity_corr,
    AVG(avg_relevance) AS mean_relevance,
    AVG(diversity) AS mean_diversity
FROM user_recs;

Часто отрицательная корреляция: больше diversity = ниже relevance. Trade-off.

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

Ошибка 1. Diversity только по category. Category — грубый proxy. Embedding-based distance точнее, но дороже.

Ошибка 2. Маленький k. k=3 в diversity мало даёт. Минимум k=10.

Ошибка 3. Diversity без relevance threshold. Random recommendations имеют 100% diversity. Это бесполезно.

Ошибка 4. Игнорировать user preferences. Некоторые юзеры предпочитают bubble (читал 1 жанр всю жизнь). Force diversity = плохой UX.

Ошибка 5. Diversity на feed разных surfaces. Homepage feed: diversity важна. «Похожие товары» strip: bubble норма.

Связанные темы

FAQ

Diversity какой нормальный?

category_diversity 0.5-0.7 для feed. ILD на embedding 0.4-0.6 — баланс.

Diversity vs serendipity?

Diversity — внутри одного списка. Serendipity — «неожиданное, но релевантное» открытие.

Можно ли diversity в A/B?

Да — но обычно стоит CTR. Используйте как secondary metric.

Diversity для cart recs?

Иногда нет смысла. «Похожие to your cart» — bubble OK.

Embedding-based vs category-based?

Embedding точнее (учитывает текст, image, behavior). Category — proxy.