DEV Community

Jesus Oviedo Riquelme
Jesus Oviedo Riquelme

Posted on

MLZC25-12. RMSE y Modelo Baseline: El Termómetro de tu Modelo

🎯 Objetivo del Post: Aprenderás a evaluar el rendimiento de tu modelo usando métricas profesionales y a establecer puntos de referencia para medir el éxito.

🏃‍♂️ ¿Por qué Necesitamos Métricas de Evaluación?

Imagina que entrenas para una carrera y nunca cronometras tus tiempos. ¿Cómo sabrías si estás mejorando? ¿Estás más rápido que ayer? Lo mismo pasa con Machine Learning. Necesitamos formas objetivas de medir qué tan bien funciona nuestro modelo.

Las métricas de evaluación son nuestro "termómetro" que nos permite:

  • 📊 Comparar diferentes modelos de manera justa
  • 🔍 Identificar problemas en nuestro enfoque
  • 💬 Comunicar el rendimiento a otros de manera clara
  • 🎯 Tomar decisiones informadas sobre mejoras

📏 ¿Qué es RMSE?

RMSE (Root Mean Squared Error) es la métrica #1 para evaluar modelos de regresión. Mide la diferencia promedio entre las predicciones y los valores reales.

🧮 La Fórmula

RMSE = √(Σ(y_real - y_predicho)² / n)
Enter fullscreen mode Exit fullscreen mode

Donde:

  • y_real: Valor real (lo que realmente pasó)
  • y_predicho: Valor predicho (lo que nuestro modelo dijo)
  • n: Número de muestras
  • : Raíz cuadrada (para volver a las unidades originales)

🤔 ¿Por qué Raíz Cuadrada?

💡 Insight Clave: La raíz cuadrada convierte las unidades de vuelta a las unidades originales.

Si estamos prediciendo precios en dólares, el RMSE también estará en dólares. Esto hace que sea fácil interpretar: "Nuestro modelo se equivoca en promedio $3,000 por auto".

Ejemplo Práctico

Supongamos que tenemos estos datos:

Precio Real    | Precio Predicho | Error | Error²
$20,000        | $22,000        | $2,000| $4,000,000
$25,000        | $24,000        | $1,000| $1,000,000
$18,000        | $19,000        | $1,000| $1,000,000
$30,000        | $28,000        | $2,000| $4,000,000
Enter fullscreen mode Exit fullscreen mode
MSE = (4,000,000 + 1,000,000 + 1,000,000 + 4,000,000) / 4 = 2,500,000
RMSE = √2,500,000 = $1,581
Enter fullscreen mode Exit fullscreen mode

Interpretación: En promedio, nuestras predicciones están $1,581 lejos del precio real.

Implementación de RMSE

Paso 1: Implementación Manual

import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# Función para calcular RMSE
def rmse(y_real, y_predicho):
    """Calcular RMSE manualmente"""
    mse = np.mean((y_real - y_predicho) ** 2)
    return np.sqrt(mse)

# Ejemplo con datos simples
y_real = np.array([20000, 25000, 18000, 30000])
y_predicho = np.array([22000, 24000, 19000, 28000])

rmse_manual = rmse(y_real, y_predicho)
print(f"RMSE manual: ${rmse_manual:,.2f}")
Enter fullscreen mode Exit fullscreen mode

Paso 2: Usando scikit-learn

# Usando scikit-learn
from sklearn.metrics import mean_squared_error

rmse_sklearn = np.sqrt(mean_squared_error(y_real, y_predicho))
print(f"RMSE scikit-learn: ${rmse_sklearn:,.2f}")

# Verificar que son iguales
print(f"¿Son iguales? {np.isclose(rmse_manual, rmse_sklearn)}")
Enter fullscreen mode Exit fullscreen mode

Paso 3: Con Nuestro Dataset de Autos

# Cargar datos y entrenar modelo
df = pd.read_csv('car_data_limpio.csv')

# Dividir datos
from sklearn.model_selection import train_test_split

X = df[['año', 'kilometraje', 'edad_auto']]
y = df['precio']

X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

# Entrenar modelo
modelo = LinearRegression()
modelo.fit(X_train, y_train)

