Batch или online ML: проверяем свежесть и цену готовых прогнозов

У модели уже есть рабочий API. Команда предлагает заранее считать прогнозы для всех клиентов и читать их из таблицы: это должно уменьшить задержку и расходы. Но если признаки меняются после расчёта, быстрый ответ может оказаться устаревшим. Выбор стоит проверить через объём работы и срок действия каждого готового прогноза.

Два способа отвечают на разный вход

При онлайн-инференсе модель получает признаки для конкретного решения в момент запроса. При предварительном расчёте она обрабатывает выбранную совокупность заранее. Онлайн-путь удобен для только что появившегося объекта или события, которое меняет решение. Готовый прогноз полезен, когда состав объектов известен и вход достаточно стабилен до следующего обновления.

Опишите, какое изменение делает ответ непригодным. Для риска оттока ежедневный пересчёт может соответствовать процессу работы отдела. Для решения по новой заявке наличие клиента во вчерашней таблице не означает, что модель уже увидела текущую заявку. Понадобится либо онлайн-расчёт, либо отдельная обработка новых событий с обновлением результата.

У каждого прогноза сохраните id объекта, время среза признаков, версию модели и момент расчёта. Добавьте правило истечения или явной инвалидизации при значимом событии. Потребитель должен уметь отличить действующий ответ от отсутствующего и устаревшего. Срок жизни определяется задачей, а не удобным периодом очистки таблицы.

Посчитаем лишнюю работу

Пусть есть миллион клиентов, но за день система спрашивает прогнозы для сорока тысяч уникальных клиентов. Сравним полный ночной расчёт, прямой онлайн-путь и обновление только изменившихся объектов. За день значимые признаки меняются у двадцати тысяч. Для иллюстрации возьмём разные условные затраты на один прогноз; это входы расчёта, а не тариф сервиса.

population = 1_000_000
requested = 40_000
changed = 20_000
batch_unit, online_unit = 0.001, 0.005
full_batch = population * batch_unit
online = requested * online_unit
incremental = changed * batch_unit
print("full_batch", full_batch, "online", online, "incremental", incremental)
assert (full_batch, online, incremental) == (1000, 200, 20)

Полный пересчёт стоит тысячу условных единиц, онлайн для сорока тысяч объектов — двести, пересчёт двадцати тысяч изменений — двадцать. Последняя цифра относится только к обновлениям после первоначального заполнения: первичный расчёт всей таблицы оплачивается отдельно. Хранение, чтение признаков, инфраструктура API и обработка событий тоже должны войти в полноценную смету.

Расчёт показывает, почему дешёвый отдельный batch-прогноз не гарантирует дешёвого процесса. Если большая часть заранее подготовленных результатов никому не нужна, выигрыш на одной операции проигрывает объёму. Но онлайн-путь должен выдержать пиковые запросы, а не только средние сорок тысяч за сутки.

Проверьте возможность обновлять часть

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

Предварительный расчёт хорошо сочетается с онлайн-досчётом. При запросе действующий прогноз берут из таблицы, для нового или устаревшего объекта запускают модель. У этого пути есть понятная цена: система поддерживает два маршрута и обязана получить одинаковые признаки при одинаковом срезе. Разделите их в журналах, чтобы видеть долю досчётов и ошибки каждого режима.

Для пакетного обновления потребителю следует читать принятую версию, а не случайную смесь старых и новых строк. Если бизнес допускает постепенное обновление по объектам, явно зафиксируйте это. Если нужна единая дневная кампания, требуется полный согласованный срез. Эти договорённости определяют способ публикации.

Примите решение по измерениям

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

Затем проверьте сценарии новой модели, пропуска ночного запуска и недоступности источника признаков. Потребитель должен получить согласованную реакцию: предыдущий действующий прогноз, досчёт, простой резервный алгоритм или отказ. Одинаковое значение score не должно скрывать разные причины ответа.

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

Следующий шаг в практике

В курсе табличных моделей вы собираете воспроизводимый inference pipeline, batch-инференс и простой REST API, работаете с признаками и корректной валидацией. Эти два способа доставки можно сопоставить на одной сохранённой модели и проверить, как меняется полный путь получения результата. Откройте программу платного курса «ML Engineer / Data Scientist: табличные модели в продакшн».

Связанный разбор: как определить срок годности признака.

Продолжить на практике

  • ML Engineer / Data Scientist: табличные модели в продакшн ↗

    Практический курс для тех, кто хочет получить навыки ML Engineer / Data Scientist на реальных табличных задачах. В курсе Вы не просто обучите CatBoost/LightGBM, а соберёте полноценный production-style пайплайн: подготовка данных, feature engineering (генерация признаков), корректная валидация, защита от leakage (утечек), тюнинг через Optuna, интерпретация через SHAP, batch-инференс и REST API для предсказаний.