{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Laboratorio 3 - Parte 1 " ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "fCTNsoLtkyaW" }, "source": [ "\n", " \"Open\n", "\n", "**Recuerda que una vez abierto, Da clic en \"Copiar en Drive\", de lo contrario no podras almacenar tu progreso**\n", "\n", "Nota: no olvide ir ejecutando las celdas de código de arriba hacia abajo para que no tenga errores de importación de librerías o por falta de definición de variables." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "gx0QZd1tkyaX" }, "outputs": [], "source": [ "#configuración del laboratorio\n", "# Ejecuta esta celda!\n", "%load_ext autoreload\n", "%autoreload 2\n", "# for local \n", "# import sys ; sys.path.append('../commons/utils/')\n", "!wget https://raw.githubusercontent.com/jdariasl/ML_2020/master/Labs/commons/utils/general.py -O general.py --no-cache\n", "from general import configure_lab3\n", "configure_lab3()\n", "from lab3 import *\n", "GRADER = part_1()" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "fL3NUNjhkyaa" }, "source": [ "## Ejercicio 1: Contextualización del problema\n", "\n", "A continuación se leen los datos de un problema de clasificación. El problema corresponde a la clasificación de dígitos escritos a mano. Los datos fueron preprocesados para reducir el número de características y solo se van usar los digitos 0 al 4. La técnica usada será analizada más adelante en el curso. Al ejecutar la celda de código, tambien se podra visualizar una muestra de los datos usados." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "rMq5O_h_kyaa" }, "outputs": [], "source": [ "digits = load_digits(n_class=5)\n", "#--------- preprocesamiento--------------------\n", "pca = PCA(0.99, whiten=True)\n", "data = pca.fit_transform(digits.data)\n", "#---------- Datos a usar ----------------------\n", "x = data\n", "y = digits.target\n", "\n", "plot_digits(digits.data)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "P9oDeolgkyac" }, "source": [ "Vamos realizar algunas pruebas para determinar que metodologia de validación es más adecuada. En el ejercicio de código, vamos usar las librerias de scikit-learn:\n", "1. [StratifiedKFold](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html?highlight=stratifiedkfold#sklearn.model_selection.StratifiedKFold)\n", "1. [Kfold](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html#sklearn.model_selection.KFold)\n", "\n", "En la función debes seleccionar la función de sklearn adecuada para lograr el efecto deseado y completar el código, donde este incompleto. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "GlubvnNCkyad" }, "outputs": [], "source": [ "#ejercicio de código\n", "def get_muestras_by_cv (X, Y, method):\n", " \"\"\"función que devuelve el numero de muestras promedios\n", " dependiendo de la metodologia de validación (method).\n", " los conjuntos de datos deben dividirse **4 veces**\n", " X: matriz numpy con los valores de las caracteristicas\n", " Y: vector numpy con las etiquetas de con conjunto de caracteriticas X\n", " method (int): solo puede tomar dos valores:\n", " 1: se debe usar el metodo de validación Bootstrapping\n", " 2: se debe usar el metodo valicacion cruzada estratificada\n", " retorna: dataframe con las siguientes columnas:\n", " - etiqueta de clase\n", " - fold\n", " - # muestras en entrenamiento\n", " \"\"\"\n", " \n", " idx = 0\n", " results = pd.DataFrame()\n", " \n", " if method == 1:\n", " #completa el codigo con el metodo adecuado\n", " cv = \n", " for n, (train_index, test_index) in enumerate (cv.split()):\n", " y_train, y_test = Y[train_index], Y[test_index]\n", " \n", " # iterar sobre las etiquetas\n", " for label in np.unique(y_train):\n", " results.loc[idx, 'etiqueta de clase'] = label\n", " results.loc[idx, 'fold'] = n\n", " results.loc[idx, 'numero de muestras entrenamiento'] = (y_train == label).sum()\n", " idx = idx+1\n", " \n", " elif method == 2:\n", " #completa el codigo con el metodo adecuado\n", " cv = \n", " for n, (train_index, test_index ) in enumerate (cv.split()):\n", " y_train, y_test = Y[train_index], Y[test_index]\n", " len(np.unique(y_train))\n", " # iterar sobre las etiquetas\n", " for label in np.unique(y_train):\n", " \n", " results.loc[idx, 'etiqueta de clase'] = label\n", " results.loc[idx, 'folds'] = n \n", " results.loc[idx, 'numero de muestras entrenamiento'] = (y_train == label).sum()\n", " idx = idx+1\n", " else:\n", " print(\"el metodo no es valido!\")\n", " \n", " return (results)\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "7uZxurAMkyaf" }, "outputs": [], "source": [ "## la funcion que prueba tu implementacion\n", "#ignora las graficas!!\n", "GRADER.run_test(\"ejercicio1\", get_muestras_by_cv)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "8WDTn2Pgkyah" }, "source": [ "Las siguientes lineas de código grafican los resultados para analizarlos." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "wSntfgF0kyah" }, "outputs": [], "source": [ "cv1 = get_muestras_by_cv(x,y, 1)\n", "cv1['validación'] = 'Bootstrapping'\n", "cv2 = get_muestras_by_cv(x,y, 2)\n", "cv2['validación'] = 'Estratificada'\n", "cvs = pd.concat([cv1, cv2], ignore_index=True)\n", "display(\"distribución de clases\")\n", "sns.catplot(data= cvs , x = 'etiqueta de clase', y='numero de muestras entrenamiento', kind='point', hue='validación')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", "id": "rmF2ffwdkyak" }, "outputs": [], "source": [ "#@title Pregunta Abierta\n", "#@markdown ¿con base en los resultados anteriores y al tipo de problema, qué tecnica de validación es más adecuada? justifique.\n", "respuesta_1 = \"\" #@param {type:\"string\"}" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "4HMh3Ajskyam" }, "source": [ "## Ejercicio 2: Mezclas de gaussinas\n", "\n", "En la siguiente celda defina una función que tome como entradas una matriz $X$ y una matriz $Y$, entrene un modelo GMM (Modelo de mezclas gaussianas) por cada clase y retorne el listado de modelos para cada clase. Debe consultar todo lo relacionado con la creación, entrenamiento y uso en predicción de este modelo usando la librería scikit-learn. Consultar aquí: http://scikit-learn.org/stable/modules/generated/sklearn.mixture.GaussianMixture.html\n", "\n", "En el notebook, ya se encuentra cargada la libreria:\n", "\n", "```python\n", "from sklearn.mixture import GaussianMixture\n", "```\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "xj9H25Qkkyan" }, "outputs": [], "source": [ "#ejercicio de código\n", "def GMMClassifierTrain(X,Y,M,tipo):\n", " \"\"\"metodo para entrenar un modelo de mezclas de gausianas\n", " X: Matriz de caracteristicas\n", " Y : Matriz con las clases\n", " M: Número de componentes\n", " tipo (str): Tipo de matriz de covarianza (los parametros que se\n", " aceptan son los nombres de la misma libreria:\n", " ‘full’, ‘tied’, ‘diag’, ‘spherical’)\n", " retorna: diccionario de con la estructura:\n", " {etiqueta_clase: modelo_gmm_entrenado}\n", " \"\"\" \n", " GMMs = {}\n", " for cl in np.unique(Y):\n", " xclass = X[Y==cl, :]\n", " gmm = \n", " \n", " #Debe retornar un objeto que contenga todos los modelos entrenados \n", " return GMMs \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "0zOl0rx_kyao" }, "outputs": [], "source": [ "## la funcion que prueba tu implementacion\n", "GRADER.run_test(\"ejercicio2\", GMMClassifierTrain)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "RW6KTAO5kyaq" }, "source": [ "Adicionalmente construya una función que use los modelos entrenados en la función anterior para hacer la clasificación de un conjunto nuevo de muestras.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "TrBGb_PFkyaq" }, "outputs": [], "source": [ "#ejercicio de código\n", "def GMMClassfierVal(GMMs,Xtest):\n", " \"\"\"funcion que recibe los modelos GMM entrenados\n", " y realiza predicciones con base a cada salida\n", " GMMs: diccionario de con la estructura:\n", " {etiqueta_clase: modelo_gmm_entrenado}\n", " Xtest: matriz numpy con el cojunto de datos\n", " de las caracteristicas de prueba/test\n", " retorna: \n", " - un numpy array con las estimaciones de de clase de cada \n", " una de las muestras de Xtest\n", " - matriz las probabilidades(en log) de cada clase por cada\n", " muestra debe tener un shape [numero de muestras, numero de clases]\n", " \"\"\"\n", " prob = np.zeros((Xtest.shape[0], len(GMMs)))\n", " \n", " #pista explora los metodos de la libreria, que metodo retorna probabilidades?\n", " for k,v in GMMs.items():\n", " \n", " \n", " # la etiqueta la asignas seleccionando le maximo de probabilidad\n", " Yest= \n", " \n", " return Yest, prob" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "ARKhErZCkyas" }, "outputs": [], "source": [ "## la funcion que prueba tu implementacion\n", "#ignora las graficas!!\n", "GRADER.run_test(\"ejercicio3\", GMMClassfierVal)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "EOorjH6nkyau" }, "source": [ "## Ejercicio 3: Experimentos\n", "Con el código completado, vamos a realizar experimentos. Complete la siguiente función para poder obtener los resultados de los experimentos. Es necesario:\n", "1. retornar errores de entrenamiento y pruebas\n", "2. retornar intervalos de confianza (desviacion estandar) para cada una de la configuración de experimentos\n", "3. en el código, ya se sugiere la metodologia de validación (usando 4 folds) y se usa, como es usual el standard scaler para normalizar los datos." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "XBLei4VPkyau" }, "outputs": [], "source": [ "#ejercicio de código\n", "def experimentar(covariance_types,num_components, X, Y):\n", " \"\"\"función que realiza experimentos del GMM\n", " covariance_types: list[str] con las matrices de covarianza a probar\n", " num_components: list[int] con el numero de componente a probar\n", " X: matriz con las caractersiticas\n", " Y: matriz de numpy con etiquetas\n", " retorna: dataframe con:\n", " - matriz de covarianza\n", " - numero de componentes\n", " - eficiencia de entrenamiento\n", " - desviacion de estandar eficiencia de entrenamiento\n", " - eficiencia de prueba\n", " - desviacion estandar eficiencia de prueba\n", " \"\"\"\n", " folds = 4\n", " skf = StratifiedKFold(n_splits=folds)\n", " resultados = pd.DataFrame()\n", " idx = 0\n", "\n", " for cov_tipo in covariance_types:\n", " for M in num_components:\n", " ## para almacenar los errores intermedios\n", " EficienciaTrain = []\n", " EficienciaVal = []\n", " for train, test in skf.split(X, Y):\n", " Xtrain = X[train,:]\n", " Ytrain = Y[train]\n", " Xtest = X[test,:]\n", " Ytest = Y[test]\n", " #Normalizamos los datos\n", " scaler = StandardScaler()\n", " scaler.fit(Xtrain)\n", " Xtrain= scaler.transform(Xtrain)\n", " Xtest = scaler.transform(Xtest)\n", " #Haga el llamado a la función para crear y entrenar el modelo usando los datos de entrenamiento\n", " gmms = \n", " #Validación se ignora la matriz de probabilidad\n", " Ytrain_pred, _ =\n", " Yest, _ = \n", " #Evaluamos las predicciones del modelo con los datos de test\n", " EficienciaTrain.append(np.mean(Ytrain_pred.ravel() == Ytrain.ravel()))\n", " EficienciaVal.append(np.mean(Yest.ravel() == Ytest.ravel()))\n", "\n", " resultados.loc[idx,'matriz de covarianza'] = cov_tipo\n", " resultados.loc[idx,'numero de componentes'] = M\n", " resultados.loc[idx,'eficiencia de entrenamiento'] = \n", " resultados.loc[idx,'desviacion estandar entrenamiento'] =\n", " resultados.loc[idx,'eficiencia de prueba'] =\n", " resultados.loc[idx,'desviacion estandar prueba'] =\n", " idx= idx +1\n", " print(\"termina para\", cov_tipo, M)\n", " \n", " return (resultados)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "shHrHnvykyaw" }, "outputs": [], "source": [ "## la funcion que prueba tu implementacion\n", "# los prints del test los puedes ignorar (se hacen unos checks!)\n", "GRADER.run_test(\"ejercicio4\", experimentar)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "JXy56hwbkyax" }, "source": [ "Ahora vamos a ejecutar nuestros experimentos:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "AhheSKcvkyay" }, "outputs": [], "source": [ "matrices = ['full', 'tied', 'diag', 'spherical']\n", "componentes = [1,2,3,4,5]\n", "resultados = experimentar(matrices, componentes, x, y)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "5uEfpgfGkyaz" }, "outputs": [], "source": [ "# para ver la tabla\n", "resultados" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", "id": "Zv18FE_nkya2" }, "outputs": [], "source": [ "#@title Pregunta Abierta\n", "#@markdown La tabla incluye un tipo de matriz de covarianza no vista en clase, Atada(tied), ¿En qué consiste este tipo de matriz según la documentación en scikit-learn?\n", "respuesta_2 = \"\" #@param {type:\"string\"}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", "id": "9E_LNaFpkya4" }, "outputs": [], "source": [ "#@title Pregunta Abierta\n", "#@markdown ¿Qué método se utilizó para la incialización de los parámetros del modelo GMM? ¿Cual es la diferencia entre el usado y la otra opción de la libreria?\n", "respuesta_3 = \"\" #@param {type:\"string\"}" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "-HcG_ejYkya5" }, "source": [ "## Ejercicio 4 Kmeans y experimentos\n", "\n", "\n", "Consultar todo lo relacionado al llamado del método KMeans de la librería scikit-learn en el siguiente enlace: http://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html. \n", "\n", "En el notebook, ya se encuentra cargada la libreria:\n", "\n", "```python\n", "from sklearn.cluster import KMeans\n", "```\n", "\n", "Vamos a resolver el mismo problema anterior pero con el K-means. La libreria nos la suficiente utilidad para ya poder comenzar a realizar experimentos con ella. Por ellos vamos a implementar la función para realizar los experimentos." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "SYFhQHutkya7" }, "outputs": [], "source": [ "#ejercicio de código\n", "#Validamos el modelo\n", "def experimentar_kmeans(numero_clusters,X, Y):\n", " \"\"\"función que realiza experimentos de Kmeans\n", " numero_clusters: list[int] numero cluster para realizar experimentos\n", " X: matriz con las caractersiticas\n", " Y: matriz de numpy con etiquetas\n", " retorna: dataframe con:\n", " - numero_clusters\n", " - el error de entrenamiento\n", " - desviacion de estandar del error entrenamiento\n", " - error de prueba\n", " - desviacion estandar eror de prueba\n", " \"\"\"\n", " folds = 4\n", " skf = StratifiedKFold(n_splits=folds)\n", " resultados = pd.DataFrame()\n", " idx = 0\n", "\n", " for n_cluster in numero_clusters:\n", " ## para almacenar los errores intermedios\n", " EficienciaTrain = []\n", " EficienciaVal = []\n", " for train, test in skf.split(X, Y):\n", " Xtrain = X[train,:]\n", " Ytrain = Y[train]\n", " Xtest = X[test,:]\n", " Ytest = Y[test]\n", " #Normalizamos los datos\n", " scaler = StandardScaler()\n", " scaler.fit(Xtrain)\n", " Xtrain= scaler.transform(Xtrain)\n", " Xtest = scaler.transform(Xtest)\n", " #verifica como pasar n_cluster a KMeans\n", " kmeans = \n", " #¿que metodo debes llamar para entrenar kmeans?\n", " kmeans\n", " #predicciones en cada conjunto\n", " # ¿que metodo debes llamar para realizar preddiciones con kmeans?\n", " Ytrain_pred = kmeans\n", " Yest = kmeans\n", " #Evaluamos las predicciones del modelo con los datos de test\n", " EficienciaTrain.append(np.mean(Ytrain_pred.ravel() == Ytrain.ravel()))\n", " EficienciaVal.append(np.mean(Yest.ravel() == Ytest.ravel()))\n", "\n", " resultados.loc[idx,'numero de clusters'] = n_cluster\n", " resultados.loc[idx,'eficiencia de entrenamiento'] = \n", " resultados.loc[idx,'desviacion estandar entrenamiento'] =\n", " resultados.loc[idx,'eficiencia de prueba'] = \n", " resultados.loc[idx,'desviacion estandar prueba'] =\n", " idx= idx +1\n", " print(\"termina para\", n_cluster)\n", " \n", " return (resultados)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "code", "colab": {}, "colab_type": "code", "id": "M_ojP0hSkya9" }, "outputs": [], "source": [ "#@title Default title text\n", "## la funcion que prueba tu implementacion\n", "#ignora las graficas!!\n", "GRADER.run_test(\"ejercicio5\", experimentar_kmeans)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "CC0WGj4Zkya-" }, "outputs": [], "source": [ "# ejecuta los experimentos y ve los resultados\n", "resultados_kmeans = experimentar_kmeans([3,5,6,8],x, y)\n", "resultados_kmeans" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", "id": "Op_AHOAgkybA" }, "outputs": [], "source": [ "#@title Pregunta Abierta\n", "#@markdown ¿Tiene sentido realizar experimentos con una configuraración de n_clusters!=5? justifique \n", "respuesta_4 = \"\" #@param {type:\"string\"}" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "zu7LsXk_kybB" }, "source": [ "tener presente que tipo de entrenamiento realiza el kmeans: ¿supervisado o no supervisado? interpreta la grafica resultante de ejecutar la siguiente linea de código. Algunas observaciones de la grafica:\n", "1. Si bien nuestro conjunto datos tiene 40 caracteristicas, vamos representarlo solo con las dos primeras dimensiones.\n", "2. Completa el codigo, con el numero de clusters con la cual se obtuvo la mejor eficiencia en los experimentos." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "-PxpuVWmkybC" }, "outputs": [], "source": [ "numero_clusters = # aca el numero de cluster con la mejor eficiencia\n", "predict = KMeans(n_clusters=numero_clusters).fit_predict(StandardScaler().fit_transform(x))\n", "real = pd.DataFrame(x[:, 0:2], columns=['PC1', 'PC2'])\n", "real['clase'] = y\n", "real['tipo de etiqueta'] = 'Real'\n", "kmeans = pd.DataFrame(x[:, 0:2], columns=['PC1', 'PC2'])\n", "kmeans['clase'] = predict\n", "kmeans['tipo de etiqueta'] = 'Asignada por Kmeans'\n", "data_to_plot = pd.concat([real, kmeans], ignore_index=True)\n", "data_to_plot['clase'] = data_to_plot['clase'].astype('category')\n", "sns.relplot(data = data_to_plot, x = 'PC1', y='PC2', hue= 'clase', col='tipo de etiqueta')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", "id": "X_xcA2LTkybE" }, "outputs": [], "source": [ "#@title Pregunta Abierta\n", "#@markdown ¿con base a los resultados que modelo es el más adecuado entre el k-means y el GMM? justifique.\n", "respuesta_6 = \"\" #@param {type:\"string\"}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "jjN45dUAkybF" }, "outputs": [], "source": [ "GRADER.check_tests()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "DrYzIcRJkybH" }, "outputs": [], "source": [ "#@title Integrantes\n", "codigo_integrante_1 ='' #@param {type:\"string\"}\n", "codigo_integrante_2 = '' #@param {type:\"string\"}" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "guu6JrtRkybJ" }, "source": [ "----\n", "esta linea de codigo va fallar, es de uso exclusivo de los profesores\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "KcaIVi5CkybJ" }, "outputs": [], "source": [ "GRADER.grade()" ] } ], "metadata": { "colab": { "name": "lab3_parte1.ipynb", "provenance": [], "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "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.7.6" } }, "nbformat": 4, "nbformat_minor": 2 }