Давно веду канал, а так до сих пор и не написал про метрики ранжирования.
В рекомендациях с метриками всё непросто. Человечество не придумало идеальной офлайн-метрики. На то есть фундаментальная причина: новая модель рекомендовала бы что-то другое, чем та, которая в продакшене, и мы в точности не знаем, как пользователи бы на это отреагировали (ground truth). А именно реакция пользователей нам важнее всего.
В то же время, как известно, all models are wrong, but some are useful. И на практике все используют какие-то метрики для оценки качества моделей на исторических данных. Это позволяет хоть как-то сравнивать модели между собой, выбирать наиболее перспективные, подбирать гипер-параметры и запускать их в онлайн-эксперимент, в котором мы уже узнаем правильный ответ (на самом деле — тоже не совсем).
Если говорить про конкретные метрики (их формулы), есть разные варианты. Но они не очень сильно отличаются друг от друга, и я считаю, что можно всё упростить и считать, что есть более-менее одно семейство метрик — https://en.wikipedia.org/wiki/Discounted_cumulative_gain Многие другие метрики (например, HitRate, Recall@k, MRR) — это всё частные случаи.
Идея метрики очень простая — у каждого документа в группе есть какая-то релевантность (например, 1 у кликнутых документов, 0 — у остальных), и мы суммируем эти релевантности с дисконтированием, которое зависит от того, на какое место наша модель поставила этот документ (чем ниже отранжировала, тем меньший бонус мы получим за релевантный документ). Вид дисконтирования можно выбирать по вкусу (или по данным): логарифмическое, экспоненциальное, гармоническое, линейное, ступенчатое.
Очень часто используют нормированный вариант метрики — NDCG. Но на самом деле это чаще вредит, чем помогает. Если релевантность не бинарная (например, у клика вес 1, у лайка — 10), то NDCG забудет про разные веса, когда они не в одной группе. Т.е. поставить на первое место лайк в одной группе или клик в другой — для NDCG одно и то же.
Ещё один частный случай метрики, который лично я часто использовал на практике — это AUC. Почти тот самый всем известный ROC AUC, только посчитанный не сразу для всех примеров, а отдельно для всех групп, а потом усредненный между группами. У AUC есть хорошая интерпретация — это доля правильно отранжированнах пар объектов с разными таргетами. Если использовать эту интерпретацию, то можно даже убрать ограничение на бинарность таргета. И если задуматься, то такой AUC — тоже частный случай DCG (точнее, NDCG), просто с линейным дисконтированием.
Но конкретный вид метрики не так важен, как то, на каких примерах мы её измеряем, как их объединяем в группы и какие значения релевантности для разных событий используем.
Например, не стоит включать в примеры те объекты, которые мы порекомендовали, но пользователь не увидел. Мы не знаем реакцию пользователя на них.
Какие веса раздать разным типам действий пользователя — может сильно повлиять на итоговый результат. И это напрямую зависит от того, какую мы хотим оптимизировать. Некоторые ML-инженеры даже работают в парадигме, что эти веса даны свыше, «продакты так сказали». Но это неправильно (точнее, это правильно только в контексте работы над некоторыми компонентами рекомендательной системы).
Наконец, одна из популярных ошибок — в разбиении на более крупные группы ранжирования — по сессии или даже по пользователю. Мотивация в этом понятна, но это ведёт к проблеме — лику данных. А именно — в одной группе в фичах одних примеров (более поздних) будет содержаться информация про таргет других примеров (более ранних). Для иллюстрации, представьте датасет, в котором в сессиях по два события (при этом во втором событии в сессии в фичах учитывается итог первого события), и модель, выдающую просто историческую долю нулей у пользователя. Такая модель получит идеальное значение метрики, но не будет уметь ранжировать вообще. Поэтому разбивать лучше всего по реквестам.
Эта ошибка не всегда критична, но чем более продвинутая модель будет оптимизировать такую неправильную метрику, тем сильнее эта проблема будет проявляться.