Saltar al contenido principal

Arquitectura de red neuronal

Eaternity Forecast utiliza una sofisticada red neuronal basada en transformadores con mecanismos de atención para predecir la demanda diaria de artículos del menú de restaurantes. Este documento explica la arquitectura técnica y la metodología de inteligencia artificial.

Visión general de la arquitectura

Tipo de modelo: Arquitectura de transformadores

Forecast emplea una arquitectura de transformadores, la misma tecnología fundamental detrás de los modelos de lenguaje modernos como GPT y BERT, adaptada específicamente para la previsión de demanda de series temporales.

¿Por qué transformadores para la previsión de demanda?

Los métodos de pronóstico tradicionales (modelo autorregresivo integrado de media móvil, suavizado exponencial) tienen dificultades con:

  • Relaciones complejas multifactoriales
  • Dependencias temporales de largo alcance
  • Patrones no estacionarios
  • Múltiples ciclos estacionales simultáneos

Los transformadores destacan en:

  • Reconocimiento de patrones a través de diferentes escalas temporales (diario, semanal, estacional)
  • Mecanismos de atención que identifican períodos históricos relevantes
  • Integración multifactorial (clima, eventos, cambios de menú)
  • Manejo de patrones irregulares (festivos, eventos especiales)

Componentes principales

Capa de entrada

Incrustación temporal

Atención multicabezal (×4 capas)

Redes de alimentación directa

Proyección de salida

Predicción + Intervalos de confianza

Arquitectura detallada

1. Capa de entrada

Propósito: Transformar datos de ventas en bruto y factores externos en representaciones numéricas

Características de entrada (por artículo, por día):

Características de ventas históricas

  • Ventas de los 7 días anteriores (cantidades diarias)
  • Ventas del mismo día de la semana de las 4 semanas anteriores
  • Ventas promedio del mes anterior
  • Ventas de la misma fecha del año anterior (si están disponibles)

Características temporales

  • Día de la semana (codificación de un solo activo: Lunes=1, Martes=2, etc.)
  • Semana del año (1-52)
  • Mes (1-12)
  • Es fin de semana (binario: 0/1)
  • Es festivo (binario: 0/1)

Características externas

  • Temperatura (°C, normalizada)
  • Precipitación (mm, normalizada)
  • Pronóstico del tiempo para el día siguiente
  • Eventos locales (banderas binarias o categóricas)

Características del menú

  • Categoría del artículo (entrante, plato principal, postre, etc.)
  • Punto de precio (normalizado)
  • Días desde el lanzamiento del artículo (para artículos nuevos)
  • Disponibilidad del artículo (binario: 0/1)

Ejemplo de ingeniería de características:

Vector de entrada para "Pasta Carbonara" el miércoles, 20 de enero de 2024:

Ventas históricas:
[52, 48, 45, 51, 49, 0, 0] # Últimos 7 días (0 = cerrado)
[49, 51, 48, 52] # Últimos 4 miércoles
47.3 # Promedio del mes pasado

Temporal:
[0, 0, 1, 0, 0, 0, 0] # Día de la semana (Mié = posición 3)
3 # Semana del año
1 # Mes (enero)
0 # Es fin de semana
0 # Es festivo

Externo:
8.2 # Temperatura (°C)
0.0 # Precipitación
7.5 # Temperatura prevista mañana

Menú:
[0, 1, 0, 0] # Categoría (Plato principal)
14.50 # Precio (normalizado a escala 0-1)
450 # Días desde el lanzamiento
1 # Disponible hoy

2. Incrustación temporal

Propósito: Codificar patrones basados en el tiempo y relaciones cíclicas

Codificación posicional:

Usa funciones sinusoidales para capturar patrones periódicos:

PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))

Donde:

  • pos = posición en la secuencia (número del día)
  • i = dimensión
  • d_model = dimensión de incrustación (256)

¿Por qué codificación sinusoidal?

  • Captura múltiples ciclos (diario, semanal, mensual, anual)
  • El modelo aprende qué ciclos son relevantes para cada artículo
  • Permite extrapolación más allá del período de entrenamiento
  • Maneja espaciado irregular (festivos, días cerrados)

Ejemplo:

# Codificación del ciclo semanal para el día de la semana
weekly_encoding = [
sin(day_of_week / 7 * 2π),
cos(day_of_week / 7 * 2π)
]

# Codificación del ciclo anual
annual_encoding = [
sin(day_of_year / 365 * 2π),
cos(day_of_year / 365 * 2π)
]

