# ================================================================
# EJERCICIO PRÁCTICO: Evaluación de Modelos de Predicción
# de Ventas con Métricas de Regresión
# ================================================================
#
# CONTEXTO:
# Una cafetería registró sus ventas diarias (en €) durante
# 30 días. Dos modelos intentaron predecir esas ventas:
# - Modelo A: regresión lineal simple
# - Modelo B: red neuronal experimental
#
# Tu misión: calcular las métricas, interpretar los resultados
# y decidir qué modelo recomendarías al dueño de la cafetería.
#
# ================================================================
import numpy as np
import matplotlib.pyplot as plt
# ----------------------------------------------------------------
# DATOS: 30 días de ventas reales y predicciones de cada modelo
# ----------------------------------------------------------------
dias = list(range(1, 31)) # Días del mes (1 al 30)
# Ventas reales registradas en la caja (en €)
ventas_reales = [
312, 298, 341, 287, 305, 198, 210, # Semana 1 (fin de semana bajo)
330, 315, 352, 298, 341, 215, 224, # Semana 2
345, 318, 361, 302, 349, 231, 228, # Semana 3
358, 334, 372, 315, 360, 244, 237, # Semana 4
365, 348 # Últimos 2 días del mes
]
# Predicciones del Modelo A (regresión lineal, más estable)
predicciones_modelo_A = [
308, 301, 338, 291, 309, 205, 214,
325, 318, 347, 303, 338, 221, 220,
340, 322, 355, 308, 344, 226, 232,
352, 330, 368, 319, 355, 240, 242,
361, 344
]
# Predicciones del Modelo B (sobreajustado en semanas centrales)
predicciones_modelo_B = [
295, 275, 360, 270, 325, 185, 240,
310, 340, 330, 285, 365, 200, 245,
325, 340, 340, 290, 370, 210, 255,
340, 350, 350, 300, 385, 225, 265,
350, 335
]
# ================================================================
# SECCIÓN 1 — CÁLCULO DE MÉTRICAS
# ================================================================
# Completa cada celda marcada con ??? usando sklearn o numpy.
# Pista: todas las funciones están en sklearn.metrics
# Documentación: https://scikit-learn.org/stable/modules/model_evaluation.html
# ================================================================
from sklearn.metrics import mean_squared_error # MSE
from sklearn.metrics import mean_absolute_error # MAE
from sklearn.metrics import root_mean_squared_error # RMSE
from sklearn.metrics import r2_score # R²
print("=" * 55)
print(" MÉTRICAS DE EVALUACIÓN — VENTAS 30 DÍAS")
print("=" * 55)
# ---- 1.1 MSE -----------------------------------------------
# Pista: mean_squared_error(valores_reales, valores_predichos)
# Un MSE menor indica mejor ajuste.
# ¿Qué ocurre si un día el modelo falla por 50 €?
# Ese error pesa 50² = 2500 en el MSE.
mse_A = ??? # Calcula el MSE del Modelo A
mse_B = ??? # Calcula el MSE del Modelo B
print(f"\nMSE → Modelo A: {mse_A:.2f} | Modelo B: {mse_B:.2f}")
# ---- 1.2 MAE -----------------------------------------------
# Pista: mean_absolute_error(valores_reales, valores_predichos)
# A diferencia del MSE, todos los errores pesan igual.
# Un MAE de 15 significa: "me equivoco ~15 € por día de media".
mae_A = ??? # Calcula el MAE del Modelo A
mae_B = ??? # Calcula el MAE del Modelo B
print(f"MAE → Modelo A: {mae_A:.2f} | Modelo B: {mae_B:.2f}")
# ---- 1.3 RMSE ----------------------------------------------
# Pista: root_mean_squared_error(valores_reales, valores_predichos)
# Es la raíz cuadrada del MSE → devuelve el error en euros (€),
# igual que los datos originales. Más fácil de interpretar.
rmse_A = ??? # Calcula el RMSE del Modelo A
rmse_B = ??? # Calcula el RMSE del Modelo B
print(f"RMSE → Modelo A: {rmse_A:.2f} | Modelo B: {rmse_B:.2f}")
# ---- 1.4 R² ------------------------------------------------
# Pista: r2_score(valores_reales, valores_predichos)
# Mide qué porcentaje de la variación en ventas explica el modelo.
# R² = 1 → perfecto | R² = 0 → igual que predecir siempre la media.
r2_A = ??? # Calcula el R² del Modelo A
r2_B = ??? # Calcula el R² del Modelo B
print(f"R² → Modelo A: {r2_A:.4f} | Modelo B: {r2_B:.4f}")
print("\n" + "=" * 55)
# ================================================================
# SECCIÓN 2 — GRÁFICA DE AJUSTE
# ================================================================
# Aquí tienes la estructura completa de la gráfica.
# Descomentar el bloque cuando tengas las métricas calculadas.
# ================================================================
# x = np.array(dias)
# fig, axes = plt.subplots(2, 1, figsize=(14, 9))
# fig.suptitle("Comparativa de Modelos — Ventas Diarias Cafetería", fontsize=14, fontweight="bold")
#
# # --- Subgráfica superior: líneas de ajuste ---
# ax1 = axes[0]
# ax1.plot(x, ventas_reales, "o-", color="#2C3E50", lw=2.5, ms=5, label="Ventas Reales")
# ax1.plot(x, predicciones_modelo_A,"s--", color="#2980B9", lw=1.8, ms=4, label=f"Modelo A (RMSE={rmse_A:.1f} €)")
# ax1.plot(x, predicciones_modelo_B,"^--", color="#E74C3C", lw=1.8, ms=4, label=f"Modelo B (RMSE={rmse_B:.1f} €)")
# ax1.fill_between(x, ventas_reales, predicciones_modelo_A, alpha=0.12, color="#2980B9")
# ax1.fill_between(x, ventas_reales, predicciones_modelo_B, alpha=0.12, color="#E74C3C")
# ax1.set_ylabel("Ventas (€)")
# ax1.set_xticks(x)
# ax1.set_xticklabels([f"D{d}" for d in dias], fontsize=7, rotation=45)
# ax1.legend(); ax1.grid(True, linestyle="--", alpha=0.4)
#
# # --- Subgráfica inferior: error absoluto por día ---
# error_A = [abs(r - p) for r, p in zip(ventas_reales, predicciones_modelo_A)]
# error_B = [abs(r - p) for r, p in zip(ventas_reales, predicciones_modelo_B)]
# ancho = 0.35
# ax2 = axes[1]
# ax2.bar(x - ancho/2, error_A, width=ancho, color="#2980B9", alpha=0.8, label="Error diario Modelo A")
# ax2.bar(x + ancho/2, error_B, width=ancho, color="#E74C3C", alpha=0.8, label="Error diario Modelo B")
# ax2.axhline(y=mae_A, color="#1A5276", linestyle="--", lw=1.5, label=f"MAE Modelo A = {mae_A:.1f} €")
# ax2.axhline(y=mae_B, color="#922B21", linestyle="--", lw=1.5, label=f"MAE Modelo B = {mae_B:.1f} €")
# ax2.set_xlabel("Día del mes")
# ax2.set_ylabel("Error absoluto (€)")
# ax2.set_xticks(x)
# ax2.set_xticklabels([f"D{d}" for d in dias], fontsize=7, rotation=45)
# ax2.legend(); ax2.grid(True, axis="y", linestyle="--", alpha=0.4)
#
# plt.tight_layout()
# plt.savefig("ajuste_ventas.png", dpi=150, bbox_inches="tight")
# plt.show()
# ================================================================
# SECCIÓN 3 — PREGUNTAS DE REFLEXIÓN
# ================================================================
# Responde a continuación como comentarios de Python (#).
# No hay una única respuesta correcta; razona tu decisión.
# ================================================================
# PREGUNTA 1 ── ¿Qué modelo tiene menor MSE?
# ¿Por qué crees que el MSE es más sensible a errores grandes
# que el MAE? Piensa en qué ocurre matemáticamente al elevar al
# cuadrado un error de 50 € frente a uno de 5 €.
#
# Tu respuesta:
#
# ─────────────────────────────────────────────────────────────
# PREGUNTA 2 ── Si el MAE de ambos modelos fuese muy similar
# pero el MSE fuese muy distinto, ¿qué nos estaría indicando
# sobre la distribución de los errores de cada modelo?
# Pista: piensa en días concretos donde un modelo falla mucho.
#
# Tu respuesta:
#
# ─────────────────────────────────────────────────────────────
# PREGUNTA 3 ── El dueño de la cafetería puede asumir errores
# pequeños cotidianos, pero le resulta muy perjudicial quedarse
# sin stock un día puntual por una predicción muy mala.
# ¿Qué métrica debería priorizar para elegir el modelo?
# ¿MSE/RMSE o MAE? Justifica tu respuesta.
#
# Tu respuesta:
#
# ─────────────────────────────────────────────────────────────
# PREGUNTA 4 ── Interpreta el valor de R² de cada modelo.
# ¿Un R² de 0.95 significa que el modelo predice bien siempre?
# ¿Podría haber algún día donde falle mucho y aun así tener
# un R² alto globalmente?
#
# Tu respuesta:
#
# ─────────────────────────────────────────────────────────────
# PREGUNTA 5 ── DECISIÓN FINAL
# Con los valores que has calculado, ¿qué modelo recomendarías
# al dueño de la cafetería y por qué?
# Menciona al menos dos métricas en tu argumento.
#
# Tu respuesta:
#
# ================================================================
# FIN DEL EJERCICIO
# ================================================================