Обучение ранжированию (LTR)
Конвейер LTR в Relevance Studio — обратная связь по кликам, коррекция позиционного смещения, обучение, версионирование моделей, A/B-тесты и активация. Как интерпретировать значимость z-критерия и выбрать победителя.
Learning to Rank (LTR) — замкнутый цикл обратной связи, превращающий реальные клики пользователей в выученную модель ранжирования. Studio поставляет четыре панели, соответствующие четырём этапам: Обратная связь по кликам, Прогоны обучения, Модели и A/B-тесты.
Конвейер кратко
клики (SearchUsageEvent)
│
▼ коррекция позиционного смещения (debias)
│
▼ обучение (сегодня — shim-алгоритм; нативные LightGBM/XGBoost отложены)
│
▼ артефакт модели + метрики (NDCG, MRR, AUC)
│
▼ A/B-тест: сплит трафика, значимость по z-критерию
│
▼ активация победителя → ранжирование на пути чтенияКаждый этап обратим. До деактивации плохой модели — один клик: прежняя активная модель всегда сохраняется.
1 · Обратная связь по кликам
Панель Обратная связь по кликам показывает сырой сигнал, который идёт обучателю. Три числа на индекс:
- клики-с-контекстом — сколько событий
clickпришло с валиднымиqueryIdиposition. БезqueryIdнельзя связать клик с поиском. - коррекция позиционного смещения — действующая кривая дебиаса.
Позиционное смещение — известный эффект, когда первая позиция кликается
независимо от релевантности. Скорректированный скор примерно равен
observed_ctr / propensity[position], гдеpropensityподбирается по индексу. - используемые строки для обучения — после дебиаса и фильтра zero-result сколько строк пригодно для обучения.
Если пригодных строк меньше ~5 тыс., Training отказывается стартовать и показывает баннер «недостаточно сигнала». Ниже этого порога обученная модель переобучается и проигрывает статическому ранкеру.
2 · Прогоны обучения
Прогон обучения создаёт артефакт модели из выбранного окна обратной связи. В Studio вы выбираете:
- Окно — последние 7, 30 или 90 дней.
- Алгоритм — сейчас
shim(единственная опция в релизных сборках). Нативные LightGBM и XGBoost — отложены, см. ниже. - Признаки — преднастроенный набор (текстовая релевантность, свежесть, цена, популярность, кохорта категории). Кастомные признаки — в roadmap.
Прогон показывает прогресс и при завершении выводит три метрики:
| Метрика | Смысл |
|---|---|
| NDCG@10 | Normalized discounted cumulative gain в топ-10 — основная метрика |
| MRR | Mean reciprocal rank первого кликнутого результата |
| AUC | Площадь под кривой click vs non-click |
Текущий статус shim (май 2026)
Отгружаемый LTR-обучатель — shim-алгоритм: упрощённый линейный
комбинатор, подбирающий небольшое число весов поверх предвычисленных
признаков. Он намеренно консервативен и работает за фичефлагом ltr.shim.
Полные нативные LightGBM- и XGBoost-обучатели отложены. Они реализованы
за флагом ltr.native, но не в GA — нужны дополнительные нагрузочные
тесты и rollout реестра моделей. Сейчас shim — единственный поддерживаемый
алгоритм; ожидайте прирост NDCG@10 в 5–15% относительно неранжированного
baseline, а не 25–40%, как в некоторых статьях. Клиенты, которым уже
сегодня нужен нативный LightGBM, могут обратиться в поддержку для
приватного preview.
3 · Модели
Каждый успешный прогон создаёт модель в панели Модели. Модели — неизменяемые артефакты, несут:
- версионированный ID (
mdl_<random>), время создания, исходный прогон, - кортеж метрик
(NDCG@10, MRR, AUC), - набор признаков и окно, на котором обучалась,
- статус деплоя:
draft,in_ab_test,activeилиarchived.
Модель в active — это то, что путь чтения консультирует на каждый
поисковый запрос по индексу. В каждый момент на индекс ровно одна
активная модель.
4 · A/B-тесты
Модель не переводится из draft сразу в active. Вместо этого
запускается A/B-тест, разделяющий живой трафик между моделью-кандидатом
(плечо B) и текущей активной моделью (плечо A, контроль).
Запуск A/B-теста
В Studio → LTR → A/B-тесты → Новый тест:
// То, что Studio делает под капотом — также вызываемо напрямую
import { client } from "@repo/api/client";
const test = await client.ltr.abTests.create.call({
indexSlug: "products",
controlModelId: "mdl_active_now",
variantModelId: "mdl_candidate",
trafficSplit: 0.10, // 10% живого трафика видят плечо B
primaryMetric: "ctr", // ctr | cvr | ndcg10
minSampleSize: 50_000, // запросов на плечо до подсчёта значимости
});Сплит трафика идёт на запрос, а не на пользователя — поэтому один и тот же пользователь между сессиями может попасть в разные плечи. На плече B применяется кандидат; плечо A продолжает использовать текущую активную модель.
Чтение результатов
Пока тест идёт, панель показывает живые счётчики по плечам:
n— запросов, попавших в плечо.clicks,ctr,cvr— основные метрики, обновляются раз в 5 минут.- z-оценка — стандартизованная разница плеч B и A по основной метрике.
- p-value — двусторонний.
- решение —
running,significant_win,significant_loss,±borderlineилиno_effect.
Как интерпретировать значимость
Обучатель использует стандартный z-критерий двух пропорций, считая каждый запрос независимым испытанием Бернулли по основной метрике. Пороги:
| Решение | Диапазон z | Что значит |
|---|---|---|
significant_win | z ≥ +1.96 (p ≤ 0.05) | Кандидат превзошёл контроль с уверенностью 95%. |
significant_loss | z ≤ −1.96 | Кандидат проиграл с уверенностью 95% — остановите тест. |
±borderline | 1.65 ≤ |z| < 1.96 | Уверенность 90–95% — ждать данных или принимать решение заранее. |
no_effect | |z| < 1.65 и n ≥ minSampleSize | Различие не различимо при выбранной выборке. |
running | n < minSampleSize | Данных пока недостаточно. |
Полоса ±borderline намеренно вынесена в отдельное решение, потому что
у большинства продуктовых команд есть предварительное правило вроде
«релизим при 90%, если дельта положительная; держим при 95%, если
отрицательная». Studio в borderline сама ничего не промотирует — нужно,
чтобы человек нажал Активировать победителя.
Подсказка по размеру выборки
Default minSampleSize — 50 000 запросов на плечо. При сплите 10%
индекс с 50 тыс. запросов/день достигает значимости примерно за 11 дней
для эффекта в 2 п.п. CTR. Меньшим индексам нужно 3–4 недели. Панель
Studio показывает живой ETA.
Активация победителя
Когда решение — significant_win (или вы решили релизить на
±borderline), нажмите Активировать победителя в A/B-панели. Это:
- Переводит модель-вариант в статус
active. - Понижает прежнюю активную модель до
archived(её можно вернуть одним кликом, если новая модель регрессирует в проде). - Закрывает A/B-тест итоговым отчётом.
- За ~60 секунд (TTL LRU
policy-cache) переключает 100% живого трафика на новую модель.
await client.ltr.abTests.activateWinner.call({
testId: test.id,
// опциональная проверка безопасности — откажет, если живое решение
// между fetch и call ушло от `significant_win`
expectedDecision: "significant_win",
});Если после активации нужен откат — панель Модели хранит прежнюю
активную модель как archived и даёт Реактивировать одним кликом.
Лучшие практики
- Всегда запускайте A/B-тест. Даже модель, побеждающая по NDCG в offline, может регрессировать по живому CTR — позиционное смещение и эффекты подачи не видны в offline-метриках.
- Выбирайте метрику, отражающую бизнес. CTR — default; для
конверсионных каталогов ставьте
primaryMetric: "cvr". - Не «peek-and-stop». z-критерий предполагает фиксированный объём
выборки — подглядывание до
minSampleSizeи ранний стоп раздувают ложноположительные срабатывания. Зафиксируйте выборку, отойдите, принимайте решение потом. - Архивируйте агрессивно. Держите не более 5–10 архивных моделей на индекс. Реестр недорог, но журнал аудита читается легче при меньшем числе строк.
Связанные материалы
- Справка LTR API — полный список процедур:
ltr.training.runs.*,ltr.models.*,ltr.abTests.*. - Персонализация — ортогональный слой, композирующийся с LTR на пути чтения.
- Архитектура → Цикл обратной связи аналитики — откуда берутся клик-события для обучателя.
- Тарифы и лимиты — LTR требует тариф Scale или выше.