3. Mecanismo de atención multicabezal

Propósito: Identificar qué períodos históricos son más relevantes para la predicción actual

Cómo funciona la atención:

El modelo pregunta: "Al predecir el almuerzo del miércoles, ¿a qué días anteriores debo prestar atención?"

Fórmula de atención:

Attention(Q, K, V) = softmax(QK^T / √d_k) V

Donde:

  • Q (Consulta): Lo que intentamos predecir (demanda de hoy)
  • K (Claves): Días históricos a considerar
  • V (Valores): Ventas reales de esos días
  • d_k: Dimensión de los vectores clave

Enfoque multicabezal:

En lugar de un mecanismo de atención, usamos 8 cabezales de atención paralelos:

  1. Cabezal 1: Se enfoca en patrones del mismo día de la semana

    • "Los miércoles son similares a los miércoles anteriores"
  2. Cabezal 2: Se enfoca en tendencias recientes

    • "El patrón de la semana pasada continúa"
  3. Cabezal 3: Se enfoca en patrones estacionales

    • "Similar a esta época del año pasado"
  4. Cabezal 4: Se enfoca en correlaciones meteorológicas

    • "Días fríos como hoy tienen demanda similar"
  5. Cabezal 5: Se enfoca en patrones de eventos

    • "Días con eventos similares cercanos"
  6. Cabezal 6: Se enfoca en dinámica del menú

    • "Días con composición de menú similar"
  7. Cabezal 7: Se enfoca en sensibilidad al precio

    • "Días con estrategias de precios similares"
  8. Cabezal 8: Se enfoca en tendencias de largo alcance

    • "Dirección de tendencia de varios meses"

Ejemplo de pesos de atención:

Prediciendo miércoles, 20 de enero de 2024 para Pasta Carbonara:

Atención del cabezal 1 (día de la semana) a miércoles anteriores:
13 de enero (último mié): 0.35 (más reciente, mayor peso)
6 de enero: 0.28
30 de diciembre: 0.18
23 de diciembre: 0.12
Otros miércoles: 0.07

Atención del cabezal 2 (tendencia reciente) a los últimos 7 días:
19 de enero (ayer): 0.42
18 de enero: 0.24
17 de enero: 0.15
16 de enero: 0.10
Más antiguos: 0.09

Atención del cabezal 3 (estacional) al año pasado:
21 de enero de 2023: 0.55 (misma fecha del año pasado)
14-28 de enero de 2023: 0.45 (fechas circundantes)

4. Redes de alimentación directa

Propósito: Transformación no lineal y combinación de características

Arquitectura:

Entrada (256 dimensiones)

Capa lineal 1 (256 → 1024)

Activación ReLU

Abandono (0.1)

Capa lineal 2 (1024 → 256)

Abandono (0.1)

Conexión residual + Normalización de capa

¿Por qué dos capas?

  • Expansión (256→1024): Crea espacio de representación de alta dimensión
  • Compresión (1024→256): Extrae las características más relevantes

Regularización por abandono:

Desactiva aleatoriamente el 10% de las neuronas durante el entrenamiento para evitar el sobreajuste:

  • El modelo aprende patrones robustos, no memorización
  • Mejora la generalización a nuevos datos
  • Crítico para conjuntos de datos pequeños (algunos restaurantes, artículos nuevos)

5. Apilamiento de capas

Cuatro bloques de transformadores apilados secuencialmente:

Bloque 1: Reconocimiento inicial de patrones

Bloque 2: Extracción refinada de patrones

Bloque 3: Aprendizaje de características de alto nivel

Bloque 4: Representación final

Cada bloque contiene:

  • Capa de atención multicabezal
  • Normalización de capa
  • Red de alimentación directa
  • Conexiones residuales

¿Por qué cuatro capas?

Equilibrio entre:

  • Complejidad: Más capas = más patrones reconocidos
  • Eficiencia: Menos capas = entrenamiento e inferencia más rápidos
  • Riesgo de sobreajuste: Demasiadas capas = memorización en lugar de aprendizaje

Las pruebas empíricas mostraron que 4 capas son óptimas para la previsión de demanda de restaurantes.

6. Proyección de salida

Propósito: Convertir la representación aprendida en predicción de cantidad

Enfoque de regresión cuantílica:

En lugar de predecir un solo valor, el modelo produce tres cuantiles:

Capa lineal (256 → 3)

