Skip to content

About

No description, website, or topics provided.

Resources

Security policy

Stars

12 stars

Watchers

0 watching

Forks

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Тормоза — прогноз пассажиропотока московского трамвая

Тормоза — веб-сервис для диспетчеров ЕДЦ ГУП «Московский метрополитен». Он прогнозирует число посадок (успешных валидаций) на трамвайных маршрутах по часам и дням для конкурсного периода ноября–декабря 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

После запуска:

Остановить: docker compose down. Удалить данные БД: docker compose down -v.

Что посмотреть в интерфейсе

Прогноз (главная страница):

  1. Выберите маршрут, горизонт и начальную дату в ноябре–декабре 2025.
  2. Сузьте результат до направления или конкретной остановки.
  3. Посмотрите KPI: пиковый час, самую загруженную остановку и сумму за период. Сумму можно пересчитать за любой интервал «с — по».
  4. На карте Москвы остановки окрашены по посадкам в час. Ползунок и кнопка «Воспроизвести» показывают, как меняется загрузка в течение дня.
  5. Включите корректирующий коэффициент, например «Погода ×1.3»: карта, KPI, график и таблицы пересчитываются сразу.
  6. «Горячие точки» — остановки и часы от 50 посадок/ч, кандидаты для усиления выпуска и сокращения интервалов.
  7. «Скачать сценарий CSV» выгружает текущий срез с коэффициентами и версией модели.
  8. Внизу страницы — область применимости модели и ссылки на внешние источники.

Опубликованный прогноз — маршрутный прогноз той же модели, чей CSV сдан на лидерборд: почасовой график на день, посуточный на месяц, выбор окна времени и CSV выбранного окна. Кнопка «1 год · качественный сценарий» открывает планирование без запроса годового опубликованного прогноза. В планировании выберите месяц: карта, KPI, таблица и CSV показывают этот месяц. Ноябрь–декабрь 2025 относятся к конкурсному периоду; месяцы 2026 — сценарное повторение недельного профиля.

Как работает Тормоза — интерактивная схема фактического пути данных, запроса и развёртывания; показывает происхождение и ограничения узлов. Откройте страницу архитектуры после запуска.

Планирование сети — отдельная страница для проверки выпуска. Маршруты ранжируются по прогнозу посадок на плановое отправление за настраиваемое окно от 1 до 24 часов. Границы окна перетаскиваются с шагом в один час. Плановые отправления и оборот оцениваются по контрольному снимку GTFS, а интервал и оборот можно изменить вручную. Для выбранного маршрута можно задать число дополнительных вагонов. Сервис показывает расчётную частоту и среднее число посадок на отправление до и после изменения, исходные почасовые значения и выгрузку опубликованного прогноза в CSV. Параметры сценария видны на экране и в выгрузку прогноза не входят. Цвет маршрута отражает его относительное число посадок на плановое отправление по сравнению с медианой сети. Общий спрос остаётся неизменным. Снимок GTFS получен 30.06.2026, хотя его календари объявляют применимость к 2025 году; последовательность рейсов одного вагона оценена по коду выхода, поскольку block_id пуст. Это эвристика для проверки решения диспетчером, не измерение заполненности салона, фактического выполнения рейсов или экономического эффекта.

Граф сети — трамвайная сеть Москвы из OpenStreetMap: 856 остановок, 919 участков, 377 км путей, поиск остановки и кратчайший путь по рельсам.

REST API

# список маршрутов
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-down

Backend не хранит состояние HTTP-сессии; для реплик нужны общий PostgreSQL и одинаковые версионированные артефакты. Выигрыш от реплик, кэша или дополнительных workers пока не доказан.

Дополнительные возможности

  • Прогноз по остановкам и направлениям с явной нераспределённой частью.
  • Корректирующие коэффициенты ×0–×3 для погоды, календаря, событий и трафика с мгновенным пересчётом.
  • Экспериментальная модель с независимо включаемыми внешними источниками.
  • Горячие точки для планирования выпуска и интервалов.
  • Анимация загрузки остановок по часам на карте.
  • Версия модели, контрольные суммы артефактов и граница данных в каждом ответе API и в CSV.
  • Атомарная публикация прогноза: при ошибке новой версии остаётся прежняя.
  • Граф трамвайной сети с длинами по рельсам и кратчайшим путём.

Ограничения

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

План развития

  1. Получить от транспортного оператора фактические данные о направлении движения трамваев с привязкой к маршруту, вагону или рейсу и времени. Сверить их с валидациями, измерить покрытие и ошибки нынешней расчётной привязки. Даже подтверждённое направление вагона само по себе не устанавливает остановку посадки каждого пассажира.
  2. Использовать проверенные направления для развития графовых признаков, заготовки для которых уже есть в ml/src/tramflow_ml/competition_graph.py и ml/src/tramflow_ml/competition.py. Учитывать версию и дату доступности геометрии маршрутов, не подмешивать будущие сведения в прошлые прогнозы. Сравнить вариант с графовыми признаками с нынешней моделью на одинаковых хронологических окнах и по маршрутам. Включать его в основной прогноз только при устойчивом улучшении качества; действующий маршрутно-часовой путь сохранять независимым от оценочных направлений.
  3. Получить многолетнюю историю валидаций, проверить перенос на новые маршруты и периоды и обучить годовую сезонность. Добавить интервалы неопределённости с проверкой их покрытия.
  4. Измерить узкие места и при необходимости кэшировать расчёты по остановкам и на год; проверить сервис под длительной нагрузкой. Подключать почасовой трафик и прогноз погоды только с проверкой доступности данных на момент прогноза и прироста качества.
  5. Добавить авторизацию, ограничение частоты запросов, 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.

Документация

About

No description, website, or topics provided.

Resources

Security policy

Stars

12 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages