Тормоза — веб-сервис для диспетчеров ЕДЦ ГУП «Московский метрополитен». Он прогнозирует число посадок (успешных валидаций) на трамвайных маршрутах по часам и дням для конкурсного периода ноября–декабря 2025. День и месяц проверены на хронологических окнах; год — качественный сценарий из 12 календарных месяцев, продолжающийся в 2026 году без подтверждённой годовой точности. Сервис показывает оценочные посадки по остановкам на карте Москвы, позволяет задавать поправки на погоду, календарь, события и трафик и выгружает результат в CSV.
| Качество на публичном лидерборде | WAPE-score 0.89195 (скриншот успешной отправки; baseline ≈ 0.48) |
| Горизонты | день · по часам и месяц · по дням (проверены); год · по месяцам (качественный сценарий) |
| Агрегация | маршрут, остановка, направление, произвольный интервал времени |
| Маршруты | 1, 5, 7, 11, 12, 17, 25, 26, 28, 50 |
| Период | конкурсный прогноз 01.11–31.12.2025; годовой сценарий с ноября/декабря 2025 до октября/ноября 2026, время московское |
| Стек | FastAPI, PostgreSQL, React 19 + TypeScript, MapLibre, CatBoost, Docker Compose |
Нужен Docker с Compose.
git clone https://github.com/BlackfireZZZ/MosTransportHackClear.git
cd MosTransportHackClear
cp .env.example .env
docker compose up --buildПосле запуска:
- веб-интерфейс — http://localhost:8080
- REST API — http://localhost:8080/api/v1
- OpenAPI (Swagger) — http://localhost:8000/docs
- проверка готовности — http://localhost:8080/api/v1/health/ready
Остановить: docker compose down. Удалить данные БД: docker compose down -v.
Прогноз (главная страница):
- Выберите маршрут, горизонт и начальную дату в ноябре–декабре 2025.
- Сузьте результат до направления или конкретной остановки.
- Посмотрите KPI: пиковый час, самую загруженную остановку и сумму за период. Сумму можно пересчитать за любой интервал «с — по».
- На карте Москвы остановки окрашены по посадкам в час. Ползунок и кнопка «Воспроизвести» показывают, как меняется загрузка в течение дня.
- Включите корректирующий коэффициент, например «Погода ×1.3»: карта, KPI, график и таблицы пересчитываются сразу.
- «Горячие точки» — остановки и часы от 50 посадок/ч, кандидаты для усиления выпуска и сокращения интервалов.
- «Скачать сценарий CSV» выгружает текущий срез с коэффициентами и версией модели.
- Внизу страницы — область применимости модели и ссылки на внешние источники.
Опубликованный прогноз — маршрутный прогноз той же модели, чей CSV сдан на лидерборд: почасовой график на день, посуточный на месяц, выбор окна времени и CSV выбранного окна. Кнопка «1 год · качественный сценарий» открывает планирование без запроса годового опубликованного прогноза. В планировании выберите месяц: карта, KPI, таблица и CSV показывают этот месяц. Ноябрь–декабрь 2025 относятся к конкурсному периоду; месяцы 2026 — сценарное повторение недельного профиля.
Как работает Тормоза — интерактивная схема фактического пути данных, запроса и развёртывания; показывает происхождение и ограничения узлов. Откройте страницу архитектуры после запуска.
Планирование сети — отдельная страница для проверки выпуска. Маршруты
ранжируются по прогнозу посадок на плановое отправление за настраиваемое окно
от 1 до 24 часов. Границы окна перетаскиваются с шагом в один час. Плановые
отправления и оборот оцениваются по контрольному снимку GTFS, а интервал и
оборот можно изменить вручную. Для выбранного маршрута можно задать число
дополнительных вагонов. Сервис показывает расчётную частоту и среднее число
посадок на отправление до и после изменения, исходные почасовые значения и
выгрузку опубликованного прогноза в CSV. Параметры сценария видны на экране и
в выгрузку прогноза не входят.
Цвет маршрута отражает его относительное число посадок на плановое отправление
по сравнению с медианой сети. Общий спрос остаётся неизменным. Снимок GTFS
получен 30.06.2026, хотя его календари объявляют применимость к 2025 году;
последовательность рейсов одного вагона оценена по коду выхода, поскольку
block_id пуст. Это эвристика для проверки решения диспетчером, не измерение
заполненности салона, фактического выполнения рейсов или экономического эффекта.
Граф сети — трамвайная сеть Москвы из OpenStreetMap: 856 остановок, 919 участков, 377 км путей, поиск остановки и кратчайший путь по рельсам.
# список маршрутов
curl http://localhost:8080/api/v1/routes
# опубликованный маршрутный прогноз: horizon=day|month, окно [start, end)
curl "http://localhost:8080/api/v1/forecasts?route_id=1001&horizon=day&start=2025-12-05T07:00:00%2B03:00&end=2025-12-05T10:00:00%2B03:00"
# прогноз на день/месяц и качественный годовой сценарий с коэффициентами
curl -X POST http://localhost:8080/api/v1/planning/forecast \
-H 'content-type: application/json' \
-d '{"route":"1","start_date":"2025-11-01","horizon":"month",
"forecast_mode":"stop_model","stop_id":null,"direction":null,
"factors":{"weather":{"enabled":true,"multiplier":1.2}}}'| Параметр | Значения |
|---|---|
horizon |
day, month, year (12 календарных месяцев, qualitative=true; points[].basis различает competition_period и scenario_projection) |
forecast_mode |
approved — маршрутная модель лидерборда; stop_model — по остановкам; external_experiment — с внешними источниками |
stop_id, direction |
GTFS-остановка и направление из поля stops ответа планирования |
factors |
weather, calendar, events, traffic: {enabled, multiplier}, множитель 0–3 |
source_enabled с теми же четырьмя ключами включает отдельные обученные ветки
в approved POST: каждая активная ветка получает вес 0,05, оставшийся вес —
у конкурсного прогноза. Без флагов approved сохраняет значения
опубликованного CSV. Вариант с источниками не отправлялся на лидерборд;
external_experiment по-прежнему использует собственный артефакт и прежнее
правило смешивания. Ветка events здесь основана на сообщениях об инцидентах
и перекрытиях, не на афише KudaGo.
Ошибки возвращаются с понятным текстом: неизвестный маршрут, дата вне ноября–декабря 2025 или некорректный коэффициент — HTTP 422, отсутствие прогноза — HTTP 404. Полная схема — в OpenAPI.
Сверенные успешные валидации организатора → маршрут × дата × час
→ календарные признаки + профиль/CatBoost → 14 640 точек CSV и SHA-манифест
→ проверка approval/полноты → PostgreSQL → FastAPI GET day/month
→ опубликованный график и CSV
GTFS-справочники + оценочная привязка остановок/направлений
→ отдельные planning-артефакты → FastAPI POST day/month/year
→ карта, сценарные коэффициенты, график и CSV
OSM → отдельный граф сети → вкладка «Граф сети»
Конкурсный маршрутно-часовой прогноз не зависит от оценочной привязки к остановкам/направлениям, графа OSM и экспериментальных погодных, дорожных или событийных факторов. GTFS-остановка обозначает справочный объект, а не наблюдённое место посадки. Опубликованный ряд есть только для дня и месяца; год в планировании — качественный сценарий из 12 месяцев. Обучение и batch inference идут отдельно от веб-worker; публикация проверяет SHA, approval и полную сетку, затем переключает активную версию в PostgreSQL.
Подробная схема работающих модулей перечисляет точные пути, входы/выходы, происхождение данных, границы сервиса и план развития. Для просмотра доступны крупная обзорная схема и подробная схема в полном разрешении.
Целевая величина — число успешных валидаций на маршруте за час. Итоговая модель — смесь трёх компонент:
- 50% — устойчивый 28-дневный профиль «маршрут × тип дня × час» с официальным производственным календарём;
- 25% — дневная поправка CatBoost;
- 25% — та же поправка CatBoost с весами давности 60 дней.
Поправка каждой CatBoost-компоненты ограничена ±5%. Все признаки строятся только по данным до даты прогноза.
| Проверка | WAPE-score |
|---|---|
| Публичный лидерборд, ноябрь–декабрь 2025 (скриншот платформы) | 0.89195 |
| 61-дневное окно с 1 мая 2025 | 0.859 |
| 61-дневное окно с 1 июля 2025 | 0.840 |
| 61-дневное окно с 1 сентября 2025 | 0.892 |
Показанный на скриншоте платформы результат 0.89195 превышает порог 0.88, которому PDF организатора соответствует 10 баллов за качество. Скриншот не связывает score с именем CSV; контрольная сумма файла подтверждается отдельно.
В этой копии нет истории прежних коммитов. Указанные в манифесте модели и
протоколе замера SHA коммитов являются историческими метаданными;
контрольные суммы файлов проверяются
локально командой sha256sum -c docs/evidence/repository-artifacts.sha256.
Проверка только хронологическая, случайного разбиения нет. Код обучения и
инференса, точные CSV всех загрузок и команды воспроизведения из dataset.zip —
в ml/competition_submissions/2026-09-27/README.md.
Прогноз по остановкам строится отдельной моделью: посадки распределяются по остановкам и направлениям GTFS по расписанию рейсов. Около 78% посадок привязано к остановкам, остаток показывается отдельной строкой «не распределено», поэтому суммы по остановкам сходятся с маршрутом.
| Источник | Как получить | Как используется |
|---|---|---|
| Валидации и справочники организаторов | dataset.zip | обучение и проверка; в Git не хранится |
| Календарь: праздники и переносы РФ 2025 | Постановление Правительства | в основной модели |
| Погода: температура и осадки | Open-Meteo Historical Forecast API, манифест выпущенных прогнозов; исторический архив для ретроспективного опыта | переключатель source_enabled.weather в approved POST и отдельный сценарный коэффициент |
| Дорожный трафик: опубликованные баллы пробок | канал Дептранса Москвы, манифест сводок | переключатель source_enabled.traffic и сценарный коэффициент; не непрерывный датчик загруженности |
| Инциденты и перекрытия | канал Дептранса Москвы, манифест сводок; KudaGo API исследован отдельно | переключатель source_enabled.events использует сообщения Дептранса, не афишу KudaGo |
| Остановки, порядок остановок, направления | GTFS-справочники из dataset.zip | геопривязка и карта |
| Граф трамвайной сети | OpenStreetMap через Overpass API, data/ | вкладка «Граф сети» |
Основная опубликованная модель использует календарь. Дополнительные обученные
ветки четырёх источников доступны в approved POST по явным флагам
source_enabled либо через выбранные пользователем веса факторов; без выбора
используется конкурсный ряд. Их сравнение на трёх хронологических окнах
не показало устойчивого улучшения над опубликованной моделью; этот вариант
не отправлялся на лидерборд. Ретроспективные опыты и ограничения покрытия
описаны в отчёте о внешних факторах.
Подробное обоснование по каждому критерию и подпункту PDF связывает заявку на баллы с кодом, замерами, артефактами и пределами доказательства.
| Критерий | Где проверить | Граница вывода |
|---|---|---|
| Качество конкурсного CSV | Скриншот результата 0.89195, файл, SHA-256 и воспроизведение, тест точной сетки и байтов | Скриншот показывает успешную отправку 27.09.2026 в 08:57 МСК, но не показывает имя CSV; точная сетка и байты файла проверяются отдельно. |
| Внешние источники | Манифесты и сравнение дополнительных веток; тест переключателей и provenance | Источники реально меняют ответ по запросу; устойчивый прирост качества для всех четырёх не доказан. |
| Область применимости и приём данных | Контракт датасета, сверка с организаторскими метками, проверка публикации | Наблюдаемая цель — маршрут × дата × час; остановки и направления оценочные. |
| Коэффициенты и функции сервиса | Тест сценария, фильтров, года и сохранения сумм, браузерные сценарии | Коэффициенты — ручной расчёт спроса, а год — качественный сценарий. |
| Архитектура и производительность | Фактический путь модулей, стенд и результат замера, проверка границ | На замере 937cca5 опубликованный GET уложился в p95 < 200 мс; часть остановочных и годовых POST превысила ориентир 200–300 мс. |
| Решение диспетчера | Проверки окна и ошибок планирования выпуска | Посадки на плановое отправление — оценка для сценария, не наблюдаемая заполненность вагона. |
Для быстрой проверки воспроизводимых контрактов из корня репозитория:
uv run --package tramflow-ml pytest ml/tests/test_checked_in_submission.py
uv run --package tramflow-backend pytest backend/tests/test_scored_bundle.py backend/tests/test_forecast_publication.py backend/tests/test_planning.py- Маршруты: 10 маршрутов датасета. Для маршрута 5 в истории нет успешных валидаций, по нему прогноз нулевой.
- Период: обучение на январе–октябре 2025, прогноз на ноябрь–декабрь 2025.
- Горизонты: день и месяц проверены на исторических окнах. Год — качественный сценарий: недельный профиль ноября–декабря продлевается на 12 месяцев без обучения годовой сезонности. HTTP 200 и 12 точек подтверждают работу функции, но не точность годового прогноза.
- Что прогнозируется: посадки, а не наполненность вагона: высадок и вместимости в данных нет.
- Остановки и направления: расчётная привязка по расписанию.
- Перенос на новый маршрут или период: история валидаций маршрута, его GTFS-каталог и повторная хронологическая проверка на 61-дневных окнах.
Замер 27.09.2026 на коммите 937cca5: backend в Docker ограничен 2 vCPU,
4 GiB RAM и нулевым swap, один Uvicorn worker; PostgreSQL 17.11 работает в
отдельном контейнере без этих лимитов. Хост — AMD Ryzen 7 5800X, Linux x86_64.
В каждом из 11 сценариев было 5 прогревочных и 200 измеряемых запросов при
concurrency 4; все 2 200 ответов соответствовали контракту, ошибок 0.
| Сценарий | Успешных RPS | p95 HTTP, мс |
|---|---|---|
| Опубликованный GET: день / месяц / интервал | 251,89 / 271,01 / 308,22 | 17,73 / 17,56 / 15,16 |
POST approved: день / месяц / качественный год |
150,46 / 44,64 / 5,47 | 39,44 / 128,72 / 1 167,85 |
POST stop_model: день / месяц / качественный год |
18,69 / 13,08 / 2,99 | 304,26 / 440,57 / 2 195,39 |
POST stop_model с фильтром остановки и направления |
20,22 | 293,72 |
| POST с неверной датой, ожидаемый HTTP 422 | 571,89 | 8,74 |
Основной опубликованный маршрутный прогноз на день и месяц укладывается в
числовые ориентиры PDF по RPS и p95 на измеренном стенде: 252–308 успешных RPS,
p95 15–18 мс при лимите backend 2 vCPU / 4 GiB и без swap. Интерактивный
approved POST на день и месяц также укладывается в ориентир по p95
(39 и 129 мс), хотя его пропускная способность ниже — 150 и 45 RPS.
Критерий 3 PDF оценивает подтверждённые командой latency/RPS в README;
отдельного нагрузочного теста жюри не проводит. Остановочные и качественные
годовые POST измерены отдельно: часть из них превышает ориентир p95 200–300 мс.
Замер короткий и локальный; масштабирование репликами и длительная устойчивость
не проверялись. Полные p50/p95/p99, выборки CPU/RAM, SHA образов, конфигурации
и артефактов приведены в протоколе и сыром результате.
Прежние несопоставимые результаты сохранены в
историческом протоколе.
Повторить замер:
make benchmark-config
make benchmark-up
make benchmark-preflight
make benchmark-run OUTPUT=docs/benchmark/results/NEW-RUN.json
make benchmark-publish INPUT=docs/benchmark/results/NEW-RUN.json
make benchmark-downBackend не хранит состояние HTTP-сессии; для реплик нужны общий PostgreSQL и одинаковые версионированные артефакты. Выигрыш от реплик, кэша или дополнительных workers пока не доказан.
- Прогноз по остановкам и направлениям с явной нераспределённой частью.
- Корректирующие коэффициенты ×0–×3 для погоды, календаря, событий и трафика с мгновенным пересчётом.
- Экспериментальная модель с независимо включаемыми внешними источниками.
- Горячие точки для планирования выпуска и интервалов.
- Анимация загрузки остановок по часам на карте.
- Версия модели, контрольные суммы артефактов и граница данных в каждом ответе API и в CSV.
- Атомарная публикация прогноза: при ошибке новой версии остаётся прежняя.
- Граф трамвайной сети с длинами по рельсам и кратчайшим путём.
- Посадки не равны наполненности вагона: данных о высадках и вместимости нет.
- Привязка к остановкам и направлениям — расчётная, по расписанию.
- Годовой прогноз — сценарий без обученной годовой сезонности.
- Прогноз точечный, без интервалов неопределённости.
- Сценарии по остановкам и на год считаются на каждый запрос, поэтому пропускная способность у них ниже.
- Получить от транспортного оператора фактические данные о направлении движения трамваев с привязкой к маршруту, вагону или рейсу и времени. Сверить их с валидациями, измерить покрытие и ошибки нынешней расчётной привязки. Даже подтверждённое направление вагона само по себе не устанавливает остановку посадки каждого пассажира.
- Использовать проверенные направления для развития графовых признаков,
заготовки для которых уже есть в
ml/src/tramflow_ml/competition_graph.pyиml/src/tramflow_ml/competition.py. Учитывать версию и дату доступности геометрии маршрутов, не подмешивать будущие сведения в прошлые прогнозы. Сравнить вариант с графовыми признаками с нынешней моделью на одинаковых хронологических окнах и по маршрутам. Включать его в основной прогноз только при устойчивом улучшении качества; действующий маршрутно-часовой путь сохранять независимым от оценочных направлений. - Получить многолетнюю историю валидаций, проверить перенос на новые маршруты и периоды и обучить годовую сезонность. Добавить интервалы неопределённости с проверкой их покрытия.
- Измерить узкие места и при необходимости кэшировать расчёты по остановкам и на год; проверить сервис под длительной нагрузкой. Подключать почасовой трафик и прогноз погоды только с проверкой доступности данных на момент прогноза и прироста качества.
- Добавить авторизацию, ограничение частоты запросов, TLS и мониторинг качества модели после развёртывания у оператора.
make bootstrap # зависимости backend, ML и frontend
make dev # PostgreSQL + backend + frontend в режиме разработки
make verify # линтеры, типы, тесты, миграции на чистой БД
make verify-full # + Docker smoke и браузерные E2EТребования к локальной среде: Python 3.13, Node 24, uv; либо .devcontainer.