Хакатон Московского транспорта · 2026

Опоздание видно
за 15 минут
до того, как оно случится

Система слушает телематику автобусов в формате NDTP, сверяет каждый пинг с расписанием и предупреждает диспетчера о задержке за 10–15 минут до остановки — с причиной и рекомендацией, что делать.

в графике риск опоздает 13 реальных маршрутов из датасета
—
ТС шлют NDTP прямо сейчас
—
пакетов телеметрии принято
—
активных алертов
—
прогнозов в окне 10–15 мин
—
мс на прогноз (p50)

Цифры идут напрямую из api.mowtransit.ru/health

01 · Горизонт

Прогноз всегда смотрит в окно (T+10, T+15] мин

Каждые 5 секунд для каждого автобуса берётся первая плановая остановка, попавшая в окно, — и ML прогнозирует задержку на ней. Время идёт, цель сдвигается, прогноз обновляется. Прогнозов «задним числом» нет: алерт поднимается только пока до остановки 10–15 минут.

T = 08:00:00
окно прогноза
T
T+5+10+15+20 мин
Цель прогноза—
План—
Упреждение—
Прогноз задержки—
100%прогнозов на живом потоке попадают в окно — сервис сам проверяет это и отдаёт horizon_ok_share в /health
lead_minв каждом ответе ML: за сколько минут до плановой остановки сделан прогноз
3 из 3проверенных алертов в прогоне на реальном дне оказались настоящими опозданиями (253–278 с)

02 · Карточка инцидента

Не просто «опоздает», а почему и что делать

Алерт поднимается, когда модель оценивает вероятность опоздания больше чем на 2 минуты в ≥ 0.7. В карточке — прогноз с интервалом, участок маршрута, вклад каждой причины в секундах и рекомендация диспетчеру. Когда автобус доезжает, алерт сверяется с фактом.

  • Интервал прогноза откалиброван: факт попадает в него в 80% случаев
  • Причины — приближённый SHAP, переведённый в человеческий текст
  • Рекомендация считает скорость, нужную, чтобы вернуться в график
пример из эфира

03 · Как устроено

Поток → прогноз → дашборд, end-to-end

Три независимых сервиса в Docker Compose. Backend сам разбирает бинарный NDTP (без готовых парсеров), ML — отдельный сервис, который можно переобучить и перезагрузить без остановки backend.

📡

NDTP-терминалы

Эмулятор организаторов с реальными треками. Бинарный TCP на ndtp.mowtransit.ru:9201

13 ТС в эфире
⚙️

Backend · приём

Свой кодек NPL/NPH, CRC-16, handshake, ячейки G6CellNav00. asyncio + uvloop

0.3 мс p50
🧭

Backend · состояние

Привязка к расписанию, прибытия по GPS, текущее отклонение, скорость на сегменте, простой

±3 с медиана
🧠

ML · CatBoost ×5

Ансамбль на 56 признаках + модели интервала и вероятностей, причины, What-if

44 мс /predict
🗺️

Дашборд

MapLibre, светофор риска, лента алертов, What-if. WebSocket, обновление раз в секунду

Вся история — телеметрия, прибытия, каждый прогноз и алерт — пишется в Postgres фоном (write-behind, COPY), так что база не может замедлить живой контур.

Python 3.12CatBoostFastAPIasyncio + uvloopONNX PostgresDocker ComposenginxMapLibreWebSocketSphinxSwagger

04 · Точность

Ошибка 40 секунд там, где бейзлайн ошибается на 93

MAE прогноза задержки на отложенной выборке. Метрика хакатона упирается в потолок: score = 1.0 и локально, и на платформе.

Прогноз «опоздания не будет» (0 с)
103 с
Бейзлайн организаторов (cur_dev_s)
93 с
Наш ансамбль CatBoost
40 с
1.0
score хакатона
6 из 6 баллов за точность
38.8 с

Как устроен validate

5 фолдов блоками по 30 минут: соседние моменты тех же автобусов. Бейзлайн — 88.4 с.

78.9 с

Честно: новый автобус

Автобус отложен целиком — модель его ни разу не видела. Всё равно лучше бейзлайна (88.4 с).

0.97

AUC «опоздает ли»

Вероятность опоздания откалибрована: прогноз ~0.89 → реально 0.95. Из неё и светофор риска.

Онлайн = батч: прогноз живого сервиса совпадает с submission.csv на 151 из 151 точки, максимальная разница — 0.00 с. Признаки считает одна и та же функция.

05 · Надёжность

Сломайте что-нибудь. Сервис не упадёт

Выберите аварию — и посмотрите, как система деградирует и восстанавливается. Всё проверено на живых контейнерах.

— —

—


      
16 000терминалов одновременно, ни один пакет не потерян
25–30kпакетов NDTP в секунду на одно ядро
7.6 µsна разбор одного пакета кодеком
2.2 схолодный старт ML до готового /health
20 мсна точку в пакетном /predict/batch
9.5 КБпамяти на одно TCP-соединение

06 · Сверх ТЗ

Дополнительные фичи

⇄

What-if

Выпустить резерв, объезд — пересчёт прогнозов по маршруту до и после, с применением к симуляции.

⚡

ONNX

Экспорт модели: fp32 в 6 раз быстрее нативного CatBoost.

∑

Ансамбль

5 моделей на разных сидах + отдельные модели квантилей и классов «рано / вовремя / поздно».

±

Конформные интервалы

Не одна цифра, а диапазон с гарантированным покрытием 80%.

⌖

Привязка к маршруту

Прибытия по GPS: 23 664 прибытия бит-в-бит совпадают с обучающим пайплайном.

⟲

Горячая перезагрузка

POST /reload подхватывает переобученную модель без рестарта контейнера.

07 · Команда

Кто это сделал