{"cells":[{"cell_type":"markdown","metadata":{"id":"pe53IRkGICfI"},"source":["# Laboratorio Redes Neuronales\n","\n","En esta clase vamos a tener la primera aproximación a redes neuronales utilizando Keras. En particular, vamos a tomar como guía el problema bien conocido de clasificación de dígitos escritos manualmente. [Aquí](https://www.tensorflow.org/datasets/catalog/mnist?hl=es-419) pueden verse su características principales.\n","\n","Keras es una biblioteca de Redes Neuronales de Código Abierto escrita en Python. Es una biblioteca de alto nivel, fácil de utilizar y muy popular. Puede utilizarse sobre otras bibliotecas o frameworks como Tensorflow, que provee funcionalidades y características adicionales.\n","\n","Para comenzar, vamos a importar los módulos necesarios."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"hPHXLeBnICfJ"},"outputs":[],"source":["import numpy as np\n","from tensorflow import keras\n","from keras.datasets import mnist\n","import matplotlib.pyplot as plt"]},{"cell_type":"markdown","metadata":{"id":"88sm4zLBICfK"},"source":["A continuación cargamos el dataset. A diferencia de otros dataset que hemos usado, este ya viene divido en train y test, con 60.000 ejemplos de entrenamiento, y 10.000 en test."]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"h5e7sPwdICfK","outputId":"4a0ffe4a-ac4e-48bd-afbb-27b36ee70265"},"outputs":[{"output_type":"stream","name":"stdout","text":["Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz\n","11490434/11490434 [==============================] - 2s 0us/step\n"]},{"output_type":"execute_result","data":{"text/plain":["((60000, 28, 28), (10000, 28, 28))"]},"metadata":{},"execution_count":3}],"source":["(x_train, y_train), (x_test, y_test) = mnist.load_data()\n","x_train.shape, x_test.shape"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"E4HRkQXYzFCU"},"outputs":[],"source":["# x_train es un array de numpy\n","type(x_train)"]},{"cell_type":"markdown","metadata":{"id":"mz6-Qe3uICfL"},"source":["Veamos algunos ejemplos del conjunto de entrenaiento..."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"DZ0CWW3eICfM"},"outputs":[],"source":["plt.figure(figsize=(10,10))\n","for i in range(25):\n"," plt.subplot(5,5,i+1)\n"," plt.xticks([])\n"," plt.yticks([])\n"," plt.imshow(x_train[i], cmap='gray')\n"," plt.xlabel(y_train[i])\n","plt.show()"]},{"cell_type":"markdown","metadata":{"id":"7GT4LZzxICfM"},"source":["El dataset esta compuesto por imágenes de 28 x 28 pixeles en escala de grises, que sencillamente se representa como una matriz de enteros, de 28 x 28, cuyos valores van del 0 (negro absoluto) al 255 (completamente blanco).\n","\n","De esta forma, x_train es de `(n_samples, height, weight)`."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"wnu2ebdiICfN"},"outputs":[],"source":["print('x_train es de ', x_train.shape)\n","print('x_test es de ', x_test.shape)\n","print('El tipo de datos es ', x_train.dtype)"]},{"cell_type":"markdown","metadata":{"id":"zztCpNRyICfN"},"source":["Si inspeccionamos el primer ejemplo de entrenamiento, vemos que el valor de los pixeles efectivamente van de 0 a 255, y que es de 28 x 28"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"NMv-BWK6ICfO"},"outputs":[],"source":["plt.title(\"digito {}\".format(y_train[0]))\n","plt.imshow(x_train[0], cmap='gray')\n","plt.colorbar()\n","plt.grid(False)\n","plt.show()"]},{"cell_type":"markdown","metadata":{"id":"PqA7dJxkICfO"},"source":["## Preprocesamiento de los datos\n","En la siguiente celda, vamos a preprocesar las imagenes que vamos a utilizar antes de comenzar el entrenamiento.\n","\n","Para la mayoría de los datos de imágenes, los valores de píxeles son números enteros con valores entre 0 y 255.\n","Las redes neuronales procesan las entradas utilizando valores de peso pequeños, y las entradas con valores enteros grandes pueden interrumpir o ralentizar el proceso de aprendizaje. Como tal, es una buena práctica normalizar los valores de los píxeles para que cada valor de los píxeles tenga un valor entre 0 y 1. Además, para que no todas las entradas sean positivas podemos centrar la media a 0, favoreciendo el aprendizaje.\n","\n","**Se pide**:\n"," - Utilizando la operacion `reshape`, convertir los ejemplos de entrenamiento de matriz a vector\n"," - Convertir el tipo de los datos de tipo `np.uint8` a `np.float32`\n"," - Dividimos el valor de cada pixel entre 255 para asegurar que todos los pixeles queden en el rango $[0,1]$\n"," - Restamos a cada pixel 0.5 para asegurar que todos los pixeles queden en el rango $[-0.5,0.5]$\n","\n"," (Utilice variables x_train1 y x_test1 para no modificar el dataset original)\n","\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"a3m1yNMqICfP"},"outputs":[],"source":["######################################## COMPLETAR SEGÚN LO PEDIDO ##################################################\n","\n","\n","####################################################################################################################\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"HWPM4g_dICfP"},"outputs":[],"source":["# Verificamos que los pasos anteriores fueron correctos\n","assert x_train1.ndim == 2, \"Deben haber 2 dimensiones, hay {}\".format(x_train1.ndim)\n","assert x_train1.min() == -.5, \"El minimo debe ser -.5 pero es {}\".format(x_train1.min())\n","assert x_train1.max() == .5, \"El minimo debe ser .5 pero es {}\".format(x_train1.max())"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"I5mkY_1C3w0-"},"outputs":[],"source":["# Cuando verificamos que quedó bien, modificamos los datos originales\n","x_train = x_train1\n","x_test = x_test1"]},{"cell_type":"markdown","metadata":{"id":"bdyEvKsoICfQ"},"source":["**Se pide**: Utilizando el metodo `train_test_split` se scikit-learn, tomar el 90% del conjunto de entrenamiento para entrenar, y utilizar el restante para validar, que llamaremos `x_val`, `y_val`, y que vamos a usar para tunear parametros. Utilizamos un random_state=0 para asegurar reproductibilidad."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"3q4dl7gnICfQ"},"outputs":[],"source":["from sklearn.model_selection import train_test_split\n","\n","######################################## COMPLETAR SEGÚN LO PEDIDO ##################################################\n","\n","\n","####################################################################################################################\n","\n","# Verificamos que todo este bien\n","assert len(x_train) == len(y_train)\n","assert len(x_val) == len(y_val)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"1GQAyX4N4-kI"},"outputs":[],"source":["print(x_train.shape)\n","print(x_val.shape)"]},{"cell_type":"markdown","metadata":{"id":"mEKgJ6_nICfQ"},"source":["## Keras Sequential Models API\n","Keras provee dos grandes APIs para trabajar con modelos: secuencial y funcional. En esta clase vamos a trabajar con la primera de ellas: _Keras Sequential Models_. Esta API permite crear modelos de deep leaning a partir de una instancia de la clase `Sequential` a la que luego se le crean y agregan las capas necesarias.\n","\n","Por ejemplo, las capas pueden ser definidas y pasadas a la clase Sequential como una lista:\n","\n","```python\n","from keras.models import Sequential\n","from keras.layers import Dense\n","model = Sequential([Dense(2, activation=\"relu\", input_dim=1, name=\"hidden_layer\"),\n"," Dense(1, activation=\"sigmoid\", name=\"output_layer\")], name=\"my_model\")\n","```\n","\n","O pueden ser agregadas de a una:\n","\n","```python\n","from keras.models import Sequential\n","from keras.layers import Dense\n","model = Sequential(name=\"my_model\")\n","model.add(Dense(2, activation=\"relu\", input_dim=1, name=\"hidden_layer\"))\n","model.add(Dense(1, activation=\"sigmoid\", name=\"output_layer\"))\n","```\n","\n","En ambos casos, `model` es una red neuronal con dos capas, donde la primera tiene dos neuronas (capa oculta), y la segunda (capa de salida) tiene solo una.\n","`Dense` es simplemente una capa densa, también conocida como completamente conectada (fully conected).\n","\n","En ambos casos, para cada capa, se indica la función de activación a utilizar. Los nombres, tanto de las capas como del modelo, son strings arbitrarios (es decir, texto) que facilitan la comprensión del modelo.\n","\n","Esta clase permite desarrollar modelos para la mayoría de las aplicaciónes que vamos a ver, es muy sencilla aunque tiene sus limitaciones (por ejemplo, unicamente permite crear modelos de tipo _feed forward_).\n","\n","Una vez creado el modelo, se puede ver un resumen de este con el método `summary`:\n","```python\n","model.summary()\n","\n","```\n","Que muestra lo siguiente:\n","```\n","Model: \"my_model\"\n","_________________________________________________________________\n","Layer (type) Output Shape Param # \n","=================================================================\n","hidden_layer (Dense) (None, 2) 4 \n","_________________________________________________________________\n","output_layer (Dense) (None, 1) 3 \n","=================================================================\n","Total params: 7\n","Trainable params: 7\n","Non-trainable params: 0\n","```\n","\n","\n"]},{"cell_type":"markdown","source":["### Para la entrega: Contestar las siguientes preguntas\n","\n","- ¿Cuál es la dimensión de la entrada?\n","- ¿por qué los parámetros de la primera capa son 4?\n","- ¿Por qué los de la segunda son 3?\n","\n"],"metadata":{"id":"jiTLbP5frtxu"}},{"cell_type":"markdown","metadata":{"id":"UPX46ZjnRhrO"},"source":["### Construir el modelo\n","\n","**Se pide:** definir un modelo completamente conectado, que en su capa oculta tenga 32 neuronas, y su capa de salida 10 (una para cada dígito). La capa oculta utilizará un función sigmoide, mientras que la capa de salida debe utilizar como activación la función softmax. Mostrar el resumen para el modelo dado. Cree el modelo utilizando una lista de capas y muestre el resultado"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"_RM4dlp6ICfR"},"outputs":[],"source":["from keras.models import Sequential\n","from keras.layers import Dense\n","\n","######################################## COMPLETAR SEGÚN LO PEDIDO ##################################################\n","\n","##########################################################################################\n"]},{"cell_type":"markdown","metadata":{"id":"btUKsMw_ICfS"},"source":["### Compilar el modelo\n","Luego que el modelo es definido, antes de pasar al entrenamiento, se necesita configurar algunas cosas más, que se agregan durante el paso de compilación:\n"," - *loss function*: función de error a minimizar. Usualmente nos referimos a ella como _loss_ o _pérdida_\n"," - *optimizer*: algoritmo utilizado para optimizar la función. Esto es, qué algoritmo de descenso por gradiente utilizar. Debe ser un objeto del módulo [optimizers](https://keras.io/optimizers), instanciado con los parámetros deseados, o un string indicando cuál utilizar, en cuyo caso se utilizan los valores por defecto.\n"," - *metrics*: métricas a ser usadas para monitorear la evolución del entrenamiento. En este ejemplo, se utiliza el acierto (accuracy)\n","\n","```python\n","from keras.optimizers import SGD\n","model.compile(optimizer=SGD(lr=0.000001),\n"," loss='sparse_categorical_crossentropy',\n"," metrics=['accuracy'])\n","```\n","**Se pide:** Compilar el modelo con la función [compile](https://keras.io/models/sequential/#compile), utilizando como optimizador una instancia de SGD, que tenga *learning rate* (`lr=0.01`), y los demás parámetros como en el ejemplo dado."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"G3662_eBICfS"},"outputs":[],"source":["from keras.optimizers import SGD\n","\n","######################################## COMPLETAR SEGÚN LO PEDIDO ##################################################\n","\n","\n","##########################################################################################\n","\n"]},{"cell_type":"markdown","metadata":{"id":"mkFkziVaICfS"},"source":["### Entrenar el modelo\n","Este paso es en el que efectivamente se entrena la red. Se deben indicar algunos parámetros más, como los ejemplos de entrenamiento y validación, la cantidad de épocas y el tamaño del batch. Todo esto se hace con la función [fit](https://keras.io/api/models/model_training_apis/#fit-method).\n","\n","- Epoch = una pasada hacia adelante y una pasada hacia atrás de todos los ejemplos de entrenamiento\n","- Batch Size = el número de ejemplos de entrenamiento en una pasada forward/backward.\n","- Iteración = una iteración realiza una pasada forward/backward de “Batch Size” número de ejemplos.\n","\n","Ejemplo: si tiene 1000 ejemplos de entrenamiento y el tamaño del batch es 500, se necesitarán 2 iteraciones para completar 1 época.\n","\n","El término \"Batch\" es ambiguo: algunas personas lo usan para designar el conjunto de entrenamiento completo, y algunas personas lo usan para referirse a la cantidad de ejemplos de entrenamiento en una pasada forward/backward. Para evitar esa ambigüedad y dejar en claro que el Batch corresponde al número de ejemplos de entrenamiento en una pasada forward/backward, se puede usar el término mini Batch.\n","\n","**Se pide**: entrenar el modelo con un batch_size de 32, durante 10 épocas. Utilice los datos de validación para ver la evolución de la accuracy."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"KT09fcbrICfT","scrolled":true},"outputs":[],"source":["######################################## COMPLETAR SEGÚN LO PEDIDO ##################################################\n","\n","\n","##########################################################################################\n"]},{"cell_type":"markdown","metadata":{"id":"rmzb4svwICfT"},"source":["### Preguntas a contestar\n","- En nuestro entrenamiento: ¿Cuántas iteraciones tendremos por época?\n","- ¿En cada época se usan los mismos ejemplos de entrenamiento? ¿Por qué será?\n","\n","____________________________________________________________________________________\n","\n","Durante el entrenamiento, se muestra el progreso en salida estándar. Una vez terminado, es importante visualizar cómo evolucionó el modelo durante el entrenamiento. El comportamiento de las distintas métricas durante el entrenamiento arrojan pistas sobre qué está pasando.\n","\n","En model.history queda el registro histórico de qué sucedió con la `accuracy` y `loss` durante el entrenamiento para ambos conjuntos."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"py5STm4GICfT"},"outputs":[],"source":["def plot_history(history):\n"," # Plot training & validation accuracy values\n"," plt.plot(history.history['accuracy'])\n"," plt.plot(history.history['val_accuracy'])\n"," plt.title('Model accuracy')\n"," plt.ylabel('Accuracy')\n"," plt.xlabel('Epoch')\n"," plt.legend(['Train', 'Validation'], loc='upper left')\n"," plt.show()\n","\n"," # Plot training & validation loss values\n"," plt.plot(history.history['loss'])\n"," plt.plot(history.history['val_loss'])\n"," plt.title('Model loss')\n"," plt.ylabel('Loss')\n"," plt.xlabel('Epoch')\n"," plt.legend(['Train', 'Validation'], loc='upper left')\n"," plt.show()\n"," plt.clf()\n","\n","# Invocamos a la función plot_history para ver cómo se comportó\n","plot_history(model.history)"]},{"cell_type":"markdown","metadata":{"id":"M_o-ohsrICfU"},"source":["### Pregunta a contestar\n","¿Qué conclusiones sacamos de nuestro primer modelo elegido? ¿Está aprendiendo?\n","\n","### Predecir\n","Una vez que tenemos el modelo entrenado, es interesante hacer predicciones sobre distintas instancias. Para esto se cuenta con el método `predict`. Este método nos devuelve una matriz de dimenciones (n_samples, n_classes), donde cada fila contiene el valor de la función softmax para cada instancia clasificada."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"YnEXZ4DRICfU"},"outputs":[],"source":["predictions = model.predict(x_val)\n","predictions.shape\n"]},{"cell_type":"markdown","metadata":{"id":"mSvHAkzCICfV"},"source":["El siguiente vector contiene la predicción para el primer ejemplo de evaluación. El valor de cada entrada se puede interpretar como una probabilidad, y cada entrada de este vector contiene la probabilidad de que el ejemplo pertenezca a la respectiva clase."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"J2lVg1e3ICfV"},"outputs":[],"source":["predictions[0]"]},{"cell_type":"markdown","metadata":{"id":"aR-fX45nICfV"},"source":["Utilizando la función de numpy np.argmax podemos obtener, para cada instancia, cuál es la clase que tiene mayor probabilidad, y utilizar esta clase como nuestra predicción"]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"SNWNU4ksICfW","outputId":"70662445-3a93-4f19-a104-d110557775bd"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["array([3, 6, 6, ..., 7, 6, 5])"]},"metadata":{},"execution_count":19}],"source":["y_val_pred = np.argmax(predictions, axis=1)\n","y_val_pred"]},{"cell_type":"markdown","metadata":{"id":"SyrC1aycijlB"},"source":["**Se pide**: imprimir imagen del primer ejemplo de x_val y valor de predicción de nuestro modelo para dicha imagen. ¿El modelo funcionó bien?"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"FXIbw1qgilfB"},"outputs":[],"source":["######################################## COMPLETAR SEGÚN LO PEDIDO ##################################################\n","\n","\n","##########################################################################################\n"]},{"cell_type":"markdown","metadata":{"id":"f8IpGbuzICfW"},"source":["Una vez que tenemos las predicciones hechas por la red, y sus valores reales, se puede utilizar cualquier métrica del módulo [sklearn.metrics](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.metrics) que hemos usado antes:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ROWgYuY3ICfW"},"outputs":[],"source":["from sklearn.metrics import classification_report\n","print(classification_report(y_val, y_val_pred))"]},{"cell_type":"markdown","metadata":{"id":"cgJ9CCwlT3te"},"source":["En este punto se espera que tengan un manejo mínimo de keras como para entrenar un modelo. En los próximos pasos, el objetivo es entender qué efecto tiene cada parámetro."]},{"cell_type":"markdown","metadata":{"id":"Bp94PxTIICfX"},"source":["#### Learning Rate\n","\n","**Se pide**: Implementar un modelo igual al anterior, pero cambiando la función de activación a relu. Entrenarlo durante 10 épocas, con `lr=2`, `lr=.01` y `lr=1e-6`. En cada caso graficar la evolución del error durante el entrenamiento. ¿Qué diferencias se observan? ¿A qué se atribuye? ¿Cuál funciona mejor?"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"FnSutilsICfY","scrolled":true},"outputs":[],"source":["for lr in [2,.01,1e-6]:\n"," print('Probamos lr={}'.format(lr))\n"," # DEFINIR EL MODELO\n","\n","\n"," # COMPILARLO CON EL LR ADECUADO\n","\n"," # ENTRENAR\n","\n"," # MOSTRAR HISTÓRICO DE ENTRENAMIENTO\n"]},{"cell_type":"markdown","metadata":{"id":"HOBscIy2ICfa"},"source":["### Regularización\n","\n","En la siguiente sección, vamos a robustecer al modelo, utilizando regularización L2 en su capa oculta. Esto es, dada la función de costo que estamos minimizando:\n","$$L(W) = \\sum_{i=1}^{n} L_i(W) $$\n","agregar una penalizacion a los pesos\n","$$L(W) = \\sum_{i=1}^{n} L_i(W)+ \\lambda \\frac{1}{2} |W|^{2}_{2}$$\n","\n","Se encuentra [implementado en keras](https://keras.io/regularizers/) en el modulo `regularizers`, y hay que pasarlo como parametro al crear la capa oculta que se desea regularizar:\n","\n","```python\n","from keras import regularizers\n","model.add(Dense(64, input_dim=64, activation=\"sigmoid\",\n"," kernel_regularizer=regularizers.l2(0.01)))\n","```\n","\n","El único parámetro que recibe es el $\\lambda$, que indica cuanto peso tiene la regularización.\n","\n","**Se pide**: Entrenar el modelo con el learning rate seleccionado el paso anterior, utilizando $\\lambda = 1$ y $\\lambda=1e-3$. En ambos casos, graficar la evolución del error.\n","¿Qué diferencias se observan? ¿A qué se atribuye? ¿Cuál funciona mejor?"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"MQshWXu8ICfb"},"outputs":[],"source":["from keras import regularizers\n","\n","for l in [1,1e-3]:\n"," print('Probamos l={}'.format(l))\n"," # DEFINIR EL MODELO\n","\n","\n","\n"," # COMPILAR EL MODELO\n","\n","\n"," # ENTRENAR EL MODELO\n","\n"," # MOSTRAR HISTÓRICO DE ENTRENAMIENTO\n"]},{"cell_type":"markdown","metadata":{"id":"C4Jvn77fICfc"},"source":["### Más capas, menos neuronas...\n","\n","Implementar un modelo similar al anterior, pero que en vez de tener una única capa oculta con 32 neuronas, contenga 3 capas ocultas con 5 neuronas cada una.\n","\n","Compilarlo, y entrenarlo con la misma configuración usada en pasos anteriores (utilice sigmoid en la primera capa oculta, y relu en las restantes). Mostrar cómo cambió su desempeño durante el entrenamiento. Mostrar el resumen del modelo con `model.summary()`"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"6Q8_UnLbICfc"},"outputs":[],"source":["\n","\n","# DEFINIR EL MODELO Y MOSTRAR EL RESUMEN\n","\n","\n","\n","# COMPILAR EL MODELO\n","\n","\n","# ENTRENAR EL MODELO\n","\n","# MOSTRAR HISTÓRICO DE ENTRENAMIENTO\n"]},{"cell_type":"markdown","metadata":{"id":"cVqvdQ7TICfc"},"source":["### Batch normalization\n","\n","A continuación, vamos a aplicar batch normalization (una forma de regularización) al modelo anterior.\n","\n","Batch normalization debe ser aplicado inmediatamente **después** de computar las preactivacion, pero **antes** de aplicar la función de activación. Sin embargo, en los ejemplos vistos, ambas operaciones la ejecuta la misma capa:\n","\n","```python\n","model.add(Dense(64, input_dim=64, activation=\"sigmoid\",\n"," kernel_regularizer=regularizers.l2(0.01)))\n","```\n","\n","Para aplicar batch normalization, se debe utilizar una funcion de activacion lineal en la capa densa, luego agregar la capa de batch normalization, y por ultimo agregar explicitamente la capa de activacion que querramos usar. El ejemplo anterior, se reescribe como sigue:\n","\n","```python\n","from keras.layers import Activation\n","from keras.layers.normalization import BatchNormalization\n","\n","model.add(Dense(64, input_dim=64, # no especificar activacion!\n"," kernel_regularizer=regularizers.l2(0.01)))\n","model.add(BatchNormalization())\n","model.add(Activation('sigmoid'))\n","\n","```\n","\n","**Opcional: se pide:** Entrenar nuevamente el modelo, esta vez agregando batch normalization a cada capa. Mostrar el desarrollo del entrenamiento y el resumen del modelo. ¿Qué se puede decir de este modelo en comparación con el anterior? ¿y con los anteriores a este? (1 capa oculta de 32 neuronas)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"QmIo70i-ICfd"},"outputs":[],"source":["from keras.layers import Activation\n","from keras.layers import BatchNormalization\n","\n","# DEFINIR EL MODELO Y MOSTRAR RESUMEN\n","\n","\n","\n","\n","# COMPILAR EL MODELO\n","\n","# ENTRENAR EL MODELO\n","\n","# MOSTRAR ENTRENAMIENTO\n"]},{"cell_type":"markdown","metadata":{"id":"hW127359ICfd"},"source":["**OPCIONAL: Se pide:** Repetir el experimento anterior, cambiando la función de activación a sigmoid, pero utilizar como algoritmo de descenso por gradiente Rmsprop, con sus parámetros por defecto.\n","\n","Comparar resultados con el escenario anterior."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Lb-5IbtJICfd"},"outputs":[],"source":["from keras.optimizers import RMSprop\n","\n","\n","# DEFINIR EL MODELO\n","\n","\n","# COMPILAR EL MODELO\n","\n","# ENTRENAR EL MODELO\n","\n","# MOSTRAR HISTÓRICO DE ENTRENAMIENTO\n"]},{"cell_type":"markdown","metadata":{"id":"tX_pJu1sICfe"},"source":["**Dropout** Dropout es una capa muy sencilla de utilizar. Simplemente se agrega luego de la capa de activación como una capa más, indicanto la proporción de neuronas que se desean eliminar:\n","\n","```python\n","from keras.layers import Dropout\n","\n","model.add(Dropout(.2)) # 20%\n","\n","```\n","\n","**Early stopping** Keras permite definir diferentes [_callbacks_](https://keras.io/callbacks/). Esto son funciones auxiliares que se ejecutan durante el entrenamiento, al terminar un batch o una epoca. Esto es muy util para monitorear el entrenamiento, y entre otras cosas implementa EarlyStopping.\n","\n","Se debe definir una lista con los callbacks a ser ejecutados, y luego se pasa esta lista al metodo fit.\n","\n","```python\n","from keras.callbacks import EarlyStopping\n","ea = EarlyStopping(monitor='val_loss',\n"," patience=2,\n"," restore_best_weights=True)\n","\n","cb_list = [ea] # lista de callbacks\n","\n","model.fit(x_train, y_train,\n"," validation_data=[x_val, y_val],\n"," epochs=10, batch_size=32, callbacks=cb_list);\n","\n","```\n","\n","**OPCIONAL: Se pide**:\n","Probar los métodos de DropOut y Eary Stopping. Luego, Utilizando las herramientas vistas hasta el momento, entrenar el mejor modelo posible, que tenga 2 capas ocultas."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"u0P_XKxaICff","scrolled":true},"outputs":[],"source":["from keras.layers import Dropout\n","from keras.callbacks import EarlyStopping\n","\n","ea = EarlyStopping(monitor='val_loss', patience=2, restore_best_weights=True)\n","cb_list = [ea] # lista de callbacks\n","\n","lr = .01\n","\n","# DEFINIR EL MODELO\n","\n","\n","# COMPILAR EL MODELO\n","\n","# ENTRENAR EL MODELO\n","\n","# MOSTRAR LA HISTORIA DE APRENDIZAJE\n","\n"]},{"cell_type":"markdown","metadata":{"id":"qHCxMZQKICff"},"source":["Reportar la performance del mejor modelo encontrado sobre el conjunto de test."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ZH2MiyP-ICff"},"outputs":[],"source":["# De todos los modelos que hice, entreno sobre el conjunto de entrenamiento el mejor\n","# Que fue el original, con lr = 0.001\n","\n","# DEFINIR EL MODELO\n","\n","\n","# COMPILAR EL MODELO\n","\n","\n","# ENTRENAR EL MODELO\n","\n","# MOSTRAR HISTÓRICO DE ENTRENAMIENTO\n","\n","# Hacer las predicciones y mostrar el reporte sobre conjunto de test\n","\n"]}],"metadata":{"colab":{"provenance":[],"gpuType":"T4"},"kernelspec":{"display_name":"Python 3","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.6"},"accelerator":"GPU"},"nbformat":4,"nbformat_minor":0}