Ends in 2 weeks
96 participants
292 submissions

Хакатон Академии ИИ «По страницам»: призовой фонд – 1 000 000 рублей.

Прими участие в заключительном хакатоне этого года от Академии ИИ! Ты сможешь попасть в сообщество самых сильных специалистов по ИИ среди школьников, а еще выиграть реальные деньги уже в школе!

AIAcademyХакатонИИ

Нажимая кнопку «Отправить решение», вы соглашаетесь с Правилами участия в соревновании.

1. Контекст

Книжный сервис хочет показывать пользователю витрину рекомендаций «на следующий период» (в нашем случае — месяц, 30 дней).

  1. Витрина должна быть максимально релевантной и увеличивать шанс будущих взаимодействий (добавление в вишлист или чтение книги).
  2. Но также сервису важно расширять кругозор пользователя, чтобы постепенно переводить пользователя на новый контент и поддерживать интерес к продукту.

Поэтому задача формулируется как баланс между точной персонализацией и жанровым разнообразием выдачи.


2. Задача

Для каждого пользователя из таблицы targets.csv необходимо сформировать ранжированный список из 20 изданий (edition_id) на следующий период (тестовое окно) из пула 200 кандидатов из таблицы candidates.csv (по каждому user_id).

Результат — ранжированный список, где rank = 1 соответствует верхней позиции витрины.


3. Формат файла решения (сабмита)

Нужно отправить файл submission.csv со списком рекомендаций.

Формат:

user_id,edition_id,rank

Требования к файлу:

  • rank — целое число от 1 до 20 (1 — верх витрины).
  • на каждого user_id должно быть ровно 20 строк.
  • edition_id и rank внутри одного user_id не должен повторяться.
  • все edition_id должны входить в 200 кандидатов для данного user_id.

4. Оценивание

Итоговый скор считается как комбинация релевантности и жанрового разнообразия:

$$Score = \alpha \cdot \overline{NDCG@20} + (1-\alpha)\cdot \overline{Diversity@20}, \qquad \alpha = 0.7$$

где черта сверху означает среднее значение по всем пользователям в тесте.

Идея: итоговая выдача должна быть релевантной, но при этом не однообразной по жанрам.


4.1. Релевантность: NDCG@20

Для каждого пользователя сравнивается ваш ранжированный список из 20 изданий с фактом будущих взаимодействий в тестовом окне.

Релевантность для издания задаётся по сильному/слабому сигналам:

$$rel(i)= \begin{cases} 3, & \text{если в тестовом окне есть событие } event\_type=2\ (\text{read}) \\ 1, & \text{если в тестовом окне есть событие } event\_type=1\ (\text{wishlist}) \\ 0, & \text{если в тестовом окне событий нет} \end{cases}$$

Примечания:

  • Если в тестовом окне у одного edition_id есть и read, и wishlist, то используется приоритет readrel=3.
  • Если событий одного типа несколько, считается только факт наличия хотя бы одного события.

Далее для пользователя u:

$$DCG_u@20 = \sum_{k=1}^{20}\frac{rel(r_{u,k})}{\log_2(k+1)}$$
$$IDCG_u@20 = \sum_{k=1}^{20}\frac{rel^*(u,k)}{\log_2(k+1)}$$

где rel^*(u,k) — релевантности в идеальной сортировке (сначала все read, затем wishlist, затем остальные) для данного пользователя.

$$NDCG_u@20 = \begin{cases} \frac{DCG_u@20}{IDCG_u@20}, & IDCG_u@20 > 0\ 0, & IDCG_u@20 = 0 \end{cases}$$

4.2. Жанровое разнообразие: Diversity@20

Каждое издание x соответствует книге (через editions.book_id) и имеет множество жанров G(x) через book_genres.

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

Определим бинарную релевантность:

$$\tilde{rel}(i) = \mathbb{1}[rel(i) > 0]$$

и дисконт позиции:

$$w_k = \frac{1}{\log_2(k+1)}$$

Далее определим relevance-weighted diversity как смесь двух компонентов: покрытие жанров и внутрисписочная разнородность.


4.2.1. Genre Coverage (relevance-weighted)

Пусть S_{u,k} — множество жанров, уже встретившихся среди релевантных рекомендаций выше позиции k:

$$S_{u,k} = \bigcup_{i=1}^{k} \left( G(r_{u,i}) \cdot \tilde{rel}(r_{u,i}) \right), \qquad S_{u,0} = \varnothing$$

где запись G(x) \cdot 0 означает пустое множество, а G(x) \cdot 1 = G(x).

Определим покрытие жанров как сумму дробных вкладов позиций (книга с m жанрами даёт суммарный вклад 1, распределённый как 1/m на каждый новый жанр), но:

  • вклад учитывается только если \tilde{rel}(r_{u,k})=1;
  • позиции дополнительно дисконтируются весом w_k;
  • нормировка выполнена так, чтобы метрика была в диапазоне [0,1].
$$Coverage_u@20 = \frac{1}{\sum_{k=1}^{20} w_k} \sum_{k=1}^{20} \left( w_k \cdot \tilde{rel}(r_{u,k}) \cdot \frac{|G(r_{u,k}) \setminus S_{u,k-1}|}{|G(r_{u,k})|} \right)$$

Пример: если книга имеет 3 жанра и приносит 2 новых, то вклад равен 2/3.


4.2.2. Intra-List Diversity (ILD) (relevance-weighted)

Определим попарную жанровую дистанцию как Jaccard-distance по множествам жанров:

$$d(x,y) = 1 - \frac{|G(x) \cap G(y)|}{|G(x) \cup G(y)|}$$

Внутрисписочную разнородность считаем только среди релевантных рекомендаций (с \tilde{rel}=1). Пусть L_u — множество индексов позиций в топ-20, на которых рекомендация релевантна:

$$L_u = {k \in {1,\dots,20}: \tilde{rel}(r_{u,k})=1}$$

Если |L_u| < 2, то ILD_u@20 = 0. Иначе:

$$ILD_u@20 = \frac{2}{|L_u|\cdot(|L_u|-1)} \sum_{\substack{i<j\ i,j \in L_u}} d(r_{u,i}, r_{u,j})$$

4.2.3. Итоговая diversity-метрика

Смешиваем покрытие и внутрисписочную разнородность:

$$Diversity_u@20 = \beta \cdot Coverage_u@20 + (1-\beta)\cdot ILD_u@20, \qquad \beta = 0.5$$

Our website uses cookies, including web analytics services. By using the website, you consent to the processing of personal data using cookies. You can find out more about the processing of personal data in the Privacy policy