Metodología

Documentación del proyecto

Explicación clara de cómo funciona UrbanFlow Valencia: datos, optimización, predicción, despliegue y seguimiento del modelo.

Resumen del proyecto

UrbanFlow Valencia es una herramienta de planificación urbana para operarios del Ayuntamiento de Valencia. Integra dos módulos independientes que juntos permiten tomar decisiones informadas sobre la ciudad:

Módulo A — Predicción de tráfico

24 modelos CatBoost predicen la intensidad de tráfico hora a hora en las 1.158 zonas de medición de Valencia. El técnico puede consultar cualquier combinación de zona, hora, día y condición meteorológica y obtener el nivel de tráfico esperado con su margen de fiabilidad.

Módulo B — Optimización de instalaciones

Un solver ILP (PuLP + CBC) selecciona las ubicaciones de polideportivos, centros de salud o estaciones Valenbisi que maximizan la cobertura de población bajo el presupuesto disponible. Opera con candidatos reales del Ayuntamiento y datos censales H3.

Ambos módulos se apoyan en los mismos datos de base: 853.000 registros horarios de tráfico del Ayuntamiento de Valencia (octubre 2023), capas GeoJSON de la ciudad, datos de movilidad en tiempo real (Valenbisi, EMT, ArcGIS) y meteorología (AEMET / Open-Meteo).

El modelo CatBoost se valida de forma temporal estricta — entrenamiento con días 1-24, prueba con días 25-31 — y su fiabilidad se monitoriza en producción con alertas automáticas de MAE.

24 modelos CatBoost por horaOptimización ILP PuLP + CBC853 k registros de tráfico de Valencia

Guía rápida de uso

La interfaz está pensada para trabajar en tres pasos: primero se revisa la ciudad, después se configura el escenario y por último se interpreta el resultado con mapa, métricas y ranking.

1. Revisar la ciudad

Usa el mapa para ver estaciones actuales, ubicaciones posibles, demanda, tráfico y cobertura.

2. Definir el escenario

Elige servicio, presupuesto, número de puntos o pesos de movilidad según lo que quieras decidir.

3. Revisar la propuesta

Comprueba resultado, coste, población cubierta y zonas recomendadas antes de aceptar la propuesta.

Idea de la interfaz

La app no muestra todos los detalles internos. Resume lo necesario para que una persona pueda usar la herramienta y entender por qué aparece una recomendación.

Metodología CRISP-DM

El proyecto sigue CRISP-DM: entender el problema, preparar los datos, modelar, evaluar y dejar la solución lista para usarse.

FaseImplementación
Entender el problemaDesarrollar una herramienta de apoyo a la decisión para operarios del Ayuntamiento de Valencia con dos módulos independientes: (1) predecir el tráfico horario en las 1.158 zonas de la ciudad, útil para planificar operaciones y eventos; y (2) optimizar dónde instalar nuevos equipamientos urbanos maximizando la cobertura de población bajo un presupuesto real.
Entender los datosDatos de tráfico del Ayuntamiento de Valencia: ~853.000 registros horarios de octubre 2023 en más de 1.158 zonas. También: hexágonos H3 con censo, candidatos a instalaciones, estaciones Valenbisi, paradas EMT y datos meteorológicos AEMET.
Preparar los datosLimpieza y alineación temporal de los registros de tráfico. Construcción del baseline histórico por zona, día y hora. Generación de embeddings de zona (5 dimensiones). Cálculo de features cíclicas (hora_sin/cos) y retardos meteorológicos. Cálculo de matrices de cobertura H3.
Modelar24 modelos CatBoost independientes, uno por hora del día (hora 0 a hora 23). Cada modelo aprende el residuo respecto al baseline histórico en escala log-ratio. Un peso sigmoid (shrink weight) regresa la predicción al baseline cuando hay poca evidencia. Solver ILP PuLP/CBC para optimización de instalaciones.
EvaluarValidación temporal estricta: entrenamiento con días 1-24 de octubre 2023, prueba con días 25-31 (nunca vistos). Métricas globales: MAE ≈ 44,4 veh/h · RMSE ≈ 87,8 · R² ≈ 0,92 · sMAPE ≈ 16,8 %. Análisis por hora del día y por zona para detectar errores sistemáticos.
DesplegarBackend FastAPI dockerizado en Hugging Face Spaces. Frontend Next.js 14 en Vercel. CI/CD con GitHub Actions: lint, tests, build y publicación automática al hacer push a la rama production.
MonitorizarAlertas automáticas cuando el MAE de una hora supera el umbral (80 veh/h). Identificación de zonas con error sistemático. Exposición de métricas del sistema (CPU, memoria, uptime). Integración de datos en tiempo real con cache TTL para Valenbisi, EMT y tráfico ArcGIS.