Salidas:
- Percentil 10 (límite inferior)
- Percentil 50 (mediana/estimación puntual)
- Percentil 90 (límite superior)

Ejemplo de salida:

{
"item": "Pasta Carbonara",
"date": "2024-01-20",
"predictions": {
"lower_bound": 45, // Percentil 10
"point_estimate": 52, // Percentil 50 (mediana)
"upper_bound": 59 // Percentil 90
}
}

¿Por qué regresión cuantílica?

  • Captura la incertidumbre de la predicción de forma natural
  • Proporciona intervalos de confianza accionables
  • Más robusta a valores atípicos que enfoques basados en varianza
  • Se alinea con las necesidades de toma de decisiones (preparar para el rango, no para un solo valor)

Proceso de entrenamiento

Preparación de datos

1. Recopilación de datos

Requisitos mínimos:

  • 30 días de datos históricos de ventas (más de 90 días recomendado)
  • Registros diarios completos (sin lagunas)
  • Cantidades a nivel de artículo

2. Preprocesamiento de datos

Normalización:

# Normalización de puntuación Z para cantidades
normalized_quantity = (quantity - mean) / std_dev

# Normalización mín-máx para características externas
normalized_temp = (temp - min_temp) / (max_temp - min_temp)

Manejo de valores faltantes:

  • Días cerrados: Marcados explícitamente (no imputados)
  • Ventas faltantes: Relleno hacia adelante si son menos de 3 días consecutivos
  • Datos meteorológicos: Interpolar desde estaciones cercanas

Detección de valores atípicos:

# Identificar y marcar (pero no eliminar) valores atípicos
z_score = (quantity - rolling_mean) / rolling_std
if abs(z_score) > 3:
flag_as_potential_outlier()

Valores atípicos preservados pero con menor peso durante el entrenamiento.

3. Generación de secuencias

Crear secuencias de entrada de longitudes variables:

Contexto corto (últimos 7 días):

[día-7, día-6, día-5, día-4, día-3, día-2, día-1] → [predecir: día-0]

Contexto medio (últimas 4 semanas):

[semana-4-mismo-día, semana-3-mismo-día, semana-2-mismo-día, semana-1-mismo-día] → [predecir: hoy]

Contexto largo (estacional):

[mes-12-misma-fecha, mes-6-misma-fecha, mes-3-misma-fecha] → [predecir: hoy]

Algoritmo de entrenamiento

Función de pérdida: Pérdida cuantílica

Para cada cuantil q (0.1, 0.5, 0.9):

L_q = (q - 1) * error  si error < 0  (subpredicción)
q * error si error ≥ 0 (sobrepredicción)

Pérdida total = L_0.1 + L_0.5 + L_0.9

¿Por qué esta pérdida?

  • Penaliza más la subpredicción para el cuantil superior (90)
  • Penaliza más la sobrepredicción para el cuantil inferior (10)
  • Equilibrada para la mediana (50)
  • Asegura el orden correcto de los cuantiles (inferior < mediana < superior)

Optimización

Optimizador: AdamW (Adam con decaimiento de pesos)

Hiperparámetros:

learning_rate = 0.001       # Tasa de aprendizaje inicial
weight_decay = 0.01 # Regularización L2
beta_1 = 0.9 # Momento
beta_2 = 0.999 # Tasa de aprendizaje adaptativa
epsilon = 1e-8 # Estabilidad numérica

Programación de tasa de aprendizaje: Recocido cosenoidal con calentamiento

# Fase de calentamiento (primer 10% del entrenamiento)
lr = initial_lr * (step / warmup_steps)

# Fase de recocido cosenoidal
lr = min_lr + 0.5 * (max_lr - min_lr) * (1 + cos(π * step / total_steps))

Beneficios:

  • El calentamiento gradual evita la divergencia temprana
  • El decaimiento cosenoidal permite el ajuste fino cerca del final
  • Múltiples ciclos permiten escapar de mínimos locales

Iteraciones de entrenamiento

Épocas: 100-200 dependiendo del tamaño de los datos

Tamaño de lote: 32 secuencias

División de validación: 20% de los datos reservados

Detención temprana:

if validation_loss_not_improved_for(patience=15_epochs):
stop_training()
restore_best_model()

Técnicas de regularización

1. Abandono

  • Abandono de atención: 0.1
  • Abandono de alimentación directa: 0.1
  • Abandono de incrustación: 0.05

2. Decaimiento de pesos

  • Penalización L2 en pesos: 0.01
  • Evita que los pesos crezcan demasiado

