Ejemplo completo

# =============================================================================
#  EJERCICIO GUIADO: Regresión Lineal Multivariable
#  Dataset: Propinas en un restaurante (tips)
#  Nivel: Principiante / Intermedio
# =============================================================================
#
#  CONTEXTO DEL PROBLEMA
#  ─────────────────────
#  En el ejercicio anterior usamos solo el total de la cuenta para predecir
#  la propina. ¡Pero hay más información disponible!
#
#  PREGUNTA: ¿Podemos predecir mejor la propina usando VARIAS variables?
#
#  Esto es lo que hace la REGRESIÓN LINEAL MULTIVARIABLE:
#  aprender cómo influye cada variable de entrada en la propina.
#
#  La fórmula pasa de tener una sola X a varias:
#
#    tip = b₀ + b₁×total_bill + b₂×size
#
#  donde cada bᵢ (coeficiente) indica cuánto influye esa variable.
#
#  Al final del ejercicio sabrás:
#   · Seleccionar múltiples variables numéricas
#   · Normalizar los datos para que las variables estén en la misma escala
#   · Entrenar un modelo de regresión multivariable
#   · Comparar su rendimiento con el modelo simple anterior
#   · Interpretar los coeficientes de cada variable
#   · Predecir la propina para una comanda nueva con múltiples datos
#
#  VARIABLES DEL DATASET
#  ─────────────────────
#   total_bill → importe total de la cuenta en dólares      [numérica]
#   tip        → propina dejada por el cliente               [numérica, objetivo]
#   sex        → sexo del cliente que paga                   [categórica]
#   smoker     → si la mesa es de fumadores                  [categórica]
#   day        → día de la semana                            [categórica]
#   time       → Lunch / Dinner                              [categórica]
#   size       → número de personas en la mesa               [numérica]
#
#  En este ejercicio usaremos: total_bill y size.
#
# =============================================================================


# ─────────────────────────────────────────────────────────────────────────────
#  PASO 0 — IMPORTACIONES
# ─────────────────────────────────────────────────────────────────────────────
#
#  Ejecuta este bloque primero. Si alguna librería no está instalada:
#      pip install seaborn scikit-learn matplotlib

import seaborn as sns
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler          # ← nueva importación
from sklearn.metrics import (
    r2_score,
    mean_absolute_error,
    mean_squared_error,
    root_mean_squared_error
)


# ─────────────────────────────────────────────────────────────────────────────
#  PASO 1 — CARGAR EL DATASET
# ─────────────────────────────────────────────────────────────────────────────
#
#  Cargamos el mismo dataset de propinas que en el ejercicio anterior.

print("=" * 60)
print("  PASO 1: Carga del dataset")
print("=" * 60)

df = sns.load_dataset("tips")

# ─────────────────────────────────────────────────────────────────────────────
#  PASO 3 — SELECCIONAR X e y
# ─────────────────────────────────────────────────────────────────────────────
#
#  Ahora X tiene DOS columnas (de ahí el nombre "multivariable"):
#     X = [total_bill, size]
#     y = tip  (lo mismo que antes)
#
#  💡 PISTA: Usa doble corchete para seleccionar varias columnas:
#       X = df[["total_bill", "size"]]
#
#  🛠️  TU TURNO:
#     1. Define X con las dos variables indicadas.
#     2. Define y como la columna "tip".
#     3. Imprime X.shape e y.shape.
#        ¿Qué diferencia ves en X respecto al ejercicio de regresión simple?

print("\n" + "=" * 60)
print("  PASO 3: Seleccionar X e y")
print("=" * 60)

# --- ESCRIBE TU CÓDIGO AQUÍ ---
X = df[["total_bill", "size"]] # ¿Qué variables? total_bill y size
y = df["tip"]



# ─────────────────────────────────────────────────────────────────────────────
#  PASO 4 — DIVIDIR EN ENTRENAMIENTO Y TEST
# ─────────────────────────────────────────────────────────────────────────────
#
#  Dividimos ANTES de normalizar para evitar "data leakage":
#  si normalizamos con todos los datos, el modelo vería información
#  del conjunto de test durante el entrenamiento (hace trampa).
#
#  Orden correcto: dividir → normalizar con train → aplicar a test.
#
#  💡 PISTA: train_test_split(X, y, test_size=0.2, random_state=42)
#
#  🛠️  TU TURNO:
#     Aplica train_test_split y guarda los cuatro conjuntos:
#         X_train, X_test, y_train, y_test
#     Imprime cuántas filas tiene cada parte.

print("\n" + "=" * 60)
print("  PASO 4: División train / test  (80% / 20%)")
print("=" * 60)

# --- ESCRIBE TU CÓDIGO AQUÍ -
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)