Cómo está montada la app

La app se divide en tres partes: la interfaz web, la API que hace los cálculos y los archivos de datos y modelos.

Usuario (técnico municipal)
        │  navegador
        ▼
Frontend Next.js  ──────────  Vercel
        │  HTTP/JSON (NEXT_PUBLIC_API_URL)
        ▼
Backend FastAPI  ───────────  Hugging Face Spaces (Docker)
        │
        ├─ Optimización PuLP/CBC   → /optimize/*
        ├─ Modelo CatBoost (.cbm)  → /predict
        └─ Artefactos (CSV/GeoJSON)→ /metrics, /map, /candidates

Frontend

Next.js, TypeScript, Tailwind, Leaflet y Recharts. Aquí está la interfaz que usa el usuario.

Backend

FastAPI. Carga datos y modelos ya preparados, y resuelve la optimización con PuLP.

Datos y modelos

Modelos CatBoost, CSV y GeoJSON con candidatos, áreas de alcance y métricas.

Despliegue

Cada parte se despliega donde encaja mejor: Vercel sirve la interfaz, Hugging Face Spaces ejecuta la API en Docker y GitHub Actions revisa que el código siga funcionando.

1 · Frontend en Vercel

Vercel está conectado al repositorio y usa la carpeta frontend/. Cuando se actualiza la rama production, construye y publica la web. La URL de la API se configura con esta variable:

NEXT_PUBLIC_API_URL = https://cofrian-edm-proyect.hf.space

2 · Backend en Hugging Face Spaces (Docker)

El Dockerfile prepara Python, instala CBC para la optimización, instala las dependencias y arranca la API con Uvicorn en el puerto que usa Hugging Face Spaces:

FROM python:3.11-slim
RUN apt-get install -y coinor-cbc          # optimizador
RUN pip install -r requirements.txt        # FastAPI, CatBoost, PuLP...
COPY . .
CMD uvicorn main:app --host 0.0.0.0 --port 7860

Los modelos .cbm se guardan con Git LFS. El acceso desde la web se controla con ALLOW_ORIGINS, donde se indican las URLs permitidas de Vercel.

3 · CI/CD en GitHub Actions

Flujo de ramas y revisiones automáticas:

feature/*  →  develop  →  main  →  production
ProcesoCuándo se ejecutaQué revisa
backend-cipush/PR en backend/Calidad del backend, tests, carga de la app, CBC y Git LFS
frontend-cipush/PR en frontend/ESLint, TypeScript y build de Next.js
docker-buildpush en mainConstrucción de la imagen Docker
deploy-hfpush a production con backend/Publicación del backend en Hugging Face Spaces
deploy-checkpush a productionComprobación de que la API desplegada responde

Quién publica cada parte

GitHub Actions revisa el código. Vercel publica el frontend y Hugging Face publica el backend. El proceso deploy-checkcomprueba que la API responde después del despliegue.

Optimización urbana (ILP — PuLP + CBC)

El optimizador resuelve un problema de programación lineal entera (ILP) usando la librería PuLP con el solver de código abierto CBC (COIN-OR Branch-and-Cut). Dado un conjunto de candidatos reales de Valencia, selecciona la combinación que maximiza la cobertura de población bajo las restricciones definidas por el usuario.

Formulación general del problema de cobertura

Variables:
  Xᵢ ∈ {0,1}  →  se construye el candidato i o no
  Yⱼ ∈ {0,1}  →  el hexágono H3 de población j queda cubierto

Objetivo:
  max  Σⱼ población_j × Yⱼ       (maximizar habitantes cubiertos)

Restricciones:
  Yⱼ ≤ Σᵢ αᵢⱼ × Xᵢ   ∀j         (cobertura según candidatos elegidos)
  Σᵢ coste_i × Xᵢ ≤ presupuesto  (restricción económica)
  Xᵢ, Yⱼ ∈ {0,1}                 (variables binarias)

αᵢⱼ = 1 si el candidato i cubre el hexágono j (radio de alcance)

Los 5 modos de optimización disponibles

ModoObjetivoRestricción extraEndpoint
PolideportivosMáx. población con cobertura deportiva nuevaΣ coste ≤ presupuesto/optimize/sports
Centros de saludMáx. población con cobertura sanitaria nuevaΣ coste ≤ presupuesto/optimize/health
Multiobjetivoλ × cobertura_deportiva + (1−λ) × cobertura_sanitariaXᵢ + X′ᵢ ≤ 1 (no solapamiento)/optimize/multi
ValenbisiMáx. score = tráfico + población + déficit_servicioΣ xᵢ = N (número fijo)/optimize/valenbisi
Cobertura generalMáx. población cubierta por cualquier equipamientoΣ coste ≤ presupuesto/optimize/coverage

Cobertura sobre hexágonos H3

La ciudad de Valencia se divide en hexágonos H3 con datos censales reales. Para cada candidato se precalcula qué hexágonos cubre en función de su radio de alcance, generando la matriz de cobertura α (candidato × hexágono). El optimizador usa esta matriz para determinar cuánta población nueva quedaría cubierta al seleccionar cada combinación de candidatos.

Modo Valenbisi: score compuesto

score_i = w_tráfico  × tráfico_normalizado_i
         + w_población × población_normalizada_i
         + w_déficit   × déficit_servicio_i

Donde déficit_i mide la falta de estaciones Valenbisi
en el entorno de la ubicación candidata i.
Los pesos son configurables por el usuario en la interfaz.

Garantía de optimalidad

A diferencia de una heurística, el solver CBC encuentra la solución óptima global para los parámetros indicados, no solo una buena aproximación. El tiempo de resolución típico es de 5 a 30 segundos para los conjuntos de candidatos de Valencia.

Flujo completo de datos

UrbanFlow encadena cuatro etapas: ingesta de datos reales de Valencia, predicción horaria de tráfico con CatBoost, optimización ILP de instalaciones y exposición de resultados vía API REST. Cada etapa está desacoplada y es reproducible de forma independiente.

EtapaQué haceImplementación
Datos de tráfico853k registros horarios del Ayuntamiento de Valencia, octubre 2023. Limpieza, alineación temporal y construcción del baseline por zona/día/hora.backend/data/processed · baseline_oct2023_SMOO.csv
Predicción CatBoost24 modelos entrenados (uno por hora). Features: hora_sin/cos, embeddings de zona, variables meteo y retardos. Shrink weight sigmoid para gestionar incertidumbre.src/pipeline.py · models/catboost_hour_HH.cbm · /predict/heatmap
Matriz de cobertura H3Para cada candidato se precalcula qué hexágonos H3 de población cubre según su radio. Genera la matriz α usada por el solver.data/processed/coverage_alpha.json · population_hexes.csv
Optimización ILPPuLP formula el problema de cobertura máxima bajo presupuesto. CBC (Branch-and-Cut) resuelve en 5-30 s. 5 modos disponibles.src/optimize_facility.py · src/optimize_valenbisi.py · /optimize/*
Movilidad tiempo realValenbisi, EMT y tráfico ArcGIS con cache TTL. AEMET con fallback a Open-Meteo. Alertas automáticas de estación vacía, retraso de bus y MAE alto.src/integrations/ · src/ttl_cache.py · /api/mobility/*
API REST + FrontendFastAPI expone 50+ endpoints JSON. Next.js renderiza mapas Leaflet, gráficos Recharts y el panel de alertas sin contener lógica de negocio.main.py · frontend/lib/api.ts

Modelo de predicción de tráfico (CatBoost)

El sistema entrena 24 modelos CatBoost independientes, uno por cada hora del día (hora 0 a hora 23), sobre datos de tráfico de Valencia de octubre de 2023. Cada modelo aprende el residuo de su hora respecto a un baseline histórico suavizado por zona, día de la semana y hora.

Fórmula de predicción (enfoque híbrido)

intensidad = baseline(zona, día_semana, hora)
           × exp(shrink_weight × residual_CatBoost)

shrink_weight = sigmoid((baseline − τ) / s)

El peso sigmoid hace que la predicción regrese al baseline
cuando el tráfico histórico es bajo (horas nocturnas,
zonas poco representadas), evitando extrapolaciones erróneas.

Features del modelo

CategoríaVariables
Temporales (cíclicas)hora_sin, hora_cos, dia_mes_norm, wind_sin, wind_cos
Embeddings de zonaz_emb1 … z_emb5 (5 dimensiones aprendidas por zona)
Meteorológicastemp_c, hum_rel, pres_mb, vel_viento_ms, precip_lm2
Retardos meteorológicostemp_c_lag1, temp_c_lag3, pres_mb_lag1, pres_mb_lag3
CategorialesZona (1.158 valores), Dia_Semana, tipo_dia (laboral / festivo / fin de semana)

Validación temporal

Entrenamiento: días 1-24 de octubre 2023. Prueba: días 25-31 (nunca usados en ninguna fase de ajuste ni selección de hiperparámetros). Resultados sobre el conjunto de prueba:

MAE

≈ 44.4

RMSE

≈ 87.8

≈ 0.92

sMAPE

≈ 16.8 %

Cómo interpretar estas métricas

MAE de 44,4 veh/h sobre una intensidad media de varios cientos de vehículos por hora representa un error relativo bajo. R² = 0,92 indica que el modelo explica el 92 % de la varianza del tráfico en el conjunto de prueba. Las horas con mayor error (madrugada, eventos puntuales) se señalan en el módulo de monitorización.

Evaluación y monitorización

EDM pone el foco en que un modelo no termina cuando se entrena: hay que evaluar su calidad, desplegarlo como servicio y vigilar que siga siendo fiable en producción. UrbanFlow implementa las tres capas.

Evaluación del modelo

La validación es temporal estricta: los días 25-31 de octubre de 2023 nunca se usan en entrenamiento, ajuste de hiperparámetros ni selección de features. Las métricas globales son:

MétricaValor (prueba)Qué mide
MAE≈ 44,4 veh/hError absoluto medio. Fácil de interpretar: en promedio el modelo se equivoca en 44 vehículos por hora.
RMSE≈ 87,8Penaliza errores grandes. Indica que hay picos de error en horas o zonas concretas.
≈ 0,92Varianza explicada. El modelo captura el 92 % del comportamiento del tráfico de Valencia.
sMAPE≈ 16,8 %Error porcentual simétrico. Útil para comparar entre zonas con distinta escala de tráfico.

La app también calcula estas métricas por hora del día y por zona, exponiendo los resultados en /metrics/by-hour y /metrics/errors-by-zone. Esto permite identificar en qué franjas horarias o zonas el modelo tiene mayor incertidumbre.

Sistema de alertas de monitorización

El módulo de monitorización compara el MAE de cada hora con un umbral configurable (por defecto 80 veh/h). Cuando una hora lo supera, genera una alerta que aparece en el panel de monitorización y se expone en la API:

Tipo de alertaCondiciónEndpoint
MAE alto por horaMAE_hora > umbral (80 veh/h)/monitoring/alerts
Zona de error sistemáticoTop zonas con mayor error en validación/monitoring/zones-to-review
Zona de baja confianzaBaseline bajo → shrink weight alto → predicción poco fiable/monitoring/zones-to-review
Valenbisi vacía / llenaEstación sin bicicletas o sin anclajes libres/api/mobility/alerts
Valenbisi cerca de eventoEstación a menos de 1 km de un evento activo/api/mobility/alerts
Bus EMT con retrasoRetraso SAE superior a 3 minutos/api/mobility/alerts
Estado del sistemaCPU, memoria, uptime del contenedor Docker/monitoring/system

Monitorización de datos en tiempo real

Además del modelo, la app monitoriza la frescura de los datos externos. Cada fuente tiene un TTL: si los datos superan ese tiempo sin actualizarse, la API devuelve un flag stale: true y puede activar el fallback. Esto garantiza que el usuario siempre sepa si está viendo datos actuales o una estimación.

Por qué la monitorización importa en EDM

Un modelo preciso en validación puede degradarse en producción si el tráfico cambia (obras, nuevas vías, cambios de comportamiento). El sistema de alertas permite detectar esta degradación automáticamente, sin esperar a que alguien note visualmente que algo falla.

Tecnología y reproducibilidad

Frontend

Next.js 14 · TypeScript · TailwindCSS · Recharts · Leaflet

Backend

FastAPI · Pydantic · CatBoost · PuLP/CBC · Pandas · PyArrow

Infraestructura

Vercel · Hugging Face Spaces (Docker) · GitHub Actions

Datos y modelos

Git LFS (.cbm, .parquet) y scripts para validar archivos

El flujo técnico documenta preparación, entrenamiento, evaluación y optimización. Los scripts permiten regenerar los archivos yvalidate_artifacts.py comprueba que estén bien.