3. Suavizado de etiquetas

  • Difumina ligeramente los valores objetivo
  • Mejora la calibración de los intervalos de confianza

4. Aumento de datos

  • Fluctuación aleatoria de valores históricos (±5%)
  • Simula la incertidumbre de medición
  • Mejora la robustez

Validación y pruebas

División entrenamiento/validación/prueba

Datos históricos (180 días en total):
- Entrenamiento: Días 1-126 (70%)
- Validación: Días 127-162 (20%)
- Prueba: Días 163-180 (10%)

Validación de avance progresivo:

En lugar de división aleatoria, usar división temporal:

  • Entrenar solo con datos pasados
  • Validar con datos futuros
  • Evita la fuga de datos (usar el futuro para predecir el pasado)

Métricas de rendimiento

Error porcentual absoluto medio:

Error porcentual absoluto medio = (1/n) * Σ |real - predicho| / real * 100%

Puntuación de calibración:

Esperado: 80% de los reales dentro del intervalo de confianza
Real: Contar cuántos reales caen dentro de [inferior, superior]
Calibración = Cobertura real / Cobertura esperada

Pérdida cuantílica:

Pérdida cuantílica = Σ todos los cuantiles (pérdida cuantílica como se definió arriba)

Proceso de inferencia

Generación de predicciones diarias

Cronograma: Se ejecuta automáticamente a las 3:00 AM hora local

Proceso:

  1. Recopilación de datos (3:00-3:05 AM)

    • Obtener datos de ventas finales de ayer
    • Recuperar pronóstico del tiempo para los próximos 7 días
    • Comprobar calendario de eventos para próximas fechas
    • Cargar configuración actual del menú
  2. Ingeniería de características (3:05-3:10 AM)

    • Calcular promedios móviles y tendencias
    • Codificar características temporales
    • Normalizar variables externas
    • Crear secuencias de entrada
  3. Inferencia del modelo (3:10-3:15 AM)

    • Paso hacia adelante a través de la red neuronal
    • Generar predicciones para los próximos 7 días
    • Calcular intervalos de confianza
    • Computar métricas de precisión
  4. Posprocesamiento (3:15-3:20 AM)

    • Redondear predicciones a enteros
    • Aplicar reglas de negocio (mínimo=0, máximo=capacidad)
    • Marcar predicciones inusuales para revisión
    • Generar informes de precisión
  5. Entrega (3:20-3:25 AM)

    • Enviar a puntos finales de la interfaz de programación de aplicaciones
    • Actualizar interfaz del panel de control
    • Enviar alertas por correo (si está configurado)
    • Registrar predicciones para seguimiento

Latencia: menos de 5 minutos para restaurante típico (100 artículos del menú)

Aprendizaje continuo

Cómo mejora el modelo con el tiempo:

Reentrenamiento semanal

Cada lunes a las 4:00 AM:

  1. Incorporar las ventas reales de la semana anterior
  2. Reentrenar el modelo con datos actualizados
  3. Evaluar mejoras de rendimiento
  4. Implementar el modelo actualizado si mejora la precisión

Integración de comentarios

Variaciones reportadas por usuarios retroalimentadas al entrenamiento:

  • Eventos especiales marcados manualmente
  • Circunstancias inusuales documentadas
  • Razones de anulación analizadas
  • Ingeniería de características mejorada

Detección de deriva conceptual

Monitorizar cambios en patrones de demanda:

if recent_accuracy < historical_accuracy - threshold:
trigger_model_refresh()
investigate_potential_concept_drift()

Causas comunes:

  • Cambios de menú
  • Nueva competencia
  • Transiciones estacionales
  • Cambios operacionales

Características avanzadas

Correlación entre artículos

Atención cruzada entre artículos:

El modelo aprende relaciones entre artículos:

  • Efectos de sustitución: "Si el salmón es popular, la demanda de ensalada disminuye"
  • Efectos complementarios: "Las ventas de postres se correlacionan con el volumen de platos principales"
  • Ingeniería del menú: "Los especiales canibalizan artículos regulares"

Implementación:

# Atender no solo al historial propio del artículo, sino a artículos relacionados
attention_context = [
item_own_history,
substitute_items_history,
complement_items_history,
category_average_history
]

Predicciones de conjunto

Múltiples variantes de modelo:

Entrenar varios modelos con diferentes arquitecturas:

  • Modelo A: Transformador (principal)
  • Modelo B: Memoria de corto y largo plazo (referencia recurrente)
  • Modelo C: Potenciación de gradiente (basado en árboles)

