# Importar las librerías necesarias
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV, KFold
from sklearn.linear_model import LinearRegression, Ridge, Lasso, RidgeCV, LassoCV
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore')
# Configurar estilo de gráficos
plt.style.use('seaborn-v0_8-darkgrid')
sns.set_palette("husl")
# Configurar seed para reproducibilidad
np.random.seed(42)Ejercicio: Análisis de Regresión con el Dataset Wine Quality
Descripción del Dataset
El dataset Wine Quality contiene resultados de análisis fisicoquímicos de vinos portugueses “Vinho Verde” y su calidad evaluada por expertos. El objetivo es predecir la calidad del vino basándose en sus propiedades químicas.
Variables del dataset:
- fixed acidity: Acidez fija (g/L de ácido tartárico)
- volatile acidity: Acidez volátil (g/L de ácido acético)
- citric acid: Ácido cítrico (g/L)
- residual sugar: Azúcar residual (g/L)
- chlorides: Cloruros (g/L de cloruro de sodio)
- free sulfur dioxide: Dióxido de azufre libre (mg/L)
- total sulfur dioxide: Dióxido de azufre total (mg/L)
- density: Densidad (g/cm³)
- pH: pH del vino
- sulphates: Sulfatos (g/L de sulfato de potasio)
- alcohol: Contenido de alcohol (% vol)
- quality: Calidad del vino (puntuación de 0-10) - Variable objetivo
En este ejercicio, trabajarás con el dataset de vinos tintos y aplicarás diferentes técnicas de regresión para predecir la calidad del vino.
1. Importar librerías y cargar datos
# Cargar el dataset de vinos tintos
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv'
wine_data = pd.read_csv(url, sep=';')
print("Dataset cargado exitosamente!")
print(f"Dimensiones del dataset: {wine_data.shape}")
print(f"\nColumnas del dataset:")
print(wine_data.columns.tolist())2. Análisis Exploratorio de Datos (EDA)
Ejercicio 2.1: Exploración inicial
Completa el análisis exploratorio inicial del dataset.
# Mostrar las primeras filas del dataset
wine_data.head()# TODO: Muestra la información general del dataset (tipos de datos, valores no nulos)
# Tu código aquí# TODO: Calcula y muestra las estadísticas descriptivas del dataset
# Tu código aquí# TODO: Verifica si hay valores nulos en el dataset
# Tu código aquíEjercicio 2.2: Análisis de la variable objetivo
# Analizar la distribución de la calidad del vino
plt.figure(figsize=(10, 6))
wine_data['quality'].value_counts().sort_index().plot(kind='bar', color='steelblue', edgecolor='black')
plt.xlabel('Calidad del Vino', fontsize=12)
plt.ylabel('Frecuencia', fontsize=12)
plt.title('Distribución de la Calidad del Vino', fontsize=14)
plt.xticks(rotation=0)
plt.grid(axis='y', alpha=0.3)
# Agregar estadísticas
mean_quality = wine_data['quality'].mean()
median_quality = wine_data['quality'].median()
plt.axhline(y=wine_data['quality'].value_counts().mean(), color='red',
linestyle='--', label=f'Media de frecuencia')
plt.legend()
plt.tight_layout()
plt.show()
print(f"Estadísticas de la calidad del vino:")
print(f"Media: {mean_quality:.2f}")
print(f"Mediana: {median_quality:.2f}")
print(f"Desviación estándar: {wine_data['quality'].std():.2f}")Ejercicio 2.3: Matriz de correlación
# TODO: Calcula la matriz de correlación y visualízala con un heatmap
# Pista: Usa sns.heatmap() con annot=True para mostrar los valores
# Tu código aquí
plt.figure(figsize=(14, 10))
# Completa el código para crear el heatmap# TODO: Identifica y muestra las 5 variables más correlacionadas con 'quality'
# Tu código aquíEjercicio 2.4: Visualización de relaciones
# Visualizar las 4 variables más correlacionadas con quality
top_features = ['alcohol', 'volatile acidity', 'citric acid', 'sulphates']
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle('Relación entre Variables Principales y Calidad del Vino', fontsize=16)
for idx, (ax, feature) in enumerate(zip(axes.flat, top_features)):
# TODO: Crea un scatter plot para cada variable vs quality
# Agrega una línea de tendencia
# Tu código aquí
pass
plt.tight_layout()
plt.show()3. Preparación de Datos
# Separar características (X) y variable objetivo (y)
X = wine_data.drop('quality', axis=1)
y = wine_data['quality']
print(f"Forma de X: {X.shape}")
print(f"Forma de y: {y.shape}")
print(f"\nCaracterísticas: {X.columns.tolist()}")# TODO: Divide los datos en conjuntos de entrenamiento y prueba
# Usa test_size=0.2 y random_state=42
# Tu código aquí
# X_train, X_test, y_train, y_test = ...
# print(f"Tamaño del conjunto de entrenamiento: ...")
# print(f"Tamaño del conjunto de prueba: ...")# TODO: Estandariza las características
# Recuerda: ajusta el scaler solo con los datos de entrenamiento
# Tu código aquí
# scaler = StandardScaler()
# X_train_scaled = ...
# X_test_scaled = ...4. Validación Cruzada para Selección de Hiperparámetros
La validación cruzada es fundamental para seleccionar los mejores hiperparámetros sin usar el conjunto de prueba.
Ejercicio 4.1: Implementación manual de validación cruzada
# Ejemplo: Validación cruzada manual para Ridge
def manual_cross_validation(X, y, alpha, n_folds=5):
"""
Implementa validación cruzada manualmente para Ridge regression
"""
kf = KFold(n_splits=n_folds, shuffle=True, random_state=42)
scores = []
for train_idx, val_idx in kf.split(X):
# Dividir datos
X_train_cv, X_val_cv = X[train_idx], X[val_idx]
y_train_cv, y_val_cv = y.iloc[train_idx], y.iloc[val_idx]
# Estandarizar
scaler_cv = StandardScaler()
X_train_cv_scaled = scaler_cv.fit_transform(X_train_cv)
X_val_cv_scaled = scaler_cv.transform(X_val_cv)
# Entrenar modelo
model = Ridge(alpha=alpha)
model.fit(X_train_cv_scaled, y_train_cv)
# Evaluar
y_pred = model.predict(X_val_cv_scaled)
rmse = np.sqrt(mean_squared_error(y_val_cv, y_pred))
scores.append(rmse)
return np.mean(scores), np.std(scores)
# Probar diferentes valores de alpha
alphas_to_test = [0.001, 0.01, 0.1, 1, 10, 100]
cv_results_manual = []
print("Validación Cruzada Manual para Ridge Regression:")
print("-" * 50)
for alpha in alphas_to_test:
mean_rmse, std_rmse = manual_cross_validation(X_train.values, y_train, alpha)
cv_results_manual.append({'alpha': alpha, 'mean_rmse': mean_rmse, 'std_rmse': std_rmse})
print(f"Alpha: {alpha:7.3f} | RMSE: {mean_rmse:.4f} (+/- {std_rmse:.4f})")
# TODO: Identifica el mejor alpha basado en el RMSE medio más bajo
# Tu código aquíEjercicio 4.2: Usar RidgeCV para validación cruzada automática
# TODO: Usa RidgeCV para encontrar automáticamente el mejor alpha
# Pista: RidgeCV tiene un parámetro 'alphas' y 'cv'
# Tu código aquí
# alphas = np.logspace(-3, 3, 100) # 100 valores entre 0.001 y 1000
# ridge_cv = RidgeCV(...)
# ridge_cv.fit(...)
# print(f"Mejor alpha encontrado por RidgeCV: ...")Ejercicio 4.3: GridSearchCV para búsqueda exhaustiva
# Ejemplo completo con GridSearchCV para Ridge
from sklearn.model_selection import GridSearchCV
# Definir parámetros a buscar
param_grid_ridge = {
'alpha': np.logspace(-3, 3, 20) # 20 valores entre 0.001 y 1000
}
# Crear modelo base
ridge_base = Ridge(random_state=42)
# TODO: Implementa GridSearchCV
# Usa cv=5, scoring='neg_mean_squared_error'
# Tu código aquí
# grid_search_ridge = GridSearchCV(...)
# grid_search_ridge.fit(...)
# print(f"Mejor alpha: ...")
# print(f"Mejor score (RMSE): ...")# TODO: Visualiza los resultados de la validación cruzada
# Crea un gráfico que muestre cómo cambia el RMSE con diferentes valores de alpha
# Tu código aquí
plt.figure(figsize=(10, 6))
# Completa el código para visualizar los resultados5. Modelos de Regresión
5.1 Regresión Lineal Normal
# TODO: Implementa y entrena un modelo de regresión lineal
# Tu código aquí
# lr_model = LinearRegression()
# lr_model.fit(...)
# Hacer predicciones
# y_pred_lr_train = ...
# y_pred_lr_test = ...
# Calcular métricas
# rmse_lr_train = ...
# rmse_lr_test = ...
# r2_lr_train = ...
# r2_lr_test = ...
# print("Regresión Lineal Normal:")
# print(f"RMSE Train: ...")
# print(f"RMSE Test: ...")
# print(f"R² Train: ...")
# print(f"R² Test: ...")5.2 Ridge Regression con mejor alpha de CV
# TODO: Entrena Ridge con el mejor alpha encontrado por validación cruzada
# Tu código aquí
# best_alpha_ridge = ... # Usa el mejor alpha de la sección anterior
# ridge_model = Ridge(alpha=best_alpha_ridge)
# ridge_model.fit(...)
# Predicciones y métricas
# ...5.3 Lasso Regression con validación cruzada
# TODO: Implementa LassoCV para encontrar el mejor alpha automáticamente
# Tu código aquí
# alphas_lasso = np.logspace(-3, 1, 100)
# lasso_cv = LassoCV(...)
# lasso_cv.fit(...)
# print(f"Mejor alpha para Lasso: ...")
# print(f"Número de características seleccionadas: ...")
# Predicciones y métricas
# ...# TODO: Identifica qué características fueron eliminadas por Lasso
# Tu código aquí6. Comparación de Modelos
# TODO: Crea una tabla comparativa con todos los modelos
# Incluye: RMSE Train, RMSE Test, R² Train, R² Test, MAE Test
# Tu código aquí
# comparison_data = {
# 'Modelo': [...],
# 'RMSE Train': [...],
# 'RMSE Test': [...],
# 'R² Train': [...],
# 'R² Test': [...],
# 'MAE Test': [...]
# }
# comparison_df = pd.DataFrame(comparison_data)
# print(comparison_df)# TODO: Crea visualizaciones para comparar los modelos
# 1. Gráfico de barras comparando RMSE
# 2. Gráfico de barras comparando R²
# Tu código aquí7. Análisis de Residuos
# TODO: Para el mejor modelo, crea:
# 1. Gráfico de residuos vs predicciones
# 2. Histograma de residuos
# 3. Q-Q plot de residuos
# Tu código aquí8. Importancia de Características
# TODO: Visualiza los coeficientes de los tres modelos en un mismo gráfico
# Esto te ayudará a entender qué características son más importantes
# Tu código aquí9. Validación Cruzada Final del Mejor Modelo
# TODO: Realiza validación cruzada con 10 folds del mejor modelo
# Reporta la media y desviación estándar del RMSE
# Tu código aquí10. Conclusiones y Preguntas de Reflexión
Preguntas para responder:
- ¿Cuál modelo tuvo el mejor desempeño? ¿Por qué crees que fue así?
- Tu respuesta:
- ¿Qué características son las más importantes para predecir la calidad del vino?
- Tu respuesta:
- ¿Observas señales de sobreajuste en algún modelo? ¿Cómo lo identificaste?
- Tu respuesta:
- ¿Cómo cambió el rendimiento de Ridge y Lasso con diferentes valores de alpha?
- Tu respuesta:
- ¿Qué ventajas observaste al usar validación cruzada para seleccionar hiperparámetros?
- Tu respuesta:
- Si Lasso eliminó algunas características, ¿crees que esto mejoró o empeoró el modelo? ¿Por qué?
- Tu respuesta:
- ¿Qué otros pasos podrías tomar para mejorar el rendimiento del modelo?
- Tu respuesta:
Ejercicio Extra: Ingeniería de Características
Desafío:
Intenta mejorar el rendimiento del modelo creando nuevas características:
- Crea interacciones entre variables (ej: alcohol × pH)
- Crea características polinomiales
- Agrupa la calidad en categorías (baja: 3-4, media: 5-6, alta: 7-8) y úsala como característica
- Crea ratios entre características relacionadas
# TODO: Implementa ingeniería de características y evalúa si mejora el modelo
# Tu código aquí