← к модулям

Cold-start и fallbacks (B5)

Каждый пользователь, айтем и компонент системы когда-то холодный — а сервис обязан ответить всегда. Здесь живая лестница fallback на реальных моделях, честный замер «когда session-сигнал начинает помогать», пара «контент vs co-ratings» для нового айтема и exploration-слоты.

⚠ Все ступени — живые вызовы уже обученных моделей (без переобучения). Замер порога — симуляция serving-time знания о пользователе (первые n его взаимодействий), а не полный cold-ретрейн; оговорки — под таблицей.

1 · Лестница fallback вживую

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

считаем порог переключения…

3 · Холодный айтем: контент против co-ratings

Представь, что фильм только что добавили в каталог: жанры/теги у него уже есть, а взаимодействий — ноль. Сравни, на что способны два вида «похожести» для одного и того же фильма.

4 · Exploration-слоты: платим кликом за сигнал

Упрощённая slate-версия ε-greedy: последние N слотов реального топ-10 отдаём случайным айтемам из хвоста (фиксированный exploration-бюджет в выдаче, а не «с вероятностью ε выбрать exploration-действие»). Немного жертвуем релевантностью сейчас, чтобы собрать сигнал о хвосте и новичках — антидот петли обратной связи (B1/B7).

Прод-оговорки: exploration идёт после eligibility-фильтров (доступность, возрастные/региональные ограничения, safety, dedup, already-seen, business constraints) — «любой случайный айтем» показывать нельзя; здесь мы фильтруем already-seen и дедуп против основного списка. Долю explore охраняют guardrail-метриками (CTR, жалобы, hide-rate), а вместо случайного выбора используют bandits — exploration с учётом неопределённости.

Теория простым языком

«Холодный старт» звучит как одна проблема, но в проде это три разные: новый пользователь, новый айтем и холодная система (упавший компонент). И решение — не «модель для cold-start», а лестница fallback: цепочка стратегий от самой персональной к самой надёжной, плюс exploration, чтобы холодное быстрее теплело.

Три вида холодного старта

Cold userистории нет (аноним) или она крошечная (первая сессия). Персональные модели бессильны — нужен fallback + быстрый сбор сигнала.
Cold itemу айтема нет взаимодействий — co-rating/коллаборативные похожести по определению пусты. Спасают признаки: контентные похожести, эмбеддинг из метаданных, popularity-prior категории.
Холодный «путь» системы (не cold-start в узком смысле)в строгом смысле cold-start — это про отсутствие данных (user/item/data sparsity). Но в проде рядом живёт ещё один «cold path»: ranker недоступен, ANN-индекс устарел, feature service лёг. Терминологически это уже graceful degradation / fallback, а не cold-start — но лестница у них общая: сервис обязан ответить хоть чем-то. См. инцидент latency/error в мониторинге (B7) и fallback-rate как метрику.
Почему cold-start — это лестница, а не модель
БылоПерсональные модели (item-CF, MF, нейро) отлично работают на тёплых пользователях.
ПроблемаКаждый пользователь, айтем и даже компонент системы когда-то холодный — а сервис обязан ответить всегда.
ИдеяЦепочка fallback: персональная модель → session fold-in → контент/priors → popularity; плюс exploration, чтобы собрать сигнал.
Стало лучшеНоль отказов, плавная деградация качества вместо пустой выдачи; холодное быстрее теплеет.
Осталось слабымПорядок ступеней часто предполагают, а не меряют; fallback может тихо стать основным путём (мониторь fallback-rate, B7).
ДальшеУмный exploration — bandits (Фаза 12); переходы «сколько сигнала достаточно» — наш замер выше и cold-срезы моделей.

Ступени лестницы (и что у нас вживую)

1. Известный пользователь → полноценная персональная модель (у нас item-CF).
2. Есть клики в сессииfold-in: центроид эмбеддингов кликнутого против замороженного item-пространства (two-tower, без переобучения — VPS не тренирует).
3. Есть контекст запроса → contextual priors: популярное по региону / устройству / surface / языку, trending now, priors категории, editorial/business-safe default. В проде между «ничего не знаем о юзере» и глобальным топом почти всегда есть этот слой — в нашей лестнице он показан «призрачной» ступенью, потому что в MovieLens контекста запроса нет.
4. Совсем ничего → глобальный popularity (sanity-check ступень) + exploration-слоты.