# Hacer predicciones
y_pred = modelo.predict(X_val)

# Calcular RMSE
rmse_autos = np.sqrt(mean_squared_error(y_val, y_pred))
print(f"RMSE en datos de autos: ${rmse_autos:,.2f}")

# Calcular RMSE porcentual
rmse_porcentual = (rmse_autos / y_val.mean()) * 100
print(f"RMSE porcentual: {rmse_porcentual:.1f}%")
Enter fullscreen mode Exit fullscreen mode

¿Qué es un Modelo Baseline?

Un modelo baseline es un modelo simple que usamos como punto de referencia. Es como establecer el "piso" de rendimiento que cualquier modelo más complejo debe superar.

¿Por qué Necesitamos un Baseline?

  1. Punto de referencia: ¿Nuestro modelo complejo realmente es mejor?
  2. Detección de problemas: Si nuestro modelo es peor que el baseline, algo está mal
  3. Comunicación: "Nuestro modelo reduce el error en 30% comparado con el baseline"
  4. Validación de datos: Si el baseline funciona mal, puede haber problemas en los datos

Tipos de Modelos Baseline

1. Modelo de Media (Mean Baseline)

El modelo más simple: siempre predice el precio promedio.

class MeanBaseline:
    def __init__(self):
        self.mean_value = None

    def fit(self, X, y):
        """Entrenar: solo calcular la media"""
        self.mean_value = np.mean(y)
        return self

    def predict(self, X):
        """Predecir: siempre devolver la media"""
        return np.full(len(X), self.mean_value)

# Usar modelo de media
baseline_media = MeanBaseline()
baseline_media.fit(X_train, y_train)

y_pred_baseline = baseline_media.predict(X_val)
rmse_baseline = np.sqrt(mean_squared_error(y_val, y_pred_baseline))

print(f"Precio promedio: ${baseline_media.mean_value:,.2f}")
print(f"RMSE Baseline (Media): ${rmse_baseline:,.2f}")
print(f"RMSE Modelo Lineal: ${rmse_autos:,.2f}")
print(f"Mejora: {((rmse_baseline - rmse_autos) / rmse_baseline * 100):.1f}%")
Enter fullscreen mode Exit fullscreen mode

2. Modelo de Mediana (Median Baseline)

Usa la mediana en lugar de la media. Más robusto a outliers.

class MedianBaseline:
    def __init__(self):
        self.median_value = None

    def fit(self, X, y):
        self.median_value = np.median(y)
        return self

    def predict(self, X):
        return np.full(len(X), self.median_value)

# Comparar diferentes baselines
baseline_mediana = MedianBaseline()
baseline_mediana.fit(X_train, y_train)
y_pred_mediana = baseline_mediana.predict(X_val)
rmse_mediana = np.sqrt(mean_squared_error(y_val, y_pred_mediana))

print(f"RMSE Baseline (Mediana): ${rmse_mediana:,.2f}")
Enter fullscreen mode Exit fullscreen mode

3. Modelo de Último Valor

Para datos temporales, usar el último valor conocido.

class LastValueBaseline:
    def __init__(self):
        self.last_value = None

    def fit(self, X, y):
        # Asumir que los datos están ordenados por tiempo
        self.last_value = y.iloc[-1]
        return self

    def predict(self, X):
        return np.full(len(X), self.last_value)
Enter fullscreen mode Exit fullscreen mode

Comparación Visual de Modelos

Gráfico de Predicciones vs Valores Reales

import matplotlib.pyplot as plt

# Crear gráfico comparativo
fig, axes = plt.subplots(2, 2, figsize=(15, 10))

# Modelo lineal
axes[0,0].scatter(y_val, y_pred, alpha=0.5, color='blue')
axes[0,0].plot([y_val.min(), y_val.max()], [y_val.min(), y_val.max()], 'r--', lw=2)
axes[0,0].set_xlabel('Precio Real ($)')
axes[0,0].set_ylabel('Precio Predicho ($)')
axes[0,0].set_title(f'Modelo Lineal (RMSE: ${rmse_autos:,.0f})')
axes[0,0].grid(True, alpha=0.3)

