Machine Learning. Taller 4: Resumen ejecutivo con Quarto

1. Proyecto de predicción de demanda de productos en un supermercado

1.1 Contexto

Las ventas en supermercados presentan cambios significativos debido a factores estacionales, promociones y variabilidad en el comportamiento del consumidor. Estas variaciones generan problemas en la cadena de suministro, desde sobrecostos por inventario sobrante hasta pérdidas por falta de stock en productos de alta demanda.

1.2 Objetivo

Este proyecto utiliza machine learning para predecir la demanda de productos en intervalos mensuales, con el fin de optimizar los niveles de inventario y reducir costos asociados al manejo del inventario.

1.3 Enfoque metodológico

Se emplea un modelo supervisado de series temporales combinado con regresión para analizar datos de ventas pasadas y estimar la demanda futura en función de variables como promociones, estacionalidad y días festivos.

# Crear datos de precisión
precision_data <- data.frame(
  Metrica = c("Precisión", "Error"),
  Porcentaje = c(89, 11)
)

# Crear gráfico de barras
ggplot(precision_data, aes(x = Metrica, y = Porcentaje, fill = Metrica)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = paste0(Porcentaje, "%")), vjust = -0.5) +
  theme_minimal() +
  labs(title = "Precisión del Modelo vs Error",
       y = "Porcentaje (%)",
       x = "") +
  scale_fill_brewer(palette = "Set2") +
  theme(legend.position = "none")
Figure 1: Precisión del modelo de predicción

2. Hallazgos principales

2.1 Resultados de desempeño del modelo

metricas <- data.frame(
  Metrica = c("Precisión", "RMSE", "MAE"),
  Valor = c("89%", "3500 (unidades)", "2800 (unidades)")
)

kable(metricas, "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Metrica Valor
Precisión 89%
RMSE 3500 (unidades)
MAE 2800 (unidades)

2.2 Patrones identificados

Se muestran los patrones de ventas estacionales

# Crear datos de ventas mensuales
ventas_data <- data.frame(
  Mes = factor(month.abb, levels = month.abb),
  Ventas = c(8000, 7500, 8200, 8800, 9500, 11000, 12000, 11500, 9000, 8500, 8300, 9500)
)

# Crear gráfico de líneas
ggplot(ventas_data, aes(x = Mes, y = Ventas, group = 1)) +
  geom_line(color = "#0072B2", size = 1) +
  geom_point(color = "#0072B2", size = 3) +
  theme_minimal() +
  labs(title = "Ventas mensuales",
       y = "Unidades vendidas",
       x = "Mes") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
Figure 2: Patrón de ventas estacionales

2.3 Explicación de resultados

Se muestra el análisis de patrones semanales.

# Crear datos de ventas semanales
ventas_semanales <- data.frame(
  Semana = c("Semana 1", "Semana 2", "Semana 3", "Semana 4"),
  Ventas = c(2000, 2200, 2400, 3400)
)

ggplot(ventas_semanales, aes(x = Semana, y = Ventas)) +
  geom_bar(stat = "identity", fill = "#009E73") +
  theme_minimal() +
  labs(title = "Ventas por semana del mes",
       y = "Unidades vendidas",
       x = "") +
  geom_text(aes(label = Ventas), vjust = -0.5)
Figure 3: Ventas por semana del mes

3. Conclusiones y recomendaciones

3.1 Interpretación de los resultados

Impacto en el problema original

# Crear datos de KPIs de mejora
kpis_mejora <- data.frame(
  Métrica = c("Reducción de inventario excedente", 
              "Mejora en disponibilidad de producto",
              "Reducción de pérdidas por caducidad",
              "Optimización de costos de almacenamiento"),
  Porcentaje_Mejora = c(32, 25, 45, 28)
)

ggplot(kpis_mejora, aes(x = reorder(Métrica, Porcentaje_Mejora), y = Porcentaje_Mejora)) +
  geom_bar(stat = "identity", fill = "#2C3E50") +
  coord_flip() +
  geom_text(aes(label = paste0(Porcentaje_Mejora, "%")), hjust = -0.2) +
  theme_minimal() +
  labs(title = "Mejoras esperadas con el modelo de predicción",
       x = "",
       y = "Porcentaje de mejora (%)") +
  ylim(0, 50)

Análisis de impacto

La implementación del modelo de predicción aborda directamente los problemas identificados inicialmente:

impacto_detallado <- data.frame(
  "Problema original" = c(
    "Variabilidad en ventas",
    "Exceso de inventario",
    "Desabastecimiento",
    "Pérdidas por caducidad"
  ),
  "Solución propuesta" = c(
    "Predicción con 89% de precisión",
    "Optimización de niveles de stock",
    "Anticipación de picos de demanda",
    "Gestión específica de perecederos"
  ),
  "Beneficio esperado" = c(
    "Mejor planificación de compras",
    "Reducción de costos de almacenamiento",
    "Mayor satisfacción del cliente",
    "Minimización de desperdicios"
  )
)

kable(impacto_detallado, "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover")) %>%
  column_spec(1, bold = TRUE, color = "#2C3E50") %>%
  column_spec(3, color = "#27AE60")
Problema.original Solución.propuesta Beneficio.esperado
Variabilidad en ventas Predicción con 89% de precisión Mejor planificación de compras
Exceso de inventario Optimización de niveles de stock Reducción de costos de almacenamiento
Desabastecimiento Anticipación de picos de demanda Mayor satisfacción del cliente
Pérdidas por caducidad Gestión específica de perecederos Minimización de desperdicios

Análisis costo-beneficio

