Eval-протокол (анти-утечка)¶
Главный научный риск проекта — утечки в оценке cold-start. Протокол ниже + тесты-инварианты сплиттера защищают от них.
Anti-leakage invariant
Test-cold айтемы должны отсутствовать в donor training, validation features для tuning, popularity computation и neighbor construction. Donor scores, которые используют transfer methods, считаются только по warm items.
flowchart LR
A[All interactions] --> B[Pick pseudo-cold items]
B --> C[Train: warm items only]
B --> D[Val-cold: tune meta-methods]
B --> E[Test-cold: final metrics]
C --> F[Train donor]
F --> G[Warm donor scores]
G --> H[Transfer method]
D --> H
H --> E
Pseudo-cold split (как делаем)¶
- Сплит по айтемам, не по взаимодействиям. Случайно (стратифицированно) выбираем подмножество warm-айтемов, объявляем их псевдо-cold и полностью удаляем все их взаимодействия из:
- train донора,
- расчёта Grouped MP и популярностей,
- построения соседей (similarity).
- Стратификация псевдо-cold по категориям и бакетам популярности — иначе оценка смещается к голове/хвосту распределения.
- Контент-фичи cold считаются только из их статики (без таргет-лика из их же взаимодействий). TF-IDF / нормировки / popularity-приоры — только по train-корпусу.
- Тюнинг гиперпараметров (k в KNN, λ в Ridge, …) — на отдельном cold-валидационном фолде, не на тесте.
- Опционально — temporal split (айтемы, появившиеся после момента T): честнее random item-holdout, ближе к проду. Естественно ложится на KION (есть время).
Обучение супервизорных мета-методов (нюанс протокола)¶
Мета-методы (stacking, stacking_plus, logreg_calib) обучают мету на val-cold фолде
(айтемы вне train донора и вне test). Их признаки (linmap-сигнал, аффинность, популярность)
считаются leak-free, метки — из val-cold (не из test).
Текущая реализация runner обучает мету по тому же множеству пользователей, что и eval
(test_users, выбранные как пользователи с взаимодействиями по test-cold айтемам). Это
не утечка исхода теста (val-метки ≠ test-метки; test-cold фичи/метки мета не видит) —
подтверждено независимым ревью (codex). В рекомендациях пользователи всегда общие между
обучением и оценкой, так что это не завышает результат. Строго говоря, в fit попадает
членство пользователя в eval-наборе; для максимально пуристичного протокола мету стоит
обучать на независимом от test множестве пользователей — отмечено как направление доработки
(потребует донор-скоров для дополнительного набора пользователей).
Инвариант сплиттера (проверяется тестами)¶
set(cold_items) ∩ set(train.item_id) == ∅и то же дляval.- Взаимодействия cold-айтемов присутствуют только в
test. - Донор физически не видит cold-айтемы (отдельный тест «no cold item in any donor training input»).
- Детерминизм при фиксированном seed.
Метрики¶
- Ranking-метрики — основное для сравнения с Grouped MP: Recall@k, Precision@k, MAP@k, NDCG@k, MRR, для k ∈ {1, 5, 10}.
- AUC + RelaImpr — дополнительно. RelaImpr = (AUC_model − 0.5) / (AUC_base − 0.5) − 1.
- Калибровка ортогональна ранжированию И AUC: Platt/isotonic — монотонные преобразования, поэтому НЕ меняют ни ranking, ни AUC (обе rank-based). Улучшают только logloss/Brier. Не считаем калибровку «методом трансфера».
- Репортим разброс по нескольким сидам (cold-оценка шумная) и по бакетам популярности cold-айтемов.
Почему calibration отделена от ranking
Монотонная calibration может сделать scores лучшими вероятностями, но сохраняет порядок scores. Ranking metrics и AUC зависят от порядка, поэтому calibration сама по себе не превращает слабый ranking method в сильный cold-start transfer method.
Соглашения метрик (фиксируем СВОИ, не полагаемся на чужие либы)¶
- Tie-breaking в top-k — детерминированный и документированный.
- Пользователи без релевантных айтемов в test — исключаются из усреднения (документируем).
- k > числа кандидатов — корректная деградация (без падения).
- Точечная сверка с эталоном (sklearn) на простых кейсах, но контракт — наш.