scieee AI-readable full text Open interactive document viewer

Clasificación de imágenes médicas de Rayos-X mediante redes neuronales convolucionales

Toquero Barón, Miguel

Abstract

Grado en Ingeniería Informática

Full text

Universidad de Valladolid ESCUELA DE INGENIERÍA INFORMÁTICA DE VALLADOLID Grado en Ingeniería Informática Mención Computación Clasificación de Imágenes Médicas de Rayos-X mediante Redes Neuronales Convolucionales Alumno: Miguel Toquero Barón Tutor: Teodoro Calonge Cano Índice general Lista de figuras v Lista de tablas vii Resumen xiii Abstract xv I Memoria del Proyecto 1 1. Introducción 3 1.1. Objetivosdeltrabajo.............................. 5 1.2. Motivación.................................... 5 1.3. Estructura.................................... 6 2. Fundamento Teórico 7 2.1. Redes Neuronales Artificiales . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.1.1. Funciones de activación . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.1.2. Función de coste o pérdida . . . . . . . . . . . . . . . . . . . . . . . 16 2.1.3. Optimizadores.............................. 16 2.2. Redes Neuronales Convolucionales . . . . . . . . . . . . . . . . . . . . . . . 17 2.2.1. Unpocodehistoria........................... 17 2.2.2. Operación de convolución . . . . . . . . . . . . . . . . . . . . . . . 18 2.2.3. Estructura de una capa convolucional . . . . . . . . . . . . . . . . . 22 2.2.4. Dimensionalidad ............................ 23 2.2.5. Pooling ................................. 23 2.3. Redes Convolucionales en la práctica . . . . . . . . . . . . . . . . . . . . . 24 2.3.1. Variantes de la operación convolución . . . . . . . . . . . . . . . . . 26 2.4. Grad-CAM ................................... 30 3. Metodología 33 3.1. Procesodedesarrollo.............................. 33 3.1.1. Entregables del proyecto . . . . . . . . . . . . . . . . . . . . . . . . 34 i Índice general 3.2. Evaluación.................................... 35 4. Marco de trabajo 37 4.1. Herramientas utilizadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.1.1. Hardware ................................ 37 4.1.2. SistemaOperativo ........................... 38 4.1.3. Lenguaje de programación . . . . . . . . . . . . . . . . . . . . . . . 38 4.1.4. Bibliotecas................................ 40 5. Planificación 43 5.1. Tareas ...................................... 43 5.2. Estimacióndecoste............................... 44 5.3. Variaciones respecto la planificación inicial . . . . . . . . . . . . . . . . . . 44 6. Datos 47 6.1. Descripción de los datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 6.2. Preprocesado .................................. 48 6.2.1. División del conjunto . . . . . . . . . . . . . . . . . . . . . . . . . . 48 6.2.2. Normalización.............................. 51 7. Construcción del sistema 53 7.1. Lecturadedatos ................................ 53 7.1.1. Lectura de datos alternativa . . . . . . . . . . . . . . . . . . . . . . 55 7.2. Creacióndemodelos .............................. 55 7.2.1. Capas convolucionales . . . . . . . . . . . . . . . . . . . . . . . . . 55 7.2.2. Perceptrón multicapa . . . . . . . . . . . . . . . . . . . . . . . . . . 58 7.3. Compilación del modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 7.4. Entrenamiento ................................. 60 7.5. Evaluación.................................... 62 7.6. Implementación................................. 63 7.6.1. Divisióndedatos............................ 63 7.6.2. Lectura ................................. 64 7.6.3. Lectura alternativa . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 7.6.4. Construcción del modelo . . . . . . . . . . . . . . . . . . . . . . . . 65 7.6.5. Compilación del modelo . . . . . . . . . . . . . . . . . . . . . . . . 66 7.6.6. Entrenamiento ............................. 66 7.6.7. Evaluación................................ 66 7.6.8. Grad-CAM ............................... 67 8. Resultados 71 8.1. Evaluación del modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 8.2. Interpretabilidad del modelo . . . . . . . . . . . . . . . . . . . . . . . . . . 73 ii Índice general 9. Aplicación 77 9.1. Análisis ..................................... 77 9.1.1. Requisitos................................ 77 9.1.2. Casosdeuso .............................. 78 9.2. Diseño...................................... 82 9.2.1. Tecnologías utilizadas . . . . . . . . . . . . . . . . . . . . . . . . . . 82 9.2.2. Arquitecturas.............................. 82 9.2.3. Diagramas de clases . . . . . . . . . . . . . . . . . . . . . . . . . . 84 9.2.4. Diagramas de secuencias . . . . . . . . . . . . . . . . . . . . . . . . 84 9.2.5. Pruebas ................................. 87 9.2.6. Seguridad ................................ 87 9.2.7. Implementación............................. 87 9.2.8. Despliegue................................ 87 10. Conclusiones 89 10.1.Trabajofuturo ................................. 91 II Apéndices 93 A. Manuales de la Aplicación 95 A.1.Manualdeinstalación ............................. 95 A.2.Manualdeusuario ............................... 96 B. Contenido del CD 99 Bibliografía 101 iii Índice general iv Índice de figuras 1.1. Relación entre los términos de Inteligencia Artificial, Aprendizaje Automático y Aprendizaje Profundo . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.1. Representación de una neurona biológica. Imagen de [47]. . . . . . . . . . . 7 2.2. Modelo de Frank Rosenblatt (perceptrón simple). . . . . . . . . . . . . . . 8 2.3. Arquitectura de una Red Neuronal. . . . . . . . . . . . . . . . . . . . . . . 9 2.4. Funciónidentidad. ............................... 11 2.5. Funciónsigno................................... 11 2.6. FunciónReLU.................................. 12 2.7. FunciónLeakyReLU.............................. 13 2.8. Funciónsigmoide ................................ 14 2.9. Función de activación softmax. Imagen de [58] . . . . . . . . . . . . . . . . 15 2.10. Función tangente hiperbólica . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.11. Ejemplo de convolución 2D. Imagen de [21]. . . . . . . . . . . . . . . . . . 19 2.12. Ejemplo de conectividad dispersa -convolución (arriba) frente a conectividad densa - mutiplicación matricial (abajo). Imagen de [21]. . . . . . . . . 20 2.13. Ejemplo de compartición de parámetros -convolución (arriba) frente a multiplicación densa de matrices (abajo). Imagen de [21]. . . . . . . . . . . . . 21 2.14. Esbozo de CNN. Imagen de [2]. . . . . . . . . . . . . . . . . . . . . . . . . 22 2.15. Ejemplo MaxPooling con filtro de 2 y paso de 2. . . . . . . . . . . . . . . . 24 2.16. Ejemplo de convolución en imagen RGB (3 canales) con filtro 3x3. Imagen de[38]....................................... 25 2.17. Ejemplo de convolución con stride de(1,1)................... 27 2.18. Ejemplo de convolución con stride de (2,2). Imagen de [14]. . . . . . . . . . 27 2.19. Ejemplo de padding same. Imagen de [55] . . . . . . . . . . . . . . . . . . 28 2.20. Ejemplo de parámetros no compartidos (arriba) frente a una convolución habitual (abajo). Imagen de [21]. . . . . . . . . . . . . . . . . . . . . . . . 29 2.21. Ejemplo de convolución en mosaico. Imagen de [21]. . . . . . . . . . . . . . 29 2.22. Arquitectura de Grad-CAM. Imagen de [56]. . . . . . . . . . . . . . . . . . 30 2.23. Detección de sesgo con Grad-CAM. Imagen de [56]. . . . . . . . . . . . . . 31 3.1. CicloCRISP-DM................................. 34 5.1. Diagrama de Gantt para el proyecto. . . . . . . . . . . . . . . . . . . . . . 46 v Índice de figuras 6.1. Muestra de imágenes de cada clase. . . . . . . . . . . . . . . . . . . . . . . 48 6.2. Metodología Hold-out. ............................. 49 6.3. Gráfico de barras para la clase de los datos originales. . . . . . . . . . . . . 50 6.4. Gráfico de barras para la clase de los datos de entrenamiento. . . . . . . . 50 6.5. Gráfico de barras para la clase de los datos de prueba. . . . . . . . . . . . 51 7.1. Ejemplo de estructura de una red neuronal secuencial. Imagen de [8]. . . . 56 7.2. Ejemplo de estructura de una red neuronal con API funcional. Imagen de [8]......................................... 56 8.1. Ejemplos de imágenes clasificadas con su correspondiente Grad-CAM. . . . 74 9.1. Diagrama de casos de uso. . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 9.2. Diagramadeclases................................ 84 9.3. Diagrama de secuencias para CU-01 Subir imagen. . . . . . . . . . . . . . . 85 9.4. Diagrama de secuencias para CU-02 Diagnosticar. . . . . . . . . . . . . . . 85 9.5. Diagrama de secuencias para CU-03 Obtener diagnóstico. . . . . . . . . . . 86 9.6. Diagrama de secuencias para CU-04 Obtener explicación. . . . . . . . . . . 86 A.1.Pantalladeinicio................................. 96 A.2. Pantalla de inicio con imagen seleccionada. . . . . . . . . . . . . . . . . . . 96 A.3.Pantalladecarga................................. 97 A.4. Pantalla de resultados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 B.1. Estructura de directorios. . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 B.2. Estructura de directorios final del repositorio. . . . . . . . . . . . . . . . . 100 vi Índice de cuadros 5.1. Estimacióndecostes .............................. 44 6.1. Distribución de clases. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 8.1. Porcentaje de buena clasificación para Train yTest.............. 72 8.2. Matrizdeconfusión. .............................. 72 8.3. Matriz de confusión condicionada por filas. . . . . . . . . . . . . . . . . . . 73 9.1. Requisitos funcionales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 9.2. Requisitos no funcionales. . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 9.3. Requisitos de Información. . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 9.4. CU-01.Subirimagen............................... 80 9.5. CU-02.Diagnosticar............................... 81 9.6. CU-03. Obtener diagnóstico. . . . . . . . . . . . . . . . . . . . . . . . . . . 81 9.7. CU-04. Obtener explicación. . . . . . . . . . . . . . . . . . . . . . . . . . . 82 vii RESUMEN xiv Abstract Several decades ago, the Artificial Intelligence (AI) became a paradigm which was the basis of a lot of computing projects to be applied to a very different fields of our life. One of them was the Health, where the IA influence is growing up everyday. Even more, nowadays no body knows limit in this area. Due to the present pandemic worldwide situation, the IA has been also applied to Covid-19 disease treatment. Precisely, one the most worrying symptoms is the pneumonia, because it could lead to the patient dead. In this work, an X-ray thorax image classification system is proposed using Machine Learning. In particular, a Deep Learning prototype was implemented to carry out the corresponding image recognition. More precisely, it is made up of several Convolutional Artificial Neurons layers, as well as set of dense neurons layers (Multiplayer Perceptron). The classification accuracy obtained was greater than 95 % using images never input to our system. In addition, a recent image interpretation belonging to Vision Artificial techniques has been proved, in particular, Grad-CAM, that tries to return the most influence image areas used by a Convolutional Neural Network in a classification problem. As for now, it is not verified if the areas obtained by Grad-CAM are similar to the lung specialist physicians use to consider for the pneumonia diagnostic. Keywords: Deep Learning, Covid-19, Convolutional Neural Networks, Image classification, Grad-CAM. xv Parte I Memoria del Proyecto Capítulo 1 Introducción El día 11 de Marzo de 2020, la Organización Mundial de la Salud (OMS) declaró que la enfermedad COVID-19 pasaba a ser una pandemia. Con esto y la situación vivida a nivel mundial, se desarrollaron muchas técnicas para la diagnosis de esta enfermedad en pacientes sospechosos de contraerla , así como de sus contactos directos. De la necesidad de obtener un rápido diagnóstico, nace este trabajo, explotando la posibilidad de detectar a nuevos pacientes, mediante el análisis de imágenes radiológicas de tórax. Con todo ello, se podrá plantear un campo de investigación multidisciplinar, con el objeto de contrastar la validez del modelo propuesto en este TFG, con el de la realidad clínica/médica. La inclusión de la Inteligencia Artificial en todos los ámbitos de nuestra vida está a la orden del día. Una de las acusas que motivan este hecho es, sin duda, la explotación de los datos como fuente de conocimiento, tal y como propone el Aprendizaje Automático. La gran cantidad de datos generada diariamente, en la actualidad, constituye un gran valor de mercado que se puede explotar en cualquier ámbito: desde análisis para mejorar las infraestructuras de transportes [49], hasta predicciones deportivas sobre la Eurocopa de fútbol [25]. Un campo muy conocido, y cada vez más aprovechado de la Inteligencia Artificial es la visión artificial o Computer Vision. Se trata de una disciplina del Aprendizaje Automático, que propone tratamientos computerizados de imágenes digitales, con el fin de clasificarlas, realizar tareas de reconocimiento, etc. En el ámbito de la salud, destaca el proyecto de Microsoft InnerEye [46], que es un software capaz de visualizar e identificar tumores u otras anomalías en las radiografías. A partir de la correspondiente imagen tridimensional, el software colorea las zonas que presentan anomalías, con el fin de prestar mayor atención a esa parte del cuerpo humano. Los términos Inteligencia Artificial (Artificial Intelligence - AI), Aprendizaje Automático (Machine Learning - ML) y Aprendizaje Profundo (Deep Learning - DL) están realmente extendidos, muchas veces, sin conocerse muy bien la diferencia entre ellos. Pues 3 Capítulo 1. Introducción bien, la Inteligencia Artificial es el campo de estudio que abarca la explicación y emulación de la conducta inteligente, en función de procesos computacionales basados en la experiencia y el conocimiento continuo del ambiente [13]. Refiriéndonos a conducta inteligente, como la capacidad que tienen las máquinas para realizar tareas que, hasta el momento, son realizadas por seres humanos [53]. El Aprendizaje Automático se define como el estudio de algoritmos de computación que mejoran automáticamente su rendimiento gracias a la experiencia. Por ello, se puede emplear una medida de rendimiento que, conforme va tratando los datos (experiencia), se espera que esta mejore [44]. Existe una gran variedad de técnicas de Machine Learning capaces de resolver el problema de clasificación de imágenes Podríamos mencionar, por ejemplo, el algoritmo de k Vecinos Más Próximos o la Regresión Logística. Sin embargo, nos decantaremos por un algoritmo de Aprendizaje Profundo. Dentro del Aprendizaje Automático, encontramos un subgrupo de algoritmos conocidos como Aprendizaje Profundo. Consiste en la agrupación de un conjunto de procedimientos de aprendizaje automático, que intenta modelar abstracciones de alto nivel en datos usando arquitecturas computacionales, que admiten transformaciones no lineales múltiples e iterativas de datos expresados en forma matricial o tensorial [3]. Es decir, una combinación de múltiples algoritmos de Aprendizaje Automático estructurados en forma de muchas capas. Figura 1.1: Relación entre los términos de Inteligencia Artificial, Aprendizaje Automático y Aprendizaje Profundo El objetivo de este proyecto es hacer un estudio sobre técnicas de Aprendizaje Automático y una adaptación de estas al problema que tratamos. En particular, elaboraremos algunos modelos de Aprendizaje Profundo sobre un conjunto de datos, que se describirá en el capítulo 6, y el desarrollo de una aplicación fácilmente usable. Nos centraremos en los modelos de Redes Neuronales Convolucionales para tratar de predecir la clase de las imágenes. Este tipo de redes se ha utilizado históricamente, precisamente, para dicho propósito, como por ejemplo, para el famoso conjunto de número manuscritos [57]. 4 1.1. Objetivos del trabajo 1.1. Objetivos del trabajo Se detallarán, en esta sección, los objetivos generales del TFG. En este caso, tiene tanto parte teórica o de estudio, como parte de desarrollo de aplicaciones software. Como hitos del presente TFG se podría contar con: Encontrar y adaptar los datos de forma adecuada para tratar el problema. Desarrollar un modelo predictivo con alta tasa de acierto. Construir una aplicación software que permita a los usuarios hacer uso del modelo. Esta aplicación también tiene sus requisitos: •El usuario debe poder elegir la imagen que desea predecir. •La aplicación debe mostrar de forma clara el resultado de la predicción. •Se presentará de forma gráfica cómo ha obtenido la predicción. Este proyecto se debe llevar a un entorno de desarrollo local fácilmente migrable. 1.2. Motivación La clasificación de imágenes es una técnica cada vez más utilizada en diversas tareas: reconocimiento de fallos, identificación de personas, clasificación de imágenes médicas, etc. En este trabajo, nos vamos a centrar en las imágenes médicas obtenidas mediante rayos X, radiografías, en particular, de tórax para el disgnóstico de la Covid-19. Durante este último año, la pandemia vivida a nivel mundial ha impulsado a la tecnología a avanzar en el campo de la medicina, para facilitar las labores técnicas a los especialistas en la materia. La diagnosis de la enfermedad COVID-19 ha resultado clave hasta ahora, para lo cual, la capacidad de realizar pruebas y tener un diagnóstico con alto grado de fiabilidad ha sido uno de los grandes objetivos de la Medicina. La prueba de reacción en cadena polimerasa o Polymerase Chain Reaction (PCR) han servido para detectar la presencia o ausencia de esta enfermedad. Estas han sido muy escasas y se han realizado de manera muy controlada para mantener una reserva de pruebas disponibles. Sin embargo, sería muy útil contar con una técnica fiable de detección de la enfermedad que no tuviese límite de uso. Con el análisis de radiografías de tórax, una técnica relativamente económica y sin un claro límite de utilización más que las restricciones temporales, permitiría obtener una gran cantidad de muestras para clasificar y obtener el resultado de la prueba diagnóstica. Por ello, en este trabajo, se presenta la inquietud de diseñar un método eficaz de clasificación de imágenes radiológicas de tórax para diagnosticar de forma rápida la enfermedad COVID-19. Podría constituir una manera más de diagnosis de la enfermedad para liberar, así, la situación de estrés con las pruebas PCR y su análisis en los laboratorios. 5 Capítulo 1. Introducción 1.3. Estructura En la presente memoria se seguirá el siguiente esquema: Capitulo 1. Introducción. Con una explicación del contexto, motivación y, finalizando, con esta estructura del documento. Capítulo 2. Fundamento Teórico. Se explican las bases de las Redes Neuronales, especialmente de las Convolucionales, pilar fundamental de este proyecto. Capítulo 3. Metodología. Metodología de trabajo. Capítulo 4. Marco de trabajo. Se comentan las herramientas utilizadas para el desarrollo del proyecto. Capítulo 5. Planificación. Se abordarán los temas relacionados con la gestión y planificación del proyecto. Capítulo 6. Datos. En este capítulo veremos la recogida, descripción y procesamiento de los datos. Capítulo 7. Construcción del sistema. Se tratará una pequeña introducción a las librerías utilizadas y la implementación del sistema. Capítulo 8. Resultados. Se comentarán los resultados obtenidos para el modelado de los datos. Capítulo 9. Aplicación. En este se abordará el proceso de desarrollo de una aplicación web capaz de implementar la funcionalidad propuesta en los objetivos. Se trata como un proyecto de Ingeniería de Software. Capítulo 10 Conclusiones. encontraremos tanto las conclusiones como futuras aplicaciones y trabajos a desarrollar que surgen de este proyecto. 6 Capítulo 2 Fundamento Teórico 2.1. Redes Neuronales Artificiales Su origen se remonta a 1943, cuando McCulloch y Pitts presentaron un modelo matemático que pretendía simular el comportamiento de una neurona biológica [43], que, en principio: a partir de una o varias entradas binarias, se obtenía una salida con respuesta también binaria. Figura 2.1: Representación de una neurona biológica. Imagen de [47]. Utilizando el trabajo anterior, Frank Rosenblantt ideó, en 1958, lo que conocemos hoy como perceptrón simple [51], representado en la Figura 2.2. En el perceptrón simple, se relajaban las restricciones: las entradas ahora son valores 7 Capítulo 2. Fundamento Teórico Figura 2.8: Función sigmoide En contraposición, esta función tiene lenta convergencia, es decir, satura o mata el gradiente. Sin embargo, tiene un buen rendimiento en la última capa por su alta interpretabilidad. Función softmax La funciónsoftmax es realmente útil cuando tratamos con problemas de clasificación en varias clases. Con una base matemática muy similar a la de la función sigmoide vista en 2.6, la función softmax puede tener tantas salidas como se deseen, extendiendo, de esta manera, la interpretación de probabilidad como la de pertenencia a cada clase. Todas las salidas están en el rango de valores (0,1). La suma de estos es igual a uno. Para kclases, tenemos la siguiente formulación: fi(yi) = eyi Pk j=0 eyi (2.7) Función tangente hiperbólica Con un alto grado de semejanza a la función sigmoide, la función tangente hiperbólica toma valores en el rango (−1,1). Está centrada en torno al cero y es estrictamente creciente. En la práctica, la optimización es más fácil que para la función logística, pero sufre del problema del desvanecimiento del gradiente. f(x) = tanh(x) = ex−e−x ex+e−x(2.8) Podemos utilizar una reformulación equivalente, pero más eficiente computacional- 14 2.1. Redes Neuronales Artificiales Figura 2.9: Función de activación softmax. Imagen de [58] mente, al reducir el cálculo de exponenciales. f(x) = tanh(x) = e2x−1 e2x+ 1 (2.9) Figura 2.10: Función tangente hiperbólica Como sucedía en la función sigmoide, tiene lenta convergencia y satura o mata el gradiente. Se utiliza para decidir entre una opción y la contraria por su rango de valores. Tiene buen desempeño en Redes Recurrentes. Más allá de las funciones de activación presentadas en este trabajo, existen muchas otras variantes. Sin embargo, usaremos las ya mencionadas por su suficiencia, utilidad y popularidad. 15 Capítulo 2. Fundamento Teórico 2.1.2. Función de coste o pérdida Representa la suma del error: la diferencia entre el valor predicho y el real. Se emplea en problemas supervisados, es decir, con la variable respuesta conocida. Su misión es medir cómo de bien se comporta nuestra red neuronal frente al problema establecido. Sea ˆy=valor predicho, y=valor real, w=pesos y x=variables de entrada. Calculamos ˆy=w·x. Destacamos las siguientes funciones de coste: MAE(Mean Absolute Error): Se utiliza cuando la salida es un valor escalar. MAE = 1 nPn i=1 |yi−ˆyi| MSE(Mean Squared Error): igual que la anterior, pero MSE =1 nPn i=1(yi−ˆyi)2 Binary Crossentropy: Se utiliza cuando estamos ante un problema de clasificación binaria. Sea pla etiqueta real y qla etiqueta predicha. H(x) = Pn i=1 pi(x)log(qi(x)) Categorical Crossentropy: Se usa en problemas de multi-clasificación. Para mclases ynmuestras, sea yij la pertenencia de la muestra i a la clase j, valor real. Y su valor predicho ˆyij.L(y, ˆy) = Pm j=0 Pn i=1(yij ·log( ˆyij)) Las funciones de coste también se deben elegir cuidadosamente según el problema tratado [21]. 2.1.3. Optimizadores Con el conocimiento obtenido acerca de la tarea de optimización de los parámetros en la etapa del entrenamiento, veremos, a continuación, qué técnicas se van a utilizar en la práctica. No debemos olvidar que todas ellas hacen uso del descenso del gradiente y del algoritmo de retropropagación. Descenso del gradiente estocástico o SGD [35]: optimizador con descenso de gradiente y momento. Puede incluirse la aceleración de Nesterov [60]. RMSprop [34]: mantiene una media móvil del cuadrado de los gradientes y divide el gradiente por la raíz de esta media. Esta implementación de RMSprop utiliza el impulso simple, no el impulso Nesterov. Utiliza esa media móvil para estimar la varianza. Adam (Adaptative moment estimation) [33]: la optimización de Adam es un método de descenso de gradiente estocástico que se basa en la estimación adaptativa de momentos de primer y segundo orden. Se ha demostrado que el método es eficiente desde el punto de vista computacional [37], tiene pocos requisitos de memoria, es invariable al reescalado diagonal de los gradientes y se adapta bien a los problemas que son grandes en términos de datos/parámetros. 16 2.2. Redes Neuronales Convolucionales Es interesante destacar que aunque la convergencia con Adam es más rápida, el algoritmo SGD generaliza mejor [65]. Para la elaboración de esta sección 2.1, se ha utilizado [62]. 2.2. Redes Neuronales Convolucionales Convolutional Neural Network (CNN) son un tipo de Redes Neuronales que constituye una variación de un perceptrón multicapa. Debido a que su aplicación es realizada en matrices bidimensionales, son muy efectivas para tareas de visión artificial, como en la clasificación y segmentación de imágenes, entre otras aplicaciones. 2.2.1. Un poco de historia Encontramos sus inicios en 1959, en el trabajo realizado por Hubel y Wiesel [27], que permitió mejorar la comprensión sobre cómo funciona la corteza visual, particularmente, las células responsables de la selectividad de orientación y detección de bordes en los estímulos visuales. En dicho trabjao, se determinó que las neuronas del córtex visual eran sensibles a la posición y a la orientación. Posteriormente, en 1980, se asentaron los fundamentos de las Redes Neuronales Convolucionales basados en el Neocognitron [18]. Yann LeCun, en 1998 [39], fue capaz de mejorar este modelo introduciendo un método de aprendizaje basado en la propagación hacia atrás, backpropagation, para poder entrenar el modelo de forma eficiente y actualizar sus pesos automáticamente. La red neuronal convolucional (CNN) es el estado del arte para la tarea de clasificación de imágenes [59]. Son consideradas el modelo base para el tratamiento y clasificación de imágenes, así como el punto de partida para otros modelos más complejos. La Redes Neuronales convolucionales se consideran un caso particular de las redes densamente conectadas o perceptrón multicapa, como hemos denominado previamente, ya que todas las neuronas se encuentran conectadas entre sí. Su principal aportación es la operación de convolución, realizada en las neuronas que veremos en detalle en la sección 2.2.2. La diferencia fundamental entre una capa densamente conectada y una capa convolutiva es la siguiente: las primeras aprenden patrones globales en su espacio de características de entrada, mientras que, las segundas aprenden patrones locales; en el caso de las imágenes, patrones encontrados en pequeñas ventanas 2D de las entradas. Esta característica clave confiere a las Redes Convolucionales dos propiedades interesantes [9]: Los patrones que aprenden son invariables a la traslación. Después de aprender un determinado patrón en una zona de una imagen, una red convolucional puede 17 Capítulo 2. Fundamento Teórico reconocerlo en cualquier lugar. Una red densamente conectada (MLP) tendría que aprender el patrón de nuevo si apareciera en una nueva ubicación. Pueden aprender jerarquías espaciales de patrones. Por ejemplo, una primera capa de convolución aprenderá pequeños patrones locales, como los bordes, una segunda capa de convolución una segunda capa de convolución aprenderá patrones más grandes, compuestos por las características de las primeras capas, y así sucesivamente. Este permite a las Redes Convolutivas aprender eficazmente conceptos visuales cada vez más complejos y abstractos. Las Redes Convolucionales reciben este nombre porque aplican la operación matemática de la convolución. 2.2.2. Operación de convolución En su forma más general, la convolución es una operación sobre dos funciones con un argumento de valor real, en otras palabras, es una operación matemática que transforma dos funciones, fyg, en una tercera función que, en cierto sentido, representa la magnitud en la que se superponen fy una versión trasladada e invertida de g. s(t)=(x∗w)(t) = ∞ X a=−∞ x(a)·w(t−a).(2.10) En nuestro caso, el primer argumento, x, se refiere a la entrada Esta suele ser un array multidimensional, y el segundo argumento, w, se refiere a la función kernel o núcleo, que suele ser un array multidimensional de parámetros que acepta el algoritmo de aprendizaje de los pesos. La salida que se obtiene se conoce como feature map o mapa de características. De ahora en adelante, nos referiremos como Ia la función de entrada, que antes habíamos llamado xy, como K, a la función kernel que habíamos llamado w. Podemos adaptar esta fórmula de convolución 2.10 a un caso bidimensional y un a instante de tiempo fijo. Sería el caso de imágenes estáticas, como las que vamos a tratar en este trabajo. S(i, j)=(I∗K)(i, j) = X mXnI(m, n)K(i−m, j −n).(2.11) La convolución es conmutativa, lo que quiere decir que podemos escribirla de forma equivalente: S(i, j)=(K∗I)(i, j) = X mXnI(i−m, j −n)K(m, n).(2.12) Normalmente, esta última fórmula 2.12 es más sencilla de implementar, porque hay menos variación en el rango de valores válidos de myn. 18 2.2. Redes Neuronales Convolucionales La propiedad conmutativa de la convolución se debe a que hemos invertido el núcleo en relación con la entrada, en el sentido de que, a medida que maumenta, el índice de la entrada crece, pero el índice del núcleo disminuye. La única razón para dar la vuelta al núcleo es obtener la propiedad conmutativa. Aunque esta es útil para escribir demostraciones, no suele ser una propiedad importante en la implementación de red neuronal. En su lugar, muchas bibliotecas de Redes Neuronales implementan una función aislada llamada correlación cruzada, que es lo mismo que la convolución, pero sin invertir el núcleo: S(i, j) = (K∗I)(i, j) = X mXnI(i+m, j +n)K(m, n).(2.13) En la Figura 2.11, podemos ver un ejemplo de convolución bidimensional sin inversión del núcleo. Restringimos la salida sólo a las posiciones en las que el núcleo se encuentra completamente dentro de la imagen, lo que en algunos contextos se denomina convolución válida. Dibujamos recuadros con flechas, para indicar cómo se forma el elemento superior izquierdo del tensor de salida, aplicando el núcleo a la correspondiente región superior izquierda del tensor de entrada. Se aprecia cómo el tamaño del núcleo es menor que el de los datos de entrada y, por ello, la ventana del núcleo se va deslizando. Figura 2.11: Ejemplo de convolución 2D. Imagen de [21]. La convolución aprovecha tres ideas importantes que pueden ayudar a mejorar un sistema de aprendizaje automático: 19 Capítulo 2. Fundamento Teórico Conectividad dispersa. Solo un grupo pequeño de neuronas se activan en un cierto momento. Se consigue haciendo el kernel más pequeño, dimensionalmente hablando, que la entrada. Podemos procesar una imagen de entrada, que puede tener miles o millones de píxeles, y, sin embargo, detectar características pequeñas y significativas, como los bordes, con núcleos que sólo ocupan decenas o cientos de píxeles. Esto significa que necesitamos almacenar menos parámetros, lo que reduce los requisitos de memoria del modelo y mejora su eficiencia estadística. También el cálculo de su salida requiere de menos operaciones. Si hay mentradas y nsalidas, la multiplicación de matrices requiere m·nparámetros y el algoritmo tiene un coste temporal de ejecución del orden de O= (m·n). Si limitamos el número de conexiones que puede tener cada salida a k, entonces la aproximación de conectividad dispersa solo requiere k·nparámetros y tiene coste del orden O= (k·n), que mejora cuando kes más pequeño que m. Figura 2.12: Ejemplo de conectividad dispersa -convolución (arriba) frente a conectividad densa - mutiplicación matricial (abajo). Imagen de [21]. Parámetros compartidos. Se refiere a la utilización de un mismo parámetro para más de una función en el modelo. En una red neuronal habitual, MLP, cada parámetro se usa exactamente una vez para calcular la salida de una neurona de una capa. 20 2.2. Redes Neuronales Convolucionales Se dice que las Redes Convolucionales tienen pesos ligados por este motivo: un mismo peso o parámetro se utiliza varias veces. Cada miembro del núcleo se usa en todas las posiciones, aunque puede haber excepciones en los bordes. Esto reduce el número de parámetros del modelo a k, que solo tenemos que aprender una vez. Siendo kmás pequeño que m, los requisitos de memoria se vuelven insignificantes en la convolución, esto es, kmucho menor frente a la multiplicación de matrices n·m. Resulta mucho más eficiente en términos de memoria. Figura 2.13: Ejemplo de compartición de parámetros -convolución (arriba) frente a multiplicación densa de matrices (abajo). Imagen de [21]. En la Figura 2.13, podemos ver, en negro, cómo el núcleo se comparte en las Redes Convolucionales. Sin embargo, en MLP, cada peso afecta a una sola entrada (píxel). Representaciones equivalentes. Debido a que los parámetros son compartidos, se da la propiedad de equivalencia dentro de la capa. Una función es equivalente si: dado un cambio en la entrada, la salida cambia de la misma manera. Una función, f(x), es equivalente a otra, g, si: f(g(x)) = g(f(x)).(2.14) La convolución es equivalente ante la traslación, es decir, sería capaz de detectar un patrón en diferentes lugares de la imagen. Sin embargo, no es equivalente a otros cambios, como la rotación y el escalado. Son necesarios otros métodos para manejar este tipo de transformaciones. 21 Capítulo 2. Fundamento Teórico 2.2.3. Estructura de una capa convolucional Cada una de las capas convolucionales tiene tres partes [26]: Etapa de convolución. Se utiliza para extraer los patrones y características de la imagen. Se realiza la operación de convolución, vista en la sección 2.2.2, sobre la imagen de entrada con un tamaño de filtro, núcleo, determinado MxM. Se desliza el filtro sobre la imagen de entrada y se realiza el producto entre las partes de la imagen y el filtro. La salida se denomina mapa de características. Nos proporciona información sobre la imagen, como las esquinas y los bordes. Más tarde, este mapa de características alimenta a otras capas para aprender otras, a menudo de mayor complejidad. La capa realiza varias convoluciones en paralelo, para producir un conjunto de activaciones lineales. Cada activación lineal, se ejecuta a través de una función de activación no lineal, como la función de activación ReLU. En la mayoría de los casos, cada capa densa, va seguida de una reducción de dimensionalidad. Esto es, un agrupamiento del mapa de características para disminuir su tamaño. De esta manera, también se reduce el coste computacional en futuras operaciones. Esta operación se llama Pooling, agrupación, y la veremos más adelante en la sección 2.2.5. Capa densa o totalmente conectada, Fully Connected(FC). Cada una de las salidas de la capa anterior tiene una conexión con cada neurona de esta capa, contiene los pesos de todas estas conexiones. Sería equivalente a añadir un MLP al final de las etapas convolutivas. Suelen situarse antes de la capa de salida y forman las últimas capas de una arquitectura CNN. Requiere de un aplanado, Flatten, de la imagen o de la salida de las capas anteriores para obtener un vector de una dimensión. Llevan a cabo el proceso final de la tarea de clasificación. Figura 2.14: Esbozo de CNN. Imagen de [2]. 22 2.2. Redes Neuronales Convolucionales 2.2.4. Dimensionalidad Debemos destacar que las Redes Convolucionales no solo se utilizan para imágenes. Según el número de dimensiones que tenga la estructura de datos, dada como entrada, y la arquitectura de la red, puede tratarse uno u otro problema [36]. Una dimensión (1D): para datos temporales, vectores. Dos dimensiones (2D): para datos espaciales, matrices. Aquí entrarían las imágenes. Tres dimensiones (3D): para datos espaciales-temporales. Estaríamos hablando de una mezcla de los dos anteriores, se utiliza especialmente en el tratamiento de vídeo, que no deja de ser una secuencia temporal de imágenes. 2.2.5. Pooling Una función de agrupación sustituye la salida de la red en un lugar determinado por un estadístico de resumen de las salidas cercanas. Esto supone una reducción de la dimensionalidad, de forma que, el número de celdas consideradas cercanas se reduce a una sola con un único valor, el estadístico utilizado como resumen. La operación pooling ayuda a que la representación sea aproximadamente invariable frente a pequeñas traslaciones de la entrada. Podemos destacar las siguientes funciones de agrupación [36], haciendo referencia a dos dimensiones pero extensible a 1 y 3: MaxPooling: submuestrea la entrada a lo largo de sus dimensiones espaciales, altura y anchura, tomando el valor máximo en de la ventana de entrada. AveragePooling: submuestrea la entrada a lo largo de sus dimensiones espaciales, altura y anchura, tomando la media como valor de salida en la ventana de entrada. GlobalMaxPooling: en esencia, es igual que MaxPooling, pero ya tiene definido el tamaño de la ventana, que coincide con el tamaño del mapa de características. GlobalAveragePooling: en esencia es igual que AveragePooling pero ya tiene definido el tamaño de la ventana, que coincide con el tamaño del mapa de características. Se podría definir cualquier función matemática, con el fin de reducir el tamaño de la ventana a un solo valor, comom por ejemplo, el uso de estadísticos como el mínimo o la mediana. Sin embargo, los mostrados en esta sección son los más utilizados en la práctica. En todos los casos, el pooling ayuda a que la representación sea aproximadamente invariable a pequeñas traslaciones de la entrada. Esto significa que si se traslada la entrada en una pequeña cantidad, los valores de la mayoría de las salidas agrupadas no cambian. Puede ser una propiedad útil si nos importa más si alguna característica está presente, que dónde está exactamente. Por ejemplo, cuando se determina si una imagen contiene 23 Capítulo 2. Fundamento Teórico 2.4. Grad-CAM Gradient-weighted Class Activation Mapping [56] (Grad-CAM) es una técnica para producir explicaciones visuales en la toma de decisiones de una gran variedad de modelos basados en CNN. Utiliza los gradientes de cualquier concepto objetivo, que se propagan hacia la capa convolucional final, para producir un mapa de localización grueso, destacando, así, las regiones importantes en la imagen para predecir el concepto. En el contexto de los modelos de clasificación de imágenes, las visualizaciones obtenidas con Grad-CAM aportan información sobre sus modos de fallo. Son resistentes a las imágenes adversas. Superan a los métodos anteriores en cuanto a localización. Son más fieles al modelo subyacente y ayudan a lograr la generalización mediante la identificación de los sesgos del conjunto de datos. Figura 2.22: Arquitectura de Grad-CAM. Imagen de [56]. Las Redes Convolucionales retienen mucha información espacial que se pierde en MLP, por lo que podemos esperar, que las últimas capas convolucionales tengan el mejor compromiso entre la semántica de alto nivel y la información espacial detallada. Las neuronas de estas capas buscan información semántica específica de la clase en la imagen, en partes del objeto. Grad-CAM utiliza la información del gradiente, que se propaga hacia la última capa convolucional de la CNN, para asignar valores de importancia a cada neurona para una decisión concreta de interés. Para cuestiones matemáticas y más metodológicas, referimos a la publicación original [56]. Grad-CAM se utiliza para la diagnosis de la clasificación de imágenes en Redes Neuronales convolucionales. Podemos detectar los siguientes problemas. Análisis de los fallos del modelo. Podemos listar las imágenes mal clasificadas por el modelo y visualizar la contribución de zonas de la imagen a la predicción de la clase 30 2.4. Grad-CAM predicha y las zonas que contribuyen dicha predicción de la clase real. La ventaja que proporciona Grad-CAM es su alta resolución y capacidad de distinguir clases. Efecto del ruido adverso. Se ha demostrado la vulnerabilidad actual de las Redes Neuronales a ejemplos adversos, que son ligeras perturbaciones imperceptibles de las imágenes de entrada, que engañan a la red para que las clasifique erróneamente. sin embargo, con las visualizaciones de Grad-CAM, se encuentra la categoría real de la imagen aunque la red no la clasifique así. Esto demuestra que Grad-CAM es bastante robusto al ruido. Identificar sesgos. Los modelos pueden estar sesgados y no generalizar correctamente a los datos del mundo real. Vemos un ejemplo muy ilustrativo de cómo se emplea esta técnica para detectar sesgos en la Figura 2.23. Figura 2.23: Detección de sesgo con Grad-CAM. Imagen de [56]. Grad-CAM revela que, el modelo central utiliza características como el pelo o la cara para predecir la imagen como enfermera. En el modelo de la derecha, vemos como no hay sesgos relacionados con el sexo y consigue detectar el fonendoscopio para realizar las predicciones, así como el color de la ropa en la imagen inferior. 31 Capítulo 2. Fundamento Teórico 32 Capítulo 3 Metodología La metodología de trabajo habitual en proyectos de desarrollo de software no es óptima para llevar a cabos proyectos de investigación, o estudios con incertidumbre sobre los resultados y los entregables. Según Bob Hughes y Mike Cotterell [28], merece la pena realizar la planificación en proyectos inciertos, como los de investigación, siempre que los planes resultantes se consideren provisionales. Por ello, el capítulo 5 presenta una programación y planificación ligeramente ambigua, pero flexible, muy adecuada para los proyectos de ciencia de datos. 3.1. Proceso de desarrollo Se opta por el modelo Cross Industry Standard Process for Data Mining (CRISP-DM). Se trata de un estándar abierto del proceso que describe los enfoques comunes más usados por los expertos en Minería de Datos [17]. Consta de las siguientes etapas: 1. Comprensión del negocio. Se debe fijar y entender los objetivos del proyecto. 2. Comprensión de los datos. Se lleva a cabo la recogida de datos y la familiarización con estos. 3. Preparación de los datos. Pre-procesamiento de los datos para su utilización en la siguiente etapa de modelización. 4. Modelización. En este punto se ajustan y entrenan los modelos. 5. Evaluación. Se consideran los mejores modelos y se comprueba si satisfacen los objetivos del proyecto. 6. Despliegue. Se entregan los resultados finales, ya sea en un informe o mediante una aplicación. Podemos ver, en la Figura 3.1, la representación gráfica del ciclo CRIPS-DM. Como se puede observar, es un ciclo iterativo ya que, al avanzar en las diferentes etapas, puede ser necesario revisar las anteriores. 33 Capítulo 3. Metodología Figura 3.1: Ciclo CRISP-DM. 3.1.1. Entregables del proyecto Podemos nombrar las siguientes etapas como hitos del proyecto o considerarlos como objetivos en la metodología de trabajo descrita. Entregable 1. Red Neuronal funcional adaptada al problema tratado. Entregable 2. Red Neuronal mejorada con alta precisión en la clasificación. Entregable 3. Visualización Grad-CAM para una predicción concreta con un modelo especificado. Entregable 4. Aplicación funcional, que implemente los requisitos que se describirán en la sección 9.1.1. Debemos destacar, que cada entregable consiste en una mejora en la implementación o añadido de funcionalidad a lo anterior. Por ello, se presenta también un proceso de 34 3.2. Evaluación desarrollo incremental, en el que es necesario haber cumplido con el entregable anterior para el desarrollo del siguiente. 3.2. Evaluación Se decide mantener reuniones periódicas con el tutor cada semana o dos semanas, como máximo, para evaluar la evolución del proyecto. En cada etapa de las descritas en CRISP-DM, se realizan comprobaciones de las etapas anteriores en estas reuniones. Se valora el curso del proyecto, así como su tarea más inmediata, de acuerdo a la planificación establecida (ver sección 5). En cada tarea, se aborda el planteamiento y la forma, o posibles formas, de llevarla a cabo, ya sea uso de bibliotecas, decisiones sobre la implementación o el proyecto, etc. De forma coordinada con el tutor, se toman las decisiones clave para el correcto desarrollo del proyecto. Durante las últimas semanas, se tiene un contacto casi a diario entre alumno y tutor, para garantizar el éxito del proyecto, tanto la implementación y modelos, como la documentación y memoria. Se reciben las correspondientes correcciones, que se van incorporando para una entrega satisfactoria del presente TFG. Se utiliza el repositorio GitLab de la UVa para llevar un control de versiones del trabajo realizado. Podemos ver la estructura del repositorio en el Anexo B. Aquí el enlace al repositorio. 35 Capítulo 3. Metodología 36 Capítulo 4 Marco de trabajo En esta sección, se entrará más en detalle en las tecnologías específicas que se han empleado para el desarrollo del proyecto y de la aplicación. Asimismo, se defenderán los criterios por los que se han seleccionado las herramientas elegidas, comparándolas con otras alternativas, haciendo referencia a posibles ventajas e inconvenientes. 4.1. Herramientas utilizadas La clasificación supervisada consiste en asignar la etiqueta o clase correcta a una observación, tras haber procesado un conjunto de ellas ya etiquetadas. En particular, en este trabajo, se aborda un problema de clasificación supervisada, cuyos datos son imágenes. Para llevar a cabo esta tarea, se pueden emplear multitud de herramientas. Existe software específico como WEKA [64], que tiene una sencilla interfaz gráfica de usuario para la construcción de modelos predictivos con algunos hiperparámetros configurables. Otra opción sería MATLAB [23], que es una plataforma de programación y cálculo numérico utilizada para analizar datos, desarrollar algoritmos y crear modelos. Sin embargo, utilizaremos como base el lenguaje de programación Python, que es interpretado, cuya filosofía hace hincapié en la legibilidad de su código. Se trata de un lenguaje de programación multiparadigma, ya que soporta parcialmente la orientación a objetos, programación imperativa y, en menor medida, programación funcional. El motivo principal para optar por este lenguaje de programación es la multitud de bibliotecas disponibles que facilitan el código de algoritmos de Aprendizaje Automático. Podemos ver, a continuación, una comparativa entre las distintas posibilidades y las decisiones tomadas. 4.1.1. Hardware Para la elaboración de este proyecto se ha utilizado una máquina virtual prestada por el Departamento de Informática (ACT,CCIA y LSI) de la UVa con 4 núcleos virtuales, 37 Capítulo 4. Marco de trabajo con Intel 440FX. Respecto a la RAM, constaba de 16GB. Teniendo 50GB de tamaño de disco. 4.1.2. Sistema Operativo Antes de empezar a trabajar debemos elegir el sistema operativo de la Máquina Virtual. Solo hay disponibilidad de Linux y Windows. Cabe destacar que, el proyecto puede realizarse en cualquier sistema operativo, pero se toma la decisión de utilizar Linux por los siguientes motivos. Es el SO de referencia en la Escuela de Ingeniería Informática. Es gratis frente a Windows, que no lo es. Es más seguro en cuanto a la intrusión de virus y malware. Es de código abierto. Cualquiera puede acceder al código del SO y modificarlo, si así lo desea, en su máquina. Los servidores basados en Linux ofrecen un mejor rendimiento que los de Windows, aparte de la ingente documentación para su implementación, hecho que no tiene parangón con los construidos en Windows. Se ha utilizado [6] para realizar esta comparación entre Sistemas Operativos. 4.1.3. Lenguaje de programación En este punto, valoramos varios lenguajes de programación, tanto para la parte de Aprendizaje Automático, como para la parte de desarrollo de software. Los lenguajes considerados son los siguientes. Python. Julia. Matlab. R. PHP. HTML. JavaScript. 38 4.1. Herramientas utilizadas A continuación, expondremos las ventajas y desventajas de cada uno de ellos, así como una breve comparativa y las decisiones tomadas. Como comentario adicional, mencionamos que se decide utilizar un lenguaje de programación, frente al software específico, por la necesidad de crear modelos complejos muy adaptados al problema y por la capacidad de extensión de esto a una aplicación. En primer lugar, debemos elegir un lenguaje para crear nuestros modelos de Aprendizaje Automático, así como para gestionar y procesar los datos. Como primera opción, pensamos en los lenguajes de programación capaces de resolver este problema. Al ser una cuestión puramente matemática, aunque compleja, se podría resolver con cualquier lenguaje de programación. Sin embargo, existen muchos con bibliotecas que implementan la funcionalidad requerida por este proyecto. Julia es un lenguaje puramente pensado para proyectos de Machine Learning y, por tanto, consideramos difícil su extensión a una aplicación, a parte de ser un lenguaje nuevo con relativamente poca documentación publicada, lo que dificultaría su aprendizaje. A pesar de ofrecer grandes ventajas como la velocidad de cómputo [4], decidimos descartar este lenguaje. PHP, aunque es un gran lenguaje en el desarrollo web, apenas proporciona bibliotecas para la elaboración del proyecto, en la parte de modelado, siendo estas unas implementaciones de las cuestiones más simples sobre la metodología que se quiere utilizar, por tanto, también se deshecha este lenguaje. A continuación, queremos comparar los lenguajes más populares en el Aprendizaje Automático: R, Python y Matlab [48]. Este último está orientado al campo matemático, con el que apenas hemos trabajado a lo largo de la carrera y con una curva de aprendizaje muy lenta, por ello, se decide descartarlo. Entre Python y R, se encuentra un considerable equilibrio en las técnicas y en la multitud de bibliotecas orientadas al Aprendizaje Automático. No obstante, Python es un lenguaje mucho más amplio que no solo está orientado a la Minería de Datos, también al desarrollo de aplicaciones web. Asimismo proporciona una más fácil interacción con el paradigma de orientación a objetos, que resulta complejo en R. Por todo ello, tomamos la decisión de utilizar Python para llevar a cabo el desarrollo de este proyecto. Python nos da la libertad de configurar los parámetros, salidas y resultados tanto como queramos en comparación con WEKA, que tiene una interfaz bien definida y solo puedes hacer uso de ella. Igualmente, Python proporciona bibliotecas útiles para cálculo matemático, emulando así la funcionalidad de MATLAB. Todo ello, sumado al previo uso de Python durante los estudios y trabajos académicos, fomenta la decisión de utilizar este lenguaje de programación en este TFG. Como herramienta, también se utilizará Anaconda, una aplicación que configura un entorno virtual, con el lanzamiento de cuadernos Jupyter, que permiten la ejecución de código por celdas y la impresión de resultados por pantalla. 39 Capítulo 5. Planificación Figura 5.1: Diagrama de Gantt para el proyecto. 46 Capítulo 6 Datos 6.1. Descripción de los datos Contamos con un conjunto de imágenes correspondientes a radiografías de tórax procedentes de una competición publicada en Kaggle. Está compuesto por 2905 imágenes con un tamaño de 1024x1024 píxeles repartidas en tres clases o categorías. Normal. Sin ninguna enfermedad o sano. Neumonía. Con neumonía, pero negativo Covid. En el conjunto de datos lo llaman Viral Pneumonia o neumonía vírica. Covid-19. Positivo en Covid-19. Las imágenes de las clases Normal y Viral Pneumonia están en escala de grises y, por lo tanto, solo tienen un canal. Las de la clase Covid-19 están en formato RGB y, por ello, tienen tres canales. Se toma la decisión inicial de tratar todas las imágenes de la misma manera, entonces se transforman las imágenes en color a escala de grises, para poder tratarlas de manera uniforme en nuestros modelos de Aprendizaje Automático. Las imágenes normales, junto con las de neumonía vírica, proceden de la base de datos de Kaggle de Paul Moore, Chest X-Ray Images (Pneumonia) [11]. Mientras que, las imágenes positivas de COVID-19 se recogen de varias fuentes abiertas: la base de datos COVID-19 de la Sociedad Italiana de Radiología Médica e Intervencionista, Società italiana di Radiologia Medica e Interventistica(SIRM), del conjunto de datos Novel Corona Virus 2019 (nCOVID-19) de Joseph Paul Cohen, Paul Morrison y Lan Dao, y de otras 43 publicaciones diferentes [54]. 47 Capítulo 6. Datos (a) Normal (b) Pneumonía vírica (c) Covid-19 Figura 6.1: Muestra de imágenes de cada clase. 6.2. Preprocesado 6.2.1. División del conjunto Los datos originales se dividen en dos grupos: entrenamiento y prueba. De esta manera, se pretende ajustar un modelo capaz de generalizar a datos que nunca ha visto. Esto lo conseguimos reservando un conjunto de observaciones, que el modelo nunca ve en su etapa de entrenamiento y solamente se usan para obtener una estimación del error que no sea optimista, esto es, una estimación justa del error. Esta técnica se conoce, en metodología experimental, como hold-out o método de resorte. Reservamos un 33.3% de observaciones del total para construir el conjunto de prueba. El 66.6 % restante constituirá el conjunto de entrenamiento. El reparto de observaciones entre ambos grupos se realiza con un muestreo de forma estratificada, para que todas las clases tengan un mismo porcentaje de observaciones representativo de la distribución inicial, es decir, se mantiene la distribución inicial de clases en los dos subconjuntos de entrenamiento y de prueba. Podemos ver, de forma gráfica, en qué consiste este método en la Figura 6.2. La situación ideal, en estos casos, es contar también con un conjunto de validación que se usa para elegir el modelo óptimo y, posteriormente, se emplea el conjunto de prueba para obtener una estimación del error verdadero. En este trabajo, por la escasez de observaciones, se prescinde del conjunto de validación. En la Tabla 6.1, podemos observar la distribución de clases de los datos. 48 6.2. Preprocesado Figura 6.2: Metodología Hold-out. Clases Conjunto de entrenamiento Conjunto de prueba Total Covid-19 146 73 219 Pneumonia 896 449 1345 Normal 894 447 1341 Tabla 6.1: Distribución de clases. En la Figura 6.3, podemos ver la distribución de clases en el conjunto de datos original. 49 Capítulo 6. Datos Figura 6.3: Gráfico de barras para la clase de los datos originales. En la Figura 6.4, apreciamos la distribución de clases en el conjunto de entrenamiento tras el muestreo de estos con la técnica, previamente mencionada: hold-out. Figura 6.4: Gráfico de barras para la clase de los datos de entrenamiento. Finalmente, observamos, en la Figura 6.5, la distribución de clases en el conjunto de prueba. 50 6.2. Preprocesado Figura 6.5: Gráfico de barras para la clase de los datos de prueba. 6.2.2. Normalización Las imágenes son sometidas a un proceso de normalización. Se escalan para que todos los valores de los píxeles se encuentren en el entorno [0,1]. Podemos realizar esta operación con la Fórmula 6.1. Xi=Xi−Xmin Xmax −Xmin (6.1) En nuestro caso, el valor mínimo de un píxel es 0 y el máximo 255. Por tanto, en la práctica, podemos efectuar esta operación dividiendo el valor de cada píxel entre 255. 51 Capítulo 6. Datos 52 Capítulo 7 Construcción del sistema Como ya se ha comentado, se ha elegido Python como lenguaje de programación para el desarrollo del proyecto, tanto los modelos de Aprendizaje Profundo, como el desarrollo de la aplicación. Utilizaremos, principalmente, el paquete Keras para desarrollar estos modelos de Aprendizaje Profundo. Keras es una API de alto nivel construida sobre TensorFlow, quien proporciona el back-end o motor de ejecución. Habitualmente, estas dos bibliotecas se usan de manera simultánea, ya que TensorFlow proporciona los medios para la realización de procesos. Por su parte, Keras construye una abstracción de alto nivel, para que estos procesos sean fácilmente usables. Tanto es así, que el propio TensorFlow incorpora los módulos de Keras. Es más, esta implicación es en ambos sentidos, ya que si importamos la librería de Keras, esta trae consigo sus dependencias, entre ellas, TensorFlow. 7.1. Lectura de datos Contamos con un cierto número Nde imágenes de 1024x1024 píxeles. Podríamos almacenarlas en memoria con una matriz de dimensiones Nx1024x1024. Sin embargo, esto rompe con cualquier almacenamiento de memoria, en tiempo de ejecución, y no nos permite el tratamiento de estas imágenes de la manera habitual. Buscamos una forma de cargar estas imágenes en memoria, en el momento que vayan a ser utilizadas. En cada época de entrenamiento, el número de imágenes utilizadas no es el total del conjunto de train, sino un pequeño subconjunto de estas llamado batch o lote. Idealmente, este número debe ser lo suficientemente pequeño para que todas las imágenes tengan una gran influencia y los pesos se actualicen de forma adecuada, pero también suficientemente grande para no ralentizar de forma notable el proceso de entrenamiento. Como indica Yan LeCun, conocido como el padre de las Redes Convolucionales, el tamaño ideal de batch sería de 1, si las condiciones computacionales nos lo permiten [40, 42] y, en cualquier caso, este tamaño no debería superar las 32 muestras. 53 Capítulo 7. Construcción del sistema Aprovechamos este hecho para cargar únicamente un número fijado de imágenes en memoria al mismo tiempo, así, podemos satisfacer las restricciones de memoria de la máquina en la que estamos trabajando. Fijamos un tamaño de lote múltiplo del número de observaciones tanto para el conjunto de prueba, como para el de entrenamiento logrando, de esta forma, que todas las imágenes se utilicen el mismo número de veces. Esto nos hace no respetar la recomendación de Yan LeCun, ya que utilizamos 44 muestras en el conjunto de entrenamiento y 19 en el de prueba como lote. Utilizamos un generador de imágenes proporcionado por la librería Keras. Tiene la función principal de crear una estructura de datos iterable con las imágenes de un directorio sin cargar su totalidad en memoria, es decir, las almacena dinámicamente de la manera indicada anteriormente: en la etapa de entrenamiento o prueba se guardan las imágenes correspondientes al lote actual. Este generador permite también utilizar técnicas de Data Augmentation. Utilizamos dos generadores, uno para el conjunto de entrenamiento y, otro, para el de prueba. Ambos realizan una lectura de imágenes en escala de grises, como se ha descrito previamente en la sección 6. Igualmente, son capaces de aplicar la normalización descrita en la sección 6.1. En ciertos puntos de la etapa de entrenamiento, se producen unos picos de uso de memoria que colapsan el proceso. Se toma la decisión de aumentar el área de memoria swap o de intercambio, para soportar esos picos y poder continuar con la ejecución del proceso con normalidad. Otra posibilidad podría haber sido la reducción del tamaño de lote, a cambio de aumentar considerablemente el tiempo de ejecución de cada época del entrenamiento. Data Augmentation Es una técnica que consiste en realizar ligeras modificaciones a imágenes ya existentes para obtener otras nuevas, las cuales comparten etiqueta. Se basa en la aplicación de transformaciones tales como rotación o escalado. Su objetivo principal es aumentar el número de imágenes disponibles, cuando la muestra es pequeña y reducir, así, el sobreajuste al introducir más variabilidad. En nuestro trabajo, se ha tomado la decisión de no utilizar esta técnica, pues las imágenes radiológicas de tórax son muy concretas, precisas y no tienen rotaciones ni escalados, puesto que se toman siempre de la misma manera. Es más, si una prueba no tiene un resultado satisfactorio, en cuanto a la imagen obtenida se refiere, el técnico de Radiología repite la prueba hasta obtener el resultado esperado. Por ello, consideramos que incluir variabilidad en las imágenes, puede no resultar beneficioso en el proceso de clasificación. 54 7.2. Creación de modelos 7.1.1. Lectura de datos alternativa Para evitar la utilización del área de memoria de intercambio, se propone utilizar otra forma de lectura de datos proporcionada por la biblioteca TensorFlow. Se opta por el formato de archivo recomendado para los conjuntos de datos de TensorFlow que es TFRecord. Este es un formato binario simple orientado a registros que contiene mensajes de búfer de protocolo de tf.train.Example, donde cada registro contiene uno o más atributos. Estos se convierten en tensores, cuando se ingresan en el modelo con fines de entrenamiento [12]. En la sección de 7.6, se proporciona, además, la versión adaptada a esta lectura de datos. 7.2. Creación de modelos Para la redacción de este capítulo, utilizaremos el libro de F. Chollet [8]. Un modelo de Aprendizaje Profundo es un grafo acíclico y dirigido de capas, como vimos en la sección 2.1. La praxis más común es el apilado de capas con un mapeado individual de cada entrada a cada salida. La API de Keras proporciona dos posibilidades igual de válidas para la implementación de estos modelos. 1. Sequential: se utiliza cuando las conexiones entre las neuronas de una capa y la siguiente son completas o densas, es decir, todas las neuronas de una capa tienen como entrada la salida de todas las neuronas de la capa anterior. Por supuesto, su salida se propaga a todas las neuronas de la capa siguiente. Podemos ver un ejemplo de esta estructura de red en la Figura 7.1. 2. functional API : se denomina API funcional a la estructura abierta del grafo en la organización de capas y neuronas. Esta permite, como ventaja sobre Sequential, un añadido de complejidad estructural en cuanto a las conexiones de neuronas entre capas. Asimismo, permite una conexión densa jugando el mismo papel que Sequential. Podemos ver un ejemplo de esta estructura de red en la Figura 7.2. En este trabajo, utilizaremos los modelos secuenciales, ya que trataremos de implementar Redes Neuronales de pocas capas. Por tanto, las arquitecturas secuenciales nos permiten explorar el desempeño de esta metodología. 7.2.1. Capas convolucionales El siguiente paso en la creación de un modelo sería el apilado de capas. Como hemos decidido utilizar el modelo secuencial, la manera de apilar una capa a la secuencia ya existente es con la función add(), cuyo argumento será la siguiente capa. Automáticamente 55 Capítulo 7. Construcción del sistema use_multiprocessing: valor booleano que indica si se utiliza o no procesamiento en paralelo. Por defecto, es falso, no se utiliza. La función de ajuste retorna un objeto de tipo History, en el cual se almacena, entre otras cosas, la información correspondiente a la función de pérdida y las métricas en cada época del proceso de entrenamiento. 7.5. Evaluación Tras construir el modelo y entrenar sus parámetros, interesa comprobar su funcionamiento con los datos reservados para evaluación, básicamente, estimando su tasa de error. La función evaluate(), disponible en la API de Keras [32], nos proporciona una herramienta útil para el desarrollo de esta tarea. Esta función necesita los siguientes argumentos: x: son los datos de entrada. Podría ser una array de Numpy, un Tensor o un dataset de TensorFlow, como es nuestro caso. y: son los datos objetivo: la clase de cada imagen. batch_size: un número entero que represente el tamaño del lote. En nuestro caso, ya se ha especificado en el generador del dataset. verbose: ’auto’, 0, 1, o 2.Hace referencia a la información de salida del porceso de entrenamiento: 0 = silencioso, 1 = barra de progreso, 2 = una linea para cada época. Por defecto, es 1. sample_weight: matriz de pesos para ponderar la función de pérdida con las muestras de entrenamiento. Por defecto, no se aplica. steps: número total de pasos, lotes, antes de declarar terminada la ronda de evaluación. Se ignora con el valor por defecto de None, en cuyo caso se ejecutará hasta que se agote el conjunto de datos. callabacks: lista de callabacks aplicadas durante la evaluación. max_queue_size: tamaño máximo de la cola del generador, si no se especifica vale 10. workers: número máximo de procesos que se pueden ejecutar en paralelo cuando se utiliza un proceso basado en hilos. Por defecto será 1. use_multiprocessing: valor booleano que indica si se utiliza, o no, procesamiento en paralelo. 62 7.6. Implementación return_dict: booleano que establece si los resultados se devuelven como un diccionario, True, o como una lista, False. Retorna un objeto con los resultados de la evaluación, tanto para la función de coste, como para las métricas establecidas. 7.6. Implementación En esta sección, veremos paso a paso la implementación del modelo completo, desde el tratamiento de las imágenes de entrada, hasta la topología de la red y la evaluación de esta. Por simplicidad, se omiten las introducciones en las que se importan los paquetes y bibliotecas utilizados. 7.6.1. División de datos Obtenemos los nombres de los ficheros para almacenarlos, en una etapa posterior, divididos en conjunto de entrenamiento y de prueba. 1mypath = "/ home / usuario / Escritorio / TFG / datos / COVID -19 " 2covid_files = [f for fin os. listdir ( mypath )] 3 4mypath = "/ home / usuario / Escritorio / TFG / datos / NORMAL " 5normal_files = [f for fin os. listdir ( mypath )] 6 7mypath = "/ home / usuario / Escritorio / TFG / datos / Viral Pneumonia " 8pneumonia_files = [f for fin os . listdir ( mypath )] 9 10 clase_n = [’NORMAL’ for iin range (0 , len(normal_files))] 11 clase_p = [’Viral Pneumonia ’ for iin range (0, len( pneumonia_files ))] 12 clase_c = [’COVID -19 ’ for iin range (0, len(covid_files))] 13 14 clase = clase_n+clase_p+clase_c 15 16 df = pd . DataFrame ( list(zip( files , clase )) , columns =[ ’ FILENAME ’,’CLASS ’ ]) 17 18 train , test = train_test_split (df , test_size =1/3 , stratify = df. CLASS ) 19 20 for iin range ( train . shape [0]) : 21 # train . iloc [i ,1] = CLASE 22 # train . iloc [i ,0] = FILE NAME 23 src = os. path .join ("/ home / usuario / Escritorio / TFG / datos ",str( train . iloc[i,1]),str( train . iloc [i ,0]) ) 24 dst = os. path .join ("/ home / usuario / Escritorio / TFG / datos / train ",str( train .iloc [i ,1]) ,str ( train . iloc [i ,0]) ) 25 shutil . copyfile (src , dst ) 26 27 for iin range ( test . shape [0]) : 28 # train . iloc [i ,1] = CLASE 63 Capítulo 7. Construcción del sistema 29 # train . iloc [i ,0] = FILE NAME 30 src = os. path .join ("/ home / usuario / Escritorio / TFG / datos ",str(test. iloc[i,1]),str(test.iloc[i,0])) 31 dst = os. path .join ("/ home / usuario / Escritorio / TFG / datos / test ",str( test.iloc[i,1]),str( test .iloc [i ,0]) ) 32 shutil . copyfile (src , dst ) Con esto, hemos logrado leer los nombres de todos los ficheros, de imágenes, en la carpeta de datos, separarlos de forma aleatoria y estratificada en dos subconjuntos: entrenamiento, 66.67%, y, prueba, 33.33%. Con esta distribución, se copian las imágenes en dos nuevos directorios independientes para cada subconjunto. 7.6.2. Lectura Vemos cómo, con los subconjuntos creados, utilizamos el generador de datos proporcionado por la API de Keras, para confeccionar un lector de datos, que usaremos en la etapa de prueba y entrenamiento. Serán dos datasets independientes, uno para los datos de entrenamiento y otro para los datos de prueba. El tamaño se elige múltiplo del número total de observaciones, para que todas las imágenes se utilicen igual cantidad de veces. Se omiten las importaciones de paquetes y bibliotecas. En la lectura de los datos se aplica el procesamiento descrito: normalización y transformación a escala de grises. 1img_gen = keras . preprocessing . image . ImageDataGenerator ( rescale =1./255. , dtype = float ) 2 3train_dataset = keras . preprocessing . image . DirectoryIterator ( directory = ’ ../ datos / train /’, image_data_generator = img_gen , target_size =(1024 ,1024) , batch_size =44 , color_mode =" grayscale ") 4 5test_dataset = keras . preprocessing . image . DirectoryIterator ( directory = ’ ../ datos / test /’, image_data_generator = img_gen , target_size =(1024 ,1024) , batch_size =19 , color_mode =" grayscale " , shuffle = False ) 7.6.3. Lectura alternativa Esta lectura no necesitaría hacer uso del área swap de memoria, ya que sigue las recomendaciones de TensorFlow en el tratamiento de conjuntos de datos [61]. Se realiza el mismo preprocesado que en la lectura anterior. 1class_dict = {’NORMAL ’: 0, ’COVID -19 ’:1, ’Viral Pneumonia ’:2} 2num2label = {0: ’NORMAL ’, 1: ’COVID -19 ’, 2: ’Viral Pneumonia ’} 3 4TRAIN_LABELS = [] 5TEST_LABELS = [] 6 7for filename in TRAIN_IMGS: 8label = str ( filename . split ( ’/’)[4]) 64 7.6. Implementación 9# print ( label ) 10 assert label in [’NORMAL’,’COVID -19 ’,’Viral Pneumonia ’] 11 label = int ( class_dict [ label ]) 12 TRAIN_LABELS . append ( label ) 13 14 for filename in TEST_IMGS : 15 label = str ( filename . split ( ’/’)[4]) 16 # print ( label ) 17 assert label in [’NORMAL’,’COVID -19 ’,’Viral Pneumonia ’] 18 label = int ( class_dict [ label ]) 19 TEST_LABELS . append ( label ) 20 21 NCLASSES = 3 22 SIZE = (1024 ,1024) 23 24 def decode_image ( filename , label = None , image_size = SIZE ): 25 26 bits = tf.io. read_file ( filename ) 27 image = tf. image . decode_png ( bits , channels =1) 28 image = tf. cast ( image , tf. float32 ) / 255.0 29 image = tf. image . resize ( image , image_size ) 30 31 if label is None: 32 return image 33 else: 34 return image , label 35 36 AUTO = tf. data . experimental . AUTOTUNE 37 38 train_dataset = ( 39 tf. data . TFRecordDataset 40 . from_tensor_slices (( TRAIN_IMGS , TRAIN_LABELS )) 41 .map( decode_image , num_parallel_calls = AUTO ) 42 .repeat() 43 . shuffle (1024) 44 . batch (44) 45 ) 46 47 test_dataset = ( 48 tf. data . TFRecordDataset 49 . from_tensor_slices (( TEST_IMGS , TEST_LABELS )) 50 .map( decode_image , num_parallel_calls = AUTO ) 51 . batch (19) 52 ) 7.6.4. Construcción del modelo Planteamos el modelo óptimo que hemos logrado obtener, en cuanto a tasa de acierto se refiere. Su topología es como sigue. La última capa requiere 3 neuronas y una función de activación softmax, ya que estamos ante un problema de clasificación con tres categorías. 65 Capítulo 7. Construcción del sistema La salida de cada una de ellas juega el papel de probabilidad de pertenencia a la clase que hace referencia esa neurona. 1model = models . Sequential () 2model . add ( layers . Conv2D (8 , (3 ,3) , activation =" relu ", input_shape =(1024 , 1024 , 1))) 3model . add ( layers . Conv2D (8 , (3 ,3) , activation =" relu ")) 4model . add ( layers . MaxPooling2D ((3 , 3))) 5model . add ( layers . Conv2D (16 , (3 ,3) , activation =" relu ")) 6model . add ( layers . Conv2D (16 , (3 ,3) , activation =" relu ")) 7model . add ( layers . MaxPooling2D ((2 ,2) )) 8model . add ( layers . Conv2D (32 , (3 ,3) , activation =" relu ")) 9model . add ( layers . Conv2D (32 , (3 ,3) , activation =" relu ")) 10 model . add ( layers . MaxPooling2D ((2 ,2) )) 11 model . add ( layers . Conv2D (64 , (3 ,3) , activation =" relu ")) 12 model . add ( layers . Conv2D (64 , (3 ,3) , activation =" relu ")) 13 model . add ( layers . MaxPooling2D ((2 ,2) )) 14 model . add ( layers . Conv2D (128 , (3 ,3) , activation =" relu")) 15 model . add ( layers . Conv2D (128 , (3 ,3) , activation =" relu")) 16 model . add ( layers . MaxPooling2D ((2 ,2) )) 17 model . add ( layers . Flatten ()) 18 model . add ( layers . Dense (256 , activation =" relu")) 19 model . add ( layers . Dense (3 , activation ="softmax")) 7.6.5. Compilación del modelo Se compila el modelo para fijar su topología y estructura antes de entrenar sus parámetros. De esta forma, asigna la función de périda, las métricas y el optimizador. 1model . compile( loss ="categorical_crossentropy", optimizer = optimizers . RMSprop (lr =1e -4) , metrics =["acc"]) 7.6.6. Entrenamiento Calculamos el ajuste de parámetros para el conjunto de entrenamiento y el resto de ejemplos se reservan para validación. Con ello, se observará como se comporta el modelo, ante datos que nunca ha visto o que no ha utilizado en la etapa de actualización de pesos. 1history = model . fit ( 2train_dataset , 3epochs = 100 , 4verbose = 1, 5validation_data = test_dataset ) 7.6.7. Evaluación Una vez que el modelo ya está entrenado, pasamos los datos del conjunto de prueba y observamos su comportamiento. Se obtiene una estimación del error de generalización, o 66 7.6. Implementación error verdadero, así como unos estadísticos resumen sobre el comportamiento del modelo con estos datos y la matriz de confusión. Podemos ver estos resultados en la sección 8 1Y_pred = model . predict ( test_dataset ) 2y_pred = np. argmax ( Y_pred , axis =1) 3target_names = [’COVID -19 ’,’NORMAL ’,’Viral pneumonia ’] 4c_matrix = confusion_matrix ( test_dataset . classes , y_pred ) 5c_report = classification_report ( test_dataset . classes , y_pred , target_names=target_names) 7.6.8. Grad-CAM Para elaborar el mapa de calor de activación de la imagen utilizamos la referencia de la propia API de Keras [10]. 1model_builder = keras . applications . xception . Xception 2preprocess_input = keras . applications . xception . preprocess_input 3decode_predictions = keras . applications . xception . decode_predictions 4 5model =tf. keras . models . load_model ("modeloGrey9M.h5") 6dims = model . input_shape [1:3] 7 8image_uri = ’/ home / usuario / Escritorio / TFG / datos / test / COVID -19/ COVID -19(135) . png ’ 9 10 im = keras . preprocessing . image . load_img ( image_uri , target_size = dims 11 , color_mode =" grayscale " 12 ) 13 last_conv_layer_name = " conv2d_9 " 14 15 def get_img_array ( img_path , size ): 16 # ‘img ‘ is a PIL image of size 299 x299 17 img = keras . preprocessing . image . load_img ( img_path , target_size = size , color_mode =" grayscale ") 18 # ‘array ‘ is a float32 Numpy array of shape (299 , 299 , 3) 19 array = keras . preprocessing . image . img_to_array ( img) 20 # We add a dimension to transform our array into a " batch " 21 # of size (1 , 299 , 299 , 3) 22 array = np. expand_dims ( array , axis =0) 23 return array 24 25 26 def make_gradcam_heatmap ( img_array , model , last_conv_layer_name , pred_index = None ): 27 # First , we create a model that maps the input image to the activations 28 # of the last conv layer as well as the output predictions 29 grad_model = tf. keras . models . Model ( 30 [ model . inputs ], [ model . get_layer ( last_conv_layer_name ). output , model . output ] 31 ) 67 Capítulo 7. Construcción del sistema 32 33 # Then , we compute the gradient of the top predicted class for our input image 34 # with respect to the activations of the last conv layer 35 with tf. GradientTape () as tape : 36 last_conv_layer_output , preds = grad_model ( img_array ) 37 if pred_index is None: 38 pred_index = tf. argmax ( preds [0]) 39 class_channel = preds [: , pred_index ] 40 41 # This is the gradient of the output neuron (top predicted or chosen ) 42 # with regard to the output feature map of the last conv layer 43 grads = tape . gradient ( class_channel , last_conv_layer_output ) 44 45 # This is a vector where each entry is the mean intensity of the gradient 46 # over a specific feature map channel 47 pooled_grads = tf. reduce_mean (grads , axis =(0 , 1, 2)) 48 49 # We multiply each channel in the feature map array 50 # by "how important this channel is" with regard to the top predicted class 51 # then sum all the channels to obtain the heatmap class activation 52 last_conv_layer_output = last_conv_layer_output[0] 53 heatmap = last_conv_layer_output @ pooled_grads [... , tf. newaxis ] 54 heatmap = tf.squeeze(heatmap) 55 56 # For visualization purpose , we will also normalize the heatmap between 0 & 1 57 heatmap = tf . maximum ( heatmap , 0) / tf .math . reduce_max ( heatmap ) 58 return heatmap . numpy () 59 60 # Prepare image 61 img_array = preprocess_input ( get_img_array ( image_uri , size =dims )) 62 63 64 # Make model 65 model =tf. keras . models . load_model ("modeloGrey9M.h5") 66 # Remove last layer ’s softmax 67 model . layers [ -1]. activation = None 68 69 # Print what the top predicted class is 70 preds = model . predict ( img_array ) 71 print (" Predicted :" , preds ) 72 73 # Generate class activation heatmap 74 heatmap = make_gradcam_heatmap(img_array, model, last_conv_layer_name) 75 76 def save_and_display_gradcam ( img_path , heatmap , cam_path ="cam .jpg", alpha =0.4) : 77 # Load the original image 68 7.6. Implementación 78 img = keras . preprocessing . image . load_img ( img_path , color_mode =" grayscale ") 79 img = keras . preprocessing . image . img_to_array ( img) 80 81 # Rescale heatmap to a range 0 -255 82 heatmap = np. uint8 (255 * heatmap ) 83 84 # Use jet colormap to colorize heatmap 85 jet = cm. get_cmap (" jet") 86 87 # Use RGB values of the colormap 88 jet_colors = jet (np. arange (256) )[: , :3] 89 jet_heatmap = jet_colors [ heatmap ] 90 91 # Create an image with RGB colorized heatmap 92 jet_heatmap = keras . preprocessing . image . array_to_img ( jet_heatmap ) 93 jet_heatmap = jet_heatmap . resize (( img . shape [1] , img . shape [0]) ) 94 jet_heatmap = keras . preprocessing . image . img_to_array ( jet_heatmap ) 95 96 # Superimpose the heatmap on original image 97 superimposed_img = jet_heatmap * alpha + img 98 superimposed_img = keras . preprocessing . image . array_to_img ( superimposed_img) 99 100 # Save the superimposed image 101 superimposed_img . save ( cam_path ) 102 103 # Display Grad CAM 104 display ( Image ( cam_path )) 105 106 107 save_and_display_gradcam ( image_uri , heatmap ) 69 Capítulo 7. Construcción del sistema 70 Capítulo 8 Resultados En este capítulo, comentaremos cuáles han sido los resultados obtenidos, el mejor modelo que hemos encontrado, la tasa de error, matriz de confusión e interpretabilidad obtenida para futuras observaciones. 8.1. Evaluación del modelo Tras ajustar los hiperparámetros manualmente y entrenar el modelo con los ejemplos, se efectúa el proceso de evaluación. Esto consiste en, con los datos reservados y no utilizados en la actualización de pesos de la red, pasar cada una de las observaciones por el modelo y obtener su clase predicha. Posteriormente, se compara esta clase con la real y, con esto, se obtiene una estimación de la tasa de error verdadero o, equivalentemente, del porcentaje de buena clasificación. Cabe destacar, que los datos utilizados para la estimación del porcentaje de buena clasificación no han sido utilizados en la etapa de entrenamiento para actualizar los pesos del modelo, pues esto podría llevarnos a sobreajustar las observaciones existentes y obtener, así, una tasa muy elevada pero con una capacidad escasa de generalización. Igualmente, es deseable comentar, que la escasez de datos y potencia computacional nos lleva a realizar un experimento de hold-out, en el cual la partición inicial resulta claramente influyente, tanto en la construcción y entrenamiento del modelo, como en la estimación de su tasa de acierto. Debemos destacar también, que el modelo se elige, de entre los modelos candidatos, el que menor error comente, tanto con los datos de entrenamiento, como con los datos de prueba. Esto podría suponer beneficios, pues es el que mejor se comporta con los datos que aún no ha visto el modelo. Sin embargo, no podemos garantizar plenamente su bondadporque sabemos que el modelo comete un error más bajo para estos datos de prueba, pues han sido los que se han utilizado para la selección del modelo. De esta manera, corremos los riesgos de que: 71 Capítulo 9. Aplicación Identificador Nombre Descripción RF-01 Selección de imagen El sistema debe permitir al usuario seleccionar una imagen. RF-02 Procesado de imagen El sistema debe ser capaz de procesar la imagen seleccionada. RF-03 Diagnóstico El sistema debe ser capaz calcular el diagnóstico a partir de una imagen. RF-04 Explicación El sistema debe ser capaz de calcular la explicación para la predicción dada. RF-05 Mostrar resultados El sistema debe mostrar el diagnóstico obtenido y la explicación para este. RF-06 Número de usos El sistema debe permitir al usuario realizar tantos diagnósticos como desee. Tabla 9.1: Requisitos funcionales. Requisitos no funcionales Los requisitos no funcionales también llamados atributos de calidad, en la ingeniería de software, son aquellos que especifican criterios que pueden usarse para juzgar la operación de un sistema, en lugar de sus comportamientos específicos, ya que estos corresponden a los requisitos funcionales. Dicho con otras palabras: se refieren a los requisitos que describen características de funcionamiento, por eso, suelen denominarse atributos de calidad de un sistema. Son las restricciones o condiciones que impone el cliente al programa que necesita, por ejemplo, el tiempo de entrega del programa, el lenguaje o la cantidad de usuarios. Se muestran en la Tabla 9.2 Requisitos de Información Describen la información que debe almacenar y gestionar el sistema para dar soporte a los procesos de negocio. Se muestran en la Tabla 9.3 9.1.2. Casos de uso Utilizamos los diagramas de caso de uso para especificar las acciones y la comunicación entre un usuario y nuestro sistema. Podemos observar el diagrama de casos de uso en la Figura 9.1. Subir imagen 78 9.1. Análisis Identificador Nombre Descripción RNF-01 Accesibilidad El sistema debe permitir a cualquier usuario hacer uso del mismo. RNF-02 Formato de imagen El sistema debe permitir imágenes en varios formatos. RNF-03 Tiempo El sistema debe ser capaz de mostrar el resultado en un tiempo inferior a un minuto. RNF-04 Seguridad El sistema debe crear una clave para encriptar las cookies. RNF-05 Plataforma El sistema se debe desarrollar en Python 3.8.5. Tabla 9.2: Requisitos no funcionales. Identificador Nombre Descripción RI-01 Modelos El sistema debe almacenar los modelos utilizados para llevar a cabo el diagnóstico. RI-02 Diagnóstico El sistema debe guardar la imagen durante el proceso de diagnóstico. RI-03 Resultados El sistema debe almacenar el diagnóstico y la imagen obtenida en la explicación hasta finalizar la visualización de resultados. Tabla 9.3: Requisitos de Información. Nombre e ID del CU CU-01. Subir imagen Actor Usuario Descripción El usuario selecciona la imagen de la cual desea obtener su diagnóstico desde su máquina local. Precondiciones 1. La aplicación esta en proceso de ejecución y escuchando peticiones. 2. El usuario ha accedido a la dirección web donde está desplegada la aplicación. 79 Capítulo 9. Aplicación Postcondiciones 1. La imagen queda almacenada en el sistema. Flujo normal 1. El usuario introduce la imagen que quiere diagnosticar en sistema. 2. El sistema comprueba la extensión de la imagen. 3. El sistema almacena la imagen. 4. El sistema muestra el nombre de la imagen. Flujo alternativo 2a. Si la extensión de la imagen no es correcta o no está contemplada en el sistema. El sistema muestra un mensaje de error y vuelve a la pantalla de inicio. Tabla 9.4: CU-01. Subir imagen. Diagnosticar Nombre e ID del CU CU-02. Diagnosticar Actor Usuario Descripción El usuario solicita el diagnóstico de la imagen previamente cargada. Precondiciones 1. El sistema tiene la imagen almacenada. Postcondiciones 1. El sistema obtiene y muestra los resultados del diagnóstico. Flujo normal 1. El usuario solicita efectuar el diagnóstico. 2. El sistema realiza el caso de uso <Obtener diagnóstico>. 3. El sistema realiza el caso de uso <Obtener explicación>. 4. El sistema muestra por pantalla los resultados. Flujo alternativo 2a. Se produce un error al procesar la imagen. El sistema muestra un mensaje de error. 80 9.1. Análisis Tabla 9.5: CU-02. Diagnosticar. Obtener diagnóstico Nombre e ID del CU CU-03. Obtener diagnóstico Actor Usuario Descripción El sistema calcula la predicción para la imagen guardada. Precondiciones El sistema debe tener una imagen y el modelo guardados. 1. Postcondiciones 1. El sistema almacena el resultado de la predicción. Flujo normal 1. El sistema procesa la imagen. 2. El sistema carga el modelo. 3. El sistema calcula la predicción. 4. El sistema almacena el resultado. Flujo alternativo 1a. Se produce un error al procesar la imagen. El sistema muestra un mensaje de error. 2a. Se produce un error al cargar el modelo. El sistema muestra un mensaje de error. Tabla 9.6: CU-03. Obtener diagnóstico. Obtener explicación Nombre e ID del CU CU-04. Obtener explicación Actor Usuario Descripción El sistema calcula la explicación para una predicción. Precondiciones El sistema debe tener una imagen, el modelo y la predicción guardados. 1. Postcondiciones 1. El sistema almacena el resultado (imagen) de la explicación. 81 Capítulo 9. Aplicación Flujo normal 1. El sistema procesa la imagen. 2. El sistema carga el modelo y la predicción. 3. El sistema calcula la explicación. 4. El sistema almacena el resultado. Flujo alternativo 1a. Se produce un error al procesar la imagen. El sistema muestra un mensaje de error. 2a. Se produce un error al cargar el modelo o la predicción. El sistema muestra un mensaje de error. Tabla 9.7: CU-04. Obtener explicación. 9.2. Diseño En esta sección, se proporcionan los detalles acerca del diseño de la aplicación web desarrollada. Se lleva a cabo logrando el cumplimiento de los requisitos expuestos en la sección de análisis, sección 9.1. 9.2.1. Tecnologías utilizadas Como ya se describió en la sección 4.1, para el desarrollo de la aplicación de utiliza Flask que es una biblioteca de Python para desarrollo web. Se busca que todas las herramientas sean compatibles con Python, pues es el lenguaje en el que hemos desarrollado los modelos. Optamos por utilizar el servidor de despliegue Gunicorn, ya que es compatible con Flask y nos facilita el uso y despliegue de la aplicación, así como su ejecución multihilo para atender diferentes peticiones. Para el desarrollo propio de las vistas, la web, se utiliza HTML y JavaScript. Estos, junto con CSS, nos permiten manipular el aspecto de la aplicación y sus acciones. 9.2.2. Arquitecturas En esta sección, veremos los patrones de diseño, de acuerdo con [19], empleados en el desarrollo de la aplicación web. 82 9.2. Diseño Figura 9.1: Diagrama de casos de uso. Patrón MVC El patrón Modelo-Vista-Controlador (MVC) es un estilo de arquitectura de software, que separa los datos de una aplicación, la interfaz de usuario y la lógica de control en tres componentes distintos. Se trata de un modelo muy utilizado, que ha demostrado su validez en todo tipo de aplicaciones y sobre multitud de lenguajes o plataformas de desarrollo [1]. El Modelo que contiene una representación de los datos que maneja el sistema, su lógica de negocio y sus mecanismos de persistencia. La Vista, o interfaz de usuario, que compone la información que se envía al cliente y los mecanismos interacción con éste. El Controlador, que actúa como intermediario entre el Modelo y la Vista, gestionando el flujo de información entre ellos y las transformaciones para adaptar los datos a las necesidades de cada uno. Se utilizará para el control de las vistas, documentos HTML, la gestión del modelo o datos y la interacciones o peticiones. Patrón Singleton Conocido como patrón de única instancia, este patrón de diseño permite restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto. Con esto, se garantiza que una clase solo tenga una instancia y proporciona un punto de acceso global a ella [63]. 83 Capítulo 9. Aplicación Patrón Fachada Define una interfaz global de acceso para no acceder directamente a los métodos del modelo. Recibe las peticiones del sistema y delega las responsabilidades en los componentes o subsistemas. 9.2.3. Diagramas de clases Figura 9.2: Diagrama de clases. Debemos comentar que, la clase Modelo_datos hace referencia al modelo del MVC donde se almacenan los datos. Por su parte, VistaCargando, VistaInicio y VistaResultados son las vistas que mostrará la aplicación. La clase Controlador es la que gestiona este cambio de vistas, así como la consulta de información del Modelo e interactúa con Fachada, para realizar las operaciones de diagnóstico. Se emplea la clase Fachada, como indica el patrón fachada, para proporcionar un punto de acceso único al modelo de predicción. Este, a su vez, sigue lo propuesto en el patrón Singleton ya que solo permite crear una instancia de él. El modelo de predicción realizará el diagnóstico, a partir de la imagen, que le envía el controlador. 9.2.4. Diagramas de secuencias Presentamos los diagramas de secuencias correspondientes a los casos de uso desarrollados en la sección 9.1.2. 84 9.2. Diseño CU_01 Figura 9.3: Diagrama de secuencias para CU-01 Subir imagen. CU_02 Figura 9.4: Diagrama de secuencias para CU-02 Diagnosticar. 85 Capítulo 9. Aplicación CU_03 Figura 9.5: Diagrama de secuencias para CU-03 Obtener diagnóstico. CU_04 Figura 9.6: Diagrama de secuencias para CU-04 Obtener explicación. 86 9.2. Diseño 9.2.5. Pruebas Al tratar con una aplicación sencilla, no se elabora una amplia batería de pruebas. Se evalúan las situaciones habituales y se comprueba su funcionamiento de estas como batería de pruebas. Se comentan brevemente las pruebas realizadas, tanto positivas, como negativas. Imágenes o archivos con extensión incorrecta: reciben el mensaje de error. Imágenes apropiadas: obtienen el diagnóstico con el curso normal de ejecución. No se encuentra el modelo: se obtiene un mensaje de error. 9.2.6. Seguridad Como el objetivo el lograr una aplicación sencilla, funcional, que dé soporte a los modelos de Aprendizaje Profundo construidos, y no desarrollar una aplicación completa con un proyecto de Ingeniería de Software. No consideramos tratar los temas de seguridad del sistema. Empero, se llevan a cabo las siguientes consideraciones para garantizar el buen funcionamiento del sistema y la buena praxis de la utilización de las bibliotecas: Se comprueba la extensión o formato de los archivos cargados en la aplicación. Con esto, garantizamos que los ficheros sean imágenes en uno de los formatos permitidos: jpg, jpeg o png. Puede que la API de Keras soporte más formatos de imágenes, pero solo hemos considerado estos por motivos de obtener garantías. Se cifran las sesiones de los usuarios. Se asigna una clave de 10 números y letras generada aleatoriamente al comienzo de la sesión para mantener las sesiones del cliente seguras. Con la clave, se encriptan las cookies del cliente para guardarlas en el navegador. 9.2.7. Implementación Se incluyen, en el CD presentado junto a esta memoria, los scripts necesarios para el correcto funcionamiento de la aplicación. La implementación tiene base en [16]. En la sección B, se explica con detalle el contenido y organización del CD. 9.2.8. Despliegue Se propone la utilización de contenedores Docker para realizar la migración y despliegue de la aplicación. Docker es una plataforma abierta, gratuita, para desarrollar, enviar y ejecutar aplicaciones [15] que permite separar la aplicación de la infraestructura. Docker ofrece la posibilidad de empaquetar y ejecutar una aplicación en un entorno poco aislado llamado contenedor. El aislamiento y la seguridad permiten ejecutar muchos 87 Apéndice A Manuales de la Aplicación A.1. Manual de instalación Se requiere un entorno Python 3.8.5 para ejecutar la aplicación. Las especificaciones de librerías utilizadas, y por ello recomendadas, se encuentran en la sección 4.1. No se proporciona ninguna garantía en un entorno con otras versiones del lenguaje o de sus librerías. En el CD, podemos encontrar un archivo llamado requirements.txt en el que se especifican las librerías que se necesitan instalar para el correcto funcionamiento de la aplicación. Se recomienda instalar las versiones de las librerias en un entorno virtual, como por ejemplo Anaconda, que ha sido el empleado en desarrollo, o directamente desde este fichero utilizando el comando pip. 1$ pip install -r requirements . txt Para la ejecución de la aplicación debemos situarnos dentro del directorio Aplicación. En él, se debe ejecutar el comando de lanzamiento para una aplicación Flask. directamente desde este fichero utilizando el comando pip. 1$ python -m flask run Tras lanzar el programa por consola, debemos acceder a un navegador y buscar una de las siguientes direcciones. 1. localhost:5000 2. 127.0.0.1:5000 De esta manera, accedemos al puerto de la máquina local que lanza la aplicación web y ya está lista para su uso. 95 Apéndice A. Manuales de la Aplicación A.2. Manual de usuario Una vez se accede a la web de la aplicación encontramos la pantalla de inicio, podemos verla en la Figura A.1. Figura A.1: Pantalla de inicio. En ella, debemos subir la imagen que queremos diagnosticar. Seleccionando el botón Examinar se despliega un explorador de archivos donde se puede seleccionar la imagen. También, se proporciona la posibilidad de arrastrarla al área de color azul. Si la imagen se carga de forma correcta, podremos observar su nombre en la pantalla, tanto en la zona superior, al lado del botón Examinar como en la zona central azul. Podemos observarlo en la Figura A.2. Figura A.2: Pantalla de inicio con imagen seleccionada. 96 A.2. Manual de usuario Tras subir la imagen al sistema, solicitaremos la obtención del diagnóstico utilizando el botón Diagnosticar. Con esto, pasamos a una pantalla de carga que se muestra mientras el sistema realiza la predicción, obtiene el diagnóstico y calcula la imagen Grad-CAM. Esta pantalla de carga se muestra en la Figura A.3. Figura A.3: Pantalla de carga. La última vista de la aplicación muestra los resultados obtenidos para la imagen seleccionada. En la zona derecha, podemos encontrar la clase predicha, en el ejemplo COVID- 19. En la zona central, podemos ver la imagen obtenida con Grad-CAM que nos indica cómo se ha realizado la predicción. En este ejemplo, vemos que encuentra información relevante en la zona de ambos pulmones. Figura A.4: Pantalla de resultados. 97 Apéndice A. Manuales de la Aplicación 98 Apéndice B Contenido del CD Explicamos el contenido del CD, o repositorio, en este caso, que se entrega junto a la Memoria, junto con el árbol de directorios correspondiente, para facilitar la navegación por los archivos del mismo. Figura B.1: Estructura de directorios. En la Figura B.2, podemos ver la estructura de directorios del CD. En el directorio Aplicación encontraremos todas las clases, ficheros y estructura de directorios necesaria para el funcionamiento de la aplicación. En el directorio Código, están los cuadernos de 99 Apéndice B. Contenido del CD Python utilizados para el procesamiento de datos y la creación de modelos de Aprendizaje Profundo. Los directorios chest_X_ray.zip y Datos constan de los datos, en el primero los originales y en el segundo estos con la división en conjunto de entrenamiento y prueba. Por último, se encontrará esta memoria. Los datos no se pueden adjuntar al repositorio por restricciones de almacenamiento. Por tanto, la estructura final del repositorio es la siguiente. Figura B.2: Estructura de directorios final del repositorio. En los directorios static y templates, podemos encontrar: los ficheros estáticos de la aplicación (hoja de estilo, imágenes guardadas para predecir...) y las plantillas HTML, respectivamente. 100 Bibliografía [1] Universidad de Alicante. Modelo Vista Controlador (MVC).url:https://si.ua. es/es/documentacion/asp-net-mvc-3/1-dia/modelo-vista-controlador- mvc.html (visitado 09-07-2021). [2] Sai Balaji. Binary Image classifier CNN using TensorFlow. 2020. url:https:// medium.com/techiepedia/binary-image-classifier-cnn-using-tensorflow- a3f5d6746697 (visitado 29-06-2021). [3] Y. Bengio, A. Courville y P. Vincent. “Representation Learning: A Review and New Perspectives”. En: IEEE Transactions on Pattern Analysis and Machine Intelligence 35.8 (ago. de 2013), págs. 1798-1828. doi:10.1109/tpami.2013.50.url:https: //doi.org/10.1109/tpami.2013.50. [4] Jeff Bezanson y col. “Julia: A fresh approach to numerical computing”. En: SIAM review 59.1 (2017), págs. 65-98. [5] Y-Lan Boureau y col. “Learning mid-level features for recognition”. En: 2010 IEEE computer society conference on computer vision and pattern recognition. IEEE. 2010, págs. 2559-2566. [6] Joe Cabrera. “Windows vs. Linux: A comparative study”. En: Proposal, Technical Writing, Blinn College, Bryan, TX. Accessed January 21 (2009), pág. 2019. [7] Nitesh V Chawla y col. “SMOTE: synthetic minority over-sampling technique”. En: Journal of artificial intelligence research 16 (2002), págs. 321-357. [8] Francois Chollet. Deep learning with Python. Simon y Schuster, 2017. [9] François Chollet. Deep Learning with Python. Manning, nov. de 2017. isbn: 9781617294433. [10] François Chollet. Grad-CAM class activation visualization. 2021. url:https:// keras.io/examples/vision/grad_cam/ (visitado 03-07-2021). [11] Muhammad EH Chowdhury y col. “Can AI help in screening viral and COVID-19 pneumonia?” En: IEEE Access 8 (2020), págs. 132665-132676. [12] Google Cloud. Procesamiento previo de datos de aprendizaje automático con TensorFlow Transform.url:https: / / cloud. google. com / architecture /data - preprocessing-for-ml-with-tf-transform-pt2?hl=es-419 (visitado 03-07-2021). 101 Bibliografía [13] A. Delgado. Inteligencia artificial y minirobots. Textos universitarios. Ecoe Ediciones, 1998. isbn: 9789586481557. url:https://books.google.com.co/books?id= cmoaPwAACAAJ. [14] Adit Deshpande. A Beginner’s Guide To Understanding Convolutional Neural Networks. 2017. url:https://adeshpande3.github.io/A-Beginner%27s-Guide- To-Understanding-Convolutional-Neural-Networks-Part-2/ (visitado 01-07-2021). [15] Docker overview.url:https : / / docs . docker . com / get - started / overview/ (visitado 12-07-2021). [16] Silvia Duque. Estudio y Aplicación de Redes Convolucionales a la Clasificación de Imágenes Estáticas. Universidad de Valladolid: Trabajo de Fin de Grado, 2019. [17] Forbes. What IT Needs To Know About The Data Mining Process. 2015. url: https://www.forbes.com/sites/metabrown/2015/07/29/what-it- needs- to - know - about - the - data - mining - process / ?sh = 523106b3515f (visitado 25-06-2021). [18] Kunihiko Fukushima. “Neocognitron: A self-organizing neural network model for a mechanism of pattern recognition unaffected by shift in position”. En: Biological Cybernetics 36.4 (abr. de 1980), págs. 193-202. doi:10.1007/bf00344251.url: https://doi.org/10.1007/bf00344251. [19] Erich Gamma y col. Elements of reusable object-oriented software. Vol. 99. Addison- Wesley Reading, Massachusetts, 1995. [20] Xavier Glorot y Yoshua Bengio. “Understanding the difficulty of training deep feedforward neural networks”. En: Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics. Ed. por Yee Whye Teh y Mike Titterington. Vol. 9. Proceedings of Machine Learning Research. Chia Laguna Resort, Sardinia, Italy: PMLR, 2010, págs. 249-256. url:http : / / proceedings . mlr . press/v9/glorot10a.html. [21] Ian Goodfellow, Yoshua Bengio y Aaron Courville. Deep Learning.http://www. deeplearningbook.org. MIT Press, 2016. [22] Ian J Goodfellow, Jonathon Shlens y Christian Szegedy. “Explaining and harnessing adversarial examples”. En: arXiv preprint arXiv:1412.6572 (2014). [23] Michael Grant y Stephen Boyd. CVX: Matlab Software for Disciplined Convex Programming, version 2.1.http://cvxr.com/cvx. Mar. de 2014. [24] Karol Gregor y Yann LeCun. “Learning fast approximations of sparse coding”. En: Proceedings of the 27th international conference on international conference on machine learning. 2010, págs. 399-406. [25] Andreas Groll y col. Hybrid Machine Learning Forecasts for the UEFA EURO 2020. 2021. arXiv: 2106.05799 [cs.LG]. 102 Bibliografía [26] MK Guruchan. Basic CNN Architecture: Explaining 5 Layers of Convolutional Neural Network. 2020. url:https : / / www . upgrad . com / blog / basic - cnn - architecture/#Convolution\_Layers (visitado 29-06-2021). [27] D. H. Hubel y T. N. Wiesel. “Receptive fields of single neurones in the cat's striate cortex”. En: The Journal of Physiology 148.3 (oct. de 1959), págs. 574-591. doi: 10.1113/jphysiol.1959.sp006308.url:https://doi.org/10.1113/jphysiol. 1959.sp006308. [28] Bob Hughes. Software Project Management 5e. McGraw Hill, 2009. [29] Keras API reference Convd2D layer.url:https : / / keras . io / api / layers / convolution_layers/convolution2d/ (visitado 02-07-2021). [30] Keras API reference Dense layer.url:https://keras.io/api/layers/core_ layers/dense/ (visitado 01-07-2021). [31] Keras API reference MaxPooling2D layer.url:https://keras.io/api/layers/ pooling_layers/max_pooling2d/ (visitado 02-07-2021). [32] Keras API reference Model training APIs.url:https://keras.io/api/models/ model_training_apis/ (visitado 03-07-2021). [33] Keras API reference optimizers Adam. [34] Keras API reference optimizers RMSprop.url:https://keras.io/api/optimizers/ rmsprop/ (visitado 25-06-2021). [35] Keras API reference optimizers SGD.url:https://keras.io/api/optimizers/ sgd/ (visitado 25-06-2021). [36] Keras API reference pooling layers.url:https : / / keras . io / api / layers / pooling_layers/ (visitado 21-06-2021). [37] Diederik P. Kingma y Jimmy Ba. Adam: A Method for Stochastic Optimization. 2017. arXiv: 1412.6980 [cs.LG]. [38] Thom Lane. Multi-Channel Convolutions explained with.. . MS Excel! 2018. url: https://medium.com/apache-mxnet/multi-channel-convolutions-explained- with-ms-excel-9bbf8eb77108 (visitado 01-07-2021). [39] Y. Lecun y col. “Gradient-based learning applied to document recognition”. En: Proceedings of the IEEE 86.11 (1998), págs. 2278-2324. doi:10.1109/5.726791. url:https://doi.org/10.1109/5.726791. [40] Yan LeCun. Training with large minibatches is bad for your health. 2018. url: https://twitter.com/ylecun/status/989610208497360896 (visitado 03-07-2021). [41] Lu Lu. “Dying ReLU and Initialization: Theory and Numerical Examples”. En: Communications in Computational Physics 28.5 (2020), 1671–1706. issn: 1991-7120. doi:10.4208/cicp.oa-2020-0165.url:http://dx.doi.org/10.4208/cicp.OA- 2020-0165. 103