# Baseline de media
axes[0,1].scatter(y_val, y_pred_baseline, alpha=0.5, color='red')
axes[0,1].plot([y_val.min(), y_val.max()], [y_val.min(), y_val.max()], 'r--', lw=2)
axes[0,1].set_xlabel('Precio Real ($)')
axes[0,1].set_ylabel('Precio Predicho ($)')
axes[0,1].set_title(f'Baseline Media (RMSE: ${rmse_baseline:,.0f})')
axes[0,1].grid(True, alpha=0.3)

# Baseline de mediana
axes[1,0].scatter(y_val, y_pred_mediana, alpha=0.5, color='green')
axes[1,0].plot([y_val.min(), y_val.max()], [y_val.min(), y_val.max()], 'r--', lw=2)
axes[1,0].set_xlabel('Precio Real ($)')
axes[1,0].set_ylabel('Precio Predicho ($)')
axes[1,0].set_title(f'Baseline Mediana (RMSE: ${rmse_mediana:,.0f})')
axes[1,0].grid(True, alpha=0.3)

# Comparación de errores
modelos = ['Lineal', 'Media', 'Mediana']
rmse_values = [rmse_autos, rmse_baseline, rmse_mediana]
colors = ['blue', 'red', 'green']

axes[1,1].bar(modelos, rmse_values, color=colors, alpha=0.7)
axes[1,1].set_ylabel('RMSE ($)')
axes[1,1].set_title('Comparación de RMSE')
axes[1,1].grid(True, alpha=0.3)

# Agregar valores en las barras
for i, v in enumerate(rmse_values):
    axes[1,1].text(i, v + max(rmse_values)*0.01, f'${v:,.0f}', 
                   ha='center', va='bottom')

plt.tight_layout()
plt.show()
Enter fullscreen mode Exit fullscreen mode

Otras Métricas de Evaluación

1. MAE (Mean Absolute Error)

MAE = Σ|y_real - y_predicho| / n
Enter fullscreen mode Exit fullscreen mode

Ventajas:

  • Más fácil de interpretar (promedio de errores absolutos)
  • Menos sensible a outliers que RMSE

Desventajas:

  • No penaliza errores grandes tanto como RMSE
from sklearn.metrics import mean_absolute_error

mae = mean_absolute_error(y_val, y_pred)
print(f"MAE: ${mae:,.2f}")
Enter fullscreen mode Exit fullscreen mode

2. R² (Coeficiente de Determinación)

R² = 1 - (SSE / SST)
Enter fullscreen mode Exit fullscreen mode

Donde:

  • SSE: Suma de errores cuadrados
  • SST: Suma total de cuadrados

Interpretación:

  • R² = 1: Predicciones perfectas
  • R² = 0: Modelo no mejor que el baseline
  • R² < 0: Modelo peor que el baseline
from sklearn.metrics import r2_score

r2 = r2_score(y_val, y_pred)
print(f"R²: {r2:.3f}")
print(f"El modelo explica {r2*100:.1f}% de la varianza")
Enter fullscreen mode Exit fullscreen mode

3. MAPE (Mean Absolute Percentage Error)

MAPE = Σ|y_real - y_predicho| / y_real / n × 100
Enter fullscreen mode Exit fullscreen mode
def mape(y_real, y_predicho):
    return np.mean(np.abs((y_real - y_predicho) / y_real)) * 100

mape_value = mape(y_val, y_pred)
print(f"MAPE: {mape_value:.1f}%")
Enter fullscreen mode Exit fullscreen mode

Función de Evaluación Completa

def evaluar_modelo(y_real, y_predicho, nombre_modelo):
    """Función completa para evaluar un modelo"""
    rmse = np.sqrt(mean_squared_error(y_real, y_predicho))
    mae = mean_absolute_error(y_real, y_predicho)
    r2 = r2_score(y_real, y_predicho)
    mape = np.mean(np.abs((y_real - y_predicho) / y_real)) * 100

    print(f"\n=== Evaluación {nombre_modelo} ===")
    print(f"RMSE: ${rmse:,.2f}")
    print(f"MAE:  ${mae:,.2f}")
    print(f"R²:   {r2:.3f}")
    print(f"MAPE: {mape:.1f}%")

    return {
        'rmse': rmse,
        'mae': mae,
        'r2': r2,
        'mape': mape
    }