Пример. Ступени — это policy-chain, тот же шов, что и re-rank в системном дизайне: условия проверяются сверху вниз, первая доступная ступень отвечает, выбор логируется (чтобы потом мониторить fallback-rate).

Честный замер вместо красивой легенды

Хочется рассказать: «после трёх кликов fold-in обгоняет popularity». Наш замер выше говорит иначе: на этих данных и этом протоколе — не обгоняет. Лучший fold-in ≈ popularity в пределах шума, centroid по two-tower-эмбеддингам заметно хуже, а полная персонализация — в ~3 раза сильнее обоих.

Почему так — три причины

1. Протокол льстит popularity: «спрятанный понравившийся» фильм чаще популярный (см. «Как устроен эксперимент»).
2. Ранние клики ≠ финальный вкус: мы симулируем новичка первыми (хронологически) взаимодействиями, а угадать надо последнее — вкус дрейфует.
3. Пространство эмбеддингов решает: bpr-центроид ≈ popularity, two-tower-центроид хуже — logQ-геометрия two-tower подавляет популярное, что честно для retrieval, но проигрышно на popularity-льстивом hit@10. Оба fold-in — эвристики (session-vector = центроид кликнутого, не retrain user-вектора и не классический ALS fold-in); two-tower концептуально «роднее» — query-vector против item-space и есть его базовая идея.

И по имени: весь замер — serving-time limited-history simulation, а не строгий cold-user протокол: item-пространство обучено на полном train (включая взаимодействия этих пользователей после первых n), мы лишь скрываем историю от policy-chain на этапе сервинга.

Важно: hit@10 по одному айтему — узкий прокси. Session fold-in может заметно улучшать ощущение выдачи (жанровый сдвиг под сессию — видно в демо на /two-tower), не двигая эту метрику. Урок: порядок ступеней и выбор пространства — эмпирика, мерь на своих данных.

Exploration: платим кликом за сигнал

ε-greedyс вероятностью ε показываем не «лучший» айтем, а исследовательский (например, случайный из хвоста). Немного теряем сейчас — быстрее прогреваем холодное и рвём петлю обратной связи (B1). Наше демо — упрощённая slate-версия: фиксированный exploration-бюджет (последние N слотов выдачи), а не probability-level ε на каждое действие — не путать эти два уровня.

В проде ε — управляемый и мониторимый параметр (guardrail на релевантность/жалобы), а следующая ступень зрелости — bandits: exploration с учётом неопределённости, а не вслепую.

Сильные стороны

  • Сервис отвечает всегда: деградация качества плавная, а не обрыв.
  • Каждая ступень — простая и объяснимая; политика логируется и мониторится.
  • Exploration превращает холодных пользователей/айтемы в данные.

Слабые стороны

  • Порядок ступеней часто «из головы» — его надо мерить (наш замер это показал).
  • Fallback может тихо стать основным путём — без fallback-rate этого не увидеть.
  • Exploration стоит кликов сейчас; долю надо подбирать и охранять guardrail'ами.

⚠️ Что может пойти не так

  • «Cold-start решается моделью X»: это набор политик (user/item/system) + exploration, а не одна модель.
  • Не мониторить, какая ступень отвечает: рост fallback-rate — ранний симптом деградации (B7).
  • Предполагать порядок ступеней без замера: на нашем протоколе fold-in не обгоняет popularity.
  • Для нового айтема ждать co-rating похожестей: их нет по определению — нужны контентные признаки/priors.
  • Выключить exploration «чтобы не терять клики»: петля обратной связи съедает хвост (B1/B7).

🧠 Проверь себя: В каталог добавили новый фильм. Почему item-CF не может порекомендовать «похожие», а content-based может?

Где это в дорожной карте

Это B5 — cold-start и fallbacks: политика надёжности поверх всех моделей. Связки: fallback-rate и деградация — B7; петля и ε-greedy — B1; cold-срезы качества моделей — /compare. Дальше — bandits (Фаза 12) как умный exploration.