Combinación ponderada:

final_prediction = (
0.70 * transformer_prediction +
0.20 * lstm_prediction +
0.10 * gbm_prediction
)

Pesos determinados por la precisión histórica.

Cuantificación de incertidumbre

Fuentes de incertidumbre:

  1. Aleatoria (aleatoriedad irreducible)

    • Comportamiento del cliente inherentemente impredecible
    • Eventos aleatorios (fluctuaciones meteorológicas)
  2. Epistémica (incertidumbre del modelo)

    • Datos de entrenamiento insuficientes
    • Limitaciones de capacidad del modelo
    • Nuevos escenarios que no están en el conjunto de entrenamiento

Puntuación de confianza:

confidence_score = f(
data_quality, # ¿Qué tan limpios son los datos históricos?
training_data_volume, # ¿Cuántos datos están disponibles?
similarity_to_training, # ¿Qué tan similar es el día de predicción a los días de entrenamiento?
model_agreement # ¿Los modelos del conjunto están de acuerdo?
)

Mayor confianza → intervalos más estrechos Menor confianza → intervalos más amplios

Aprendizaje por transferencia

Aprendizaje entre ubicaciones:

Para cadenas de restaurantes:

  • Preentrenar con datos de todas las ubicaciones
  • Ajustar con datos de ubicación individual
  • Transferir patrones (estacionales, meteorológicos, eventos)
  • Inicio más rápido para nuevas ubicaciones

Beneficios:

  • Predicciones para nueva ubicación disponibles inmediatamente
  • Mayor precisión inicial
  • Convergencia más rápida del modelo
  • Aprendizaje compartido en toda la organización

Rendimiento del modelo

Puntos de referencia

Precisión vs referencias:

MétodoError porcentual absoluto medioNotas
Eaternity Forecast12,8%Arquitectura de transformadores
Pronosticador humano experto17,1%25% menos preciso
Mismo día de la semana anterior22,4%Referencia ingenua
Promedio de 4 semanas19,7%Referencia estadística simple
Modelo autorregresivo integrado de media móvil16,2%Series temporales tradicionales
Memoria de corto y largo plazo14,1%Red neuronal recurrente

Calibración del intervalo de confianza:

Esperado: 80% de los reales dentro de [inferior, superior] Logrado: 78,5% (bien calibrado)

Requisitos computacionales

Entrenamiento:

  • Unidad de procesamiento gráfico: NVIDIA RTX 4090 o equivalente
  • Memoria: 32 GB mínimo
  • Tiempo de entrenamiento: 2-6 horas (depende del volumen de datos)
  • Almacenamiento: 5-20 GB por restaurante

Inferencia:

  • Unidad de procesamiento central: Suficiente para predicciones en tiempo real
  • Memoria: 8 GB
  • Latencia: menos de 100ms por predicción
  • Almacenamiento: menos de 1 GB para modelo implementado

Fundamento de investigación

Referencias académicas

Forecast se basa en investigación revisada por pares:

  1. Arquitectura de transformadores

    • Vaswani et al. (2017) "Attention Is All You Need"
    • Artículo original de transformadores para procesamiento de lenguaje natural
  2. Previsión de series temporales

    • Zhou et al. (2021) "Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting"
    • Transformadores temporales para previsión
  3. Previsión de demanda

    • Taylor & Letham (2018) "Forecasting at Scale" (Facebook Prophet)
    • Sistemas de previsión a escala industrial
  4. Regresión cuantílica

    • Koenker & Bassett (1978) "Regression Quantiles"
    • Teoría fundamental de regresión cuantílica
  5. Operaciones de restaurantes

    • Miller et al. (2015) "Forecasting Restaurant Demand"
    • Desafíos de previsión específicos del dominio

Mejoras futuras

Hoja de ruta

T2 2024: Visualización de atención

  • Mostrar qué días históricos el modelo enfoca
  • Explicar predicciones a los usuarios

T3 2024: Previsión a nivel de receta

  • Predecir requisitos de ingredientes directamente
  • Integración con sistemas de inventario

T4 2024: Inferencia causal

  • Comprender el impacto de cambios de menú antes de la implementación
  • Simular efectos promocionales

2025: Aprendizaje multimodal

  • Incorporar sentimiento de redes sociales
  • Análisis visual del menú
  • Sentimiento de reseñas de clientes

Ved también