🎯 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)
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
MSE = (4,000,000 + 1,000,000 + 1,000,000 + 4,000,000) / 4 = 2,500,000
RMSE = √2,500,000 = $1,581
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}")
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)}")
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}%")
¿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?
- Punto de referencia: ¿Nuestro modelo complejo realmente es mejor?
- Detección de problemas: Si nuestro modelo es peor que el baseline, algo está mal
- Comunicación: "Nuestro modelo reduce el error en 30% comparado con el baseline"
- 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}%")
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}")
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)
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()
Otras Métricas de Evaluación
1. MAE (Mean Absolute Error)
MAE = Σ|y_real - y_predicho| / n
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}")
2. R² (Coeficiente de Determinación)
R² = 1 - (SSE / SST)
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")
3. MAPE (Mean Absolute Percentage Error)
MAPE = Σ|y_real - y_predicho| / y_real / n × 100
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}%")
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')
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))
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})")
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)
}
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)