{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "9aA5RfAWzYcS" }, "source": [ "# Clasificación con imágenes" ] }, { "cell_type": "markdown", "metadata": { "id": "QU4PLZGrzhHX" }, "source": [ "## Imports" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "RJC534VzzDYN" }, "outputs": [], "source": [ "#Datos\n", "from sklearn.datasets import fetch_openml\n", "\n", "#Tratamiento de datos\n", "import numpy as np\n", "import pandas as pd\n", "\n", "#Visualización\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", "#Reducción de dimensionalidad\n", "from sklearn.decomposition import PCA\n", "\n", "#Medir el progreso de ejecucion en loops\n", "from tqdm import tqdm" ] }, { "cell_type": "markdown", "metadata": { "id": "JxLB0qp8zkzy" }, "source": [ "## MNIST dataset" ] }, { "cell_type": "markdown", "metadata": { "id": "lLoAfynQYIIj" }, "source": [ "El conjunto de datos mnist_784 proviene de la base de datos MNIST (Modified National Institute of Standards and Technology), que es un conjunto de datos ampliamente utilizado en reconocimiento de imágenes y aprendizaje automático. MNIST es una colección de 70,000 imágenes de dígitos escritos a mano.\n", "\n", "Cada imagen en el conjunto de datos MNIST es una imagen en escala de grises de 28x28 píxeles. En la versión mnist_784 de este conjunto de datos, cada imagen se ha \"aplanado\" en un vector de 1D de 784 características (es decir, 28x28 = 784), donde cada característica representa la intensidad de un píxel en la imagen. Por lo tanto, cada fila en el conjunto de datos mnist_784 representa una imagen.\n", "\n", "El objetivo de este conjunto de datos es clasificar correctamente cada imagen en términos del dígito que representa (de 0 a 9). Las etiquetas correctas para cada imagen se proporcionan en el conjunto de datos." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "6SJNgEOKzrji" }, "outputs": [], "source": [ "#ATENCIÓN: esta celda puede demorar.\n", "mnist = fetch_openml('mnist_784')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "_QLO2qgiztlz" }, "outputs": [], "source": [ "mnist.keys()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "GrooHFD41haF" }, "outputs": [], "source": [ "mnist.data.shape" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "hMMNMvLa2SZY" }, "outputs": [], "source": [ "mnist.DESCR" ] }, { "cell_type": "markdown", "metadata": { "id": "lTz1r_OHcf1C" }, "source": [ "## EDA" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "PoEiLTSu51e_" }, "outputs": [], "source": [ "#Imprimimos las primeras 5 imagenes\n", "plt.figure(figsize=(10,2))\n", "for index, (image, label) in enumerate(zip(mnist.data.to_numpy()[0:5], mnist.target[0:5])):\n", " plt.subplot(1, 5, index + 1)\n", " plt.imshow(np.reshape(image, (28,28)), cmap=plt.cm.gray,interpolation='nearest')\n", " plt.title(f\"Label: {label}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "tKAE-Zdo9s3B" }, "outputs": [], "source": [ "#Definimos X (las variables/features) e y (target)\n", "X, y = mnist[\"data\"], mnist[\"target\"]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "z-mm8a5uZymy" }, "outputs": [], "source": [ "y.value_counts().plot(kind='bar')\n", "plt.title('Distribución de las clases en el conjunto de datos MNIST')\n", "plt.xlabel('Clase/Digito')\n", "plt.ylabel('Cantidad')\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "p0OfuRQibFVh" }, "outputs": [], "source": [ "#Convertimos cada imagen a matriz 28x28 y las clases a enteros solo a los efectos de un análisis exploratorio\n", "X_image = X.to_numpy().reshape(-1, 28, 28)\n", "y_image = y.astype(int)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "UZNT9DXdZP22" }, "outputs": [], "source": [ "# Calculamos la imagen promedio y la desviación estándar para cada dígito\n", "mean_images = []\n", "std_images = []\n", "for i in range(10):\n", " mean_images.append(np.mean(X_image[y_image==i], axis=0))\n", " std_images.append(np.std(X_image[y_image==i], axis=0))\n", "\n", "# Visualizamos las imágenes promedio y las desviaciones estándar\n", "fig, axs = plt.subplots(2, 10, figsize=(20, 5))\n", "\n", "for i, (mean_img, std_img) in enumerate(zip(mean_images, std_images)):\n", " axs[0, i].imshow(mean_img, cmap=plt.cm.gray,interpolation='nearest')\n", " axs[0, i].set_title(f\"Mean of {i}\")\n", " axs[0, i].axis('off')\n", "\n", " axs[1, i].imshow(std_img, cmap=plt.cm.gray,interpolation='nearest')\n", " axs[1, i].set_title(f\"Std. Dev. of {i}\")\n", " axs[1, i].axis('off')\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "i4mcE-buWu5e" }, "source": [ "## PCA" ] }, { "cell_type": "markdown", "metadata": { "id": "5Efm0AILWwIv" }, "source": [ "El Análisis de Componentes Principales (PCA, por sus siglas en inglés) es un método estadístico que se utiliza para reducir la dimensionalidad de un conjunto de datos, mientras se conserva la mayor cantidad posible de la variación en los datos.\n", "\n", "PCA transforma el conjunto de datos original a un nuevo sistema de coordenadas en el que la base está formada por los vectores propios. Los nuevos ejes (o componentes principales) son ortogonales entre sí y capturan la mayor variación en los datos.\n", "\n", "Una de las ventajas de PCA es que al reducir la dimensionalidad del conjunto de datos, también puede ayudar a aliviar problemas de tiempos de ejecución que pueden surgir al trabajar con conjuntos de datos de alta dimensión. También se utiliza frecuentemente para la visualización de datos de alta dimensión." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "7PlLX51vQ9UK" }, "outputs": [], "source": [ "n_components = 50 # Nueva cantidad de features\n", "pca = PCA(n_components=n_components)\n", "X_pca = pca.fit_transform(X)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "H5a6Bn1hRDUR" }, "outputs": [], "source": [ "pd.DataFrame(X_pca).shape" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "uAz-rTx0-8Wx" }, "outputs": [], "source": [ "# Seteamos ademas una semilla para tener reproducibilidad\n", "np.random.seed(42)\n", "\n", "# Vamos a seleccionar 30k imagenes para realizar el entrenamiento y las predicciones (por un tema de tiempos de ejecución)\n", "indices_train = np.random.choice(\n", " X_pca.shape[0],\n", " size = 30000,\n", " replace=False\n", " )\n", "\n", "# Guardamos algunos de los índices restantes para validación\n", "indices_not_in_train = np.array([z for z in range(X_pca.shape[0]) if not z in indices_train])\n", "indices_val = np.random.choice(indices_not_in_train, 20000)\n", "\n", "# Seleccionamos las imagenes y su target\n", "X_train = X_pca[indices_train]\n", "y_train = y.iloc[indices_train]\n", "\n", "X_val = X_pca[indices_val]\n", "y_val = y.iloc[indices_val]" ] }, { "cell_type": "markdown", "metadata": { "id": "a6hb8e5uk9Q5" }, "source": [ "# Ejercicios" ] }, { "cell_type": "markdown", "metadata": { "id": "KYV8HmU9jgK9" }, "source": [ "## Parte 1\n", "\n", "Entrenar tres clasificadores: KNN, Regresión Logística y Árboles de decisión. Utilizar los parámetros por defecto." ] }, { "cell_type": "markdown", "source": [ "KNN" ], "metadata": { "id": "f5F6O8hRZNqX" } }, { "cell_type": "code", "source": [ "from sklearn.neighbors import KNeighborsClassifier" ], "metadata": { "id": "lHEEP7TOZX6y" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "#COMPLETAR" ], "metadata": { "id": "rlVvC81PZNIH" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "Regresión Logística" ], "metadata": { "id": "Y9fCuSf4ZQuh" } }, { "cell_type": "code", "source": [ "from sklearn.linear_model import LogisticRegression" ], "metadata": { "id": "sQHdcolvZeOR" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "qXAtuOSI-8Zv" }, "outputs": [], "source": [ "#COMPLETAR" ] }, { "cell_type": "markdown", "source": [ "Árboles de Decisión" ], "metadata": { "id": "qT-__OXVZTCs" } }, { "cell_type": "code", "source": [ "from sklearn.tree import DecisionTreeClassifier\n", "\n", "#Visualización de árboles de decisión\n", "from sklearn.tree import plot_tree" ], "metadata": { "id": "tlh76gNMZgCc" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "mskvsOHmj8XF" }, "outputs": [], "source": [ "#COMPLETAR" ] }, { "cell_type": "markdown", "source": [ "## Parte 2" ], "metadata": { "id": "SFnat8N6aGrv" } }, { "cell_type": "markdown", "metadata": { "id": "XajTtUx2kqUC" }, "source": [ "a) Graficar el error en entrenamiento y en validación en función del parámetro *K* para KNN" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "wvu66wSrkzLi" }, "outputs": [], "source": [ "#COMPLETAR" ] }, { "cell_type": "markdown", "source": [ "b) Graficar el error en entrenamiento y en validación en función del parámetro *max_depth* para el Árbol de Decisión\n" ], "metadata": { "id": "tVUF6Z6taWU-" } }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "qBJ3sm8KkzOF" }, "outputs": [], "source": [ "#COMPLETAR" ] }, { "cell_type": "markdown", "metadata": { "id": "EiY7bY6_kEEt" }, "source": [ "## Parte 3\n", "Comparar los tres modelos construidos en la parte 1, utilizando matrices de confusión y las métricas que considere convenientes." ] }, { "cell_type": "code", "source": [ "from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, ConfusionMatrixDisplay" ], "metadata": { "id": "O8sF5T-ca0Cx" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pO3ZS3IdkOyk" }, "outputs": [], "source": [ "#COMPLETAR" ] }, { "cell_type": "markdown", "metadata": { "id": "GWTk7Q0kkOE8" }, "source": [ "## Parte 4\n", "Seleccionar el modelo que entiende tiene un mejor rendimiento. Justificar." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "0Z-AZZRjkjuW" }, "outputs": [], "source": [ "#COMPLETAR" ] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.15" } }, "nbformat": 4, "nbformat_minor": 0 }