# Evaluar todos los modelos
resultados = {}
resultados['Lineal'] = evaluar_modelo(y_val, y_pred, 'Modelo Lineal')
resultados['Media'] = evaluar_modelo(y_val, y_pred_baseline, 'Baseline Media')
resultados['Mediana'] = evaluar_modelo(y_val, y_pred_mediana, 'Baseline Mediana')
Enter fullscreen mode Exit fullscreen mode

Interpretación de Resultados

¿Qué Significan los Números?

RMSE de $3,000

  • Bueno: Si el precio promedio es $25,000 (error del 12%)
  • Malo: Si el precio promedio es $8,000 (error del 37.5%)

R² de 0.75

  • Interpretación: El modelo explica 75% de la variación en precios
  • Comparación: Un R² de 0.5 sería mediocre, 0.9 sería excelente

MAPE del 15%

  • Interpretación: En promedio, las predicciones están 15% lejos del valor real
  • Contexto: Para precios de autos, esto podría ser aceptable

Benchmarks de la Industria

Para predicción de precios de autos usados:

  • RMSE < 10% del precio promedio: Excelente
  • RMSE 10-20%: Bueno
  • RMSE 20-30%: Aceptable
  • RMSE > 30%: Necesita mejora

Mejores Prácticas

1. Siempre Usa Múltiples Métricas

# Crear tabla comparativa
comparacion = pd.DataFrame(resultados).T
print("\nComparación de Modelos:")
print(comparacion.round(3))
Enter fullscreen mode Exit fullscreen mode

2. Considera el Contexto de Negocio

  • ¿Qué nivel de error es aceptable para el negocio?
  • ¿Es peor subestimar o sobreestimar precios?

3. Usa Validación Cruzada

from sklearn.model_selection import cross_val_score

# Validación cruzada para RMSE
scores = cross_val_score(modelo, X_train, y_train, cv=5, 
                        scoring='neg_mean_squared_error')
rmse_cv = np.sqrt(-scores)
print(f"RMSE promedio (CV): ${rmse_cv.mean():,.2f} (+/- ${rmse_cv.std() * 2:,.2f})")
Enter fullscreen mode Exit fullscreen mode

4. Documenta tus Métricas

# Guardar resultados
resultados_finales = {
    'fecha': '2024-01-15',
    'dataset': 'car_data_limpio.csv',
    'modelo': 'LinearRegression',
    'caracteristicas': ['año', 'kilometraje', 'edad_auto'],
    'rmse': rmse_autos,
    'mae': mae,
    'r2': r2,
    'mejora_vs_baseline': ((rmse_baseline - rmse_autos) / rmse_baseline * 100)
}
Enter fullscreen mode Exit fullscreen mode

Errores Comunes

1. Usar Solo RMSE

  • RMSE penaliza errores grandes más que MAE
  • Para algunos casos, MAE puede ser más apropiado

2. No Comparar con Baseline

  • Siempre necesitas un punto de referencia
  • Un modelo complejo no siempre es mejor

3. Ignorar el Contexto

  • Un RMSE de $1,000 puede ser excelente o terrible dependiendo del rango de precios

4. Sobreajuste en Validación

  • No ajustes tu modelo basándote solo en métricas de validación
  • Usa un conjunto de prueba separado para evaluación final

Conclusión

RMSE y los modelos baseline son herramientas esenciales para evaluar modelos de Machine Learning. Nos ayudan a:

  • Medir el rendimiento: Cuantificar qué tan bien funciona nuestro modelo
  • Comparar enfoques: Decidir entre diferentes modelos
  • Comunicar resultados: Explicar el rendimiento a otros
  • Detectar problemas: Identificar cuando algo no está funcionando

Puntos clave:

  • Siempre compara con un modelo baseline simple
  • Usa múltiples métricas, no solo RMSE
  • Considera el contexto de negocio
  • Documenta tus resultados

En el siguiente post, exploraremos cómo crear características más útiles (feature engineering) y manejar variables categóricas para mejorar nuestro modelo.


¿Qué métricas usas para evaluar tus modelos? ¿Has comparado alguna vez tu modelo con un baseline simple?

Top comments (0)