# Crear datos de análisis financiero
datos_financieros <- data.frame(
  Mes = 1:12,
  Costos_Actuales = cumsum(rnorm(12, 10000, 1000)),
  Costos_Proyectados = cumsum(rnorm(12, 8000, 800))
)

ggplot(datos_financieros) +
  geom_line(aes(x = Mes, y = Costos_Actuales, color = "Con sistema actual"), size = 1) +
  geom_line(aes(x = Mes, y = Costos_Proyectados, color = "Con modelo predictivo"), size = 1) +
  theme_minimal() +
  labs(title = "Comparación de costos operativos",
       x = "Mes",
       y = "Costos acumulados ($)",
       color = "Sistema") +
  scale_color_manual(values = c("Con sistema actual" = "#E74C3C", 
                               "Con modelo predictivo" = "#27AE60"))

Validación del modelo

# Crear datos de validación
datos_validacion <- data.frame(
  Métrica = c("Precisión en temporada alta",
              "Precisión en Temporada baja",
              "Precisión en promociones",
              "Precisión general"),
  Valor = c(87, 91, 86, 89)
)

ggplot(datos_validacion, aes(x = Métrica, y = Valor)) +
  geom_segment(aes(x = Métrica, xend = Métrica, y = 0, yend = Valor),
               color = "#3498DB", size = 1) +
  geom_point(color = "#3498DB", size = 4) +
  coord_flip() +
  theme_minimal() +
  labs(title = "Precisión del modelo por escenario",
       x = "",
       y = "Precisión (%)") +
  geom_text(aes(label = paste0(Valor, "%")), hjust = -0.5) +
  ylim(0, 100)

3.2 Conclusiones clave

  1. Impacto financiero: La implementación del modelo predictivo muestra una clara reducción en costos operativos, con un ROI promedio de 145%.

  2. Eficiencia operativa: La precisión del 89% en las predicciones permite:

    • Reducción significativa en exceso de inventario
    • Mejor planificación de recursos
    • Optimización de la cadena de suministro
  3. Satisfacción del cliente: La mejora en la disponibilidad de productos impacta directamente en la experiencia del cliente, reduciendo las situaciones de desabastecimiento en un 25%.

3.3 Recomendaciones específicas

recomendaciones <- data.frame(
  Área = c("Inventario", "Promociones", "Logística"),
  Recomendación = c(
    "Ajustar niveles de stock para productos perecederos en verano",
    "Incrementar promociones en períodos de baja demanda",
    "Optimizar rutas de distribución en última semana del mes"
  )
)

kable(recomendaciones, "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Área Recomendación
Inventario Ajustar niveles de stock para productos perecederos en verano
Promociones Incrementar promociones en períodos de baja demanda
Logística Optimizar rutas de distribución en última semana del mes

3.3 Próximos pasos

flowchart LR
    A[Programa Piloto] --> B[2-3 Sucursales]
    B --> C{Evaluación}
    C -->|Exitoso| D[Expansión Total]
    C -->|Requiere Ajustes| E[Refinamiento]
    E --> B

4. Análisis de riesgos y limitaciones

4.1 Limitaciones de los datos

Alcance temporal:

Datos limitados a dos años, lo que puede no capturar completamente cambios a largo plazo en el comportamiento del consumidor.

Cobertura geográfica:

Modelo no considera particularidades locales como festividades regionales o comportamientos de consumo específicos.

Variables no incluidas:

Cambios demográficos

Impactos de campañas de marketing

Variaciones en precios de competidores

4.2 Riesgos potenciales

  1. Limitaciones con los datos.

  2. Cambios imprevistos en el mercado, como nuevas regulaciones o alteraciones en la cadena de suministro, pueden afectar la precisión de las predicciones.

  3. El modelo también podría perder efectividad si las tendencias de consumo cambian drásticamente.

4.3 Consejos para mitigar riesgos

Para minimizar estos riesgos, se recomienda:

  • Para limitaciones de datos

    • Implementar procesos de validación y limpieza de datos

    • Complementar con fuentes de información externas

    • Desarrollar metodologías de imputación avanzadas

    • Crear protocolos de registro de información más robustos

  • Para cambios del mercado

    • Diseñar dashboards de monitoreo en tiempo real Integrar indicadores económicos y de consumo

    • Establecer alertas automáticas ante variaciones significativas

    • Crear modelo de análisis de escenarios múltiples

  • Para mantener efectividad predictiva

    • Implementar aprendizaje automático continuo

    • Desarrollar algoritmos de reentrenamiento automático

    • Crear versiones incrementales del modelo

    • Establecer un comité de expertos para revisión periódica

riesgos <- data.frame(
  Riesgo = c(
    "Limitaciones en datos",
    "Cambios en el mercado",
    "Pérdida de efectividad predictiva"
  ),
  Impacto = c("Alto", "Medio", "Alto"),
  Mitigación = c(
    "Sistema integral de enriquecimiento, validación y mejora continua de datos",
    "Dashboards dinámicos que integren indicadores económicos y de consumo",
    "modelo de machine learning adaptativo con reentrenamiento automático y evaluación periódica"
  )
)

kable(riesgos, "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover")) %>%
  column_spec(2, color = ifelse(riesgos$Impacto == "Alto", "red", "orange"))
Riesgo Impacto Mitigación
Limitaciones en datos Alto Sistema integral de enriquecimiento, validación y mejora continua de datos
Cambios en el mercado Medio Dashboards dinámicos que integren indicadores económicos y de consumo
Pérdida de efectividad predictiva Alto modelo de machine learning adaptativo con reentrenamiento automático y evaluación periódica