Anatomía completa del motor de predicción de EpiForecast-MX
v6 — Febrero 2026 — 312 modelos · 3 padecimientos · 32 entidades
Tres pasos secuenciales convierten los conteos crudos en el espacio donde Prophet entrena
y_tasa = (incidencia / población) × 100,000
Normaliza por tamaño de la entidad. CDMX y Colima ahora son directamente comparables. El RMSE deja de estar dominado por los estados grandes.
Fuente de población: data/utils/inegi.csv — columna Total (proyecciones CONAPO por año)
y = log(1 + y_tasa)
Estabiliza la varianza. Series con picos extremos (Depresión post-pandemia, alertas epidemiológicas) quedan comprimidas. El +1 garantiza que log(0)=0 sin indefinidos.
Impacto medido: redujo el RMSE mediano de Depresión en -64% vs serie sin log-transform
Prophet.fit(df[y = log(1 + y_tasa)])
El modelo aprende en espacio log-tasa. Al predecir, se revierten ambas transformaciones para obtener conteos absolutos:
conteos = (exp(ŷ) - 1) × población / 100,000
Conteos absolutos desnormalizados por entidad y semana. El CSV sidecar del .pkl guarda y_original y Total (población) para la inversión exacta en producción.
Columnas: yhat (conteos), yhat_lower, yhat_upper (IC 95%)
Comparación conceptual: varianza antes y después. Datos estilizados representativos.
El log comprime colas largas a la derecha. Series de Depresión con CV >2 quedan cerca de distribución normal en log-espacio.
Prophet modela cambios relativos (multiplicativos en log-espacio). Un cambio de +0.1 en y representa ~+10.5% en tasa original.
exp(ŷ) ≥ 0 siempre. Nunca se predice una tasa negativa, lo que elimina post-procesamiento de clipping.
normalizar_tasa: truelog_transform: truetasa_por: 100000columna_poblacion: "Total"
Configuración de los componentes estructurales de Prophet para series epidemiológicas semanales
La estacionalidad anual default de Prophet usa periodo=365.25 días (sin decimales), impreciso para series semanales. Se reemplaza con una estacionalidad personalizada de periodo exacto.
Sustituida por: add_seasonality(period=52.18, fourier_order=5)
Los datos tienen una observación por semana epidemiológica (SINAVE). No existe variación intra-semanal que modelar — activarla solo agrega ruido al modelo.
Frecuencia de datos: 1 obs/semana (resolución temporal = semana)
Mismo razonamiento: sin variación diaria en datos semanales. Activarla introduce 14 coeficientes sin respaldo empírico (7 sin + 7 cos para fourier_order=7).
Siempre False en series epidemiológicas semanales
Equivalente exacto de 365.25 / 7 = 52.1786... semanas. Captura el ciclo anual real con mayor precisión que el periodo default de Prophet en días.
365.25 / 7 = 52.178... — el 0.25 captura los años bisiestos en promedio
Genera 5 funciones seno + 5 coseno = 10 regresores en la matriz de diseño. Permite patrones estacionales complejos con hasta 5 "armónicos".
Ejemplo: brotes de otoño + temporada navideña + repunte primaveral = 3 armónicos mínimo
Series estatales son más cortas y volátiles. Con fourier_order=5 en series de ~285 puntos, hay riesgo de overfitting al patrón de entrenamiento. -40% coeficientes.
Activo cuando: modelado_estados: true en params.yaml
1 changepoint cada ~11 semanas en la serie completa (~285 semanas). Captura cambios de tendencia anuales y post-pandemia con suficiente granularidad.
Prophet los distribuye uniformemente en el 80% inicial de la serie
Con 25 changepoints en series cortas (~150 puntos para estados pequeños), Prophet sobreajusta cambios locales. 12 = 1 changepoint cada ~12 semanas (~1 por trimestre).
Activo cuando: modelado_estados: true — previene overfitting en estados <1M hab.
Tendencia lineal (por tramos, ajustada en changepoints). La tendencia "logistic" requiere definir una capacidad de saturación (cap) que no está justificada epidemiológicamente.
Apropiado para padecimientos crónicos sin límite observable de saturación a corto plazo
Comparación conceptual de la riqueza de patrones estacionales con 3 vs 5 armónicos (1 año = 52 semanas)
Grids v5 diferenciados por padecimiento — optimizados con datos de 297 modelos v4
Controla qué tanto puede cambiar la tendencia en cada changepoint. Es una prior Laplace sobre los deltas de tendencia.
Controla la amplitud de los coeficientes de Fourier. Prior Normal(0, sp). Valores bajos = estacionalidad más suave y regularizada.
Define cómo interactúa la componente estacional con la tendencia.
y(t) = tendencia(t) + estacionalidad(t) + ruido
La amplitud estacional es constante independiente del nivel de tendencia. Mejor para Depresión.
y(t) = tendencia(t) × (1 + estacionalidad(t)) + ruido
La amplitud escala con la tendencia. Mejor para Alzheimer (crecimiento poblacional).
| cp \ sp | 0.05 nuevo | 0.1 | 0.5 |
|---|---|---|---|
| cp=0.01 | Ganador 41% | Frecuente | Raro |
| cp=0.03 | Moderado | Moderado | Raro |
seasonality_mode: solo multiplicative (additive eliminado: +51% RMSE vs multiplicative)
| cp \ sp | 0.025 nuevo | 0.05 | 0.1 | 0.5 |
|---|---|---|---|---|
| cp=0.01 | Moderado | Alto | Moderado | Bajo |
| cp=0.03 | Moderado | Alto | Moderado | Bajo |
| cp=0.05 | Bajo | Moderado | Moderado | Bajo |
| cp \ sp | 0.025 | 0.05 | 0.1 | 0.5 |
|---|---|---|---|---|
| cp=0.01 | Bajo | Moderado | Moderado | Bajo |
| cp=0.03 | Bajo | Moderado | Alto | Bajo |
| cp=0.05 | Bajo | Bajo | Moderado | Bajo |
| cp \ sp | 0.1 | 0.5 ganador | 1.0 |
|---|---|---|---|
| cp=0.03 | Moderado | RMSE 0.046 | Raro |
| cp=0.04 nuevo | Moderado | Alto | Raro |
| cp=0.05 | Moderado | Moderado | Bajo |
seasonality_mode: [multiplicative, additive]
Total de combinaciones en el grid de CV por enfermedad
Valores de changepoint_prior_scale por padecimiento
| Parámetro / Padecimiento | v4 | v5 | v6 | Motivo |
|---|---|---|---|---|
| Alzheimer · additive | Incluido | Eliminado | Eliminado | +51% RMSE vs multiplicative |
| Alzheimer · sp=0.05 | No estaba | Agregado | Mantiene | Ganador en 41% de modelos Alzheimer |
| Depresión · sp=0.025 | No estaba | Agregado | Mantiene | Mayor regularización para series volátiles |
| Depresión · sp=1.0 | Incluido | Eliminado | Eliminado | Ganaba 29% individual pero peor RMSE medio |
| Parkinson · cp=0.01 | Incluido | Eliminado | Eliminado | Newton-prone en 35% de series Parkinson |
| Parkinson · cp=0.07 | Incluido | Eliminado | Eliminado | Nunca ganaba — desechar para ahorrar tiempo |
| Parkinson · cp=0.04 | No estaba | Agregado | Mantiene | Interpolación 0.03–0.05, ganador en 20% Parkinson |
| fourier_order estatal | 5 (igual que nacional) | 3 (reducido) | Mantiene 3 | Previene overfitting en series cortas estatales |
| n_changepoints estatal | 25 (igual que nacional) | 12 (reducido) | Mantiene 12 | 1 changepoint cada 24 sem vs 11 sem (más estable) |
| MASE metric en CV | No estaba | No estaba | Agregado v6 | MAE_modelo / MAE_naive_lag52 — escala-independiente |
| Modo híbrido (fallback regional) | No estaba | No estaba | Agregado v6 | 100% cobertura estatal (vs 87% en v5) |
4 folds con pesos progresivos — los periodos recientes pesan más en la selección del modelo
En lugar de np.mean(metrics) sobre los 4 folds, se usa:
El fold post-COVID (2020-2021) recibe la mitad del peso del fold actual. Evita que el periodo atípico domine la selección de hiperparámetros.
Mayor peso a periodos recientes — menor al periodo pandémico
Después de la CV, el mejor conjunto de hiperparámetros se usa para entrenar el modelo con la serie completa (2014-2026), no solo el split de entrenamiento del último fold.
Razonamiento
CV evalúa el desempeño predictivo. El .pkl en producción necesita toda la información disponible para el pronóstico futuro — incluir 2024-2026 mejora la proyección a 52 semanas.
Impacto
+53 semanas de datos adicionales en el modelo final vs v4 (que entrenaba solo hasta el split de CV). Mejora especialmente la proyección en series con tendencia reciente marcada.
Sistema de 5 capas para prevenir que Prophet caiga al optimizador Newton (100-500x más lento)
changepoint_prior_scale muy bajo — cae silenciosamente al optimizador Newton, que puede tardar 30-90 minutos por modelo. Chihuahua-Depresión tardaba 39 minutos en v4. Con las 5 capas de protección, pasó a 4 minutos en v5 — una reducción de 9.75x.
El grid se ordena de mayor a menor changepoint_prior_scale antes de iniciar CV. Los combos con cp alto (ej. 0.05) son menos propensos a Newton y convergen más rápido — se prueban primero para establecer un baseline rápido.
Cada fold de CV corre en un ThreadPoolExecutor con un timeout de 35 segundos. Si el fold excede ese límite, se cancela y el combo recibe RMSE=infinito para ese fold.
Si un combo con cp=X genera timeout en cualquier fold, se registra X como "umbral Newton". Todos los combos con cp < X se saltan (skip) automáticamente, ya que son aún más propensos a Newton.
Backstop total por combinación. Si los 4 folds juntos superan 90 segundos, el combo completo se descarta. Evita que un solo combo atípico bloquee el grid search.
Si todos los combos del grid generan timeout, se usa el primer valor del grid con el mayor cp disponible (el menos propenso a Newton). Garantiza que siempre se produce un modelo, aunque sea con hiperparámetros conservadores.
Tiempo de entrenamiento v4 vs v5 — impacto de la protección anti-Newton
Con changepoint_prior_scale=0.01, la prior Laplace es extremadamente estrecha. L-BFGS necesita muchos pasos para encontrar la curvatura correcta en ese espacio de parámetros — y a menudo falla la convergencia, activando el fallback a Newton.
Optimizador quasi-Newton de memoria limitada. Típicamente converge en 50-200 iteraciones. Tiempo: 2-10 segundos por fold.
Newton completo requiere la Hessiana exacta. En espacio de alta dimensión (Fourier + changepoints), puede tardar 500-2000 iteraciones. Tiempo: 5-40 minutos por fold.
cp=0.01 se prueba primero (orden descendente). Si timeout en fold 1, se salta todos los cp menores. Tiempo total: <5 min por serie.
Cobertura 100% estatal — estados con datos insuficientes usan modelos regionales como fallback
Si el promedio semanal de una serie estatal es < 0.5, se marca como confianza: "insuficiente". Reducido de 1.0 (v5) a 0.5 (v6) para recuperar ~40 modelos que tenían datos usables pero escasos.
CV y entrenamiento regional se realizan normalmente (datos agregados suficientes)
Estado insuficiente: el .pkl regional del estado correspondiente se usa para predicción
La desnormalización usa la población individual del estado, no la regional — escala correcta
El CSV all_forecast.csv incluye columna usar_regional y mapeo a .pkl regional
CDMX, Jalisco, Nuevo León, Estado de México. Alta densidad, servicios de salud mental desarrollados.
Aguascalientes, Querétaro, Guanajuato, Coahuila. Urbanización creciente, cobertura IMSS media.
Chiapas, Oaxaca, Guerrero, Veracruz. Alta marginalidad, sub-registro alto, series más cortas.
Durango, Zacatecas, Colima, BCS, Nayarit. Baja densidad, mayor proporción de modelos insuficientes.
Modelos con confianza "normal" vs "insuficiente" — los insuficientes usan fallback regional en v6
Holidays de Prophet que absorben eventos extraordinarios sin contaminar los patrones estacionales normales
holidays con lower_window y upper_window. Prophet aprende un efecto específico para esas fechas, separándolo del componente estacional. Esto evita que COVID-19, por ejemplo, distorsione el patrón anual aprendido para todos los años.
Declaración de pandemia. Los tres padecimientos experimentaron disrupciones distintas: Depresión con pico de demanda + colapso de reporte, Parkinson con interrupción de consultas, Alzheimer con sub-registro en domicilios. La ventana de 913 días cubre hasta mediados de 2022, absorbiendo la fase de recuperación gradual.
Quiebre estadístico en la serie de Depresión de Tabasco a principios de 2023 — posiblemente asociado a cambio en protocolo de diagnóstico o sistema de reporte. Sin este holiday, el RMSE de Tabasco-Depresión era 6.2% más alto. Filtrado por entidad="Tabasco" y padecimiento="Depresión".
No produjo mejora estadísticamente significativa en ningún padecimiento. Removido en v5.
Cambios de régimen permanentes (posibles fusiones de clínicas o redefinición de catchment). Prophet trata los holidays como eventos temporales — mal ajuste para escalones permanentes. Empeoraron el RMSE.
Cuatro métricas complementarias — cada una captura un aspecto distinto del error de pronóstico
Error cuadrático medio. Penaliza errores grandes (outliers) más que errores pequeños debido al cuadrado. Se minimiza en el grid search de CV. Expresado en unidades de log-tasa por 100K.
Error absoluto medio. Más interpretable que RMSE: representa el error típico en unidades log-tasa. Más robusto a outliers que RMSE. Se incluye en all_forecast.csv como métrica de diagnóstico.
Error porcentual absoluto medio. Problemático cuando y ≈ 0 (explosión a infinito). Se usa la bandera mape_confiable: solo se reporta si el mínimo de y es >0.1. Se clipea a 999 para evitar infinitos.
Error absoluto medio escalado. El denominador es el MAE de un modelo naive que predice el mismo valor que hace 52 semanas (lag-52). MASE < 1 significa que el modelo supera al baseline seasonal naive.
RMSE y MASE medios — normalizado para visualización conjunta (escala diferente entre métricas)
297 modelos estatales + 15 fallback regionales — 312 series, ~45 minutos con n_jobs=-2
| Padecimiento | Modelos | Insuficientes | Fallback regional | RMSE medio | MAE medio | MASE medio | Tiempo |
|---|---|---|---|---|---|---|---|
| Alzheimer | 99 | 36 | 36 | 0.027 | 0.021 | 0.74 | ~2 min |
| Depresión | 99 | 0 | 0 | 0.183 | 0.143 | 0.80 | ~28 min |
| Parkinson | 99 | 5 | 5 | 0.057 | 0.044 | 0.75 | ~14 min |
Los tres padecimientos presentan MASE < 1 — los modelos Prophet superan consistentemente al baseline naive estacional (lag-52 semanas). El modo híbrido elevó la cobertura estatal informada del 87% (v5) al 100% (v6). La protección anti-Newton redujo el tiempo de entrenamiento de Depresión de >2 horas (v4) a 28 minutos. El sistema está listo para producción con 52 semanas de proyección por entidad.
En espacio log-tasa por 100K — escalas diferentes entre padecimientos
MASE < 1.0 indica superioridad sobre el baseline naive estacional
Referencia exhaustiva de todos los parámetros de configuración del sistema Prophet en EpiForecast-MX
| Parámetro | Archivo config | Valor | Tipo | Condicional | Impacto |
|---|---|---|---|---|---|
| Target y normalización | |||||
| normalizar_tasa | modelado.yaml | true | bool | Siempre | Convierte conteos a tasa por 100K |
| tasa_por | modelado.yaml | 100000 | int | Siempre | Factor de escala per cápita |
| columna_poblacion | modelado.yaml | "Total" | str | Siempre | Columna INEGI para desnormalizar |
| log_transform | modelado.yaml | true | bool | Siempre | log(1+y_tasa) — estabiliza varianza |
| Estacionalidad | |||||
| yearly_seasonality | prophet.py | False | bool | Siempre | Reemplazada por custom add_seasonality |
| weekly_seasonality | prophet.py | False | bool | Siempre | Sin variación intra-semanal (1 obs/sem) |
| daily_seasonality | prophet.py | False | bool | Siempre | Sin variación diaria en datos semanales |
| period (custom anual) | prophet.py | 52.18 | float | Siempre | 365.25/7 — captura años bisiestos |
| fourier_order (nacional) | modelado.yaml | 5 | int | modelado_estados: false | 10 coeficientes — patrones complejos |
| fourier_order_regional | modelado.yaml | 3 | int | modelado_estados: true | 6 coeficientes — previene overfitting estatal |
| Tendencia y changepoints | |||||
| growth | prophet.py | "linear" | str | Siempre | Sin capacidad de saturación definida |
| n_changepoints (nacional) | prophet.py | 25 | int | modelado_estados: false | 1 cp cada ~11 sem — resolución alta |
| n_changepoints_regional | modelado.yaml | 12 | int | modelado_estados: true | 1 cp cada ~24 sem — evita sobreajuste |
| Hiperparámetros del grid | |||||
| changepoint_prior_scale | modelado.yaml | [0.01–0.05] | float | Por padecimiento | Flexibilidad de tendencia — riesgo Newton si muy bajo |
| seasonality_prior_scale | modelado.yaml | [0.025–1.0] | float | Por padecimiento | Regularización estacional — mayor = más compleja |
| seasonality_mode | modelado.yaml | additive / multiplicative | str | Por padecimiento | Interacción estacionalidad-tendencia |
| Cross-validation | |||||
| n_splits | modelado.yaml | 4 | int | Siempre | Folds temporales de CV |
| test_size | modelado.yaml | 53 | int (semanas) | Siempre | ~1 año de evaluación por fold |
| cv_weights | modelado.yaml | [0.5, 0.75, 1.0, 1.25] | list[float] | Siempre | Ponderación progresiva — más peso a folds recientes |
| Protección anti-Newton | |||||
| fold_timeout_seg | modelado.yaml | 35 | int (seg) | Siempre | Máximo por fold en ThreadPoolExecutor |
| combo_timeout_seg | modelado.yaml | 90 | int (seg) | Siempre | Backstop total por combinación de hiperparámetros |
| Modo híbrido y confianza | |||||
| modelado_hibrido | params.yaml | true | bool | v6+ | Fallback regional para estados insuficientes |
| umbral_minimo_semanal | modelado.yaml | 0.5 | float | modelado_hibrido: true | Casos/sem mínimo para confianza "normal" |
| Periodos atípicos (holidays) | |||||
| COVID-19 holiday | modelado.yaml | 2020-03-23 + 913d | date + days | Todos los padecimientos | Absorbe disrupción pandémica sin contaminar estacionalidad |
| Tabasco-Depresión holiday | modelado.yaml | 2023-01-09 + 365d | date + days | Solo Tabasco + Depresión | -6.2% RMSE en esa serie específica |
| Entrenamiento paralelo | |||||
| n_jobs | modelado.yaml | -2 | int | make train | joblib: todos los núcleos menos uno (loky backend) |
| backend | prophet.py | "loky" | str | Siempre | Multiprocessing robusto para Prophet (fork-safe) |