# ─────────────────────────────────────────────────────────────────────────────
#  PASO 5 — NORMALIZACIÓN (StandardScaler)
# ─────────────────────────────────────────────────────────────────────────────
#
#  PROBLEMA: total_bill va de 3 a 51 $, pero size va de 1 a 6 personas.
#  Son escalas muy distintas. Si no normalizamos, el modelo puede dar
#  más "peso" a total_bill simplemente porque sus valores son más grandes,
#  no porque sea más importante.
#
#  StandardScaler convierte cada variable para que tenga:
#     · media = 0
#     · desviación típica = 1
#
#  Fórmula:  z = (x − media) / desviación_típica
#
#  ⚠️  REGLA IMPORTANTE: el scaler se "aprende" (fit) SOLO con X_train.
#     Luego se aplica (transform) tanto a X_train como a X_test.
#     Nunca hagas fit con X_test: estarías mirando datos que no deberías ver.
#
#  💡 PISTA:
#       scaler = StandardScaler()
#       X_train_sc = scaler.fit_transform(X_train)   # aprende Y transforma
#       X_test_sc  = scaler.transform(X_test)         # solo transforma
#
#  🛠️  TU TURNO:
#     1. Crea el scaler y aplícalo según el ejemplo de arriba.
#     2. Imprime la media y desviación típica que aprendió el scaler.
#        Pista: scaler.mean_  y  scaler.scale_
#     3. Comprueba que X_train_sc tiene media ≈ 0 y std ≈ 1 por columna.
#        Pista: pd.DataFrame(X_train_sc, columns=X.columns).describe().round(2)

print("\n" + "=" * 60)
print("  PASO 5: Normalización con StandardScaler")
print("=" * 60)


# --- ESCRIBE TU CÓDIGO AQUÍ ---
scaler = StandardScaler()
X_train_sc = scaler.fit_transform(X_train)
X_test_sc  = scaler.transform(X_test)


# ─────────────────────────────────────────────────────────────────────────────
#  PASO 6 — ENTRENAR EL MODELO
# ─────────────────────────────────────────────────────────────────────────────
#
#  Entrenamos con X_train_sc (los datos normalizados), no con X_train.
#
#  Con dos variables normalizadas, la fórmula aprendida será:
#    tip = b₀ + b₁×total_bill_sc + b₂×size_sc
#
#  Ahora los coeficientes b₁ y b₂ SÍ son directamente comparables:
#  el mayor indica la variable que más influye en la propina.
#
#  💡 PISTA:
#       modelo = LinearRegression()
#       modelo.fit(X_train_sc, y_train)
#
#  🛠️  TU TURNO:
#     1. Crea el modelo y entrénalo con los datos normalizados.
#     2. Imprime los coeficientes junto al nombre de cada variable.
#        Pista: zip(X.columns, modelo.coef_)
#     3. ¿Qué variable tiene el coeficiente más alto?
#        Después de normalizar, eso sí que indica cuál importa más.

print("\n" + "=" * 60)
print("  PASO 6: Entrenamiento del modelo")
print("=" * 60)

# --- ESCRIBE TU CÓDIGO AQUÍ ---
modelo = LinearRegression()
modelo.fit(X_train_sc, y_train)

# ─────────────────────────────────────────────────────────────────────────────
#  PASO 7 — EVALUAR EL MODELO
# ─────────────────────────────────────────────────────────────────────────────
#
#  Calcula las predicciones sobre X_test_sc y luego las tres métricas:
#     · R²   → ¿qué porcentaje de la variación explica el modelo?
#     · MAE  → error medio en dólares
#     · RMSE → igual que MAE pero penaliza más los errores grandes
#
#  💡 PISTA: El modelo simple (solo total_bill, sin normalizar) obtenía R² ≈ 0.46.
#            ¿Mejora al usar dos variables normalizadas?
#
#  🛠️  TU TURNO:
#     1. Obtén y_pred con modelo.predict(X_test_sc).
#     2. Calcula r2, mae y rmse.
#     3. Imprime los resultados y compáralos con el modelo simple.

print("\n" + "=" * 60)
print("  PASO 7: Evaluación del modelo")
print("=" * 60)

# --- ESCRIBE TU CÓDIGO AQUÍ ---
y_pred = modelo.predict(X_test_sc)
r2   = r2_score(y_test, y_pred)
mae  = mean_absolute_error(y_test, y_pred)
rmse = root_mean_squared_error(y_test, y_pred)

print(f"  R²   = {r2:.4f}")
print(f"  MAE  = {mae:.4f} $")
print(f"  RMSE = {rmse:.4f} $")
print("\n  ¿Mejoró respecto al modelo simple (R² ≈ 0.46)?")


Publicado por

Juan Pablo Fuentes

Formador de programación y bases de datos