jueves, 16 de abril de 2026
Pronóstico de Ventas a Escala: Lecciones de 1,782 Series de Tiempo

Cuando Corporación Favorita, la cadena de supermercados más grande de Ecuador, publicó una competencia en Kaggle para pronosticar ventas diarias en sus tiendas, el dataset parecía simple a primera vista: cuatro años de historial, un puñado de archivos de apoyo y un solo objetivo. Predecir los siguientes 15 días.
Lo complicado: hay que pronosticar 1,782 series de tiempo a la vez, una por cada combinación de 54 tiendas y 33 familias de productos. Algunas venden miles de unidades al día; otras pasan semanas en cero. Un solo modelo tiene que cubrir todo eso.
Acá comparto lo que aprendí armando una solución que le sacó un 38% de ventaja a los baselines más fuertes.
El Problema
El pronóstico más simple es "mañana va a parecerse a la semana pasada". Para un supermercado, no es mala apuesta: la demanda es muy estacional y los patrones semanales se mantienen estables. Cualquier modelo que armes tiene que demostrar que hace algo más que memorizar el día de la semana.
Ese baseline pone la vara:
- Seasonal naive (repetir el valor del año pasado): RMSLE ≈ 0.84
- Repetir la semana pasada: RMSLE ≈ 0.71
Son sorprendentemente difíciles de superar. Muchos modelos "sofisticados" no lo logran.
Lo Que Realmente Hizo la Diferencia
Tres cosas, en orden de impacto.
1. Ingeniería de features, no complejidad del modelo
Dediqué más o menos el 70% del tiempo a features y el 30% al modelo. Las que más pesaron:
- Lags: ventas de hace 7, 14, 28 y 365 días
- Estadísticas móviles: media, desviación y máximo a 7 y 28 días por tienda-familia
- Calendario: día de la semana, mes, feriados nacionales de Ecuador y días de pago (el 15 y fin de mes, porque en Ecuador los salarios se pagan quincenalmente y eso mueve fuerte la demanda de abarrotes)
- Precio del petróleo: la economía ecuatoriana depende del crudo; un promedio móvil rezagado a 7 días del precio del barril correlaciona bien con el gasto discrecional
- Promociones: conteos de
onpromotionpor tienda-familia por día, más sumas móviles a 7 días
El salto más grande en precisión vino de los features de días de pago. Es una señal de dominio que un modelo genérico jamás descubriría solo.
2. Validación que simula el mundo real
Hacer k-fold aleatorio en series de tiempo es un error disfrazado de buena práctica. Si tus splits dejan que el modelo vea datos del "futuro" durante el entrenamiento, las métricas offline van a ser optimistas, a veces por mucho.
Usé un esquema walk-forward: entrenas con las semanas 1 a N, validas con N+1 y N+2, avanzas y repetís. Es más lento, pero refleja cómo funciona el modelo en producción. La diferencia entre mi error de validación y mi score en el leaderboard quedó por debajo del 3%, que es justo lo que buscas.
3. Árboles potenciados por encima del deep learning (para este dataset)
Probé dos caminos en paralelo:
- LightGBM con features armados a mano
- Un transformer chico (estilo N-HiTS / TFT-lite) sobre secuencias crudas
LightGBM ganó por un margen claro y a una fracción del costo de entrenamiento (unas 40 veces menos). El deep learning en series de tiempo rinde cuando tenés datos homogéneos de alta frecuencia con un historial enorme, como curvas de carga eléctrica con millones de muestras al año. Para 1,782 series de frecuencia media con 4 años de historial y variables externas ricas, gradient boosting sigue siendo la opción práctica en 2026.
Resultados
| Métrica | Valor |
|---|---|
| RMSLE final (leaderboard privado) | 0.44 |
| vs. baseline seasonal-naive | -48% |
| vs. baseline de semana pasada | -38% |
| Tiempo de entrenamiento (modelo completo) | ~22 min en una MacBook |
| Tiempo de inferencia (15 días, 1,782 series) | < 3 seg |
La mejora del 38% sobre el baseline de la semana pasada es el número con el que abro cuando hablo de este proyecto. Es la comparación más honesta, porque nadie que ponga un sistema de pronóstico en producción lo mide contra un modelo que ya de por sí es malo.
Qué Haría Distinto
- Dedicarle más tiempo a familias con poco historial. Algunas familias de productos tenían datos escasos (empezaron a mitad del dataset o pasaron largos períodos en cero). Un modelo jerárquico que comparta información entre familias similares probablemente mejoraría esos casos puntuales.
- Reconciliar los pronósticos. Mis pronósticos por tienda-familia no suman a un total consistente por tienda. En producción, esa inconsistencia se vuelve un dolor de cabeza operativo. Una reconciliación jerárquica (MinT, ERM) lo resolvería.
- Estimar incertidumbre, no solo dar un número. Los equipos de operaciones necesitan saber qué tan seguro está el modelo, no solo el valor puntual. Regresión por cuantiles o predicción conforme sobre la salida de LightGBM haría que el pronóstico sea realmente útil para tomar decisiones.
Conclusiones
- Los baselines son honestos. Superalos en público, no solo en tu set de validación local.
- El modelo es la parte fácil. Los features, los splits y la función de pérdida son donde se gana la partida.
- Los modelos simples e interpretables ganan en producción. Cada vez que probé un transformer en series de tiempo tabulares, un LightGBM bien ajustado le quedó a la par, y se desplegó más rápido, costó menos y fue mucho más fácil de debuggear.
El notebook completo, los requirements y los archivos de submission están en GitHub. Si estás trabajando en algo parecido, hablemos.