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.
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
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.
| Fase | Implementación |
|---|---|
| Entender el problema | Desarrollar 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 datos | Datos 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 datos | Limpieza 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. |
| Modelar | 24 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. |
| Evaluar | Validació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. |
| Desplegar | Backend 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. |
| Monitorizar | Alertas 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, /candidatesFrontend
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
| Proceso | Cuándo se ejecuta | Qué revisa |
|---|---|---|
| backend-ci | push/PR en backend/ | Calidad del backend, tests, carga de la app, CBC y Git LFS |
| frontend-ci | push/PR en frontend/ | ESLint, TypeScript y build de Next.js |
| docker-build | push en main | Construcción de la imagen Docker |
| deploy-hf | push a production con backend/ | Publicación del backend en Hugging Face Spaces |
| deploy-check | push a production | Comprobación de que la API desplegada responde |
Quién publica cada parte
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
| Modo | Objetivo | Restricción extra | Endpoint |
|---|---|---|---|
| Polideportivos | Máx. población con cobertura deportiva nueva | Σ coste ≤ presupuesto | /optimize/sports |
| Centros de salud | Máx. población con cobertura sanitaria nueva | Σ coste ≤ presupuesto | /optimize/health |
| Multiobjetivo | λ × cobertura_deportiva + (1−λ) × cobertura_sanitaria | Xᵢ + X′ᵢ ≤ 1 (no solapamiento) | /optimize/multi |
| Valenbisi | Máx. score = tráfico + población + déficit_servicio | Σ xᵢ = N (número fijo) | /optimize/valenbisi |
| Cobertura general | Má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
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.
| Etapa | Qué hace | Implementación |
|---|---|---|
| Datos de tráfico | 853k 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 CatBoost | 24 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 H3 | Para 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 ILP | PuLP 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 real | Valenbisi, 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 + Frontend | FastAPI 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ía | Variables |
|---|---|
| Temporales (cíclicas) | hora_sin, hora_cos, dia_mes_norm, wind_sin, wind_cos |
| Embeddings de zona | z_emb1 … z_emb5 (5 dimensiones aprendidas por zona) |
| Meteorológicas | temp_c, hum_rel, pres_mb, vel_viento_ms, precip_lm2 |
| Retardos meteorológicos | temp_c_lag1, temp_c_lag3, pres_mb_lag1, pres_mb_lag3 |
| Categoriales | Zona (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
R²
≈ 0.92
sMAPE
≈ 16.8 %
Cómo interpretar estas métricas
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étrica | Valor (prueba) | Qué mide |
|---|---|---|
| MAE | ≈ 44,4 veh/h | Error absoluto medio. Fácil de interpretar: en promedio el modelo se equivoca en 44 vehículos por hora. |
| RMSE | ≈ 87,8 | Penaliza errores grandes. Indica que hay picos de error en horas o zonas concretas. |
| R² | ≈ 0,92 | Varianza 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 alerta | Condición | Endpoint |
|---|---|---|
| MAE alto por hora | MAE_hora > umbral (80 veh/h) | /monitoring/alerts |
| Zona de error sistemático | Top zonas con mayor error en validación | /monitoring/zones-to-review |
| Zona de baja confianza | Baseline bajo → shrink weight alto → predicción poco fiable | /monitoring/zones-to-review |
| Valenbisi vacía / llena | Estación sin bicicletas o sin anclajes libres | /api/mobility/alerts |
| Valenbisi cerca de evento | Estación a menos de 1 km de un evento activo | /api/mobility/alerts |
| Bus EMT con retraso | Retraso SAE superior a 3 minutos | /api/mobility/alerts |
| Estado del sistema | CPU, 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
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.