{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<div style=\"width: 100%; clear: both;\">\n<div style=\"float: left; width: 50%;\">\n<img src=\"http://www.uoc.edu/portal/_resources/common/imatges/marca_UOC/UOC_Masterbrand.jpg\", align=\"left\">\n</div>\n<div style=\"float: right; width: 50%;\">\n<p style=\"margin: 0; padding-top: 22px; text-align:right;\">M2.875 · Deep Learning · Práctica</p>\n<p style=\"margin: 0; text-align:right;\">2020-2 · Máster Universitario en Ciencia de Datos (MUDS)</p>\n<p style=\"margin: 0; text-align:right; padding-button: 100px;\">Estudios de Informática, Multimedia y Telecomunicación</p>\n<p style=\"margin: 0; text-align:right; padding-button: 100px;\">Iñaki Galech Amillano-MSDS 2020/21 <a href=\"mailto:igalech@uoc.edu\">igalech@uoc.edu</a></p>\n</div>\n</div>\n<div style=\"width:100%;\">&nbsp;</div>","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-05-21T23:50:30.481272Z","iopub.execute_input":"2021-05-21T23:50:30.481872Z","iopub.status.idle":"2021-05-21T23:50:36.90064Z","shell.execute_reply.started":"2021-05-21T23:50:30.481758Z","shell.execute_reply":"2021-05-21T23:50:36.899794Z"}}},{"cell_type":"markdown","source":"Este notebook no forma parte de la entrega final de la práctica 1, si bien se ha utilizado para determinar qué modelos pudieran ser los más adecuados para resolver el <u>problema o desafío **original** de Kaggle</u>.","metadata":{}},{"cell_type":"markdown","source":"<div style=\"background-color: #EDF7FF; border-color: #7C9DBF; border-left: 5px solid #7C9DBF; padding: 0.5em;\">\n<strong>Nombre y apellidos:</strong> Iñaki Galech Amillano - MSDS 2020/21  <a href=\"mailto:igalech@uoc.edu\">igalech@uoc.edu</a>\n</div>","metadata":{}},{"cell_type":"code","source":"# %pylab inline\nimport cv2\nimport glob\nimport os\nimport matplotlib.pylab as plt\nimport seaborn as sns\nimport pandas as pd\nimport numpy as np\nimport os\nimport tensorflow as tf\nimport keras\nimport keras_preprocessing\nfrom sklearn.model_selection import train_test_split\nfrom tqdm.notebook import tqdm\nimport tensorflow_addons as tfa\nimport albumentations\nimport shutil","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-06-04T23:13:25.874415Z","iopub.execute_input":"2021-06-04T23:13:25.874755Z","iopub.status.idle":"2021-06-04T23:13:32.432173Z","shell.execute_reply.started":"2021-06-04T23:13:25.874681Z","shell.execute_reply":"2021-06-04T23:13:32.431356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Cargamos los datos 'originales' del problema en Kaggle.","metadata":{}},{"cell_type":"code","source":"p_train = pd.read_csv('/kaggle/input/plant-pathology-2021-fgvc8/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:13:36.705422Z","iopub.execute_input":"2021-06-04T23:13:36.705794Z","iopub.status.idle":"2021-06-04T23:13:36.743184Z","shell.execute_reply.started":"2021-06-04T23:13:36.705759Z","shell.execute_reply":"2021-06-04T23:13:36.742428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"En primer lugar mostramos las etiquetas iniciales en número mediante un gráfico.","metadata":{}},{"cell_type":"code","source":"# Gráfico inicial del conteo de etiquetas\nplt.figure(figsize=(10,8))\nlabels = sns.barplot(x=p_train.labels.value_counts().index, y=p_train.labels.value_counts());\n# Labels, incluidos multilables\nfor item in labels.get_xticklabels():\n    item.set_rotation(90);\n\n# Para imprimir los valores por columnas\nfor i, v in enumerate(p_train.labels.value_counts()):\n    #print (i, v)\n    labels.text(i-0.25, v , str(v), color='darkblue', fontsize=10, fontweight='bold')\nplt.title('Número de imágenes por clase', fontsize =14, color = 'darkblue');","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:13:39.135186Z","iopub.execute_input":"2021-06-04T23:13:39.135531Z","iopub.status.idle":"2021-06-04T23:13:39.426767Z","shell.execute_reply.started":"2021-06-04T23:13:39.135498Z","shell.execute_reply":"2021-06-04T23:13:39.425820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Debido a la sobreimposición de etiquetas no es posible distinguir multietiquetas en algunos casos. Para resolver este problema separamos las multietiquetas aplicando un `string.split()` a cada instancia.","metadata":{}},{"cell_type":"code","source":"p_train['labels'] = p_train['labels'].apply(lambda string: string.split(' '))","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:13:42.713396Z","iopub.execute_input":"2021-06-04T23:13:42.713767Z","iopub.status.idle":"2021-06-04T23:13:42.728928Z","shell.execute_reply.started":"2021-06-04T23:13:42.713738Z","shell.execute_reply":"2021-06-04T23:13:42.728134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A partir de aquí, podemos encodificar las etiquetas de cada imagen con un [MultiLabelBinarizer](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MultiLabelBinarizer.html) de Sklearn","metadata":{}},{"cell_type":"code","source":"from sklearn.preprocessing import MultiLabelBinarizer\n\n# Convertimos el array a una lista\ns = list(p_train['labels'])\nmlb = MultiLabelBinarizer()\n# Construimos un dataframe con el resultado de aplicar el MLB con las nuevas clases como columnas con el mismo índice que p_train.\ntrainx = pd.DataFrame(mlb.fit_transform(s), columns=mlb.classes_, index=p_train.index)\nlistadoetiquetas = list(mlb.classes_)","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:13:45.084555Z","iopub.execute_input":"2021-06-04T23:13:45.084890Z","iopub.status.idle":"2021-06-04T23:13:45.112488Z","shell.execute_reply.started":"2021-06-04T23:13:45.084862Z","shell.execute_reply":"2021-06-04T23:13:45.111567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Juntamos imágenes y nuevas etiquetas y mostramos unos cuantos registros.","metadata":{}},{"cell_type":"code","source":"labels = pd.concat([p_train['image'], trainx], axis=1)\n# Mostramos cómo quedan tras la binarización.\nlabels.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:13:47.573741Z","iopub.execute_input":"2021-06-04T23:13:47.574053Z","iopub.status.idle":"2021-06-04T23:13:47.593007Z","shell.execute_reply.started":"2021-06-04T23:13:47.574025Z","shell.execute_reply":"2021-06-04T23:13:47.592244Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Graficamos de nuevo por clases","metadata":{}},{"cell_type":"code","source":"# Nueva gráfica una vez tenemos agrupadas las labels en MultiLabels para cada imagen.\nlabelslista = list(trainx.sum().keys())\nlabel_counts = trainx.sum().values.tolist()\n\nfig, ax = plt.subplots(1,1, figsize=(10,6))\n\nsns.barplot(x= labelslista, y= label_counts, ax=ax)\n\nfor i,j in enumerate(label_counts):\n    ax.text(i-0.15, j, str(j), color='darkblue', fontsize=10, fontweight='bold');\n\nplt.title('Núevo Total de imágenes de cada clase', fontsize =14, color = 'darkblue');","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:13:55.415787Z","iopub.execute_input":"2021-06-04T23:13:55.416104Z","iopub.status.idle":"2021-06-04T23:13:55.563064Z","shell.execute_reply.started":"2021-06-04T23:13:55.416075Z","shell.execute_reply":"2021-06-04T23:13:55.562128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A continuación se muestran las cifras anteriores en cuanto a sus frecuencias relativas.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(6,6))\nplt.title(\"Frecuencias relativas en % para las clases (labels)\", fontsize = 14, color = 'darkblue')\n#labels = list(trainx.sum().keys())\n#label_counts = trainx.sum().values.tolist()\n#sorted_counts = round(p_train['labels'].value_counts()/len(p_train['labels'])*100,2)\n\nsorted_counts = list(np.round(np.array(label_counts)/sum(label_counts),2))\nplt.pie(sorted_counts, labels = labelslista, startangle = 30,\n        counterclock = False, autopct='%.2f%%', textprops={'fontsize':'14'}, normalize=False)\n#plt.axis('square')\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:13:58.294875Z","iopub.execute_input":"2021-06-04T23:13:58.295220Z","iopub.status.idle":"2021-06-04T23:13:58.421280Z","shell.execute_reply.started":"2021-06-04T23:13:58.295182Z","shell.execute_reply":"2021-06-04T23:13:58.420324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Pasamos a mostrar cinco imágenes de cada clase. En este caso mostramos cada clase incluidas las 'multiclase'. Es decir, si una imágen tiene más de una clase asociada la mostramos cinco veces, independientemente de si la clase individual se muestra por separado con otras cinco imágenes. La idea es mostrar cómo de cercanas o diferentes (visualmente) son las imágenes asignadas con multietiquetas respecto a aquéllas imágenes con una sola etiqueta.","metadata":{}},{"cell_type":"code","source":"from PIL import Image\npathimagenes = '../input/plant-pathology-2021-fgvc8/train_images/'\nindices = []\nimagenes = []\netiquetas = []\n\nwhile len(etiquetas) < len(labelslista):\n    for i, j in zip(p_train['image'],p_train['labels']):\n        if len([x for x in etiquetas if x==j]) < 5:\n            #if ((j in etiquetas)==False):\n            img = cv2.imread(pathimagenes + i, 1)\n            imagenes.append(img)\n            etiquetas.append(j)\n\nfig = plt.figure(figsize=(24, 24))\nfig.suptitle(\"5 imágenes de cada clase (label)\", fontsize = 14);\nfor i in range(len(imagenes)):\n    ax = plt.subplot(10, 10, i+1)\n    plt.imshow(imagenes[i])\n    plt.title(etiquetas[i], fontsize = 8)\n    plt.axis(\"off\")\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:14:02.087688Z","iopub.execute_input":"2021-06-04T23:14:02.087996Z","iopub.status.idle":"2021-06-04T23:14:41.433356Z","shell.execute_reply.started":"2021-06-04T23:14:02.087968Z","shell.execute_reply":"2021-06-04T23:14:41.432445Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Juntamos en un dataframe las imágenes con las nuevas etiquetas. Como vemos ahora tenemos un problema multiclase-multilabel. Este problema es algo diferente al de nuestra práctica, pero sin embargo los modelos nos proporcionarán información valiosa sobre qué modelos y en qué circunstancias se acoplan mejor a resolver nuestro problema.","metadata":{}},{"cell_type":"code","source":"labels2 = labels.drop(columns = 'image', axis =1)\ndf_entreno = pd.concat([p_train, labels2], axis=1)\n#df_entreno.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:14:47.236761Z","iopub.execute_input":"2021-06-04T23:14:47.237071Z","iopub.status.idle":"2021-06-04T23:14:47.243281Z","shell.execute_reply.started":"2021-06-04T23:14:47.237045Z","shell.execute_reply":"2021-06-04T23:14:47.242466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Así es cómo quedan ahora.\ndf_entreno.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:14:49.463115Z","iopub.execute_input":"2021-06-04T23:14:49.464619Z","iopub.status.idle":"2021-06-04T23:14:49.486814Z","shell.execute_reply.started":"2021-06-04T23:14:49.464570Z","shell.execute_reply":"2021-06-04T23:14:49.482893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Para la estrategia de test y validación se subdivide el conjunto de entrenamiento mediante un generador de imágenes a partir del directorio Keras donde está alojadas las imágenes. Como veremos hemos empleado dos directorios. Por un lado se comenzaron los tests con el directorio de Kaggle.com `../kaggle/input/plant-pathology-2021-fgvc8/train_images/` donde se encuentran las imagenes originales. Aumentar las imágenes originales lleva asociado un coste computacional significativo dado el número y tamaño de las imágenes. Para agilizar los tests Kaggle dispone de colaboradores que ya han reducido el tamaño de las imagenes originales a diversos tamaños (256x256, 512x512, etc.) y nos podemos beneficiar de un proceso ya establecido, simplemente haciendo referencia a su autor, Ankur Singh en [resized-plant2021](https://www.kaggle.com/ankursingh12/resized-plant2021) el cual podemos simplemente añadir en Kaggle con `+Add data` en la esquina superior derecha de la plataforma.\n\nDe esta forma construimos nuestos juegos de entrenamiento y validación a partir de estos conjuntos ya disminuidos (rescaled) en tamaño, lo cual facilita el entrenamiento muy considerablemente. Si tomamos las imágenes originales los modelos que probamos más adelante (ResNet50, EfficientNet, etc.) tardan del orden de 40 minutos por epoch, mientras que con el tamaño reducido cada epoch tarda 5 o 6 minutos (con GPUs). Dado que el número de horas gratuitas es limitado se opta por las pruebas con tamaños 256x256 con un split o división al 80-20 entre entrenamiento y validación. Este parámetro lo establecemos al construir los generadores de datasets de Keras `ImageDataGenerator()` donde establecemos, además de otros parámetros, la división train-validación (80/20) como vemos `validation_split = 0.2`","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator,load_img\n\ntrain_datagen = keras.preprocessing.image.ImageDataGenerator(\n    rescale = 1/255.,\n    rotation_range=20,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    horizontal_flip=True,\n    validation_split = 0.2,\n    zoom_range = 0.2,\n    shear_range = 0.2,\n    vertical_flip = False)\n\ntest_datagen = keras.preprocessing.image.ImageDataGenerator(\n    rescale = 1/255.,\n    rotation_range=20,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    horizontal_flip=True,\n    validation_split = 0.2,\n    zoom_range = 0.2,\n    shear_range = 0.2,\n    vertical_flip = False)","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:14:53.057981Z","iopub.execute_input":"2021-06-04T23:14:53.058292Z","iopub.status.idle":"2021-06-04T23:14:53.064157Z","shell.execute_reply.started":"2021-06-04T23:14:53.058264Z","shell.execute_reply":"2021-06-04T23:14:53.063354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<u>Estrategia de aumento de datos</u>  \nEn este punto hay que considerar de forma combinada los resultados obtenidos en cuanto a la binarización de las multilabels y también el tamaño y calidad de las imágenes. Por el enunciado sabemos que tenemos aproximadadmente 23000 imágenes en alta resolución en formato RGB, las cuales además según se indica incluyen: diferentes iluminaciones, diferentes contextos y fondo de la imagen, obtenidas en diferentes estaciones y horas del día y a diferentes niveles de maduración de las manzanas. Además las cámaras que han tomado las fotografías son de muy diversa índole (no es la misma cámara ni son del mismo tipo). En resumen, imágenes muy grandes con una gran resolución pero nada uniformes en cuanto a sus parámetros.\nEl objetivo por tanto es hacer uso en lo posible de una estandarización de tamaño que sea computacionalmente razonable reduciendo en la medida de lo posible el tamaño de la imagen, pero al mismo tiempo manteniendo la no uniformidad en la posición y contexto de las fotografías para forzar a nuestros modelos a aprender condiciones muy variadas que son las que realmente se dan en el mundo agrícola.\nEs también importante resaltar que el objetivo es categorizar imágenes con enfermedades, es decir, teniendo en cuenta que una imagen (una hoja) puede presentar varias enfermedades el objetivo es categorizarla con *al menos* una enfermedad. El motivo es que si el agricultor sabe que un determinado árbol tiene una enfermedad irá a inspeccionarlo y de esta forma podrá determinar 'in-situ' si además presenta otro tipo de patología además de la indicada por nuestro modelo.\n\nDel enunciado de la competición: \"The main objective of the competition is to develop machine learning-based models to accurately classify a given leaf image from the test dataset to a particular disease category, and to identify an individual disease from multiple disease symptoms on a single leaf image.\" ","metadata":{}},{"cell_type":"markdown","source":"Con lo comentado se opta por elegir imágenes reducidas a 256x256 en tres canales RGB y sobre las cuales se emplearán técnicas de aumentado de datos (data augmentation). Para ello se usa de nuevo la librería de imágenes de Keras (images) dónde a nuestro generador de imágenes obligamos a realizar: rotaciones, ensanchado y estirado, volteos horizontales, zoom  y desenfoque (shear) con los parámetros que se muetran a continuación. Esto producirá imagenes ","metadata":{}},{"cell_type":"markdown","source":"<u>Tipo de modelo y tamaño de imagen de entrada</u>  \nPor lo expuesto anteriormente se entrenan tres modelos ya paraemtrizados y entrenados: ResNet50, EfficientNetB0, y . Los modelos elegidos están especialmente contrastados en problemas multietiquetas como nuestro caso. ","metadata":{}},{"cell_type":"code","source":"labelslista = list([str(i) for i in labelslista])\n#columns=[\"desert\", \"mountains\", \"sea\", \"sunset\", \"trees\"]","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:14:56.645596Z","iopub.execute_input":"2021-06-04T23:14:56.645916Z","iopub.status.idle":"2021-06-04T23:14:56.650150Z","shell.execute_reply.started":"2021-06-04T23:14:56.645886Z","shell.execute_reply":"2021-06-04T23:14:56.648994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_entreno2 = df_entreno.drop(['labels'], axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:15:00.375643Z","iopub.execute_input":"2021-06-04T23:15:00.375969Z","iopub.status.idle":"2021-06-04T23:15:00.381241Z","shell.execute_reply.started":"2021-06-04T23:15:00.375938Z","shell.execute_reply":"2021-06-04T23:15:00.380277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator,load_img\n\ntrain_data = train_datagen.flow_from_dataframe(\n    df_entreno2,\n    directory= '/kaggle/input/resized-plant2021/img_sz_256/', # originales en 'plant-pathology-2021-fgvc8/train_images/'\n    x_col = \"image\",\n    y_col=  labelslista,\n    color_mode=\"rgb\",\n    #target_size = (256,256),\n    #class_mode=\"categorical\",\n    batch_size=58,\n    subset = \"training\",\n    shuffle=True,\n    seed=27,\n    class_mode='raw'\n)\n\nvalidacion_data = train_datagen.flow_from_dataframe(\n    df_entreno2,\n    directory= '/kaggle/input/resized-plant2021/img_sz_256/', # originales en 'plant-pathology-2021-fgvc8/train_images/'\n    x_col = \"image\",\n    y_col=  labelslista,\n    color_mode=\"rgb\",\n    #target_size = (256,256),\n    #class_mode=\"categorical\",\n    batch_size=54,\n    subset = \"validation\",\n    shuffle=True,\n    seed=27,\n    class_mode='raw'\n)\n\n# Este último set no implementa shuffle (shuffle=False) y se usará para las \n# predicciones y así poder comparar las clases de las predicciones vs. clases \n# verdaderas.\nset_validacion_ordenado = train_datagen.flow_from_dataframe(\n    df_entreno,\n    directory = '/kaggle/input/resized-plant2021/img_sz_256/',\n    x_col=\"image\",\n    y_col = labelslista,\n    #target_size=(256, 256),\n    color_mode=\"rgb\",\n    #class_mode=\"categorical\",\n    batch_size=54,\n    shuffle=False,\n    seed=27,\n    subset='validation',\n    interpolation=\"nearest\",\n    class_mode='raw'\n)\n\nset_test = test_datagen.flow_from_directory(\n    directory = '/kaggle/input/plant-pathology-2021-fgvc8/',\n    batch_size=1,\n    # No tenemos y_col porque son las que tenemos que predecir\n    target_size=(256, 256),\n    classes = ['test_images'],\n    color_mode=\"rgb\",\n    class_mode=None,\n    shuffle=False,\n    seed=27,\n#    interpolation=\"nearest\",\n)","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:15:02.438379Z","iopub.execute_input":"2021-06-04T23:15:02.438752Z","iopub.status.idle":"2021-06-04T23:15:55.521808Z","shell.execute_reply.started":"2021-06-04T23:15:02.438722Z","shell.execute_reply":"2021-06-04T23:15:55.520856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <u>Construcción y entrenamiento de 6 modelos</u>:\n    1.-Resnet50v2\n    2.-InceptionV3\n    3.-EfficientNetB0\n    4.-Resnet50\n    5.-InceptionResNetV2\n    6.-DenseNet121","metadata":{}},{"cell_type":"markdown","source":"### <u>Modelo ResNet50V2:</u>","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.layers import Input, Lambda, Dense, Flatten\nfrom tensorflow.keras.models import Model\n#from tensorflow.keras.applications.inception_resnet_v2 import InceptionResNetV2\n#from tensorflow.keras.applications.inception_resnet_v2 import preprocess_input\nfrom tensorflow.keras.applications.resnet_v2 import ResNet50V2\nfrom tensorflow.keras.applications.resnet_v2 import preprocess_input\nfrom tensorflow.keras.models import Sequential\n\ndef create_model():\n    \n    pretrained = ResNet50V2(include_top=False, weights='imagenet',input_shape=[256,256, 3])\n    # pretrained = InceptionResNetV2(include_top=False, weights='imagenet',input_shape=[256, 256, 3])\n            \n    x = pretrained.output\n    x = tf.keras.layers.GlobalAveragePooling2D()(x)\n    #x = tf.keras.layers.Dense(64, activation='relu')(x)\n    #x = tf.keras.layers.Dense(16, activation='relu')(x)\n    # Obsérvese aquí que la activación es sigmoid\n    outputs = tf.keras.layers.Dense(len(labelslista), activation=\"sigmoid\", dtype='float32')(x)\n        \n    model = tf.keras.Model(pretrained.input, outputs, name='modeloResNetV2')\n    return model\n\nmodel = create_model()","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:15:59.898174Z","iopub.execute_input":"2021-06-04T23:15:59.898518Z","iopub.status.idle":"2021-06-04T23:16:05.357567Z","shell.execute_reply.started":"2021-06-04T23:15:59.898483Z","shell.execute_reply":"2021-06-04T23:16:05.356735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check del nombre del modelo\n#model.name","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:07:55.697229Z","iopub.execute_input":"2021-06-04T23:07:55.697603Z","iopub.status.idle":"2021-06-04T23:07:55.702517Z","shell.execute_reply.started":"2021-06-04T23:07:55.697576Z","shell.execute_reply":"2021-06-04T23:07:55.701226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Función que compilará el modelo con SGD y la learning rate como parámetro. \n# Nótese que la función de pérdida es BinaryCrossentropy porque **no** queremos excluir clases unas de otras (Multilabel). \n# También introducimos nuestra medidad como F1-score 'macro' \n\ndef compile_model(model, lr=0.03):\n    \n    #optimizer = tf.keras.optimizers.Adam(lr=lr)\n    optimizer = tf.keras.optimizers.SGD(lr=0.03, decay=1e-4, momentum=0.8, nesterov=True)\n    \n    loss = tf.keras.losses.BinaryCrossentropy()\n    \n    # tf.keras.metrics.CategoricalAccuracy(name='categorical_accuracy')\n    metrics = [\n    tfa.metrics.F1Score(num_classes = len(labelslista), average = \"macro\",name = \"f1_score\")\n    ]\n\n    model.compile(optimizer=optimizer, loss=loss, metrics=metrics)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:16:12.543897Z","iopub.execute_input":"2021-06-04T23:16:12.544234Z","iopub.status.idle":"2021-06-04T23:16:12.550151Z","shell.execute_reply.started":"2021-06-04T23:16:12.544199Z","shell.execute_reply":"2021-06-04T23:16:12.549101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Los siguientes parámetros son comunes a todos los modelos. Introducen un 'checkpoint' para guardar los mejores modelos según se van obteniendo máximos en nuestra función (f1-score en validación). También definimos un EarlyStop con 5 epochs de paciencia y un parámetro que actúa como reductor del learning rate si se producen situaciones de estancamiento ([`ReduceLROnPlateau()`](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/ReduceLROnPlateau))","metadata":{}},{"cell_type":"code","source":"METRIC = \"val_f1_score\"\n\ndef create_callbacks(metric = METRIC):\n    \n    guardar_path = './mejor_modelo_origKaggle_'+ model.name + '.h5'\n    \n    checkpoint = tf.keras.callbacks.ModelCheckpoint(\n        filepath = guardar_path,\n        monitor = metric,\n        mode ='max',\n        save_best_only=True,\n        verbose=1,\n    )\n\n    reducccionlr = tf.keras.callbacks.ReduceLROnPlateau(\n        monitor = metric,\n        mode = 'max',\n        factor = 0.1,\n        patience = 3,\n        verbose = 0\n    )\n\n    earlystop = tf.keras.callbacks.EarlyStopping(\n        monitor = metric,\n        mode ='max',\n        patience = 5, \n        verbose = 1\n    )\n    \n    callbacks = [checkpoint, reducccionlr, earlystop]         \n    \n    return callbacks","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:16:15.273884Z","iopub.execute_input":"2021-06-04T23:16:15.274222Z","iopub.status.idle":"2021-06-04T23:16:15.280389Z","shell.execute_reply.started":"2021-06-04T23:16:15.274191Z","shell.execute_reply":"2021-06-04T23:16:15.279320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS = 10\nVERBOSE = 1\n\ntf.keras.backend.clear_session()\n\nwith tf.device('/device:GPU:0'):\n    \n    model = create_model()\n    model = compile_model(model, lr=0.03)\n   \n    callbacks = create_callbacks()\n    \n    history = model.fit(\n                        train_data,\n                        epochs=EPOCHS,\n                        callbacks=callbacks,\n                        validation_data = validacion_data,\n                        verbose=VERBOSE\n                       )","metadata":{"execution":{"iopub.status.busy":"2021-06-04T23:16:18.621842Z","iopub.execute_input":"2021-06-04T23:16:18.622167Z","iopub.status.idle":"2021-06-05T00:05:01.985685Z","shell.execute_reply.started":"2021-06-04T23:16:18.622136Z","shell.execute_reply":"2021-06-05T00:05:01.984804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Guardamos los resultados de cada entrenamiento en un dataframe y a apartir de éste lo volcamos en un fichero CSV que iremos subiendo al dataset de Kaggle.com que entregamos con la práctica.","metadata":{}},{"cell_type":"code","source":"resultados = pd.DataFrame(history.history)","metadata":{"execution":{"iopub.status.busy":"2021-06-05T00:05:06.397610Z","iopub.execute_input":"2021-06-05T00:05:06.397951Z","iopub.status.idle":"2021-06-05T00:05:06.406043Z","shell.execute_reply.started":"2021-06-05T00:05:06.397920Z","shell.execute_reply":"2021-06-05T00:05:06.405229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"modeloResNetV2 = 'modeloResNetV2_history05282021Kaggle.csv'\nwith open(modeloResNetV2, mode='w') as f:\n    resultados.to_csv(f)","metadata":{"execution":{"iopub.status.busy":"2021-06-05T00:05:08.978365Z","iopub.execute_input":"2021-06-05T00:05:08.978712Z","iopub.status.idle":"2021-06-05T00:05:08.987037Z","shell.execute_reply.started":"2021-06-05T00:05:08.978681Z","shell.execute_reply":"2021-06-05T00:05:08.986198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <u>Modelo InceptionV3:</u>","metadata":{}},{"cell_type":"code","source":"try: # TPUs, si tenemos habilitado el cluster y generamos archivos tipo .tfrec\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect() # TPU detection\n    strategy = tf.distribute.TPUStrategy(tpu)\n\nexcept ValueError: # GPUs\n    strategy = tf.distribute.MirroredStrategy() # for GPU or multi-GPU machines\n    #strategy = tf.distribute.get_strategy() # una CPU y una GPU\n    #strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy() # for clusters of multi-GPU machines\n\nprint(\"Number of accelerators: \", strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2021-05-22T23:22:23.223338Z","iopub.execute_input":"2021-05-22T23:22:23.223798Z","iopub.status.idle":"2021-05-22T23:22:23.23364Z","shell.execute_reply.started":"2021-05-22T23:22:23.22376Z","shell.execute_reply":"2021-05-22T23:22:23.232542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications.inception_v3 import InceptionV3\nfrom tensorflow.keras.applications.inception_v3 import preprocess_input\n\ndef create_InceptionV3():\n    \n    pretrained = InceptionV3(include_top=False, weights='imagenet',input_shape=[256, 256, 3], pooling = 'avg')\n    x = pretrained.output\n    #x = tf.keras.layers.GlobalAveragePooling2D()(x) # No necesitamos pooling porque lo ponemos en la salida del EfficientNetB0\n    outputs = tf.keras.layers.Dense(len(validacion_data.class_indices),activation=\"sigmoid\", dtype='float32')(x)\n    model = tf.keras.Model(pretrained.input, outputs, name = 'modeloInceptionV3')\n    return model\n\nmodel = create_InceptionV3()\n\n\ndef compile_model(model, lr=0.0001):\n    \n    optimizer = tf.keras.optimizers.Adam(lr=lr)\n    \n    loss = tf.keras.losses.CategoricalCrossentropy()\n    \n    #tf.keras.metrics.CategoricalAccuracy(name='categorical_accuracy')\n    metrics = [\n    tfa.metrics.F1Score(num_classes = len(validacion_data.class_indices), average = \"macro\",name = \"f1_score\")\n    ]\n\n    model.compile(optimizer=optimizer, loss=loss, metrics=metrics)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-05-23T16:59:51.57546Z","iopub.execute_input":"2021-05-23T16:59:51.575795Z","iopub.status.idle":"2021-05-23T16:59:54.670484Z","shell.execute_reply.started":"2021-05-23T16:59:51.575765Z","shell.execute_reply":"2021-05-23T16:59:54.669696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.name","metadata":{"execution":{"iopub.status.busy":"2021-05-23T16:59:56.292123Z","iopub.execute_input":"2021-05-23T16:59:56.292434Z","iopub.status.idle":"2021-05-23T16:59:56.299479Z","shell.execute_reply.started":"2021-05-23T16:59:56.292405Z","shell.execute_reply":"2021-05-23T16:59:56.29843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS= 10\nVERBOSE =1\n\ntf.keras.backend.clear_session()\n\nwith tf.device('/device:GPU:0'):\n    \n    #model = create_model()\n    model = compile_model(model, lr=0.0001)\n   \n    callbacks = create_callbacks()\n    \n    historyIncepcionV3 = model.fit(\n                        train_data,\n                        epochs=EPOCHS,\n                        callbacks=callbacks,\n                        validation_data = validacion_data,\n                        verbose=VERBOSE\n                       )","metadata":{"execution":{"iopub.status.busy":"2021-05-23T16:59:59.206758Z","iopub.execute_input":"2021-05-23T16:59:59.20715Z","iopub.status.idle":"2021-05-23T17:54:12.768618Z","shell.execute_reply.started":"2021-05-23T16:59:59.207115Z","shell.execute_reply":"2021-05-23T17:54:12.767837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resultadosInceptionV3 = pd.DataFrame(historyIncepcionV3.history)\nmodeloInceptionV3_cvs_file = 'resultadosInceptionV3_history.csv'\nwith open(modeloInceptionV3_cvs_file, mode='w') as f:\n    resultadosInceptionV3.to_csv(f)","metadata":{"execution":{"iopub.status.busy":"2021-05-23T17:54:24.621405Z","iopub.execute_input":"2021-05-23T17:54:24.621747Z","iopub.status.idle":"2021-05-23T17:54:24.630865Z","shell.execute_reply.started":"2021-05-23T17:54:24.621713Z","shell.execute_reply":"2021-05-23T17:54:24.62986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <u>Modelo EfficientNetB0:</u>","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications.efficientnet import EfficientNetB0\nfrom tensorflow.keras.applications.efficientnet import preprocess_input\n\ndef create_EffNetB0model():\n    \n    pretrained = EfficientNetB0(include_top=False, weights='imagenet',input_shape=[256, 256, 3], pooling = 'avg')\n    x = pretrained.output\n    #x = tf.keras.layers.GlobalAveragePooling2D()(x) # No necesitamos pooling porque lo ponemos en la salida del EfficientNetB0\n    outputs = tf.keras.layers.Dense(6,activation=\"sigmoid\", dtype='float32')(x)\n    model = tf.keras.Model(pretrained.input, outputs, name = 'modeloEffNetB0')\n    return model\n\n#model = create_EffNetB0model()\n\n\ndef compile_model(model, lr=0.0001):\n    \n    optimizer = tf.keras.optimizers.Adam(lr=lr)\n    \n    loss = tf.keras.losses.BinaryCrossentropy()\n    \n    #tf.keras.metrics.CategoricalAccuracy(name='categorical_accuracy')\n    metrics = [\n    tfa.metrics.F1Score(num_classes = 6, average = \"macro\",name = \"f1_score\")\n    ]\n\n    model.compile(optimizer=optimizer, loss=loss, metrics=metrics)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-05-24T23:03:41.686614Z","iopub.execute_input":"2021-05-24T23:03:41.686933Z","iopub.status.idle":"2021-05-24T23:03:41.698866Z","shell.execute_reply.started":"2021-05-24T23:03:41.686901Z","shell.execute_reply":"2021-05-24T23:03:41.697486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS = 10\nVERBOSE = 1\n\ntf.keras.backend.clear_session()\n\nwith tf.device('/device:GPU:0'):\n    \n    model = create_EffNetB0model()\n    model = compile_model(model, lr=0.0001)\n \n    callbacks = create_callbacks()\n    \n    history = model.fit(\n                    train_data,\n                    epochs=EPOCHS,\n                    callbacks=callbacks,\n                    validation_data = validacion_data,\n                    verbose = VERBOSE\n                   )","metadata":{"execution":{"iopub.status.busy":"2021-05-24T23:03:46.786957Z","iopub.execute_input":"2021-05-24T23:03:46.787264Z","iopub.status.idle":"2021-05-24T23:24:32.02134Z","shell.execute_reply.started":"2021-05-24T23:03:46.787233Z","shell.execute_reply":"2021-05-24T23:24:32.018551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resultadosEffNetB0 = pd.DataFrame(history.history)","metadata":{"execution":{"iopub.status.busy":"2021-05-23T15:53:05.719958Z","iopub.execute_input":"2021-05-23T15:53:05.720277Z","iopub.status.idle":"2021-05-23T15:53:05.725691Z","shell.execute_reply.started":"2021-05-23T15:53:05.720246Z","shell.execute_reply":"2021-05-23T15:53:05.724564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resultadosEffNetB0_csv_file = 'resultadosEffNetB0_history2.csv'\nwith open(resultadosEffNetB0_csv_file, mode='w') as f:\n    resultadosEffNetB0.to_csv(f)","metadata":{"execution":{"iopub.status.busy":"2021-05-23T16:50:12.48962Z","iopub.execute_input":"2021-05-23T16:50:12.489979Z","iopub.status.idle":"2021-05-23T16:50:12.498302Z","shell.execute_reply.started":"2021-05-23T16:50:12.489946Z","shell.execute_reply":"2021-05-23T16:50:12.497466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <u>Modelo RestNet50:</u> \nCreamos y entrenamos el modelo RestNet50 con el mismo set de datos, mismos parámetros y guardamos tanto el modelo como los resultados del entrenamiento.","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications.resnet import ResNet50\nfrom tensorflow.keras.applications.resnet import preprocess_input\n\ndef create_RestNet50():\n    \n    pretrained = ResNet50(include_top=False, weights='imagenet',input_shape=[256, 256, 3])\n    x = pretrained.output\n    x = tf.keras.layers.GlobalAveragePooling2D()(x) \n    # Para RestNet50 debemos usar softmax si utilizamos los pesos pre-entrenados.\n    outputs = tf.keras.layers.Dense(6,activation=\"sigmoid\", dtype='float32')(x)\n    model = tf.keras.Model(pretrained.input, outputs, name = 'modeloRestNet50')\n    return model\n\nmodel = create_RestNet50()\n\n\ndef compile_model(model):\n    \n    #optimizer = tf.keras.optimizers.Adam(lr=lr)\n    optimizer = tf.keras.optimizers.SGD(lr=0.03, decay=1e-4, momentum=0.8, nesterov=True)\n\n    \n    loss = tf.keras.losses.BinaryCrossentropy()\n    \n    #tf.keras.metrics.CategoricalAccuracy(name='categorical_accuracy')\n    metrics = [\n    tfa.metrics.F1Score(num_classes = 6, average = \"macro\",name = \"f1_score\")\n    ]\n\n    model.compile(optimizer=optimizer, loss=loss, metrics=metrics)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-05-24T22:13:20.279133Z","iopub.execute_input":"2021-05-24T22:13:20.279478Z","iopub.status.idle":"2021-05-24T22:13:21.639106Z","shell.execute_reply.started":"2021-05-24T22:13:20.279445Z","shell.execute_reply":"2021-05-24T22:13:21.638311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Entrenamos el modelo RestNet50","metadata":{}},{"cell_type":"code","source":"EPOCHS = 10\nVERBOSE = 1\n\ntf.keras.backend.clear_session()\n\nwith tf.device('/device:GPU:0'):\n    \n    callbacks = create_callbacks()\n    model = compile_model(model)\n    historyResNet50 = model.fit(\n                    train_data,\n                    epochs=EPOCHS,\n                    callbacks=callbacks,\n                    validation_data = validacion_data,\n                    verbose = VERBOSE\n                   )","metadata":{"execution":{"iopub.status.busy":"2021-05-24T22:13:25.014442Z","iopub.execute_input":"2021-05-24T22:13:25.014846Z","iopub.status.idle":"2021-05-24T22:59:44.504384Z","shell.execute_reply.started":"2021-05-24T22:13:25.014802Z","shell.execute_reply":"2021-05-24T22:59:44.503366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resultadosRestNet50 = pd.DataFrame(historyResNet50.history)\nmodeloResNet50 = 'modeloResNet50_history2.csv'\nwith open(modeloResNet50, mode='w') as f:\n    resultadosRestNet50.to_csv(f)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T23:01:41.948101Z","iopub.execute_input":"2021-05-24T23:01:41.948462Z","iopub.status.idle":"2021-05-24T23:01:41.955122Z","shell.execute_reply.started":"2021-05-24T23:01:41.948428Z","shell.execute_reply":"2021-05-24T23:01:41.954311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications.densenet import DenseNet121\nfrom tensorflow.keras.applications.densenet import preprocess_input\n#tf.keras.applications.densenet.DenseNet121\n\nseed = 1200\ntf.random.set_seed(seed)\n\n#base_model = tf.keras.applications.DenseNet121(weights=weight_path, include_top=False, pooling='avg')\nbase_model = tf.keras.applications.DenseNet121(input_shape=(256,256,3),\n                                               include_top=False,\n                                               weights='imagenet',\n                                               pooling='avg')\n#pesos_entrenados = '../input/keras-pretrained-models/'\n#model = keras.applications.InceptionResNetV2(weights=pesos_entrenados, include_top=False, input_shape=(256, 256, 3))\nbase_model.trainable = False\n\nx = base_model.output\n#fully connected layer\nx = tf.keras.layers.Dense(64, activation='relu')(x)\nx = tf.keras.layers.Dense(16, activation='relu')(x)\n# finally, the softmax for the classifier \npredictions = tf.keras.layers.Dense(6, activation='sigmoid')(x)\nmodeloDenseNet121 = tf.keras.Model(base_model.inputs, predictions, name='DenseNet121')\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resultados = pd.read_csv('/kaggle/input/resultadosmodelosprac1gpu/modelos_Resultados.csv')","metadata":{"execution":{"iopub.status.busy":"2021-05-28T23:24:58.845838Z","iopub.execute_input":"2021-05-28T23:24:58.846193Z","iopub.status.idle":"2021-05-28T23:24:58.8736Z","shell.execute_reply.started":"2021-05-28T23:24:58.846159Z","shell.execute_reply":"2021-05-28T23:24:58.872817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":" resultados.modelo","metadata":{"execution":{"iopub.status.busy":"2021-05-28T23:19:43.786725Z","iopub.execute_input":"2021-05-28T23:19:43.787061Z","iopub.status.idle":"2021-05-28T23:19:43.79365Z","shell.execute_reply.started":"2021-05-28T23:19:43.787031Z","shell.execute_reply":"2021-05-28T23:19:43.792616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resultados[resultados['modelo']=='EfficeintNetB0']['epoch'].to_list()","metadata":{"execution":{"iopub.status.busy":"2021-05-28T23:44:08.623813Z","iopub.execute_input":"2021-05-28T23:44:08.624201Z","iopub.status.idle":"2021-05-28T23:44:08.631483Z","shell.execute_reply.started":"2021-05-28T23:44:08.62416Z","shell.execute_reply":"2021-05-28T23:44:08.630586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seed = 1200\ntf.random.set_seed(seed)\n\npesos_entrenados = '../input/keras-pretrained-models/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5'\nmodel = keras.applications.InceptionResNetV2(weights=pesos_entrenados, include_top=False, input_shape=(256, 256, 3))\n# Tamaños entrada-salida del modelo InceptionResnet50v2\n#print(model.input)\n#print(model.output)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T11:05:11.278898Z","iopub.execute_input":"2021-05-24T11:05:11.279228Z","iopub.status.idle":"2021-05-24T11:05:21.357121Z","shell.execute_reply.started":"2021-05-24T11:05:11.279193Z","shell.execute_reply":"2021-05-24T11:05:21.356209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"modelo_sobre_IncRSNet50V2 = tf.keras.Sequential([\n    model,\n    keras.layers.GlobalAveragePooling2D(),\n    keras.layers.Dense(len(labelslista), \n    kernel_initializer=keras.initializers.RandomUniform(seed=seed),\n    bias_initializer=keras.initializers.Zeros(), name='dense_top', activation='sigmoid')\n])\n\n# Freezing the weights\nfor layer in modelo_sobre_IncRSNet50V2.layers[:-1]:\n    layer.trainable=False\n    \nmodelo_sobre_IncRSNet50V2.summary()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T11:05:59.207245Z","iopub.execute_input":"2021-05-24T11:05:59.20757Z","iopub.status.idle":"2021-05-24T11:06:00.572303Z","shell.execute_reply.started":"2021-05-24T11:05:59.207539Z","shell.execute_reply":"2021-05-24T11:06:00.571504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"VERBOSE = 10\nf1 = tfa.metrics.F1Score(num_classes=6, average='macro')\n\n#callbacks = keras.callbacks.EarlyStopping(monitor=f1, patience=3, mode='max', restore_best_weights=True)\n\n\nmodelo_sobre_IncRSNet50V2.compile(loss=tf.keras.losses.CategoricalCrossentropy(), optimizer=keras.optimizers.Adam(lr=1e-4), \n              metrics= [f1])\n\nwith tf.device('/device:GPU:0'):\n    \n    callbacks = create_callbacks()\n    #model = compile_model(model, lr=0.0001)\n    history_IncRSNet50V2 = modelo_sobre_IncRSNet50V2.fit(\n                    train_data,\n                    epochs=10,\n                    callbacks=callbacks,\n                    validation_data = val_data,\n                    verbose = VERBOSE\n                   )\n\n#modelo_sobre_IncRSNet50V2.fit(train_data, epochs=20, callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T11:10:51.548656Z","iopub.execute_input":"2021-05-24T11:10:51.548985Z","iopub.status.idle":"2021-05-24T11:44:39.929477Z","shell.execute_reply.started":"2021-05-24T11:10:51.548955Z","shell.execute_reply":"2021-05-24T11:44:39.9284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resultadosIncepRSNet50V2 = pd.DataFrame(history_IncRSNet50V2.history)\nmodeloIncepResNet50v2 = 'modeloIncepRSNet50V2_history.csv'\nwith open(modeloIncepResNet50v2, mode='w') as f:\n    resultadosIncepRSNet50V2.to_csv(f)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T11:46:55.479967Z","iopub.execute_input":"2021-05-24T11:46:55.480337Z","iopub.status.idle":"2021-05-24T11:46:55.49068Z","shell.execute_reply.started":"2021-05-24T11:46:55.480302Z","shell.execute_reply":"2021-05-24T11:46:55.489851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Modelo DenseNet121","metadata":{}},{"cell_type":"code","source":"# Probamos un DenseNet121\nfrom tensorflow.keras.applications.densenet import DenseNet121\nfrom tensorflow.keras.applications.densenet import preprocess_input\n#tf.keras.applications.densenet.DenseNet121\n\nseed = 43\ntf.random.set_seed(seed)\n\n#base_model = tf.keras.applications.DenseNet121(weights=weight_path, include_top=False, pooling='avg')\nbase_model = tf.keras.applications.DenseNet121(input_shape=(256,256,3),\n                                               include_top=False,\n                                               weights='imagenet',\n                                               pooling='avg')\nx = base_model.output\n#fully connected layer\nx = tf.keras.layers.Dense(64, activation='relu')(x)\nx = tf.keras.layers.Dense(16, activation='relu')(x)\n# finally, the softmax for the classifier \noutput = tf.keras.layers.Dense(6, activation='sigmoid')(x)\nmodel = tf.keras.Model(base_model.inputs, output, name='DenseNet121')\n","metadata":{"execution":{"iopub.status.busy":"2021-05-24T21:07:31.040676Z","iopub.execute_input":"2021-05-24T21:07:31.040986Z","iopub.status.idle":"2021-05-24T21:07:33.51448Z","shell.execute_reply.started":"2021-05-24T21:07:31.040955Z","shell.execute_reply":"2021-05-24T21:07:33.513639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"optimizer = keras.optimizers.SGD(lr=0.03, decay=1e-4, momentum=0.8, nesterov=True)\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS = 20\nVERBOSE = 1\nf1 = tfa.metrics.F1Score(num_classes=6, average='macro')\n\ntf.keras.backend.clear_session()\n\nwith tf.device('/device:GPU:0'):\n\n    callbacks = create_callbacks()\n    model = compile_model(model)\n    history_DenseNet121 = model.fit(\n                    train_data,\n                    epochs=EPOCHS,\n                    callbacks=callbacks,\n                    validation_data = validacion_data,\n                    verbose = VERBOSE\n                   )","metadata":{"execution":{"iopub.status.busy":"2021-05-24T21:07:53.052381Z","iopub.execute_input":"2021-05-24T21:07:53.052698Z","iopub.status.idle":"2021-05-24T22:07:34.13944Z","shell.execute_reply.started":"2021-05-24T21:07:53.052669Z","shell.execute_reply":"2021-05-24T22:07:34.138291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resultadosDenseNet121= pd.DataFrame(history_DenseNet121.history)\nmodeloDenseNet121 = 'modeloDenseNet121_history2.csv'\nwith open(modeloDenseNet121, mode='w') as f:\n    resultadosDenseNet121.to_csv(f)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T22:07:58.679319Z","iopub.execute_input":"2021-05-24T22:07:58.679646Z","iopub.status.idle":"2021-05-24T22:07:58.68783Z","shell.execute_reply.started":"2021-05-24T22:07:58.679615Z","shell.execute_reply":"2021-05-24T22:07:58.687004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Predicciones (pruebas con el problema original Kaggle).","metadata":{}},{"cell_type":"code","source":"test_generator.reset()\npredicciones = model.predict_generator(test_generator, verbose=1)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_generator = test_datagen.flow_from_directory(\n)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <u>Gráficas preliminares de resultados a partir de las pruebas con el problema original Kaggle </u>\nSe muestra a continuación la evolución de la pérdida y de F1-Score para los conjuntos de entrenamiento y de validación para nuestros cuatro modelos.","metadata":{}},{"cell_type":"code","source":"fig, ((ax1,ax2, ax3, ax4), (ax5, ax6, ax7, ax8)) = plt.subplots(2,4, figsize=(24,8))\nplt.suptitle(\"Gráficas de pérdida y f1-score para los modelos \\n (Sets entrenamientor y validación)\", color='darkblue')\nplt.style.use('seaborn')\n\nax1.plot(resultados[resultados['modelo']=='ResNet50']['loss'], color='blue')\nax1.plot(resultados[resultados['modelo']=='ResNet50']['val_loss'], color='orange')\nax1.set_xticks(resultados[resultados['modelo']=='ResNet50']['epoch'])\nax1.legend(['pérdida entren.', 'perdida val.'])\nax1.set_xlabel('Epochs')\nax1.set_ylabel('Pérdida (loss)')\nax1.set_title(\"Pérdida Modelo ResNet50\")\n               \nax2.plot(resultados[resultados['modelo']=='ResNet50']['f1_score'].to_list(),color='maroon')\nax2.plot(resultados[resultados['modelo']=='ResNet50']['val_f1_score'].to_list(),color='lime')\nax2.legend(['f1-score entren.', 'f1-score valid.'])\nax2.set_xticks(resultados[resultados['modelo']=='ResNet50V2']['epoch'].to_list())\nax2.set_xticklabels(resultados[resultados['modelo']=='ResNet50V2']['epoch'].to_list())\nax2.legend(['f1-score entren.', 'f1-score valid.'])\nax2.set_xlabel('Epochs')\nax2.set_ylabel('Pérdida (loss)')\nax2.set_title(\"f1-score (macro) Modelo ResNet50\")\n\n\nax3.plot(resultados[resultados['modelo']=='ResNet50V2']['loss'].to_list(),color='blue')\nax3.plot(resultados[resultados['modelo']=='ResNet50V2']['val_loss'].to_list(),color='orange')\nax3.set_xticks(resultados[resultados['modelo']=='ResNet50V2']['epoch'].to_list())\nax3.set_xticklabels(resultados[resultados['modelo']=='ResNet50V2']['epoch'].to_list())\nax3.legend(['pérdida entren.', 'perdida val.'])\nax3.set_xlabel('Epochs')\nax3.set_ylabel('Pérdida (loss)')\nax3.set_title(\"Pérdida Modelo ResNet50v2\")\n\nax4.plot(resultados[resultados['modelo']=='ResNet50V2']['f1_score'].to_list(),color='maroon')\nax4.plot(resultados[resultados['modelo']=='ResNet50V2']['val_f1_score'].to_list(),color='lime')\nax4.legend(['f1-score entren.', 'f1-score valid.'])\nax4.set_xticks(resultados[resultados['modelo']=='ResNet50V2']['epoch'].to_list())\nax4.set_xticklabels(resultados[resultados['modelo']=='ResNet50V2']['epoch'].to_list())\nax4.set_xlabel('Epochs')\nax4.set_ylabel('Pérdida (loss)')\nax4.set_title(\"f1-score (macro) Modelo ResNet50v2\")\n\n\nax5.plot(resultados[resultados['modelo']=='EfficeintNetB0'][['loss', 'val_loss']])\nax5.set_xticklabels(resultados[resultados['modelo']=='EfficeintNetB0']['epoch'].to_list())\nax5.legend(['pérdida entren.', 'perdida val.'])\n#ax5.set_xticks(resultados[resultados['modelo']=='EfficeintNetB0']['epoch'].to)\nax5.set_xlabel('Epochs')\nax5.set_ylabel('Pérdida (loss)')\nax5.set_title(\"Pérdida Modelo EfficeintNetB0\")\n\nax6.plot(resultados[resultados['modelo']=='EfficeintNetB0'][['f1_score', 'val_f1_score']])\nax6.set_xticklabels(resultados[resultados['modelo']=='EfficeintNetB0']['epoch'].to_list())\nax6.legend(['f1-score entren.', 'f1-score valid.'])\nax6.set_xlabel('Epochs')\nax6.set_ylabel('f1-score')\nax6.set_title(\"f1-score (macro) Modeloo EfficeintNetB0\")\n\nax7.plot(resultados[resultados['modelo']=='InceptionV3'][['loss', 'val_loss']])\nax7.set_xticklabels(resultados[resultados['modelo']=='InceptionV3']['epoch'].to_list())\nax7.legend(['pérdida entren.', 'perdida val.'])\nax7.set_xlabel('Epochs')\nax7.set_ylabel('Pérdida (loss)')\nax7.set_title(\"Pérdida Modelo InceptionV3\")\n\nax8.plot(resultados[resultados['modelo']=='InceptionV3'][['f1_score', 'val_f1_score']])\nax8.set_xticklabels(resultados[resultados['modelo']=='InceptionV3']['epoch'].to_list())\nax8.legend(['f1-score entren.', 'f1-score valid.'])\nax8.set_xlabel('Epochs')\nax8.set_ylabel('f1-score')\nax8.set_title(\"f1-score (macro) Modeloo InceptionV3\")\nfig.tight_layout(h_pad=5, w_pad=5)\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2021-05-28T23:44:33.383565Z","iopub.execute_input":"2021-05-28T23:44:33.383925Z","iopub.status.idle":"2021-05-28T23:44:34.978328Z","shell.execute_reply.started":"2021-05-28T23:44:33.383891Z","shell.execute_reply":"2021-05-28T23:44:34.977187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A continuación obtenemos las predicciones con el mejor modelo","metadata":{}},{"cell_type":"code","source":"val_generator_ej4_sin_shuffle = data_generator_ej4.flow_from_directory(\n  directory='/k /drive/MyDrive/UCMerced_LandUse/Images/',\n  target_size=(224, 224),\n  #color_mode=\"rgb\",\n  class_mode='categorical',\n  seed = 42,\n  shuffle = False,\n  follow_links=False,\n  subset='validation')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}}]}