MAT281 - Laboratorio N°07¶
Objetivo: Aplicar técnicas básicas de Machine Learning (tanto regresión como clasificación), desde la preparación de datos hasta el entrenamiento y evaluación de modelos.
Nota: Puede ayudarse de algún asistente virtual como ChatGPT, Gemini u otros, así como del autocompletado de Google Colab, para avanzar en este laboratorio debido a su extensión.
Regresión¶
Los datos utilizados corresponden a propiedades localizadas en un distrito específico de California, junto con algunas estadísticas resumen extraídas del censo de 1990. Es importante tener en cuenta que los datos no han sido procesados previamente, por lo que será necesario realizar algunas etapas de limpieza y preprocesamiento.
Las columnas incluidas en el conjunto de datos son las siguientes (sus nombres son descriptivos):
- longitude: Longitud geográfica de la propiedad.
- latitude: Latitud geográfica de la propiedad.
- housingmedianage: Edad media de las viviendas en la zona.
- total_rooms: Número total de habitaciones.
- total_bedrooms: Número total de dormitorios.
- population: Población en el área circundante.
- households: Número de hogares en la zona.
- median_income: Ingreso medio por hogar.
- medianhousevalue: Valor medio de la propiedad.
- ocean_proximity: Proximidad al océano.
El objetivo de este análisis es predecir el valor medio de las propiedades utilizando las características proporcionadas.
Para completar este laboratorio, se recomienda seguir la siguiente rúbrica de trabajo:
- Definición del problema: Clarificar el objetivo del análisis y los resultados esperados.
- Estadística descriptiva: Resumir las principales características de los datos a través de medidas estadísticas.
- Visualización descriptiva: Utilizar gráficos para explorar los datos y sus relaciones.
- Preprocesamiento: Realizar los pasos necesarios de limpieza y transformación de los datos.
- Selección de modelo: Comparar al menos cuatro modelos de predicción diferentes.
- Métricas y análisis de resultados: Evaluar el rendimiento de los modelos utilizando métricas apropiadas.
- Visualización de resultados del modelo: Crear gráficos que muestren el desempeño de los modelos.
- Conclusiones: Resumir los hallazgos del análisis.
Nota: Se anima a los estudiantes a desarrollar un análisis más profundo si lo desean. Pueden consultar como referencia el siguiente enlace.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import mean_absolute_error, mean_squared_error
def mean_absolute_percentage_error(y_true, y_pred):
return np.mean(np.abs((y_true - y_pred) / y_true)) * 100
def regression_metrics(df):
"""
Aplicar las distintas métricas definidas
:param df: DataFrame con las columnas: ['y', 'yhat']
:return: DataFrame con las métricas especificadas
"""
df_result = pd.DataFrame()
y_true = df['y']
y_pred = df['yhat']
df_result['mae'] = [round(mean_absolute_error(y_true, y_pred), 4)]
df_result['mse'] = [round(mean_squared_error(y_true, y_pred), 4)]
df_result['rmse'] = [round(np.sqrt(mean_squared_error(y_true, y_pred)), 4)]
df_result['mape'] = [round(mean_absolute_percentage_error(y_true, y_pred), 4)]
df_result['smape'] = [round(2 * mean_absolute_percentage_error(y_true, y_pred) / (mean_absolute_percentage_error(y_true, y_pred) + 100), 4)]
return df_result
from sklearn.datasets import fetch_california_housing
# Cargar los datos de housing
housing_data = fetch_california_housing(as_frame=True)
# Convertir los datos en un DataFrame de pandas
housing = housing_data['data']
housing['target'] = housing_data['target']
# Visualizar las primeras filas del DataFrame
housing.head()
MedInc | HouseAge | AveRooms | AveBedrms | Population | AveOccup | Latitude | Longitude | target | |
---|---|---|---|---|---|---|---|---|---|
0 | 8.3252 | 41.0 | 6.984127 | 1.023810 | 322.0 | 2.555556 | 37.88 | -122.23 | 4.526 |
1 | 8.3014 | 21.0 | 6.238137 | 0.971880 | 2401.0 | 2.109842 | 37.86 | -122.22 | 3.585 |
2 | 7.2574 | 52.0 | 8.288136 | 1.073446 | 496.0 | 2.802260 | 37.85 | -122.24 | 3.521 |
3 | 5.6431 | 52.0 | 5.817352 | 1.073059 | 558.0 | 2.547945 | 37.85 | -122.25 | 3.413 |
4 | 3.8462 | 52.0 | 6.281853 | 1.081081 | 565.0 | 2.181467 | 37.85 | -122.25 | 3.422 |
# FIXME
Clasificación¶
El objetivo de este proyecto es realizar la mejor predicción posible de las imágenes a partir de los datos disponibles. Para lograrlo, es necesario seguir los pasos habituales en un proyecto de Machine Learning, que incluyen la exploración estadística, la visualización y el preprocesamiento de los datos.
Se solicita lo siguiente:
Ajustar al menos tres modelos de clasificación:
- Regresión logística.
- K-Nearest Neighbors.
- Un algoritmo adicional o más, de libre elección. Puedes consultar esta lista de algoritmos para obtener ideas.
Realizar predicciones con cada uno de los tres modelos utilizando el conjunto de datos de test y calcular sus respectivas puntuaciones (score).
Evaluar y analizar los resultados de los modelos utilizando las siguientes métricas de rendimiento:
- Accuracy
- Precision
- Recall
- F1-score
Exploración de los datos¶
A continuación se carga el conjunto de datos a utilizar, a través del sub-módulo datasets
de sklearn
.
import numpy as np
import pandas as pd
from sklearn import datasets
import matplotlib.pyplot as plt
%matplotlib inline
digits_dict = datasets.load_digits()
print(digits_dict["DESCR"])
# informacion de las columnas
digits_dict.keys()
# informacion del target
digits_dict["target"]
A continuación se crea dataframe declarado como digits
con los datos de digits_dict
tal que tenga 65 columnas, las 6 primeras a la representación de la imagen en escala de grises (0-blanco, 255-negro) y la última correspondiente al dígito (target
) con el nombre target.
# leer datos
digits = (
pd.DataFrame(
digits_dict["data"],
)
.rename(columns=lambda x: f"c{x:02d}")
.assign(target=digits_dict["target"])
.astype(int)
)
digits.head()
Ejercicio 1¶
Análisis exploratorio: Realiza tu análisis exploratorio, no debes olvidar nada! Recuerda, cada análisis debe responder una pregunta.
Algunas sugerencias:
- ¿Cómo se distribuyen los datos?
- ¿Cuánta memoria estoy utilizando?
- ¿Qué tipo de datos son?
- ¿Cuántos registros por clase hay?
- ¿Hay registros que no se correspondan con tu conocimiento previo de los datos?
# FIXME
Ejercicio 2¶
Visualización: Para visualizar los datos utilizaremos el método imshow
de matplotlib
. Resulta necesario convertir el arreglo desde las dimensiones (1,64) a (8,8) para que la imagen sea cuadrada y pueda distinguirse el dígito. Superpondremos además el label correspondiente al dígito, mediante el método text
. Esto nos permitirá comparar la imagen generada con la etiqueta asociada a los valores. Realizaremos lo anterior para los primeros 25 datos del archivo.
digits_dict["images"][0]
Visualiza imágenes de los dígitos utilizando la llave images
de digits_dict
.
Sugerencia: Utiliza
plt.subplots
y el métodoimshow
. Puedes hacer una grilla de varias imágenes al mismo tiempo!
nx, ny = 5, 5
fig, axs = plt.subplots(nx, ny, figsize=(12, 12))
## FIXME
Ejercicio 3¶
Machine Learning: En esta parte usted debe entrenar los distintos modelos escogidos desde la librería de skelearn
. Para cada modelo, debe realizar los siguientes pasos:
train-test
- Crear conjunto de entrenamiento y testeo (usted determine las proporciones adecuadas).
- Imprimir por pantalla el largo del conjunto de entrenamiento y de testeo.
modelo:
- Instanciar el modelo objetivo desde la librería sklearn.
Métricas:
- Graficar matriz de confusión.
- Analizar métricas de error.
Preguntas a responder:
- ¿Cuál modelo es mejor basado en sus métricas?
- ¿Cuál modelo demora menos tiempo en ajustarse?
- ¿Qué modelo escoges?
# features, target
X = digits.drop(columns="target").values
y = digits["target"].values
Ejercicio 4¶
Comprensión del modelo: Tomando en cuenta el mejor modelo entontrado en el Ejercicio 3
, debe comprender e interpretar minuciosamente los resultados y gráficos asocados al modelo en estudio, para ello debe resolver los siguientes puntos:
- Curva AUC–ROC: Replica el ejemplo del siguiente link pero con el modelo, parámetros y métrica adecuada. Saque conclusiones del gráfico.
# FIXME
Ejercicio 5¶
Visualizando Resultados: A continuación se provee código para comparar las etiquetas predichas vs las etiquetas reales del conjunto de test.
def mostrar_resultados(digits, model, nx=5, ny=5, label="correctos"):
"""
Muestra los resultados de las predicciones de un modelo de clasificación en particular.
Se toman aleatoriamente los valores de los resultados.
- label == 'correctos': muestra los valores en los que el modelo acierta.
- label == 'incorrectos': muestra los valores en los que el modelo no acierta.
Observación: El modelo que se recibe como argumento no debe estar entrenado.
:param digits: dataset 'digits'
:param model: modelo de sklearn
:param nx: número de filas (subplots)
:param ny: número de columnas (subplots)
:param label: 'correctos' o 'incorrectos'
:return: gráficos matplotlib
"""
X = digits.drop(columns="target").values
y = digits["target"].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model.fit(X_train, y_train) # Ajustar el modelo
y_pred = model.predict(X_test)
# Mostrar los datos correctos
if label == "correctos":
mask = (y_pred == y_test)
color = "green"
# Mostrar los datos incorrectos
elif label == "incorrectos":
mask = (y_pred != y_test)
color = "red"
else:
raise ValueError("Valor incorrecto")
X_aux = X_test[mask]
y_aux_true = y_test[mask]
y_aux_pred = y_pred[mask]
# Mostrar los resultados
n_samples = min(nx * ny, len(X_aux))
indices = np.random.choice(len(X_aux), n_samples, replace=False)
fig, ax = plt.subplots(nx, ny, figsize=(12, 12))
for i, index in enumerate(indices):
data = X_aux[index, :].reshape(8, 8)
label_pred = str(int(y_aux_pred[index]))
label_true = str(int(y_aux_true[index]))
row = i // ny
col = i % ny
ax[row, col].imshow(data, interpolation='nearest', cmap='gray_r')
ax[row, col].text(0, 0, label_pred, horizontalalignment='center', verticalalignment='center', fontsize=10, color=color)
ax[row, col].text(7, 0, label_true, horizontalalignment='center', verticalalignment='center', fontsize=10, color='blue')
ax[row, col].get_xaxis().set_visible(False)
ax[row, col].get_yaxis().set_visible(False)
plt.show()
Pregunta
Tomando en cuenta el mejor modelo entontrado en el
Ejercicio 3
, grafique los resultados cuando:el valor predicho y original son iguales
el valor predicho y original son distintos
Cuando el valor predicho y original son distintos , ¿Por qué ocurren estas fallas?
Ejercicio 6¶
Conclusiones: Entrega tu veredicto, responde las preguntas iniciales, visualizaciones, trabajos futuros, dificultades, etc.